dsh-codex-handoff:把 Codex CLI 多轮会话接进 DeepSeek Harness

前言

在 DSH(DeepSeek Harness)里做开发时,常见一种情况:两边都有命令行助手,DSH 跑 DeepSeek、本机还装着 Codex CLI,但两者的会话互不相通——这边派一个任务过去,那边答完就断了,下一轮只能重贴上下文,模型选择和工作强度也无法控制。

hato-24/dsh-codex-handoff(gpt_bridge)就是为这个问题写的客户端插件:把本机 Codex CLI 的多轮会话接进 DSH,往来记录在侧栏可查,会话落库后可以 resume 续接,模型与推理强度还能切换。下面介绍它的定位、安装方式和实际用法。

这是什么

一句话定位:Codex CLI 的多轮对话桥。插件装上后,DSH 里出现 GPT 对话面板,同时给 agent 注册一个 codex_gpt 工具,GPT 因此能被当成子代理调用;会话默认持久化,可用 codex exec resume 续接同一条 thread。

  • 维护者:HATO-24
  • 分类:客户端(同时含 Host 侧与 Client 侧组件)
  • 许可证:MIT

它解决的三件事:一是往来可见,每一轮问答在 DSH 侧栏点开就能看;二是可续接,会话写进 Codex 会话库,换命令也能接着聊;三是可选档位,模型和推理强度在界面上切换,而不是写死在脚本里。

核心功能

插件由三部分组成:

组件 作用
Host 侧 lib/index.js 调 codex exec、维护 .bridge 存储、提供 /api/codex-bridge/* 路由、注册 codex_gpt 工具
Client 侧 lib/client.js 侧栏「GPT 对话」入口 + 主面板(会话列表、逐轮提问/回复)
gpt_bridge.ps1(升级版) 命令行桥,默认持久化会话、记录 thread_id、支持 -Resume

数据落在工作区的 <workspace>/.bridge/,与 gpt_bridge.ps1 共用同一套目录,所以升级前的旧记录也能看到。

安装与启用

前置条件:本机已安装 DSH,且 Codex CLI 已登录、可正常调用。插件会自动在 %LOCALAPPDATA%\OpenAI\Codex\bin\*\codex.exe、CODEX_BIN、PATH 里找 codex 可执行文件。

dsh-codex-handoff@0.1.1

两种方式安装,任选其一:

1、界面操作:插件 页 → 添加 → 输入 dsh-codex-handoff

2、工具安装:plugin_manager → install_bundle,target 填 dsh-codex-handoff@0.1.1

说明:这里的版本号按 README 安装章节原文填写;仓库 package.json 中声明的版本是 0.1.3。

装好后界面会出现三处入口:

  • 左下角(Settings 旁、催更姬旁边)新增 GPT 按钮,点击在 DSH 右侧栏打开对话面板
  • 右侧栏顶部出现 GPT 对话 标签(和「开始」并列)
  • 会话标题栏最右侧的对话气泡按钮,作为快捷入口

两个注意点:

  • Client 插件改了 inject 后要重启 DSH,新配置才会被解析;
  • 本地改代码后,在插件页把该插件禁用 → 启用即可重载,不用重启 DSH。

另外,左侧栏图标不能用作入口:它会切走当前 conversation,导致 sidebarRight.mounted 变空,openResource 抛 sidebarRight: no session surface is mounted,这是 DSH 的机制限制。

在侧栏查看记录与发消息

点左下角的 GPT 按钮(或会话头部气泡按钮),右侧栏展开「GPT 对话」标签。右侧栏可拖动分隔条调宽度,主面板不受影响,对话照常进行。

面板底部是发送区:

  • 输入框 Enter 发送、Shift+Enter 换行;
  • 模型下拉来自 codex debug models 列出的全部 10 个模型(GPT-6.1-Sol、GPT-6-Astra、GPT-6.1 Terra、GPT-6-Sol 等);
  • 推理下拉跟着所选模型支持的档位走(low/medium/high/xhigh/max/ultra);
  • 选中某段会话时,两个下拉自动回填该会话上次用的模型与推理强度,直接发送即沿用;切换会话才重置。

记录的是「实际用了什么」:每轮结束后插件会读 rollout 里 turn_context 的真实 model 与 effort,写进 inbox/<id>.json 的 actualModel/actualEffort,不传模型时也不会显示空值。README 里的实测对照如下(请求参数 model=gpt-6.1-sol, reasoning=high):

来源 model effort
请求参数 gpt-6.1-sol high
桥记录 actualModel gpt-6.1-sol high
rollout turn_context gpt-6.1-sol high

卡片和会话头部因此能区分 gpt-6.1-sol 与 gpt-6-sol,这两个是不同模型,前者默认推理是 low,后者是 medium。

会话标识规则:选中某段会话时发送等于续接那个 Codex 会话,没选中则新开一段;发送完会自动选中新会话并刷新列表。

让 GPT 当子代理:codex_gpt 与多轮续接

DSH agent 会看到新工具 codex_gpt,参数是 message(必填)、conversationId/threadId(二选一)、model、reasoning:

codex_gpt({ message: "审查 docs/plan.md 的里程碑,找不可执行之处", reasoning: "high" })
→ { conversationId: "c-...", threadId: "01a1...", reply: "..." }

第二轮传同一个 conversationId,即续接同一个 Codex 会话,不用重发上下文:

codex_gpt({ conversationId: "c-...", message: "第 2 点展开,给具体改法" })

也可以直接续接任意 Codex thread:

codex_gpt({ threadId: "01a1ac8e-01a4-79a2-a70d-855254e70751", message: "继续上次的方案" })

两个坑值得写在前面:

  1. 推理档位统一是 low / medium / high / xhigh / max / ultra,没有 minimal 也没有 none;传给旧脚本习惯的 minimal 会直接 turn.failed。
  2. model/reasoning 不传就用 Codex 配置默认,传了会走 -m 与 -c model_reasoning_effort=…,README 实测生效。

HTTP 接口

路由前缀 /api/codex-bridge,默认端口 http://127.0.0.1:12530:

方法 路径 作用
GET /list 会话列表(含老记录)+ 当前默认配置
GET /read?id=<id> 某段会话的逐轮提问与回复 + Codex 侧原文
GET /status 工作区、codex 路径、隔离开关
GET /models 可用模型目录(slug / 显示名 / 支持的推理档位)
POST /send 发一轮真实对话,body:{message, conversationId?, threadId?, model?, reasoning?}
POST /promote 把一段会话标记成 Codex App 可见,body:{threadId} 或 {conversationId}

发送一轮:

$body = @{ message = "只回复两个字:收到"; reasoning = "low" } | ConvertTo-Json -Compress
Invoke-WebRequest -Uri "http://127.0.0.1:12530/api/codex-bridge/send" -Method POST `
  -Body $body -ContentType "application/json" -UseBasicParsing -TimeoutSec 900
# → {"conversationId":"c-...","threadId":"01a1...","reply":"收到"}

需要留意两点:POST /send 会真实消耗 Codex 额度,而且是同步等待,README 实测一次 low 推理约 58 秒;另外路由用了 Node 原生 handler 而非 resource,因为 resource 路由只放行 GET/HEAD,POST 会被平台层直接 405。

上下文与隔离:GPT 能看到什么

这是本插件最初要回答的问题。README 用零额度的方式实测:codex debug prompt-input "test" 会把模型实际收到的输入原样打印成 JSON 数组,逐条看,模型看到的东西远超桥发过去的那一段 prompt。

注入项 实测证据 大小/内容
全局人设指令 developer message 第 1 条 ~/.codex/config.toml 里 model_instructions_file 指向的 prompts/gpt-with-taste/main.md,24,461 字符
skills 清单 developer message 第 2 条 <skills_instructions> 4,897 字符,列出 ~/.codex/skills/.system、plugins/cache/openai-bundled 等 skill roots,GPT 看到路径就能自己读 SKILL.md
MCP 工具 工具表 mcp__cua_repl.js 等,来自 config.toml 的 [mcp_servers.node_repl]
插件推荐列表 developer message <recommended_plugins> 876 字符,16 个「可用未安装」插件
多代理系统提示 developer message <multi_agent_role> / <multi_agent_mode> 2,400 + 271 字符
环境上下文 user message <environment_context> cwd、shell、日期、时区、文件系统权限根
Codex 记忆 config.toml 的 [features] memories = true / [memories] use_memories = true 会读取 memories_1.sqlite / memories_v2_1.sqlite

结论:桥只负责发一段 prompt,其余全是 Codex 自己加载的。想让上下文更干净,可以开本插件的隔离开关 DSH_CODEX_BRIDGE_ISOLATE=1(或命令行 -Isolate),默认关闭。更彻底的隔离手段是 Codex CLI 自身的参数,README 给了三档:

# 1) 完全隔离:不加载 ~/.codex/config.toml(auth 仍用 CODEX_HOME)
codex exec --ignore-user-config -m gpt-6-sol ...

# 2) 只关插件推荐
codex exec --disable plugins ...

# 3) 只关 MCP
codex exec -c 'mcp_servers={}' ...

注意 --ignore-user-config 同时会丢掉 model 等配置,隔离时要显式传 -m。

适用场景与注意

适合这几类用法:想让 GPT 以子代理身份参与 DSH 里的多轮协作;想让 Codex 的会话在 Codex 桌面版或 CLI 里继续,而不是用完即散;需要按任务切换模型和推理强度并留档。

上手前需要确认几件事:

  • 插件以当前 DSH 进程的权限运行,能读到 Codex CLI 的环境与配置,未核实的源码建议安装前自行过一遍,许可证为 MIT。
  • 会话会消耗 Codex 账号额度,建议先用 codex debug prompt-input 和隔离开关确认上下文范围,再决定是否定向提问。
  • 老记录来自 outbox/*.prompt.md 与 inbox/<id>.json、logs/<id>.stdout.jsonl,thread_id 能从这两处回捞;README 实测升级前的 3 条老记录全部列出,其中 2 条成功恢复 thread_id,另 1 条是模板没写回复的空记录。

结尾

这个插件把「用过即弃」的 Codex CLI 对话变成了 DSH 工作流里可查、可续、可调档位的一环,改造集中在侧栏面板、codex_gpt 工具和 HTTP 路由三处,改动面不大但桩点明确。社区插件目录页:https://www.skillhub.cn/plugins/HATO-24/dsh-codex-handoff ;源码:https://github.com/HATO-24/dsh-codex-handoff 。该目录是独立站点,与 DeepSeek / 幻方无官方从属关系。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜