dsh-codex-bridge:把 Codex CLI 接入 DeepSeek Harness 的双面插件

前言

用 DeepSeek Harness(dsh)做智能体开发时,你可能会遇到这样的需求:让会话里的 agent 找一个外部编码智能体——比如 OpenAI 的 Codex——要个第二意见,或者并行跑一段编码任务。手动做这件事,意味着自己 spawn codex 进程、捕获 JSONL 输出、轮询状态、再把结果接回会话。这些脚手架代码与主任务无关,却每次都要写一遍。

dsh-codex-bridge 要解决的就是这个问题。DSH 的理念是「一切皆插件」,能力以插件形式挂进 harness,这个项目是这一思路下的一个具体实现。下面介绍它是什么、怎么装、提供了哪些工具、有哪些限制。

这是什么

dsh-codex-bridge 是 pandashere 维护的双面(host + browser)插件,把 Codex CLI 接入 DeepSeek Harness,许可证为 MIT。双面的含义是:宿主侧向 agent 暴露一组工具,浏览器侧在 Web 会话窗格里提供可视化。对 agent 而言,Codex 成为一个可以直接调用的工具;对使用者而言,每次 Codex 会话的完整过程在网页上可观测。

核心功能

call_codex:把 Codex 当工具调用

在 dsh 会话的工作目录启动 Codex(底层命令为 codex -a never exec --json),支持两种模式:

  • async:立即返回,多个调用可并行;
  • block:等待最终答案。

参数为 { prompt, mode?: async|block, sandbox?: read-only|workspace-write, model?, timeout_ms?, codex_session_id? }

codex_status 与 codex_abort

codex_status 列出当前 dsh 会话的 codex 会话,包括状态、prompt 预览和进度,适合在 async 启动后轮询。

codex_abortcodex_session_id 终止 codex 进程组:先发 SIGTERM,超过 killGraceMs(默认 2000ms)再发 SIGKILL。

codex_steer:在同一 thread 上续接

codex_steer 用于在同一 thread 上继续一个已结束(settled)的 Codex 会话,底层是 codex exec resume <thread_id>,新记录通过 parent 链回溯到原会话。参数为 { codex_session_id, prompt, mode?: async|block, model?, timeout_ms? }。典型用途是在已有会话基础上追问或调整方向。

Web 端 Codex 标签页

浏览器侧在 Web 会话窗格提供 Codex 标签页(与 Chat / Trajectory 并列),显示:状态、prompt、Agent Loop 瀑布图(消息、带命令与参数的工具调用、可折叠的工具输出与退出码、轮次分隔符)、transcript 与最终答案。

状态通过 session projection 通道实时推送(codex/session 事件、codex/sessions 投影),页面刷新后可通过历史回放恢复。浏览器端由 /plugins/dsh-codex-bridge/client.js 提供,遵循 __ModuleLoader__.load({id, factory}) 协议。

安装与启用

运行要求:

  • Node.js 22 或更新版本;
  • @deepseek-ai/dsh@0.1.0-rc.6
  • 已认证且可用的 Codex CLI(可执行名 codex,或用 codexPath 指定路径)。

插件不读取也不存储 API key,认证由 Codex CLI 自持。

先在插件目录构建打包,生成独立 bundle:

npm install
npm run check
npm pack

再把生成的 tarball 安装到 DSH profile,然后启动 dsh web 并重启:

npx @deepseek-ai/dsh@0.1.0-rc.6 plugin --profile web add ./dsh-codex-bridge-0.1.0.tgz
npx @deepseek-ai/dsh@0.1.0-rc.6 web

注意:不支持把源码目录以链接方式安装(host peers 由 DSH profile 提供),必须安装打包后的 tarball 并重启。

验证浏览器端是否就位(默认 Web profile 跑在本机 3080 端口时):

curl -s http://127.0.0.1:3080/plugins/dsh-codex-bridge/client.js | head

更新时,用更新的包版本重新打包 tarball,先移除已安装 bundle,再添加新 tarball 并重启。卸载命令:

npx @deepseek-ai/dsh@0.1.0-rc.6 plugin --profile web remove dsh-codex-bridge

配置项

README 给出的配置项及默认值如下:

配置项 默认值 含义
codexPath codex codex 可执行文件(绝对路径或 PATH 查找)
defaultSandbox read-only codex 自身 shell 命令的 sandbox 策略(部署可调高)
defaultTimeoutMs 0 单个 codex 会话的生命周期上限(0 = 不限)
maxParallel 3 全局并发 codex 进程上限
maxSessionsPerSession 8 每个 dsh 会话内活跃 codex 会话上限
maxRetained 16 每个 dsh 会话保留的已结束记录数(淘汰最旧)
maxPromptChars 16384 prompt 长度上限(超限拒绝)
maxTranscriptChars 16384 事件/投影中记录的 transcript 上限
maxLoopSteps 32 agent-loop 窗口的步数上限
maxLoopBytes 16384 loop 窗口的序列化字节上限(UTF-8,淘汰最旧的已完成步骤)
allowedAgents roots 谁可调用 call_codexrootsall
killGraceMs 2000 abort 时 SIGTERM → SIGKILL 的宽限期

设计立场与资源限制

README 明确了设计立场:这是一个 UX 通道,不是安全边界。Codex 以调用用户的权限、在其自身 sandbox 策略下运行——read-onlyworkspace-write 会提供给模型,danger-full-access 仅限部署配置。

模型可见的调用面刻意收得很紧:

  • Codex 始终在会话工作目录运行,绝不使用宿主 cwd(fail closed);
  • 默认仅顶级 agent 可调用(allowedAgents: roots,可改为 all);
  • 通过 maxParallelmaxSessionsPerSessionmaxLoopStepsmaxLoopBytes 限制资源占用与写入放大。

已知限制

使用前值得知道的几条,列自 README:

  • 每次调用一次性执行,之后靠 codex_steer 续接。标准 CLI 不支持运行中实时插话,那需要实验性的 codex app-server / remote-control 路径。
  • loop 窗口是近期活动,不是审计日志。旧步骤会在 maxLoopSteps / maxLoopBytes 下被物理淘汰;dsh 会话日志仍保留完整快照,但标签页只显示保留窗口。
  • sandbox 是 Codex 自己的。defaultSandbox 映射到 codex -s,约束的是 Codex 的 shell 命令能碰什么,不是 harness 的安全边界。
  • 进程组终止仅支持 POSIX。Windows 移植需要 Job Object 或 taskkill /T 树状终止。
  • 遥测脱敏仅覆盖 dsh 导出,Codex 自身的遥测不在范围内。

适用场景与注意

适合的人群:在 dsh 上做智能体开发、希望把 Codex 作为第二意见或并行编码通道、又不想到处写进程管理脚手架的开发者。典型用法是用 async 模式启动并行任务,codex_status 轮询进度,结束后用 codex_steer 续问,整个过程在 Web 端的 Codex 标签页可观测。

安装前注意:插件以当前 dsh 进程的权限运行,装进 profile 前建议先读一遍源码,确认许可证(本项目为 MIT)符合自己的使用场景。

结尾

dsh-codex-bridge 把「调用外部编码智能体」从手工脚手架变成一个受控的工具调用加一个可观测的标签页,接入成本和出错面都小了不少。项目地址:

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

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

Xiaoye