OmniRoute 的 codex-app-server 提供商:用 WebSocket JSON-RPC 驱动 Codex CLI app-server,实现零 token 重放的 Codex 接入
OmniRoute 的 codex-app-server 提供商用 WebSocket JSON-RPC 驱动 Codex CLI app-server实现零 token 重放的 Codex 接入【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline Copilot. Quota-aware auto-fallback, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRouteOmniRoute 提供两种接入 OpenAI Codex 的方式直接重放 OAuth token 的codex提供商以及本文重点讲解的codex-app-server提供商。后者通过 WebSocket 上的 JSON-RPC 2.0 协议驱动 Codex CLI 自带的codex app-server进程由 CLI 自行拥有并刷新 OpenAI OAuth 凭据OmniRoute 全程不接触、不重放任何 API token。读完本文你可以完成 sidecar 的 compose 部署、理解端点与能力令牌capability token的解析规则和凭据绑定安全约束并掌握仪表板登录流程背后的双层健康检查实现。1. 两种 Codex 提供商的本质区别OmniRoute 中暴露了两个使用 OpenAI Codex 的入口提供商与 OpenAI 的通信方式使用注意事项codex将你的 ChatGPT/OpenAI OAuth token 直接重放到 Responses API有— 官方会话并不授权用于代理/路由场景codex-app-server通过 JSON-RPC/WebSocket 驱动Codex CLI 自带的codex app-serverCLI 像交互式codex会话一样拥有并自我刷新 OAuth~/.codex/auth.json无— OmniRoute 从不向 API 重放 token正因为codex-app-server从不重放 token它不携带会话重放使用注意事项。代价是它要求一个在配置的 app-server URL 上可达的 Codex CLI并且该 CLI 必须已完成登录。在提供商注册表中见 codex-app-server 注册项可以确认这一设计export const codexAppServerProvider: RegistryEntry { id: codex-app-server, alias: cxa, format: openai-responses, executor: codex-app-server, // Sentinel: 执行器从 providerSpecificData 拨号 WebSocket app-server URL // 而不是这个 baseUrl。保留此值仅用于目录/调试展示。 baseUrl: codex-app-server://cli/websocket, reasoningTransport: opaque, authType: none, // 无 oauth、无 API key —— sidecar 自己持有认证 authHeader: none, defaultContextLength: 400000, models: [...codexProvider.models], // 与 codex 提供商共享同一组模型 };几个要点authType: none这是一个免认证no-auth提供商——仪表板添加连接时不需要 API key 或 token因为认证由 sidecar 里的 Codex CLI 自己负责baseUrl是文档哨兵值真正的 WebSocket 端点来自每条连接的providerSpecificData或环境变量这一点与codex提供商通过baseUrl直连 API 的模式完全不同模型列表直接从codexProvider导入保证两个提供商暴露的模型清单永远同步。2. 架构应用 app-server sidecar┌─ OmniRoute app ─────────────────┐ ┌─ codex-app-server sidecar ─────────┐ │ CodexAppServerExecutor │ WS │ codex app-server │ │ ws://codex-app-server:1456 ─────┼───────▶│ --listen ws://0.0.0.0:1456 │ │ ( capability token) │ JSON │ --ws-auth capability-token │ │ │ RPC │ self-manages OpenAI OAuth │ └──────────────────────────────────┘ │ (~/.codex/auth.json, auto-refresh) │ │ shares (compose volumes) └─────────────────────────────────────┘ ▼ codex-appserver-token → WS 能力令牌两边都挂载它 codex-appserver-home → ~/.codexauth.json 由仪表板写入 由 sidecar 的 codex app-server 读取sidecar只监听内部 compose 网络ws://codex-app-server:1456且背后有一层能力令牌capability token守卫。它永不发布到宿主机或互联网Codex CLI 被打包进omniroute:base基础镜像因此宿主或用户机器上无需安装 codex。在 docker-compose.yml 中sidecar 服务定义为profiles: [codex-app-server]其启动命令首次启动时生成一个 32 字节 hex 能力令牌写入共享卷然后exec进入codex app-servercodex-app-server: image: omniroute:base container_name: omniroute-codex-app-server restart: unless-stopped entrypoint: [/bin/sh, -c] command: - | set -e TOKEN_FILE/run/codex-appserver/token mkdir -p /run/codex-appserver if [ ! -s $TOKEN_FILE ]; then # 32 字节 hex 能力令牌通过 token 卷与主应用共享 TF$TOKEN_FILE node -e require(fs).writeFileSync(process.env.TF, require(crypto).randomBytes(32).toString(hex)) 2/dev/null || \ { head -c 32 /dev/urandom | od -An -tx1 | tr -d \n $TOKEN_FILE; } chmod 600 $TOKEN_FILE fi exec codex app-server \ --listen ws://0.0.0.0:1456 \ --ws-auth capability-token \ --ws-token-file $TOKEN_FILE environment: - CODEX_HOME/home/node/.codex - RUST_LOG${CODEX_APPSERVER_RUST_LOG:-warn} volumes: - codex-appserver-token:/run/codex-appserver - codex-appserver-home:/home/node/.codex # 无 ports: —— 仅限内部。主应用在 compose 网络上以 # ws://codex-app-server:1456 访问。 healthcheck: test: [CMD, node, -e, require(http).get(http://127.0.0.1:1456/readyz,rprocess.exit(r.statusCode200?0:1)).on(error,()process.exit(1))] profiles: - codex-app-server主应用一侧通过两个环境变量指向 sidecar同样定义在 docker-compose.yml 的环境变量段- OMNIROUTE_CODEX_APPSERVER_WS${OMNIROUTE_CODEX_APPSERVER_WS:-ws://codex-app-server:1456} - OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE${OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE:-/run/codex-appserver/token}codex-appserver-token卷挂载到/run/codex-appserversidecar 生成、应用读取同一个令牌文件codex-appserver-home卷挂载到/home/node/.codex基础镜像以node用户运行这是仪表板Apply auth写入auth.json、sidecar 里codex app-server读取同一份认证的位置。3. 启动 sidecar 栈# 以 codex app-server sidecar profile 启动整套栈 docker compose --profile base --profile codex-app-server up -d # (podman 同理podman compose --profile base --profile codex-app-server up -d)sidecar 首次启动时把 WS 能力令牌写入共享卷codex-appserver-token应用再通过OMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE读取同一份令牌——无需任何手工令牌接线。这两个 profile 不激活时上述环境变量对应用是惰性的inertCodex 回落到其它传输方式。4. 连接配置解析URL、令牌与凭据绑定规则执行器侧的配置解析集中在 appServerConfig.ts。它把每条连接的providerSpecificDatapsd与环境变量按固定优先级合并所有可用配置项在 .env.example 中有完整注释配置项psd 字段环境变量默认值说明app-server 端点codexAppServerUrlOMNIROUTE_CODEX_APPSERVER_WS无必填ws://或wss://URL不配置则传输禁用能力令牌内联codexAppServerTokenOMNIROUTE_CODEX_APPSERVER_WS_TOKEN无作为Authorization: Bearer token发送能力令牌文件codexAppServerTokenFileOMNIROUTE_CODEX_APPSERVER_WS_TOKEN_FILE无文件由codex app-server --ws-token-file path生成工作目录codexAppServerCwdOMNIROUTE_CODEX_APPSERVER_CWD/tmp传入thread/start { cwd }审批策略codexAppServerApprovalPolicyOMNIROUTE_CODEX_APPSERVER_APPROVALnever如never、on-request沙箱策略codexAppServerSandboxOMNIROUTE_CODEX_APPSERVER_SANDBOXworkspace-write如read-only、workspace-write、danger-full-access自动批准codexAppServerAutoApproveOMNIROUTE_CODEX_APPSERVER_AUTO_APPROVE关接受true/1/yes解析逻辑resolveAppServerConfig的关键行为URL 与令牌缺一不可两者任一缺失即返回null门控谓词判定为未配置 app-server 传输Codex 自动回落 HTTP 传输令牌优先内联、其次文件先读 psd/env 的内联令牌再读 psd/env 指向的令牌文件凭据/URL 绑定规则安全加固来自环境变量的令牌属于运维方的共享秘密只允许发往a同为环境变量来源的 URL或b判定为运维本地的主机。psd 里写的外部主机 URL 配合 env 令牌会被直接拒绝返回null——否则任何能写连接的人都能借 DNS 把 env 凭据走私出去。本地主机的判定函数isLocalAppServerHost只做字面量匹配、不做 DNS 解析localhost/*.localhost、*.local、*.ts.net、*.internal、回环/ULA/链路本地 IPv6、RFC1918 与169.254/16网段以及单标签主机名无点如 compose 服务名codex-app-server由运维方自己的 hosts/mDNS 解析都算本地带点的公共域名一律不算。5. 仪表板连接与登录Sign in with ChatGPT在仪表板为OpenAI Codex (App-Server)添加连接。它不需要任何 API key 或 tokenno-auth 提供商——sidecar 持有认证若 sidecar 的 Codex CLI尚未登录连接健康检查会报告 running but not signed in而不是刺眼的红色认证错误。此时使用Sign in with ChatGPT它在你的浏览器里跑标准 Codex 设备 OAuthdevice-OAuth随后通过Apply auth把~/.codex/auth.json写入共享卷同一次登录同时服务codex与codex-app-server两个提供商登录完成后健康检查变绿它同时校验/readyz和account/read——即进程活着且已认证连接即可工作。仪表板从不覆盖一个健康的既有~/.codex/auth.json——仅当文件缺失或其 token 过期时才写入且总会先做备份。双层健康检查的源码实现健康检查实现在 codexAppServerHealth.ts分两层第一层HTTP/readyz。把ws://host:port换算成http://host:port/readyz发 GET 请求带 Bearer 令牌8 秒超时redirect: manual——绝不跟随可能携带令牌外泄的重定向。非 200 则报app_server_not_ready连接失败则报app_server_unreachable。注意该连接不走普通 OAuth token 校验路径——因为 app-server 连接没有可校验的 OpenAI token若走普通探测会对占位值报出虚假的 Token invalid or revoked 401。第二层JSON-RPCaccount/read认证探针。/readyz只能证明进程活着不能证明 CLI 已登录。探针实现在 appServerAuthProbe.ts用执行器同一套 WS 客户端打开一条短生命周期连接依次发initialize与account/read。已认证的服务器返回{ account: { type, email, planType }, ... }未登录则无 account或返回 AuthRequiredError 一类 JSON-RPC 错误——探针将其同样归类为logged_out而非unknown这样仪表板会引导用户点Sign in with ChatGPT而不是显示吓人报错。三种状态的处置authenticated→ 健康logged_out→ 报app_server_login_required并提示登录unknown探针超时/不可用→ 服务器既已可达视为健康不因一个不确定的探针阻塞。6. 执行模型JSON-RPC 客户端与默认拒绝的审批策略执行器入口是 codex-app-server.ts它把 OpenAI Responses 请求体扁平化为用户文本extractPromptText图像/工具部件不在首批 app-server 传输范围内再经 appServerClient.ts 的 JSON-RPC 2.0 客户端发起 turn。该客户端有几个对路由场景至关重要的设计id 关联的请求/响应单调递增 id pending 表通知与响应严格区分响应只结算一次服务端到客户端请求的兜底处理器app-server 会向客户端发起审批类 ServerRequestitem/commandExecution/requestApproval、item/fileChange/requestApproval、item/permissions/requestApproval、applyPatchApproval、execCommandApproval。OmniRoute 是路由器——消费它的 harness 才拥有工具执行与策略所有权因此 codex 绝不能卡在自己的交互审批上。所有入站 ServerRequest 都必然被应答审批提示默认自动拒绝无法服务的一律回 JSON-RPC 错误保证 id 被结算、turn 永不悬挂item/tool/call透传harness 定义的动态函数工具走这条单独的透传通道——执行器把它呈现为 Responsesfunction_call并结束本轮与拒绝 codex 自身审批互不干扰。turn 启动策略由 resolveThreadStartPolicy 决定approvalPolicy默认never——codex 不阻塞在路由轮次上的自身交互审批sandbox默认workspace-write此前为danger-full-access经安全评审后收紧——codex 自身的命令/文件执行被限制在本轮 cwd 树内除非运维方通过 psd 或 env 显式放宽autoApprove默认false只有显式设为true/1/yes时才自动批准 codex 的宿主执行审批——这关闭了提示注入 → 宿主执行的路径且不影响 harness 工具调用它们走item/tool/call透传。7. 部署场景原文档区分了三类部署形态已有认证 Codex CLI 的运维方——把宿主机~/.codex挂载进 sidecarcodex-appserver-home卷跳过仪表板登录步骤本地未安装 codex 的公共用户——无需关心sidecar 自带 CLI用户只通过仪表板完成认证即可裸金属 OmniRoute无 sidecar用宿主机 codex——把OMNIROUTE_CODEX_APPSERVER_WS指向你自己的codex app-server并确保宿主机 codex 已登录二进制缺失时会出现 codex not installed 提示。8. 住宅出口 / UDP egress运维方自选不随版发行上文的通用 sidecar 走容器正常网络出口。若运维方需要让 Codex 流量经住宅出口例如携带 TCP UDP/QUIC 的 TUN tailscale sidecar流出需以独立的 compose override 运行该 TUN sidecar——它被有意排除在随版发行的codex-app-serverprofile 之外详见内部运维手册。9. 小结关注点结论是否重放 token否。OpenAI OAuth 完全由 sidecar 内的 Codex CLI 拥有与自刷新连接所需凭据仅 WS 能力令牌compose 部署时自动共享无需手工接线健康判定/readyz进程就绪account/readCLI 已登录双层校验安全默认审批默认拒绝、沙箱默认workspace-write、env 令牌只准发往本地主机验证参考codex-app-server.test.ts与codex提供商共用模型清单但零 token 重放使codex-app-server成为在代理/路由场景下使用 ChatGPT Codex 会话时更干净的合规路径其代价是运维上多了一个必须常驻、必须登录的内部 sidecar 进程——理解了本文的令牌共享、凭据绑定与双层健康检查后这套部署的日常维护基本只剩登录态是否仍有效一件事。【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline Copilot. Quota-aware auto-fallback, RTKCaveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550 contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考