Codex + DeepSeek 桥接技能
问题背景
Codex CLI(OpenAI 官方 AI 编程助手)在 macOS 上存在两个与 DeepSeek 不兼容的问题:
-
API 格式不兼容:Codex 强制使用 OpenAI 的 Responses API(
/v1/responses), 而 DeepSeek 仅支持 Chat Completions API(/v1/chat/completions)。 直接配置 Codex 调用 DeepSeek 会报404 Not Found。 -
macOS 权限 Bug:Codex CLI v0.137.0+ 在 macOS 上执行
codex exec时, 会尝试在进程内启动 app-server,触发沙箱权限限制,报错:failed to initialize in-process app-server client: Operation not permitted
解决方案架构
本方案通过三层代理桥接实现完整连通:
用户任务
|
v
codex_client.mjs (WebSocket 客户端)
|
v
Codex app-server (ws://127.0.0.1:9998)
|
v
codex-bridge 代理 (http://127.0.0.1:4000)
|
v
DeepSeek 官方 API (https://api.deepseek.com/v1)
|
v
AI 回复
| 组件 | 作用 | 端口 | |------|------|------| | codex-bridge | API 格式转换:Responses API ↔ Chat Completions | 4000 | | Codex app-server | Codex 核心服务(独立进程绕过 macOS bug) | 9998 | | codex_client.mjs | WebSocket 客户端,发送任务并接收回复 | - |
前置条件
- macOS 系统(本方案主要解决 macOS 问题)
- Node.js 22+(已安装
ws模块) - Codex CLI 已安装:
npm install -g @openai/codex - DeepSeek API Key(格式
sk-...,余额大于 ¥0)
快速开始
方式一:一键启动(推荐)
运行 bundled 脚本 scripts/start_all.sh:
# 1. 编辑脚本填入你的 Key
export DEEPSEEK_KEY="sk-your-deepseek-key"
export PROXY_KEY="sk-proxy-local-anything"
bash ~/.workbuddy/skills/codex-deepseek-bridge/scripts/start_all.sh
# 2. 发送任务
node ~/.workbuddy/skills/codex-deepseek-bridge/scripts/codex_client.mjs "写一个 Python 计算器"
方式二:分步手动启动
Step 1: 启动 codex-bridge 代理
cd ~/codex-bridge # 或 skill scripts 目录
DEEPSEEK_API_KEY="sk-your-key" \
PROXY_AUTH_KEY="sk-proxy-local-anything" \
node ~/.workbuddy/skills/codex-deepseek-bridge/scripts/proxy.mjs
代理将监听 http://127.0.0.1:4000。
验证:
curl http://127.0.0.1:4000/health
Step 2: 启动 Codex app-server
export OPENAI_API_KEY="sk-proxy-local-anything"
codex app-server \
-c 'model="deepseek-v4-flash"' \
-c 'model_providers.local_proxy.name="local_proxy"' \
-c 'model_providers.local_proxy.base_url="http://127.0.0.1:4000/v1"' \
-c 'model_providers.local_proxy.wire_api="responses"' \
-c 'model_providers.local_proxy.requires_openai_auth=true' \
-c 'model_provider="local_proxy"' \
--listen "ws://127.0.0.1:9998"
验证:
curl http://127.0.0.1:9998/healthz
Step 3: 发送任务
node ~/.workbuddy/skills/codex-deepseek-bridge/scripts/codex_client.mjs "你的任务描述"
关键配置说明
codex-bridge 环境变量
| 变量 | 必填 | 说明 |
|------|------|------|
| DEEPSEEK_API_KEY | 是 | DeepSeek 官方 API Key |
| PROXY_AUTH_KEY | 是 | 代理认证 Key(任意字符串) |
| PROXY_PORT | 否 | 代理端口,默认 4000 |
| LOG_LEVEL | 否 | 日志级别:silent/error/warn/info/debug,默认 info |
Codex app-server 配置项
| 配置键 | 值 | 说明 |
|--------|-----|------|
| model | deepseek-v4-flash 或 deepseek-v4-pro | 使用的 DeepSeek 模型 |
| model_provider | local_proxy | 使用本地代理而非 OpenAI |
| model_providers.local_proxy.base_url | http://127.0.0.1:4000/v1 | 代理地址 |
| model_providers.local_proxy.wire_api | responses | Codex 使用 Responses API |
模型选择
DeepSeek 支持模型:
deepseek-v4-pro— 推理能力强,适合复杂任务deepseek-v4-flash— 速度快,成本低,适合日常任务
在 Codex 配置中设置 model="deepseek-v4-flash" 即可切换。
故障排查
codex-bridge 启动失败
# 检查端口占用
lsof -i :4000
# 查看日志
cat /tmp/codex-bridge.log
app-server 启动失败
# 检查端口占用
lsof -i :9998
# 查看日志
cat /tmp/codex-appserver.log
# 常见问题:SQLite 只读错误
# 解决:chmod 644 ~/.codex/*.sqlite*
客户端连接失败
# 测试 WebSocket 连通性
curl http://127.0.0.1:9998/healthz
# 测试代理连通性
curl http://127.0.0.1:4000/health
DeepSeek API 返回 401/429
- 检查
DEEPSEEK_API_KEY是否正确 - 检查 DeepSeek 账户余额是否充足
- 检查是否使用了 Codex CLI 内置 Key 而非 DeepSeek Key
Bundled Resources
scripts/
| 文件 | 说明 |
|------|------|
| proxy.mjs | codex-bridge 代理服务(Responses ↔ Chat Completions 转换) |
| codex_client.mjs | WebSocket 客户端,用于向 app-server 发送任务 |
| start_all.sh | 一键启动脚本,自动启动 bridge + app-server |
references/
| 文件 | 说明 |
|------|------|
| protocol.md | Codex app-server WebSocket JSON-RPC 协议文档 |
高级用法
自定义工作目录
编辑 scripts/codex_client.mjs 中的 cwd 字段:
cwd: '/Users/yourname/your-project'
使用其他模型
修改 scripts/start_all.sh 中的 model= 配置行:
-c 'model="deepseek-v4-pro"' \
同时支持 OpenAI + DeepSeek
在 proxy.mjs 中同时配置 OPENAI_API_KEY 和 DEEPSEEK_API_KEY,
代理会根据模型名称自动路由到对应的上游服务商。
技术细节
为什么 Codex 不能直接连 DeepSeek?
Codex CLI 内部调用 /v1/responses 端点,这是 OpenAI 在 2025 年推出的新 API 格式。
DeepSeek 目前仅支持传统的 /v1/chat/completions 格式。
两个 API 的请求/响应结构完全不同,无法直接互通。
codex-bridge 做了什么转换?
- 请求转换:将 Responses API 的
input数组转换为 Chat Completions 的messages数组 - 工具调用转换:将
function_call/function_call_output转换为tool_calls/tool - 响应转换:将 Chat Completions 的 SSE 流转换为 Responses API 的 SSE 事件格式
- 历史管理:通过
responseStore维护previous_response_id链式调用
为什么需要独立 app-server?
Codex CLI 的 exec 子命令尝试在同一个 Node.js 进程中加载 Rust 编写的 app-server 二进制,
macOS 的 System Integrity Protection / 沙箱机制阻止了这一操作。
通过 codex app-server --listen ws://... 独立启动服务后,
CLI 只需通过 WebSocket 连接即可,无需在进程内加载二进制。
Scan to join WeChat group