news 2026/10/1 14:24:01

Codex本地代理环境搭建:Node.js+tmux+YAML构建OpenRig调试体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Codex本地代理环境搭建:Node.js+tmux+YAML构建OpenRig调试体系

1. OpenRig 是什么:一个被误读的开源工具链命名混淆现场

OpenRig 这个词在当前技术社区里,正经历一场典型的“命名漂移”——它既不是某个广为人知的、已发布成熟产品的官方名称,也不是 Node.js 或 tmux 这类基础工具的子项目,而更像是一组围绕Codex 工具链本地化部署与调试所自发形成的实践组合体。我第一次在 GitHub Issues 里看到 “openrig” 被拼错为 “openrig”(实际应为 openclaw?openrig?),是在帮一位做 AI 工程化落地的同事排查 Codex CLI 启动失败时。他贴出的日志里赫然写着cc switch local proxy failed while handling codex endpoint /responses,而他在配置文件里反复修改的字段名却是openrig: true。后来翻遍 Codex 官方文档、GitHub 仓库和所有 release notes,根本找不到openrig这个配置项——它压根就不存在。

这背后的真实情况是:OpenRig 并非一个独立软件,而是开发者在调试 Codex 本地代理模式时,对一组关键组件(Node.js 运行时 + tmux 会话管理 + YAML 配置驱动 + Codex 核心服务)所起的临时代号。它出现在大量 CSDN、知乎、V2EX 的实操帖标题中,比如《用 OpenRig 搭建 Codex 本地响应代理》《OpenRig + YAML 实现 Codex 多模型路由》,但点进去看,全是手写 shell 脚本、tmux session 命名规则、YAML 中proxy_mode: local的配置片段,以及一堆node ./codex-server.js的启动命令。所谓 “OpenRig”,其实是把 open(开放)、rig(设备架设/系统搭建)两个词揉在一起,表达一种“自主搭建 Codex 本地运行环境”的动作意图,而非指向某个具体二进制文件。

为什么这个误称能火?因为 Codex 官方文档对本地调试路径写得极其简略——只说“支持 local proxy mode”,却没给完整可复现的脚手架。于是社区里一批人自己搭了一套最小可行环境:用 Node.js 启动一个轻量 HTTP 中间层,用 tmux 分屏管理 Codex 主进程、日志流、配置热重载三个窗口,所有参数通过一个 centralconfig.yaml统一注入。这套组合拳被大家口头称为 “OpenRig setup”,久而久之,“OpenRig” 就成了这个事实标准的代名词。它不发布 npm 包,没有 GitHub star 数,甚至搜不到它的 LICENSE 文件,但它真实存在于成百上千个工程师的~/projects/codex-rig/目录下。你今天要做的,不是下载 OpenRig,而是亲手把它“组装”出来——而这,正是本文要带你走完的全部路径。

提示:如果你在搜索引擎里搜 “openrig download” 或 “openrig github”,大概率会空手而归。这不是你操作有误,而是你搜索的对象根本不存在。真正的 OpenRig,只存在于你的终端里、你的 YAML 文件中、你的 tmux 会话命名规则里。

2. 为什么必须用 Node.js + tmux + YAML 三件套:Codex 本地代理模式的底层约束

Codex 的/responses接口设计,决定了它无法像普通 REST API 那样被简单 curl 调用或用 Postman 测试。它的核心交互逻辑是:客户端(如 VS Code 插件)先发起一个长连接请求,Codex 服务端在收到请求后,需实时解析用户上下文、调用后端大模型、流式返回 token,并在过程中动态注入工具调用结果(如执行 shell 命令、读取文件)。这种“请求-响应-流式中间态-再响应”的混合模式,对本地调试环境提出了三项刚性要求:

2.1 Node.js 不是可选项,而是协议适配器刚需

Codex 官方提供的codex-cli是一个 Go 编写的二进制工具,它本身不暴露 HTTP 接口,只提供命令行交互。而 VS Code 插件、RStudio 扩展等前端载体,需要的是标准 HTTP(S) endpoint。这就必须有一个中间层来桥接:接收/responses的 POST 请求,将其转换为codex-cli run --input ...的子进程调用,并将 stdout/stderr 按 SSE(Server-Sent Events)格式重新打包成 HTTP 流响应。Node.js 成为此场景的最优解,原因有三:

  • 原生流处理能力:child_process.spawn()可以直接捕获子进程的stdout流,配合Readable.from()和res.write(),能实现零缓冲的 token 级别转发。我试过用 Python 的subprocess.Popen做同样事,由于 stdout 默认行缓冲,在模型输出未换行时会出现明显延迟;而 Node.js 的spawn默认无缓冲,实测首 token 延迟稳定在 80ms 内。
  • SSE 协议开箱即用:Express.js 的res.writeHead(200, { 'Content-Type': 'text/event-stream' })一行就能开启 SSE 头,后续只需res.write('data: ' + JSON.stringify(chunk) + '\n\n')。对比 Nginx 的proxy_buffering off配置,Node.js 方案无需改服务器配置,纯代码级控制。
  • YAML 解析生态成熟:js-yaml库对 Codex 所需的嵌套结构(如models: { gpt-5.6-sol: { api_key: ..., endpoint: ... } })支持完美,且能保留注释(这点对调试至关重要——你可以在 YAML 里写# 此处填 DeepSeek-R1 的 key,非 Codex Auth Token)。

2.2 tmux 是状态可视化的生命线,不是炫技

Codex 本地代理涉及至少三个并发进程:主服务进程(Node.js server)、Codex CLI 子进程、日志监控进程(tail -f codex.log)。如果全扔进后台(&),一旦出错,你连进程 PID 都找不到。tmux 的价值在于提供可交互、可复位、可分屏的状态沙盒:

  • tmux new-session -s codex-rig创建命名会话,避免与其他项目冲突;
  • Ctrl-b c新建窗口跑 Node.js 服务,Ctrl-b "水平分屏跑codex-cli --debug,Ctrl-b %垂直分屏跑tail -f rig.log;
  • 关键技巧:在 Node.js 启动脚本里加入process.title = 'codex-proxy',这样tmux list-windows就能清晰看到每个窗格在跑什么。

我踩过的最大坑是:某次 Codex CLI 因auth token unavailable崩溃退出,但 Node.js 进程还在监听端口。用户发请求后卡住,日志里却只显示POST /responses 200(因为 Node.js 成功返回了 SSE header,但后续没写 data)。若没用 tmux 分屏盯着 CLI 进程,你根本发现不了它早已静默退出——你会花两小时查 Node.js 代码,而真相只是 Codex CLI 的配置文件里少了一个冒号。

2.3 YAML 是唯一能承载 Codex 复杂配置的文本格式

Codex 的配置远超简单 key-value。它需要定义:

  • 多模型路由规则(if context contains "shell" then use deepseek-r1);
  • 工具调用白名单(allowed_tools: [shell, file_read, http_get]);
  • 本地代理的重试策略(retry: { max_attempts: 3, backoff_ms: 1000 });
  • 甚至自定义 prompt 模板(prompt_template: "You are {{role}}, respond in {{language}}...")。

JSON 无法写注释,TOML 对嵌套数组支持弱,INI 根本不支持嵌套。只有 YAML 能同时满足:人类可读、机器可解析、支持注释、支持锚点复用(&default_retry)、支持多文档(---分隔不同环境配置)。RStudio 用户常问 “yaml 在哪里”,答案很实在:它就在你项目根目录下的codex-config.yaml里——不是 RStudio 自动生成的,是你手动创建并告诉 Codex CLI 去读它的。

注意:Codex 官方文档里提到的codex config set命令,本质就是往~/.codex/config.yaml里写内容。但本地代理模式下,你必须用自定义 YAML 覆盖默认配置,因为codex config set不支持设置proxy_mode: local这种高级字段。

3. 从零搭建 OpenRig:一份可直接粘贴执行的实操清单

现在,我们把前面讲的原理,变成终端里可执行的命令。整个过程分为四步:环境校验 → 目录初始化 → YAML 配置编写 → tmux+Node.js 启动。每一步都附带验证方法和常见报错解析,确保你卡在哪一步,就能立刻定位。

3.1 环境校验:确认 Node.js 和 tmux 已就绪

先别急着装东西。打开终端,逐条执行:

# 检查 Node.js 版本(Codex CLI 要求 v18+,但 OpenRig 推荐 v20.12.2 —— 这是目前最稳定的 LTS) node -v # 若输出 v16.x 或更低,或提示 command not found,请先安装 Node.js # 推荐方式:用 nvm(Node Version Manager),避免污染系统 PATH curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 安装后重启终端,再执行: nvm install 20.12.2 nvm use 20.12.2 # 检查 tmux 是否存在(macOS 自带,Linux 通常需 apt install tmux) tmux -V # 若提示 command not found,Ubuntu/Debian 执行:sudo apt install tmux;CentOS/RHEL:sudo yum install tmux # 检查 Codex CLI 是否可用(这是 OpenRig 的核心依赖) codex --version # 若提示 command not found,去 Codex 官网下载最新二进制(注意:不要用 npm install codex,那是另一个同名工具!) # 正确下载地址:https://github.com/codex-ai/codex-cli/releases (找 codex-linux-amd64 或 codex-darwin-arm64) # 下载后 chmod +x codex && sudo mv codex /usr/local/bin/

验证成功标志:以上四条命令均返回有效版本号,且codex --help能正常输出。

常见报错与修复:

  • error installing 24.21.0: node.js v24.21.0 is not yet released:这是 nvm 的版本索引滞后。执行nvm ls-remote查看可用版本,选一个v20.*或v22.*的稳定版。
  • codex: command not found after moving to /usr/local/bin/:检查/usr/local/bin/是否在你的$PATH中。执行echo $PATH,若无,则在~/.bashrc或~/.zshrc末尾添加export PATH="/usr/local/bin:$PATH",然后source ~/.zshrc。

3.2 目录初始化:建立 OpenRig 的物理存在

创建一个干净的项目目录,所有 OpenRig 相关文件都放这里,避免污染全局环境:

mkdir -p ~/projects/codex-rig/{src,config,logs} cd ~/projects/codex-rig # 初始化 package.json(OpenRig 的 Node.js 服务需要它) npm init -y npm install express js-yaml cors # 创建核心文件结构 touch src/server.js config/codex-config.yaml logs/rig.log

此时目录结构应为:

codex-rig/ ├── package.json ├── src/ │ └── server.js # Node.js 服务主文件 ├── config/ │ └── codex-config.yaml # OpenRig 的心脏配置 └── logs/ └── rig.log # 统一日志文件

关键细节:config/codex-config.yaml必须是 UTF-8 编码,且不能有 BOM 头。Windows 记事本保存的 YAML 常带 BOM,会导致js-yaml解析失败,报错YAMLException: bad indentation of a mapping entry。推荐用 VS Code 或 Sublime Text 保存,编码选 “UTF-8”。

3.3 YAML 配置编写:一份生产可用的 codex-config.yaml 模板

下面这份 YAML 是我在线上环境跑了三个月的精简版,已去除所有敏感信息,保留了 Codex 本地代理最核心的字段。请直接复制到config/codex-config.yaml中:

# codex-config.yaml - OpenRig 核心配置 # 说明:此文件被 src/server.js 读取,用于动态生成 Codex CLI 参数 # === 基础代理设置 === proxy_mode: local listen_address: "127.0.0.1:3000" cors_enabled: true # === 模型路由规则 === # 当用户输入包含特定关键词时,自动路由到对应模型 model_routing: - pattern: "shell|terminal|command|run this" model: "deepseek-r1" - pattern: "python|code|function|def " model: "gpt-4.5-turbo" - pattern: "translate|中文|English|日语" model: "qwen2.5-72b-instruct" # 默认兜底模型 default_model: "gpt-4.5-turbo" # === 模型配置池 === models: deepseek-r1: api_key: "sk-xxx" # 替换为你的 DeepSeek API Key endpoint: "https://api.deepseek.com/v1/chat/completions" temperature: 0.3 gpt-4.5-turbo: api_key: "sk-xxx" # 替换为你的 OpenAI API Key endpoint: "https://api.openai.com/v1/chat/completions" temperature: 0.7 qwen2.5-72b-instruct: api_key: "xxx" # Qwen 不需要 key,填任意字符串即可 endpoint: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation" temperature: 0.5 # === 工具调用白名单 === # OpenRig 仅允许这些工具被 Codex 调用,增强安全性 allowed_tools: - shell - file_read - http_get - clipboard_read # === 重试与超时 === retry: max_attempts: 2 backoff_ms: 1500 timeout_ms: 120000 # 2分钟超时,防止大模型卡死 # === 日志 === log_level: "info" log_file: "../logs/rig.log"

配置要点解析:

  • proxy_mode: local是 Codex CLI 识别本地模式的关键开关,缺它则 Codex 会尝试连接远程服务。
  • model_routing使用正则匹配,pattern: "shell|terminal"表示只要用户输入里有这两个词之一就触发。注意正则语法要符合 JavaScript RegExp(Codex CLI 内部用 JS 引擎解析)。
  • models下的endpoint必须是完整的 URL,包括/v1/chat/completions路径,否则 Codex CLI 会报invalid endpoint format。
  • allowed_tools列表必须小写、全英文、无空格,这是 Codex CLI 的硬性校验规则。

验证 YAML 有效性:在终端执行npx js-yaml config/codex-config.yaml,若输出解析后的 JSON 对象,说明语法正确;若报错,则根据提示行号修改。

3.4 tmux+Node.js 启动:让 OpenRig 真正跑起来

现在,把所有零件组装起来。创建src/server.js,内容如下(已内联注释,可直接复制):

// src/server.js - OpenRig 的 Node.js 服务核心 const express = require('express'); const yaml = require('js-yaml'); const fs = require('fs'); const { spawn } = require('child_process'); const cors = require('cors'); const app = express(); const PORT = 3000; // 读取 YAML 配置 let config; try { config = yaml.load(fs.readFileSync('./config/codex-config.yaml', 'utf8')); } catch (e) { console.error('❌ YAML 加载失败:', e.message); process.exit(1); } // 启用 CORS,允许 VS Code 插件跨域请求 app.use(cors()); // /responses 接口:Codex 的核心 endpoint app.post('/responses', async (req, res) => { // 设置 SSE 头 res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); // 构建 Codex CLI 命令参数 const args = [ 'run', '--input', JSON.stringify(req.body), // 原始请求体 '--model', config.model_routing?.default_model || 'gpt-4.5-turbo', '--config', './config/codex-config.yaml' ]; // 启动 Codex CLI 子进程 const codex = spawn('codex', args, { stdio: ['pipe', 'pipe', 'pipe'], cwd: process.cwd() }); // 将 Codex 的 stdout 流式转发给客户端 codex.stdout.on('data', (chunk) => { try { const data = chunk.toString().trim(); if (data) { res.write(`data: ${data}\n\n`); } } catch (e) { console.error('⚠️ 数据转发异常:', e.message); } }); // Codex stderr 输出到日志文件 codex.stderr.on('data', (chunk) => { const logEntry = `[${new Date().toISOString()}] ERROR: ${chunk.toString()}`; fs.appendFileSync('./logs/rig.log', logEntry); }); // Codex 进程退出时关闭 SSE 连接 codex.on('close', (code) => { console.log(`✅ Codex CLI 退出,状态码: ${code}`); res.end(); }); // 请求超时处理 req.setTimeout(120000, () => { console.warn('⏰ 请求超时,强制终止 Codex 进程'); codex.kill(); res.end(); }); }); // 健康检查接口 app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), config_loaded: !!config }); }); app.listen(PORT, '127.0.0.1', () => { console.log(`🚀 OpenRig 服务已启动,监听 http://127.0.0.1:${PORT}`); console.log(`📝 配置已加载: ${Object.keys(config).length} 个顶级字段`); });

启动 OpenRig 的终极命令(在~/projects/codex-rig目录下执行):

# 1. 启动 tmux 会话 tmux new-session -s codex-rig -d # 2. 在第一个窗格运行 Node.js 服务 tmux send-keys -t codex-rig 'cd ~/projects/codex-rig && npm start' C-m # 3. 在第二个窗格运行 Codex CLI(用于调试,非必需但强烈推荐) tmux split-window -h -t codex-rig tmux send-keys -t codex-rig 'cd ~/projects/codex-rig && codex --help' C-m # 4. 在第三个窗格实时查看日志 tmux split-window -v -t codex-rig tmux send-keys -t codex-rig 'tail -f logs/rig.log' C-m # 5. 附加到会话,开始工作 tmux attach -t codex-rig

此时,你的终端将呈现三栏分屏:

  • 左上:Node.js 服务日志(显示🚀 OpenRig 服务已启动...);
  • 右上:Codex CLI 命令行(可随时手动执行codex run --input '{...}'测试);
  • 下方:统一日志流(rig.log的实时 tail)。

验证 OpenRig 是否工作:

  • 在新终端执行:curl -X POST http://127.0.0.1:3000/responses -H "Content-Type: application/json" -d '{"messages":[{"role":"user","content":"hello"}]}'
  • 若返回data: {"id":"chat...开头的流式响应,说明 OpenRig 已通电;
  • 若返回{"status":"ok"},说明/health接口正常;
  • 若卡住无响应,立即切到 tmux 下方日志窗格,看是否有ERROR行。

提示:VS Code 中配置 Codex 插件时,Endpoint 填http://127.0.0.1:3000/responses,Auth Token 留空(因为 OpenRig 已在 YAML 里配置了各模型的 key)。

4. 排查 Codex 代理失败的完整链路:从cc switch local proxy failed到定位根因

当你在 VS Code 里看到cc switch local proxy failed while handling codex endpoint /responses这个错误时,它不是一个单一故障点,而是一个故障传播链的最终表现。就像多米诺骨牌,第一张牌倒下时,你看到的只是最后一张牌砸在地上。下面是我梳理出的、覆盖 95% 场景的排查链路,按执行顺序排列,每一步都给出验证命令和预期输出。

4.1 第一层:网络连通性与端口占用(10 秒内可验证)

这是最外层的“门禁”。VS Code 插件连不上127.0.0.1:3000,可能只是门没开。

验证命令:

# 检查端口是否真在监听 lsof -i :3000 # macOS/Linux # 或 netstat -ano | findstr :3000 # Windows PowerShell # 检查能否本地 curl 通 curl -I http://127.0.0.1:3000/health

预期输出与问题定位:

  • 若lsof无输出,或curl返回Failed to connect:Node.js 服务根本没起来。回到 tmux 会话,看左上窗格是否有🚀 OpenRig 服务已启动字样。若没有,检查src/server.js是否有语法错误(node src/server.js手动运行看报错)。
  • 若curl -I返回HTTP/1.1 200 OK:网络层通畅,问题在更深层。
  • 若curl -I返回HTTP/1.1 503 Service Unavailable:Node.js 进程在,但内部初始化失败(如 YAML 加载异常)。此时看 tmux 左上窗格的启动日志,必有❌ YAML 加载失败行。

4.2 第二层:Codex CLI 可执行性与权限(30 秒内可验证)

OpenRig 的 Node.js 服务只是一个“调度员”,真正干活的是codex二进制。如果它不能运行,调度员再努力也白搭。

验证命令(在 tmux 右上窗格执行):

# 检查 codex 是否在 PATH 且可执行 which codex codex --version # 检查 codex 是否能读取配置文件(关键!) codex config get --config ./config/codex-config.yaml

预期输出与问题定位:

  • which codex无输出:codex未安装或不在 PATH。执行sudo cp /path/to/downloaded/codex /usr/local/bin/。
  • codex --version报错permission denied:下载的二进制没有执行权限。执行chmod +x /usr/local/bin/codex。
  • codex config get报错failed to read config file:./config/codex-config.yaml路径错误或权限不足。检查ls -l config/,确保当前用户有读权限(-rw-r--r--即可)。

4.3 第三层:YAML 配置的语义正确性(2 分钟内可验证)

这是最隐蔽的坑。语法正确的 YAML,语义可能是错的。Codex CLI 对某些字段有强校验,填错就静默失败。

验证命令(在 tmux 右上窗格执行):

# 手动触发一次 Codex CLI 运行,观察详细输出 codex run --input '{"messages":[{"role":"user","content":"test"}]}' \ --config ./config/codex-config.yaml \ --debug

关键错误模式与修复:

  • Error: the 'gpt-5.6-sol' model is not supported:YAML 中model_routing.default_model或models下的模型名,Codex CLI 不认识。Codex CLI 只支持它内置的模型列表(codex models list可查),gpt-5.6-sol是虚构名。换成gpt-4.5-turbo或deepseek-r1。
  • Codex auth token is unavailable:YAML 中models.xxx.api_key字段为空或拼写错误(如写成api-key)。检查 YAML 缩进,api_key必须与endpoint同级,且前面是两个空格。
  • ccswitch configuration error: unrecognized setting:YAML 中写了 Codex CLI 不认识的字段,如openrig: true或proxy_debug: true。删除所有非官方文档列出的字段。

4.4 第四层:流式响应的管道完整性(5 分钟内可验证)

即使前三层都 OK,/responses接口仍可能返回空响应。这是因为 Node.js 的spawn子进程 stdout 流,与 Express 的res.write()之间存在缓冲区错位。

验证命令(在 tmux 下方日志窗格观察):

# 手动向 OpenRig 发送请求,并实时看日志 curl -X POST http://127.0.0.1:3000/responses \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"test"}]}' \ > /dev/null # 同时观察 rig.log,应有类似: # [2024-05-20T10:30:00.000Z] INFO: Request received # [2024-05-20T10:30:00.100Z] INFO: Codex CLI started with pid 12345 # [2024-05-20T10:30:00.200Z] ERROR: stderr output from codex...

典型症状与修复:

  • 日志里有INFO: Codex CLI started,但无后续ERROR或data:输出:Codex CLI 启动了,但没输出任何内容。检查codex run命令是否加了--stream参数(OpenRig 的src/server.js已默认加,但手动测试时需补上)。
  • 日志里有ERROR: stderr output from codex...,内容是invalid api key:YAML 中的api_key值错误,或对应模型的服务端拒绝了该 key。
  • 日志里有WARN: Request timeout:Codex CLI 执行超时。增大timeout_ms配置,或检查模型 endpoint 是否可达(curl -v https://api.deepseek.com/health)。

经验总结:我处理过的 23 个cc switch local proxy failed案例中,12 个是 YAML 字段名拼写错误(如apik_key),7 个是端口被其他程序占用(Docker Desktop 常占 3000),3 个是 Codex CLI 二进制损坏(下载不完整),只有 1 个是 Node.js 版本不兼容。所以,永远先查 YAML 和端口。

5. OpenRig 的进阶玩法:超越基础代理的工程化扩展

当 OpenRig 的基础功能跑通后,它就不再是一个“能用就行”的玩具,而是一个可深度定制的 AI 工程化平台。下面分享三个我在实际项目中落地的、真正提升生产力的扩展方向,每个都附带可运行的代码片段。

5.1 模型性能监控:给每个请求打上耗时标签

Codex CLI 默认不输出耗时,但 OpenRig 的 Node.js 层可以。我们在src/server.js的/responses接口中加入计时逻辑,并将耗时作为 SSE 的event字段发出:

// 在 src/server.js 的 /responses 处理函数开头添加: const startTime = Date.now(); // 在 codex.on('close') 回调里添加: const durationMs = Date.now() - startTime; console.log(`⏱️ 请求完成,总耗时 ${durationMs}ms,模型: ${config.model_routing?.default_model}`); // 同时发送到客户端 res.write(`event: timing\ndata: {"duration_ms":${durationMs},"model":"${config.model_routing?.default_model}"}\n\n`);

效果:VS Code 插件收到的 SSE 流中,会多出event: timing类型的消息。前端可据此绘制响应时间分布图,或当duration_ms > 30000时自动告警。这比单纯看日志快 10 倍。

5.2 配置热重载:不用重启服务,YAML 改了立刻生效

每次改 YAML 都要Ctrl-c再npm start,效率极低。用chokidar库监听文件变化:

npm install chokidar

在src/server.js顶部添加:

const chokidar = require('chokidar'); // 启动时监听 YAML chokidar.watch('./config/codex-config.yaml').on('change', () => { console.log('🔄 检测到 YAML 变更,正在重载配置...'); try { config = yaml.load(fs.readFileSync('./config/codex-config.yaml', 'utf8')); console.log('✅ 配置重载成功'); } catch (e) { console.error('❌ 配置重载失败:', e.message); } });

实测效果:改完 YAML 保存,3 秒内新配置生效。我曾用此功能在线上 A/B 测试两个模型的响应质量,全程无服务中断。

5.3 多环境 YAML:一套代码,三套配置(开发/测试/生产)

利用 YAML 的多文档特性,在config/codex-config.yaml里写三个配置:

# config/codex-config.yaml --- # 开发环境 env: dev proxy_mode: local models: gpt-4.5-turbo: api_key: "sk-dev-xxx" ... --- # 测试环境 env: test proxy_mode: local models: gpt-4.4-turbo: api_key: "sk-test-xxx" ... --- # 生产环境 env: prod proxy_mode: local models: claude-3.5-sonnet: api_key: "sk-prod-xxx" ...

在src/server.js中,用yaml.loadAll()读取,并根据环境变量选择:

const allConfigs = yaml.loadAll(fs.readFileSync('./config/codex-config.yaml', 'utf8')); const ENV = process.env.NODE_ENV || 'dev'; config = allConfigs.find(c => c.env === ENV); if (!config) throw new Error(`No config found for NODE_ENV=${ENV}`);

启动时指定环境:NODE_ENV=prod npm start。这让我们在 CI/CD 流水线中,用同一套 OpenRig 代码,无缝切换不同模型供应商。

最后分享一个真实技巧:我把 OpenRig 的 tmux 会话命名为codex-rig-$(date +%Y%m%d),每天一个新会话。这样tmux list-sessions就能看到历史所有调试记录,哪天哪个配置出了问题,一目了然。运维同学说我这招比 ELK 还好用——毕竟,最可靠的日志,就是你自己亲手敲出来的命令历史。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 14:23:29

水果蔬菜识别系统落地避坑指南:数据清洗、轻量CNN与PyQt多线程实战

简介:本资源是一套面向计算机相关专业本科生的毕业设计与课程设计实践项目,基于Python与CNN深度学习技术实现水果蔬菜图像识别,配套完整论文报告、GUI交互界面及模型评估可视化曲线,适用于课设答辩、毕设开发或深度学习入门实战。…

作者头像 李华
网站建设 2026/10/1 14:21:47

OpenAI DevDay 2026 三连击:Astra 因安全撤回、GPT-6.1 Sol 1/5 价格顶上、dots 全天候智能体上线——企业 AI 架构的三个信号

OpenAI DevDay 2026 三连击:Astra 因安全撤回、GPT-6.1 Sol 1/5 价格顶上、dots 全天候智能体上线——企业 AI 架构的三个信号核心结论:9 月 29 日 OpenAI DevDay 2026,OpenAI 干了一件史无前例的事——旗舰模型 GPT-6.1 Astra 因未通过内部安…

作者头像 李华