工作原理
Codex 使用 OpenAI Responses API。opencodex 接收通过 HTTP 与 Server-Sent Events 发送的
POST /v1/responses,也可选择在同一路径上启用 WebSocket 升级。它会把请求转换为 provider
的 wire 格式,再把响应转换回 Responses 事件,因此 Codex 无需知道自己正在与非 OpenAI 模型通信。
┌──────────────────────────── opencodex ────────────────────────────┐ │ │ Codex ──▶ │ parser ──▶ router ──▶ [vision] ──▶ adapter ──▶ provider │ ──▶ Codex (/v1/ │ │ │ │ │ │ │ (SSE / WS) responses)│ OcxParsed provider describe buildRequest parseStream │ │ Request +adapter images + fetch AdapterEvent[] │ │ │ │ │ │ [web-search loop] bridge ─▶ SSE │ └─────────────────────────────────────────────────────────────────────┘Codex 认证账号选择
Section titled “Codex 认证账号选择”当选择的 provider 使用 ChatGPT/Codex 直通时,opencodex 可以在转发请求前从已保存的账号池中选择账号。
- 已有线程保持绑定。 线程绑定到开始时所选的账号代次,长时间运行的 SSH、tmux 或移动端 Codex 会话不会在正常对话过程中重新分配账号。
- 新会话可以重新分配。 新线程按
accountPoolStrategy选择可用账号,默认为quota,也支持round-robin和fill-first。quota比较已知的 5 小时、每周和 30 天额度使用量,并在当前账号 超过autoSwitchThreshold时选择使用量更低的账号。冷却中或需要重新认证的账号会被跳过。 - 额度和失败信号参与路由。 仪表盘通过
GET /api/codex-auth/accounts?refresh=1强制刷新额度。 成功的上游响应会更新额度头信息;429 使账号进入冷却,401/403 会将账号标记为需要重新认证。 - 空闲额度窗口可以自动激活。 高级设置中的自动激活默认关闭,统一控制当前主账号和附加账号 已报告的 5 小时及每周窗口;新添加账号不会自动启用。在 Pool 模式下,窗口到期后会通过对应账号 发送最小化、不保存的请求,并消耗少量额度;同时到期的窗口合并为一次请求。暂停、需要重新认证 的账号会被跳过,主账号硬锁限制也会得到遵守。成功响应的额度头会更新缓存;已启用且符合条件的 空闲账号还会每隔至少 5 分钟刷新过期的额度元数据,无需保持仪表盘打开。已观察到的到期时间会保留 至激活完成,重启或后续查询的时间变化不会丢失待处理窗口。元数据查询复用现有的有次数限制的认证 恢复逻辑;推理请求返回 401 时,被拒绝的凭据会标记为需要重新认证。失败日志仅记录不透明账号标签 和安全的状态原因。该功能独立于为传入请求选择账号的路由逻辑。
降级说明: 运行旧版本前,请仅移除自动激活设置中的 nextFiveHourResetAt 和
nextWeeklyResetAt。旧版严格校验不接受这两个新字段,可能因此禁用整个自动激活设置块。
Sub-agent 模型选择
Section titled “Sub-agent 模型选择”全新安装会通过 subagentModels 在 Codex 的 sub-agent 选择器中优先显示 gpt-6-astra、GPT-5.6
Sol/Terra/Luna 三个模型和 gpt-5.5。仪表盘可以从原生或已路由模型中重新排序或替换最多
五个条目。对于 v1 协作请求,可选的 injectionModel 与 injectionEffort 会添加开发者指令,
告诉 spawn_agent 应使用哪个模型和 reasoning effort;v2 请求保留 Codex 原生的多智能体指引。
-
解析 ——
responses/parser.ts使用 Zod schema(responses/schema.ts)校验请求, 并将其降级为内部的OcxParsedRequest:系统提示词、一份规范化的消息列表 (文本、图像、工具调用、工具结果)、工具定义、生成选项,以及诸如_webSearch(请求了托管的网络搜索) 和_structuredOutput(设置了 JSON schema / JSON 对象的text.format)等特性标志。图像会被保留为真正的内容部分 —— 绝不会被内联为 base64 文本。 -
路由 ——
router.ts按固定的优先级将请求的模型 id 映射到一个已配置的 provider: 显式的provider/model→ provider 的defaultModel→ 内置前缀模式 (claude-、gpt-、o1-/o3-/o4-、llama-/mixtral-/gemma-) → provider 的models[]→defaultProvider回退。参见 模型路由。 -
认证 —— 对于
oauth类型的 provider,opencodex 会换入一个全新、自动刷新的 access token 作为 bearer key,从而让现有的 adapter 无需改动即可完成认证。 -
Vision sidecar(可选) —— 如果已路由的模型被列在
provider.noVisionModels中,且 请求携带了图像,opencodex 会通过你的 ChatGPT 登录凭据,使用已配置的 vision sidecar 描述 每张图像并将其替换为文本,让纯文本模型仍可对图像进行推理。 参见 Sidecar。 -
直通快速路径 —— 对于 Responses 直通 adapter(
openai-responses或azure-openai), opencodex 会保留 Responses body,只执行必要的路由与兼容性改写,然后直接转发 provider 响应, 不再转换为AdapterEvent。 -
网络搜索 sidecar(可选) —— 如果 Codex 启用了托管的
web_search,但已路由的模型 并非 OpenAI,opencodex 会暴露一个合成的web_search函数工具,并在一个小型 agentic 循环中运行该模型,默认通过你的 ChatGPT 登录凭据调用gpt-5.6-luna执行真实搜索, 再将结果作为工具结果注入回去。 -
压缩(按需) —— Codex v1 会调用
POST /v1/responses/compact,v2 则在 Responses turn 中 加入compaction_trigger。原生直通路由会把压缩请求发送到上游;已路由模型则在禁用工具的 情况下执行摘要,并返回 Codex 所需的替代历史记录格式。 -
适配 —— 否则,所选 adapter 的
buildRequest()会以 provider 的原生格式生成上游 HTTP 请求 (URL、headers、body),由 opencodex 对其执行fetch。 -
桥接 —— adapter 的
parseStream()(或parseResponse())会产出内部的AdapterEvent(text、reasoning、tool-call start/delta/end、done、error)。bridge.ts会将该流转换回 Responses SSE 事件 ——response.output_text.delta、response.reasoning_summary_text.delta、response.function_call_arguments.delta、response.completed等等。启用 WebSocket 时,同样的 event payload 会作为 text frame 发送。
为什么是代理而不是 fork 一份 Codex?
Section titled “为什么是代理而不是 fork 一份 Codex?”Codex 把 Responses API 硬编码在内部。通过在协议边界处进行翻译,opencodex 可以与
Codex 的 CLI、App 和 SDK 无改动地协作,能在 Codex 更新后继续工作,并让你能够按请求切换 provider
而无需改动 Codex 本身。这种翻译是双向且忠于 streaming 的:
推理摘要、MCP 工具命名空间、freeform(apply_patch)工具,以及 tool_search 发现
都能正确地往返。关于逐事件的映射,参见 架构参考。

