ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenCodex Windows 无窗口服务实现路线图:hidden Launcher 默认修复与 WinSW --native 可选后端

OpenCodex Windows 无窗口服务实现路线图:hidden Launcher 默认修复与 WinSW --native 可选后端 【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载OpenCodex 在 Windows 上的ocx service install默认基于 Task Scheduler 注册服务但长期存在两个被社区反复报告的问题服务运行时会弹出 cmd 控制台窗口且用户关闭该窗口会导致代理进程连带死亡、所有模型连接中断对应 GitHub 问题 #165 与 #166。本文以 devlog/_fin/260720_windows_service/040_roadmap.md 的确认路线图为主线完整展开四项决策、WP2/WP3/WP4 依赖顺序、macOS 开发约束下的验证策略、Windows 实测矩阵与提交门禁规则并结合仓库源码src/service/windows-taskxml.ts、src/service/cli.ts、src/lib/winsw.ts说明实现落地细节。读者读完可以掌握 OpenCodex Windows 服务模式的完整技术方案、底层机制与验收方法。背景问题定位与根因分析2026-07-15 的社区报告指出closing the proxys console window can make every model (even gpt models) disconnect。完整复现路径详见 001_research.md在 Windows 上执行ocx service installTask Scheduler 任务opencodex-proxy以 LogonTrigger 触发执行~/.opencodex/opencodex-service.cmdcmd 控制台窗口直接显示在用户会话中。用户点击窗口关闭按钮会话注销、任务管理器强制结束属同一类强制终止Windows 向该控制台的所有进程发送CTRL_CLOSE_EVENT默认处理器直接结束进程。包装批处理对 Bun 子进程是同步执行%OCX_BUN% %OCX_CLI% start见 windows-taskxml.ts 中buildWindowsServiceScript()的start调用行因此包装器与代理被绑定在同一个控制台生命周期内一起死亡批处理内部的 5 秒重启循环ping -n 6延迟也随批处理自身退出而失效。localhost 代理消失Codex 依赖的所有路由模型包括 GPT 系全部断开。根因是三个要素的组合而非单独某一项对应 Bug 报告 010_issue_bug_console_window.md#要素说明aLogonTypeInteractiveToken/LogonType任务在用户的交互式会话中运行天然伴随可见窗口b任务动作直接执行.cmd控制台批处理交互会话 控制台子系统 可见的 cmd 窗口c缺少隐藏启动hidden-launch机制没有 VBS/PowerShell-WindowStyle Hidden一类 launcher分析中还排除了两个常见误解Hidden只是 Task Scheduler UI 列表中的隐藏任务开关与控制台窗口无关windowsHide: truerunFile管理调用选项只作用于 OpenCodex 自身调用schtasks.exe时对已注册任务运行时的窗口没有任何影响包装脚本注释中 runs in its own hidden console 与实际行为矛盾InteractiveToken 下并非隐藏后续在实现中已同步修正注释。对照而言ocx stop的正常退出路径服务管理器停止 → graceful drain → 原生 Codex 恢复是完整的问题仅存在于关闭窗口这类强制终止路径。路线图四项确认决策040_roadmap.md 于 2026-07-20 经用户批准与 sol 架构审查后定稿确认方向如下默认值保持并修复ocx service install继续使用 Task Scheduler InteractiveToken但改为通过 hidden launcher 运行控制台窗口不再出现。保留无需凭据的 passwordless Microsoft 账户兼容性。#165 的两个症状窗口暴露、关窗即死通过直接消除窗口一并解决。可选原生模式ocx service install --native使用 WinSW 2.12.0NET461 构建注册为真正的 SCM 服务以用户账户运行。LocalSystem 被明确禁止——因为 ACL 加固只对用户 SID 授予权限、没有 SYSTEM ACE--scheduler作为显式默认后端参数。持久化service-state.json v2 记录后端选择ocx update的服务重装流程按该后端原样保留。UAC 被拒绝时不得静默降级到 scheduler。提升暂缓将 WinSW 提升为默认值的决定留待 Windows 实测矩阵通过之后另行决策不属于本轮循环范围。工作阶段依赖顺序PHASE-SPLIT-01路线图按公共资产层 → 新后端 → 后端选择持久化/传播的构建顺序拆分而非按效果大小拆分WP对应文档内容依赖WP2050_hidden_launcher.mdhidden launcher默认路径消除窗口无在现有资产上做最小扩展WP3060_winsw_native.mdWinSW--native可选 state v2 架构/访问器复用 050 的资产写入模式CLI 参数解析在 060 引入WP4070_backend_state_v2.mdupdate 双路径 backend 传播 孤儿/冲突检测 SoT #166 评论在 060 的 state v2/访问器之上传播WP2默认 Task Scheduler 路径的窗口消除hidden launcherWP2 的目标是让默认后端注册的任务在无控制台窗口的情况下运行同时保持InteractiveToken不要求凭据兼容 passwordless 账户直接修复 #165。机制选择wscript.exe VBS launcher选用wscript.exe.vbs作为隐藏启动机制理由wscript.exe是 GUI 子系统可执行文件任务直接执行它也不会产生控制台VBS 内通过WshShell.Run cmd, 0, True以**窗口样式 0隐藏**启动批处理。bWaitOnReturnTrue常驻 launcher是核心wscript 必须存活到批处理结束任务实例才会保持运行中状态MultipleInstancesPolicyIgnoreNew的防重复与schtasks /end的停止目标才能维持。若设为Falsewscript 立即退出、任务被判定为已结束防重复将失效审计 blocker 1。PowerShell 备选被否决powershell.exe自身是控制台应用直接执行仍会出窗或闪烁且-File会被客户端默认 ExecutionPolicyRestricted拦截。隐藏执行使关窗致死路径从根源消失批处理内 5 秒重启循环在隐藏控制台内继续正常工作。需实测并文档化的例外企业策略禁用 WSH注册表Software\Microsoft\Windows Script Host\Settings\Enabled0时任务不会执行需要作为已知限制与实测矩阵项记录。实现变更要点源码实现见 src/service/windows-taskxml.ts新增buildWindowsLauncherVbs()L163-L173生成 launcher 内容核心两行 OpenCodex service launcher — runs the batch wrapper with a hidden window. Generated by ocx service install; do not edit. Set shell CreateObject(WScript.Shell) shell.Run script 路径, 转义为 , 0, TrueVBS 字符串只需将转义为并以 CRLF 结尾。脚本路径通过windowsLauncherVbsPath()定位配置目录下的opencodex-service-launcher.vbs。编码契约审计 blocker 2禁止无 BOM 的 UTF-8——非 ASCII如韩文等用户路径可能被 WSH 版本/代码页误读。与任务 XML 一致以UTF-16LE BOM写入writeServiceAssetWithRetry(path,\uFEFF${vbs}, utf16le)。改造buildWindowsTaskXml()L201-L266Exec改为CommandC:\Windows\System32\wscript.exe/CommandArguments/b /nologo launcher.vbs/Arguments单斜杠为现行规范形式。/b为批处理模式抑制脚本错误弹窗。launcher 路径独立经 XML 转义防等字符路径wscript 路径通过windowsWscript()使用SystemRoot回退模式解析。签名扩展为buildWindowsTaskXml(script, launcher)便于测试注入。安装/卸载联动installWindows()在写任务 XML 前用writeServiceAssetWithRetry一并写入 launcher.vbsuninstallWindows()同步删除 launcher.vbs。会话恢复触发器实现中同时纳入了RemoteConnect/SessionUnlock/ConsoleConnect三类SessionStateChangeTrigger按安装账户 SID 显式限定UserId——因为 InteractiveToken 下代理随交互会话销毁这些触发器保证下次连接时自动拉起对应 windows-taskxml.ts 的WINDOWS_SESSION_RECOVERY_STATE_CHANGES。测试策略在tests/service.test.ts的 Windows service task describe 中扩展字符串级契约测试buildWindowsTaskXml必须含Command…wscript.exe/Command与/b /nologo 引号包裹的 launcherArguments且含的 launcher 路径被转义为amp;buildWindowsLauncherVbs必须含shell.Run, 0, True路径中的转义为含恶意路径样例与非 ASCII 路径样例install 源码字符串包含 launcher.vbs 经writeServiceAssetWithRetry以 UTF-16LE \uFEFFBOM 写入uninstall 源码包含 launcher 路径的 unlink既有 XML 设置测试保持通过设置块不变。WP3WinSW--native可选原生 SCM 后端WP3 让ocx service install --native以 WinSW 2.12.0 将代理注册为真正的 Windows 服务SCM 管理仅面向显式选择不改变默认值且禁止 LocalSystem。核心实现位于 src/lib/winsw.ts。二进制获取与供应链校验仓库策略不提交真实二进制因此--native首次安装时从 WinSW 官方 GitHub 发布页下载WinSW.NET461.exev2.12.0到配置目录~/.opencodex/winsw/保存为opencodex-proxy.exeWinSW 要求 XML 与 exe 同名。下载后仅通过 SHA-256 固定值校验后才使用不一致则 fail-closed删除文件并报错。离线/代理环境失败时错误信息会给出手动放置路径。npm 内置二进制作为后续决策。账户模型与 LocalSystem 结构性拒绝审计 blocker 3WinSW v2.12 架构使用serviceaccount内的domain/user/password/allowservicelogon形式区别于 v3 的username。密码不写入 XML。凭据通过winsw install /p交互式提示输入——由于/p是控制台 stdin 提示现有runFilestdin 为 ignore无法胜任需要新的runFileInteractive()helperstdio: inherit让用户直接应答。依赖 WinSW 自身的 UAC 自提升用户拒绝 UAC 时以明确错误中止禁止静默回退 scheduler。安装后验证与回滚执行sc.exe qc opencodex-proxy-native核对SERVICE_START_NAME与预期用户一致若为 LocalSystem 立即winsw uninstall回滚并报错——结构上阻断XML 未生效却以 LocalSystem 运行的事故WinSW 默认账户就是 LocalSystem。已存在服务时的重装路径跳过 install重写资产 winsw stop可忽略失败winsw start无需重新提示凭据。passwordless Microsoft 账户的失败以明确错误呈现列入实测矩阵。graceful stop 与令牌注入优雅停止交由 WinSWstoptimeout CtrlC 优先行为同时ocx service stop继续走既有 drainstopTrackedProxyForServiceCommand形成 WinSW 先杀子进程场景下的双重保险。native 后端不经过包装批处理令牌由应用直接读取OCX_API_TOKEN_FILE环境变量在应用层被消费——OPENCODEX_API_AUTH_TOKEN为空且OCX_API_TOKEN_FILE已设置时从文件读取并注入process.env.OPENCODEX_API_AUTH_TOKEN服务器认证在 src/server/index.ts 读取该环境变量。秘密绝不进入 WinSW XML。实现为src/lib/service-secrets.ts中的纯函数loadServiceTokenFromFile()不改动 env 本身由调用方赋值并做单元测试。WinSW XML 关键配置buildWinswXml()生成的service包含idopencodex-proxy-nativeexecutablebun、argumentscli startenv nameOCX_SERVICE value1/、OCX_API_TOKEN_FILE、CODEX_HOME/OPENCODEX_HOME绝对路径env namePATH value当前 PATH, XML 转义/——SCM 服务环境没有用户交互式 PATH不 bake PATH 会令 provider 可执行文件解析失败与 Scheduler/launchd/systemd 既有契约一致logpath配置目录、log moderoll-by-size、onfailure actionrestart delay5 sec/、stoptimeout20 sec/stoptimeout、serviceaccountv2 架构domain/user/allowservicelogon无 password 元素。注意不使用%USERPROFILE%间接化统一 bake 绝对路径。backend 切换事务与状态语义审计 blocker 5ServiceOps选择接收 backend 参数platformOps(backend?: scheduler | native)win32 且backendnative时返回 winsw ops默认 scheduler。serviceCommand(sub, flags)签名扩展--native/--scheduler仅允许用于 install其他子命令从 state 读取 backendsrc/service/cli.ts 中parseServiceArgs同时拒绝--native/--scheduler互斥冲突非 install 子命令携带 backend 参数会得到明确错误。backend 切换事务install --native若检测到已存在的 scheduler 安装先stopWindows()uninstallWindows()移除后再装 native反向install --scheduler同理。native 安装失败时不自动重装 scheduler而是明确报告未安装任何服务状态禁止静默回退。冲突检测stopServiceIfInstalled/serviceStatusSummary与 state 无关地同时查询两端 backendschtasks 任务存在 → schedulerwinsw status 非NonExistent→ native两者都存在则报告冲突并全部停止。native 的 stop/uninstall/status 从 state 读取 backend 选择相应 opslegacy无字段按 scheduler 处理。native uninstall 后允许 exe/xml 残留为重装保留--purge不在本轮范围。状态语义收敛fail-closed后续审计将WinswStatus增加unknown——WinSW status 查询失败不得被映射为 nonexistent否则会放过活跃 SCM 服务parse/查询失败均 fail-closedinstall 在unknown状态下显式拒绝详见 080_done.md。CLI 接线src/service/cli.ts 中case service将参数切片传给serviceCommandnormalizeServiceSubcommand以第一个非旗标 token 为子命令。非 install 子命令使用readServiceBackend()win32决定 opsmacOS/其他平台固定 scheduler。WP3 测试tests/service.test.ts 新增tests/winsw.test.tsbuildWinswXml断言 serviceaccount/allowservicelogon 存在、LocalSystem 缺席、OCX_SERVICE1env、PATH env 存在且转义、stoptimeout、onfailure restart、XML 转义路径含、秘密令牌值缺席、v2 架构domain/user、无 username 元素ensureWinswBinary哈希不一致时 fail-closedmock fetch/fsstatusWinsw解析Started/Stopped/NonExistent三分支backend 切换时install --native先行移除 scheduler 的源码契约、失败无回退CLI 参数parseServiceArgs([install,--native])分支loadServiceTokenFromFile文件存在/缺失/空白修剪。WP4backend 持久化state v2与 update 传播WP4 确保 backend 选择在安装生命周期内保持ocx update按所选 backend 原样重装并让文档SoT反映真实行为对应 070_backend_state_v2.md。state v2 架构ServiceInstallState增加version: 1 | 2、backend?: scheduler | native、winswVersion?: string、winswSha256?: stringnative 时。writeServiceInstallState(backend)写 v2readServiceInstallState()接受 v1legacy 无 backend → 按 scheduler 处理。该 schema 与访问器在 WP3 一并引入避免把同一 schema 契约拆到两个 phase审计 WARN 9。导出访问器新增 exportreadServiceBackend(): scheduler | nativeupdate 代码访问私有 state 的唯一通道审计 blocker 4新增 exportserviceReinstallArgs(): string[]由 backend 推导[service,install]或[service,install,--native]。update 双路径传播src/update/index.ts 与 src/update/job.tsGUI/后台更新路径均改用serviceReinstallArgs()不再硬编码service installisServiceInstalled()保持原语义任一 backend 已装即 truetests/update-job.test.ts固定期望值同步更新。孤儿/冲突检测stopServiceIfInstalled/uninstallServiceIfInstalled/serviceStatusSummary同时查询两端 backendbakedServicePathsDiagnostic在 native 时追加检查 winswExePath 存在。SoT 更新README 支持平台表 Windows 行改为 Task Scheduler (hidden) / opt-in native service (--native, WinSW) 并注明 known limitationlogon 启动native 为 boot 启动starts on boot 表述按平台修正mac/linux 分别 login/bootWindows 默认 logon、--native为 bootdocs/codex-path-investigation.md Windows 服务节同步 hidden launcher 与--nativeocx service --help/usage 字符串补充--native/--scheduler说明。#166 评论发布方向决策sol 审查要点无窗口 Scheduler 默认 --native可选 持久化WinSW 默认提升留待实测、实现提交摘要与 Windows 实测请求矩阵。macOS 开发约束下的验证策略开发机为 macOS无法实机观测 Windows 行为窗口不显示、schtasks /end树终止、WinSW graceful stop、passwordless 账户注册等因此C 门禁以单元测试 类型检查为准扩展tests/service.test.ts并以bunx tsc --noEmit把关。用测试将生成物XML/脚本的字符串契约固定下来。实测项显式化每个 decade 文档的实测矩阵节列出需 Windows 实机确认的项WP4 在 #166 评论发布实测请求清单。既有套件先例tests/service.test.ts的 Windows service task describe 已在字符串层验证 XML 设置/转义/BOM 契约。实测矩阵需 Windows 用户/后续确认hidden launcher窗口不显示schtasks /run正常启动schtasks /end后代理 drain 路径正常、日志连续IgnoreNew防重复在常驻 wscript 下真实维持验证 blocker 1 中常驻 launcher前提WSH 被禁环境的失败模式。WinSW安装 UAC 流程用户账户凭据提示passwordless MS 账户失败模式错误信息清晰SCM stop 的 graceful drainCtrlC 信号是否传递到 Bun 进程boot 启动ACL 加固令牌文件可读。updatebackend 保留重装stale 资产诊断。提交与门禁规则每个 WP 本地提交LOOP-GIT-01禁止 push。每个实现 WP 走 sol 审查流程审查员审计A→ 实现B→bunx tsc --noEmitbun test tests/service.test.ts含受影响套件C→ 提交摘要D。工作区既有 dirty 变更gui/src/pages/Models.tsx保持不动。落地结果与后续修复本轮实现已在 080_done.md 记录为 DONE关键提交包括WP2 的 VBS wscript launcherUTF-16LEBOM 防非 ASCII 路径、WP3 的 WinSW v2.12--nativeSHA-256 固定下载、/p凭据提示、LocalSystem 回滚验证、state v2 readServiceBackend()/serviceReinstallArgs()、WP3 审计 R3 的事务性 backend 切换禁止双管理器共存、冲突旗标拒绝、WP4 的 update 双路径 backend 保留重装与 README SoT 修正。验证结果bun test tests/winsw.test.ts tests/update-stop-first.test.ts tests/service.test.ts tests/update-job.test.ts→ 69 pass / 0 failbunx tsc --noEmitrootgui 均 green。同轮后续修复还包括 WinSW statusunknown状态 fail-closed、updateChildStdio()/logSpawnOutput()stdio 管道移植serviceReinstallArgs()保留、ocx update --help误执行 self-update 的缺陷修复。Windows 实机冒烟服务安装/更新/关窗因 macOS 开发环境未执行已留待 Windows 用户按实测矩阵反馈后进入后续单元。结论该路线图的核心设计取舍可以概括为一句话默认路径用藏窗口解决症状wscript 常驻 launcher 消除关窗致死路径可选用真正服务语义WinSW SCM 用户账户 SHA-256 固定 LocalSystem 结构性拒绝并用 state v2 与 update 传播保证两种选择在升级中不被悄悄改变。源码层面生成物契约VBS/XML/WinSW XML 的转义、编码、账户字段全部由单元测试在字符串层锁定Windows 专属行为则通过实测矩阵显式移交实机验证——这套文档先行、测试锁契约、实机补矩阵的组合正是 Windows 平台服务代码在非 Windows 开发机上可以稳定演进的关键。赞分享【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载相关推荐ZonyLrcToolsX 歌词批量下载实战指南5分钟给整张歌单配齐歌词ZonyLrcToolsX 歌词批量下载实战指南5分钟给整张歌单配齐歌词 有没有过这样的体验辛苦整理了上千首本地歌曲播放器里却一片空白没有歌词可看想逐种子卡在 99% 不动trackerslist 公共 Tracker 列表配置全解种子卡在 99% 不动trackerslist 公共 Tracker 列表配置全解 种子卡在 99% 不动、速度只有几 KB/s 时第一怀疑对象就是种子里的Lucide 图标可访问性实践指南从 aria-hidden 默认行为到完整无障碍实现Lucide 图标可访问性实践指南从 aria hidden 默认行为到完整无障碍实现 Lucide 图标库默认将图标对屏幕阅读器隐藏 aria hidde前端UI组件设计系统上一篇RedisInsight终极指南如何用官方可视化工具轻松管理Redis数据库下一篇从入门到精通proxmox-stuff的高级使用技巧与最佳实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表