前言¶
在 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: "繼續上次的方案" })
兩個坑值得寫在前面:
- 推理檔位統一是
low / medium / high / xhigh / max / ultra,沒有minimal也沒有none;傳給舊腳本習慣的minimal會直接turn.failed。 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 / 幻方無官方從屬關係。