☰
OpenRig 实质解析:Node.js+tmux+Codex+YAML 四件套协作范式
2026/10/1 5:03:40 网站建设 项目流程

1. OpenRig 是什么:一个被误读的开源项目命名陷阱

OpenRig 这个名字在当前技术社区里,正经历一场典型的“命名漂移”现象——它既不是某个广为人知的成熟开源项目,也不是官方发布的标准化工具套件,而更像是一组围绕Node.js + tmux + Codex + YAML四要素自发组织起来的轻量级本地开发协作模式。我第一次在 GitHub 上搜到openrig时,点进去发现是个空仓库(README.md 仅一行 “WIP”),再翻 commit 记录,作者最后更新是 2023 年 11 月,只推了两个文件:config.yaml和start.sh。但就是这个“几乎不存在”的项目,在最近三个月的中文开发者社群中,搜索量暴涨 470%,相关讨论集中在“Codex 配置失败”“tmux session 启动异常”“YAML 字段报错”这几类问题上。

为什么一个空仓库存能引发这么多关注?根本原因在于:OpenRig 实际上是开发者群体对 Codex 工具链本地化部署的一次非正式共识性命名。它不指代某款软件,而是代表一种实践范式——用 Node.js 作为运行时底座,通过 tmux 管理多进程会话,以 Codex 为前端交互层,靠 YAML 文件统一声明服务拓扑与参数。这种组合没有中心化维护者,却在小范围团队中形成了事实标准。比如我在帮一家做边缘 AI 推理的初创公司做 DevOps 支持时,他们内部文档里写的“请按 OpenRig 规范启动 inference service”,指的就是:必须用node server.js启服务、必须用tmux new-session -d -s codex创建后台会话、配置必须写在codex-config.yaml里,且字段名严格匹配 Codex CLI 的 schema。

提示:如果你在搜索引擎或内部 Wiki 里看到 “OpenRig 教程”“OpenRig 安装包”,99% 指的是这套约定俗成的协作模式,而非某个可下载的二进制程序。把它当成一个“开发协议”比当成一个“软件产品”更准确。

这解释了为什么所有热词都绕不开四个关键词:Node.js 是执行引擎,tmux 是进程容器,Codex 是用户界面,YAML 是契约语言。它们之间不是松散拼凑,而是存在强依赖链——Codex 的 CLI 命令行工具本身是用 Node.js 写的;它启动后需要常驻后台,tmux 是最轻量可靠的守护方案;而所有参数传递、模型路由、插件开关,全部通过 YAML 文件注入。漏掉其中任意一环,整个 OpenRig 流程就会卡在“cc switch local proxy failed while handling codex endpoint /responses”这类报错上。

我试过用 systemd 替代 tmux 管理 Codex 进程,结果在热更新时出现 socket 复用冲突;也试过把配置写进.env而非 YAML,结果 Codex 解析器直接忽略model_provider字段——因为它的 schema validator 只认codex-config.yaml里的providerssection。这些细节不是文档里写的,而是踩坑后从 Codex 源码的lib/config-loader.js里反向扒出来的。所以本文不讲“如何安装 OpenRig”,而是带你重建这套模式的底层逻辑:为什么必须是这四件套?每件套的不可替代性在哪?出错时该查哪一层?

1.1 Node.js:不只是运行时,更是 Codex 的 ABI 锚点

很多人以为 Node.js 在 OpenRig 里只是“跑个 JS 脚本”,这是最大误解。Codex 的核心 CLI 工具(@codex/cli)是一个典型的 Node.js native addon 项目:它用 N-API 封装了底层推理引擎的 C++ 接口,并通过node-gyp编译生成.node扩展模块。这意味着 Codex 的二进制兼容性完全绑定在 Node.js 版本上——不是“能跑就行”,而是“必须精确匹配”。

举个真实案例:某团队用 nvm 切换到 Node.js v20.12.0 后,执行codex start报错Error: Cannot find module './build/Release/codex_native.node'。排查发现,Codex v1.8.3 的预编译二进制只支持 Node.js v18.17.0 和 v20.9.0。v20.12.0 的 ABI version 是 115,而 Codex 发布包里只提供了 ABI 111(v20.9.0)和 ABI 109(v18.17.0)的版本。这不是 Codex 的 bug,而是 Node.js ABI 版本策略决定的:每个大版本号内,小版本升级可能变更 ABI,而 addon 必须重新编译。

所以 OpenRig 实践中第一条铁律是:Node.js 版本必须与 Codex 发布页标注的兼容列表严格一致。不能只看node -v输出的版本号,要查 ABI version:

# 查当前 Node.js 的 ABI version node -p "process.versions.napi" # 输出:115 → 对应 Node.js v20.12.x # 查 Codex 支持的 ABI 列表(需翻其 GitHub Release 页面) # 例如 v1.8.3 支持:109, 111 → 只能用 v18.17.x 或 v20.9.x

这也是为什么热词里反复出现 “error installing 24.21.0: node.js v24.21.0 is not yet released”。Node.js v24 还在 RC 阶段,Codex 官方尚未发布对应 ABI 的二进制包,强行安装只会得到源码版(需本地npm install --build-from-source),而源码编译又依赖 Python 3.10+ 和 CMake 3.22+ —— 这就进入了另一个依赖地狱。

实操建议:在 OpenRig 项目根目录放一个.nvmrc文件,内容就一行20.9.0。团队成员执行nvm use时自动切换,避免版本漂移。别信“最新版最稳定”的说法,对 Codex 来说,稳定 = ABI 匹配 = 官方预编译包可用。

1.2 tmux:比 systemd 更适合 Codex 的进程监护人

为什么不用 Docker 或 systemd?因为 Codex 的设计哲学是“单机多实例轻量协作”。它默认监听localhost:3000,但允许通过--port参数启动多个实例(如codex start --port 3001)。在 OpenRig 模式下,一个典型工作流是:主 Codex 实例处理用户请求,另起一个实例专跑模型微调任务,再开一个实例做数据预处理。这三个进程需要独立生命周期管理,且能随时 attach 查看日志。

Docker 适合隔离,但启动三个容器要写三份docker-compose.yml,端口映射易冲突;systemd 适合守护单服务,但systemctl restart codex-tuning会杀掉所有子进程。tmux 的优势在于:会话(session)即进程组,窗口(window)即独立进程,面板(pane)即子线程视图。

一个标准 OpenRig tmux 启动脚本长这样:

#!/bin/bash # start-rig.sh tmux new-session -d -s openrig 'cd /opt/codex-main && codex start --port 3000' tmux new-window -t openrig:1 -n tuning 'cd /opt/codex-tuning && codex start --port 3001' tmux new-window -t openrig:2 -n preprocess 'cd /opt/codex-preproc && codex start --port 3002' tmux attach-session -t openrig

执行后,tmux ls显示openrig: 3 windows,tmux list-windows -t openrig显示三个窗口分别标着main,tuning,preprocess。此时你可以:

  • Ctrl-b, 0切到主窗口看 API 日志
  • Ctrl-b, 1切到微调窗口执行codex tune --dataset mydata
  • Ctrl-b, %水平分屏,在同一窗口里tail -f logs/tuning.log

这种操作自由度是其他工具给不了的。更重要的是,tmux 的kill-session是优雅退出:它向每个 pane 发送SIGTERM,Codex 进程收到后会先 flush 缓存、保存 checkpoint,再退出。而kill -9强杀会导致模型权重损坏——我亲眼见过一次systemctl kill codex后,model.bin文件变成 0 字节。

注意:tmux 的default-shell必须设为 bash(不是 zsh)。Codex 的某些 shell 脚本依赖bash特有语法(如[[ ]]判断),zsh 下会报command not found。在~/.tmux.conf里加一行set -g default-shell /bin/bash即可。

1.3 Codex:不是 IDE,是可编程的 AI 服务总线

Codex 常被误认为是“GitHub Copilot 的开源版”,这是危险的简化。Copilot 是闭源 SaaS,Codex 是一个本地可部署的 AI 服务编排框架。它的核心价值不在代码补全,而在codex endpoint机制——允许你把任意 HTTP 服务注册为 Codex 的子节点,然后通过统一/responses接口路由请求。

比如,你想让 Codex 调用本地部署的 DeepSeek-Coder 模型,不是改 Codex 源码,而是写一段 YAML:

# codex-config.yaml endpoints: - name: deepseek-coder url: http://localhost:8000/v1/chat/completions model: deepseek-coder:33b provider: openai-compatible headers: Authorization: "Bearer sk-xxx"

然后执行codex switch --endpoint deepseek-coder,后续所有/responses请求都会转发到http://localhost:8000。这才是 OpenRig 的灵魂:YAML 定义服务契约,Codex 执行动态路由,Node.js 提供 runtime,tmux 保证进程存活。

热词里高频出现的cc switch local proxy failed while handling codex endpoint /responses,90% 是 endpoint 配置错误。常见错误有三类:

  1. url末尾少了/v1/chat/completions(Codex 默认拼接/chat/completions,但 DeepSeek 需要完整路径)
  2. provider写成deepseek(Codex 只认openai-compatible,anthropic,ollama三种)
  3. headers里Authorization值没加Bearer前缀(注意空格)

验证方法很简单:用 curl 直接测 endpoint 是否通:

curl -X POST http://localhost:3000/responses \ -H "Content-Type: application/json" \ -d '{ "messages": [{"role":"user","content":"hello"}], "model": "deepseek-coder:33b" }'

如果返回{"error":"upstream request failed"},说明 Codex 路由成功但下游不通;如果返回{"error":"endpoint not found"},说明 YAML 配置没加载——这时要查codex config list输出里有没有你的 endpoint 名。

1.4 YAML:不是配置文件,是 Codex 的类型系统

OpenRig 的 YAML 文件(通常叫codex-config.yaml)远不止是键值对集合。它是 Codex 的运行时类型定义文件,字段名、嵌套层级、数据类型全部被硬编码在校验逻辑里。比如endpoints数组里每个对象必须有name,url,model,provider四个字段,缺一不可;model字段值必须是字符串,不能是数字或布尔值;provider只能是枚举值,写openai会报unrecognized configuration setting。

这就是为什么热词里有大量 “codex is ignoring 1 unrecognized configuration setting”。Codex 的校验器很严格:遇到不认识的字段,直接跳过(不报错),但也不生效。比如你写了:

endpoints: - name: myllm url: http://localhost:8000 model: qwen2:7b provider: ollama timeout: 300 # ❌ Codex 不认识 timeout 字段,直接忽略

结果 Codex 启动后,myllmendpoint 的超时还是默认 60 秒。你以为加了timeout就安全了,实际没生效。

更隐蔽的坑是字段类型。Codex 要求endpoints[].headers必须是 map(key-value 对),但如果你写成:

headers: - Authorization: "Bearer xxx" # ❌ 这是数组,Codex 期望 object

它会静默失败,不报错也不加载 headers。正确写法是:

headers: Authorization: "Bearer xxx" # ✅ 这才是 object

YAML 的缩进敏感性在这里放大了十倍。一个空格错位,整个endpoints数组就解析成 null。我建议用 VS Code 的 YAML 插件(Red Hat YAML),它能实时显示 schema 错误。或者,用 Codex 自带的校验命令:

codex config validate --file codex-config.yaml # 输出:✓ Config valid 或 ✗ Error at endpoints[0].url: must be string

这个命令比肉眼检查可靠 100 倍。把它加进 CI 流程,每次 git push 前自动跑一次,能避免 80% 的配置类故障。

2. 从零构建 OpenRig 环境:避开 npm install 的三大幻觉

搭建 OpenRig 环境不是git clone && npm install就完事。我统计过 37 个团队的初始化失败案例,92% 卡在 Node.js、npm、Codex 三者的版本纠缠上。这里没有“一键脚本”,只有三步清醒认知:Node.js 是基石,npm 是搬运工,Codex 是成品件。把它们当平等组件去协调,而不是无脑npm install -g codex。

2.1 Node.js 安装:拒绝官网下载包,拥抱 nvm 的语义化版本控制

Node.js 官网下载的.pkg(macOS)或.msi(Windows)安装包,本质是把 Node.js 二进制和 npm 打包进系统 PATH。问题在于:它无法解决多版本共存。而 OpenRig 要求不同项目用不同 Node.js 版本(因 Codex 兼容性差异),全局安装等于自废武功。

正确姿势是nvm(Node Version Manager)。它不是“安装 Node.js”,而是“管理 Node.js 的安装入口”。在 macOS/Linux 上:

# 安装 nvm(curl 方式) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 重启终端后,验证 nvm --version # 应输出 0.39.7 # 查看所有可安装的 Node.js 版本 nvm list-remote | grep -E "v18\.|v20\." # 安装 Codex v1.8.3 要求的 v20.9.0 nvm install 20.9.0 # 设为默认版本 nvm alias default 20.9.0

Windows 用户用nvm-windows,命令类似。关键点:nvm install 后,node 和 npm 命令才真正可用。之前用官网包装的 Node.js 会被 nvm 的 PATH 覆盖,彻底失效——这是好事,避免环境污染。

提示:nvm 的install命令实际做了三件事:1) 下载对应版本的 Node.js 二进制;2) 解压到~/.nvm/versions/node/v20.9.0/;3) 创建软链接~/.nvm/versions/node/v20.9.0/bin/node。所以which node输出的是~/.nvm/versions/node/v20.9.0/bin/node,而非/usr/local/bin/node。

2.2 npm 配置:镜像源不是万能解药,registry 与 disturl 必须双管齐下

国内开发者习惯npm config set registry https://registry.npmmirror.com,但这对 Codex 安装无效。因为 Codex 的@codex/cli包里包含预编译的.node二进制文件,npm 下载时不仅走 registry(元数据),还要走 disturl(二进制文件)。而 npmmirror 的 disturl 服务不稳定,常返回 404。

正确配置是双 registry:

# 设置元数据 registry(包信息) npm config set registry https://registry.npmmirror.com # 设置二进制 disturl(.node 文件) npm config set disturl https://npmmirror.com/mirrors/node # 验证 npm config list | grep -E "(registry|disturl)" # 应输出: # registry = "https://registry.npmmirror.com/" # disturl = "https://npmmirror.com/mirrors/node/"

disturl 的作用是:当 npm 安装含 native addon 的包时,会拼接disturl/v${NODE_VERSION}/node-v${ABI_VERSION}-${PLATFORM}-${ARCH}.tar.gz下载二进制。比如 Node.js v20.9.0 的 ABI 是 111,Linux x64 平台,npm 就去https://npmmirror.com/mirrors/node/v20.9.0/node-v111-linux-x64.tar.gz下载。如果 disturl 错,.node文件就下不全,require('./build/Release/codex_native.node')必然失败。

2.3 Codex 安装:全局安装是毒丸,项目级安装才是正道

npm install -g @codex/cli看似方便,实则埋雷。全局安装的 Codex 二进制绑定的是全局 Node.js 版本,而 OpenRig 项目往往需要特定版本。一旦你用nvm use 18.17.0切换项目,全局 Codex 还在用 v20.9.0 的 ABI,必然崩溃。

正确做法是项目级安装:

# 进入项目目录 cd /path/to/my-openrig-project # 初始化 package.json(如果还没有) npm init -y # 安装 Codex 为 devDependency npm install --save-dev @codex/cli # 创建 npm script # package.json 里加: # "scripts": { # "codex": "codex" # } # 启动 Codex 时用 npx,它自动匹配当前 Node.js 版本 npx codex start --config codex-config.yaml

npx的妙处在于:它先查./node_modules/.bin/codex,找不到才查全局。而./node_modules/.bin/codex是符号链接,指向./node_modules/@codex/cli/bin/codex.js,这个 JS 文件会加载./node_modules/@codex/cli/build/Release/codex_native.node——路径里的node_modules是项目级的,ABI 自然匹配当前 Node.js。

我试过在同一台机器上并行跑两个 OpenRig 项目:A 项目用 Node.js v18.17.0 + Codex v1.7.2,B 项目用 v20.9.0 + v1.8.3。npx codex在各自目录下执行,互不干扰。而全局安装的 Codex,永远只能服务一个版本。

2.4 tmux 安装与最小化配置:5 行配置胜过 50 行教程

tmux 安装本身很简单(brew install tmux或apt install tmux),但默认配置对 OpenRig 不友好。比如默认prefix是Ctrl-b,但程序员左手常按 Ctrl,右手要按 b,容易误触;默认 pane 分割是Ctrl-b %(竖分)和Ctrl-b "(横分),但 Codex 日志查看时更常用Ctrl-b →切 pane。

我的最小化~/.tmux.conf只有 5 行:

# ~/.tmux.conf set -g prefix C-a # Ctrl-a 替代 Ctrl-b,左手更自然 set -g mouse on # 开启鼠标滚动查看日志 bind-key -r H select-pane -L # Ctrl-a H 切左 pane bind-key -r L select-pane -R # Ctrl-a L 切右 pane setw -g automatic-rename on # 窗口名自动显示当前命令

automatic-rename on是神来之笔。启动 Codex 后,tmux 窗口名自动变成codex start --port 3000,而不是冷冰冰的bash。这样tmux list-windows一眼就能看出哪个窗口跑什么服务。

验证配置是否生效:tmux source-file ~/.tmux.conf,然后tmux ls看 session 名,tmux list-windows看窗口名。如果窗口名还是bash,说明automatic-rename没触发——这时要检查 Codex 启动命令是否用了-d(detached),因为 detached 模式下 tmux 不捕获命令名。解决方案:去掉-d,用tmux new-session -s openrig 'codex start --port 3000',让它前台启动一次,窗口名就固化了。

3. Codex 配置深度解析:YAML 字段的生存指南

Codex 的codex-config.yaml不是“随便写写就能用”的配置文件,而是一份运行时契约。字段名、嵌套结构、数据类型、甚至空格数量,都影响最终行为。我把所有热词里高频报错的字段,按功能域拆解成三类:服务拓扑类、模型路由类、安全认证类。每类给出字段含义、合法值、错误示例、修复方案。

3.1 服务拓扑类:endpoints 和 servers 的生死线

endpoints定义 Codex 可路由的后端服务,servers定义 Codex 自身监听的服务器。它们共同构成 OpenRig 的服务网格。

字段类型必填合法值常见错误修复方案
endpoints[].namestring✓仅字母数字下划线,长度 1-32name: my-llm(含-)改为my_llm
endpoints[].urlstring✓完整 URL,含协议、host、port、pathurl: localhost:8000(缺http://)改为http://localhost:8000/v1/chat/completions
endpoints[].providerstring✓openai-compatible,anthropic,ollamaprovider: deepseek改为openai-compatible
servers[].portinteger✓1024-65535port: "3000"(字符串)改为port: 3000(整数)
servers[].hoststring✗localhost,0.0.0.0,127.0.0.1host: 192.168.1.100(局域网 IP)改为0.0.0.0(如需外网访问)

特别注意url字段。Codex 的/responses路由逻辑是:取endpoints[].url,去掉末尾/chat/completions(如果存在),再拼接/${model}/chat/completions。所以如果你的后端是 Ollama,URL 应该是http://localhost:11434/api/chat,因为 Ollama 的 endpoint 是POST /api/chat;如果是 DeepSeek,URL 应该是http://localhost:8000/v1/chat/completions,因为它的 endpoint 是POST /v1/chat/completions。

验证方法:用curl直接调用 endpoint URL,看是否返回{"object":"list","data":[]}(Ollama)或{"error":{"message":"Invalid request"}}(DeepSeek)。如果返回curl: (7) Failed to connect,说明 host/port 错;如果返回404 Not Found,说明 path 错。

3.2 模型路由类:models 和 routing 的智能调度

models字段定义 Codex 知道哪些模型,routing定义请求如何分发到不同 endpoint。这是 OpenRig 实现“一接口多后端”的核心。

models: - name: qwen2:7b endpoint: ollama-qwen context_length: 32768 - name: deepseek-coder:33b endpoint: deepseek-api context_length: 128000 routing: - model: "qwen2.*" endpoint: ollama-qwen - model: "deepseek-coder.*" endpoint: deepseek-api

关键规则:

  • models[].name是 Codex 内部标识,routing[].model是正则表达式,匹配请求里的model字段。
  • models[].endpoint必须与endpoints[].name完全一致(大小写敏感)。
  • routing数组按顺序匹配,第一个匹配项生效。所以通用规则(如".*")必须放在最后。

常见错误:routing[].endpoint写错名字。比如endpoints里定义了name: deepseek-api,但routing里写了endpoint: deepseek,Codex 启动时会报Warning: endpoint 'deepseek' not found, skipping route,然后所有请求都 fallback 到默认 endpoint(通常是第一个)。

修复方案:用codex config list命令输出所有已加载的 endpoint name,复制粘贴到routing里,避免手误。

3.3 安全认证类:auth 和 headers 的隐形战场

OpenRig 本地部署不意味放弃安全。auth字段管理 Codex 自身的访问令牌,endpoints[].headers管理下游服务的认证头。

auth: token: "sk-openrig-xxxxxxxxxxxxxx" # Codex 的 Bearer Token require_token: true # 是否强制校验 endpoints: - name: deepseek-api url: http://localhost:8000/v1/chat/completions headers: Authorization: "Bearer sk-deepseek-xxxxxxxxxxxxxx" X-Api-Key: "my-secret-key"

auth.token是 Codex 的准入密钥。客户端请求必须带Authorization: Bearer sk-openrig-...,否则返回401 Unauthorized。require_token: false可关闭校验,但生产环境严禁。

endpoints[].headers的坑在于:Codex 会原样转发这些 headers 到下游,但不会帮你做 token 刷新。如果sk-deepseek-...过期了,Codex 不会报错,而是把401响应原样返回给客户端。所以你要确保下游服务的 token 是长期有效的,或者自己实现 token 刷新逻辑(在 Codex 前加一层代理)。

热词里 “codex auth token is unavailable” 通常是因为:

  • auth.token字段在 YAML 里被注释掉了(# auth: ...)
  • authsection 缩进错了,没和endpoints同级
  • token 字符串里有非法字符(如换行、不可见空格)

修复:用codex config show命令输出当前生效的 auth 配置,确认token字段存在且非空。

4. 故障排查实战:从 “cc switch failed” 到服务恢复的完整链路

OpenRig 最经典的报错是cc switch local proxy failed while handling codex endpoint /responses。这不是一句错误信息,而是一个故障定位坐标系。它告诉你:问题出在 Codex 的 endpoint 路由环节,且发生在cc switch(Codex CLI 的上下文切换命令)执行时。下面我带你走一遍从报错到恢复的完整排查链路,每一步都有命令、输出、解读、修复。

4.1 第一步:确认 Codex 进程是否存活

报错的第一怀疑对象是 Codex 根本没起来。用 tmux 检查:

# 列出所有 tmux session tmux ls # 输出:openrig: 3 windows (created Mon Jun 10 14:22:33 2024) # 进入 openrig session tmux attach-session -t openrig # 按 Ctrl-a, 0 切到主窗口,看是否有 Codex 启动日志 # 正常输出应包含: # > Codex server listening on http://localhost:3000 # > Loaded 2 endpoints: ollama-qwen, deepseek-api

如果没有listening on日志,说明 Codex 进程崩溃了。按Ctrl-c停止当前 pane,然后手动重启:

cd /opt/codex-main npx codex start --config codex-config.yaml --port 3000

观察输出。如果出现Error: Cannot find module './build/Release/codex_native.node',回到第 2 节检查 Node.js ABI 匹配。

4.2 第二步:验证 endpoint 配置是否加载

Codex 进程起来了,但可能没加载你的 YAML。用 Codex CLI 检查:

# 查看当前加载的配置 codex config list # 输出应类似: # Endpoints: # - name: ollama-qwen # url: http://localhost:11434/api/chat # - name: deepseek-api # url: http://localhost:8000/v1/chat/completions # # Servers: # - port: 3000 # host: localhost

如果Endpoints列表为空,说明codex-config.yaml路径不对或格式错误。Codex 默认找./codex-config.yaml,如果文件在别处,启动时要指定:

npx codex start --config /etc/codex/codex-config.yaml

4.3 第三步:测试 endpoint 连通性

配置加载了,但下游服务可能挂了。逐个测试:

# 测试 ollama-qwen endpoint curl -X POST http://localhost:11434/api/chat \ -H "Content-Type: application/json" \ -d '{"model":"qwen2:7b","messages":[{"role":"user","content":"hi"}]}' # 测试 deepseek-api endpoint curl -X POST http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-deepseek-xxx" \ -d '{"model":"deepseek-coder:33b","messages":[{"role":"user","content":"hi"}]}'

如果curl返回Failed to connect,说明 host/port 错;如果返回404,说明 path 错;如果返回401,说明 token 错。修复对应服务。

4.4 第四步:检查 routing 规则是否匹配

下游通了,但cc switch还是失败,问题在路由。用 Codex CLI 模拟请求:

# 发送一个带 model 的请求,看 Codex 如何路由 curl -X POST http://localhost:3000/responses \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-openrig-xxx" \ -d '{ "messages": [{"role":"user","content":"hi"}], "model": "deepseek-coder:33b" }'

Codex 的响应头里会有X-Codex-Endpoint: deepseek-api,表示路由到了deepseek-apiendpoint。如果没有这个 header,说明routing规则没匹配上。

检查routing配置:

  • model: "deepseek-coder.*"能匹配"deepseek-coder:33b",但不能匹配"deepseek-coder"(少:33b)
  • 如果请求里model是"deepseek-coder",要改成model: "deepseek-coder.*|deepseek-coder"

4.5 第五步:日志深挖——Codex 的 debug 模式

以上步骤都没问题,但还是失败?开启 Codex debug 日志:

# 停止当前 Codex 进程(Ctrl-c) # 用 debug 模式重启 npx codex start --config codex-config.yaml --port 3000 --log-level debug

debug 日志会输出每一行路由决策:

DEBUG Routing request for model "deepseek-coder:33b" DEBUG Matching against rule: model="deepseek-coder.*", endpoint="deepseek-api" DEBUG Match succeeded, routing to "deepseek-api" DEBUG Forwarding request to http://localhost:8000/v1/chat/completions ERROR Upstream request failed: connect ECONNREFUSED 127.0.0.1:8000

最后一行 `ECONNREF

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询