docs(adapter): 新增 dsh 接入指南 - #883
Conversation
deepcoldy
left a comment
There was a problem hiding this comment.
感谢贡献这份 dsh 接入文档 🙏 整体质量很高,能看出是对着 src/adapters/cli/dsh.ts、src/dsh-runner.ts 逐项核过的——显示名、cliId、model 默认值与候选、固定 deepseek-official provider、DSH_CORDIS_CONFIG 覆写、每次启动覆写 ~/.botmux/dsh/cordis.yml、不读 ~/.dsh 等都与实现一致;对 master 也 merge 干净。
审下来有 3 处会把用户带偏的事实性问题,建议修订后再合入(纯文档,改动都很小):
1)沙箱下 per-bot env 的说明写反了(安全相关,优先)
「凭据配置 → 注入方式」里写沙箱模式下 per-bot env「可能不会传递,遇到时改用 daemon 环境」,FAQ 里也有对应一条。按当前启动链,这个结论正好相反:
- worker 始终把
bots.json的env作为injectEnv传给后端; - PTY 后端把它并入启动 bwrap 的父进程环境;tmux 后端通过 pane 内
/usr/bin/env KEY=VAL … bwrap注入; - bwrap 参数里没有
--clearenv,只用--setenv覆盖少量键,所以DEEPSEEK_API_KEY会被子进程继承。
实测(真实 bwrap:父环境放一个测试变量 + 沙箱同款 --setenv/--unsetenv、无 --clearenv)子进程能读到该变量。保留原文案会引导用户把本可以按 bot 隔离的 key 搬到 daemon 全局环境,反而扩大泄露 / 串 bot 的风险。
建议:删掉这条 caveat 和对应 FAQ。真正值得提醒的是另一件事——DSH_CORDIS_CONFIG 指向的文件也必须在文件沙箱可见范围内,否则沙箱内 resolveConfigPath() 的 existsSync 判空会静默回退到内置组合;最稳妥是放在 ~/.botmux/dsh/(适配器已把该目录声明为 authPaths,例如 ~/.botmux/dsh/custom.yml)或放在 workingDir 内。
2)「自定义组合」示例其实不是默认组合,整块复制会改变会话落盘位置
这段文案同时称「默认组合如下」又称「以下为走 zen/go 网关的示例」,实际展示的是 zen/go 示例。相对 src/dsh-runner.ts 里真正的 VENDORED_CONFIG,示例少了 4 个 config 子树:
agent-core.config.workspaceContext.maxBytes: 65536sessions.config.root: !!js process.env.DSH_SESSION_ROOT ?? './.sessions'bash.config.cwd: !!js process.env.DSH_CWD ?? process.cwd()fs-local.config.cwd: !!js process.env.DSH_CWD ?? process.cwd()
(llm-deepseek 段是示例有意修改,不算遗漏。)
最实际的后果:用户整块复制成 DSH_CORDIS_CONFIG 后,sessions 的 root 会退回 workingDir 下的 ./.sessions,与文档后面「会话目录在 ~/.botmux/dsh/」直接冲突。
建议:先原样贴出完整的真实默认组合,再单独给出 zen/go 的最小 diff;或者把示例补全并明确标注「示例(基于默认修改)」。
3)daemon 重启命令
「daemon 环境」里的 pm2 restart --update-env 缺少进程目标参数,按 PM2 CLI 语法不能直接执行,而且会绕过 botmux 自己的安全重启 / 会话恢复入口。建议改成 botmux restart;若明确是在仓库 checkout 内操作,用 pnpm daemon:restart。
两个小 nit(非阻塞)
- 结尾的
GET /api/cli-options:实际返回的是options数组,dsh 项形如{ id: "dsh", available: … },不是顶层dsh: available。建议改成「查看id: dsh条目的available」。 - 「安装 dsh 运行时」可顺带注明需要 Python
>=3.10。
关于安装命令本身:核过 PyPI,在当前只有 pre-release(0.1.0rc6)的情况下,裸 pip install deepseek-harness-sdk 会解析到该 rc,无需额外加 --pre,保持现状即可。
改好后我再复核一遍~ 再次感谢 🙏
- 删除「沙箱下 per-bot env 不传递」的错误结论与对应 FAQ:worker 始终把 bots.json env 作为 injectEnv 传给后端,bwrap 无 --clearenv,key 会被子进程继承;改为提醒 DSH_CORDIS_CONFIG 文件须在沙箱可见范围内,否则 existsSync 判空静默回退内置组合 - 自定义组合章节改为先原样贴出 VENDORED_CONFIG 完整默认组合(含 agent-core workspaceContext、sessions root、bash/fs-local cwd 四个子树),再单独给出 zen/go 网关的最小 llm-deepseek 改动,避免整块复制导致会话落盘退回 workingDir/.sessions - daemon 重启命令由 pm2 restart --update-env 改为 botmux restart(checkout 内可用 pnpm daemon:restart),避免绕过安全重启与会话恢复 - 安装章节补充 Python >= 3.10 要求;/api/cli-options 返回结构更正为 options 数组中 id=dsh 条目的 available
- 凭据配置改为「组合 + settings」两层叙事,讲清 apiKeyEnv 是环境变量名引用;环境变量表只留通用项(DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL / DSH_CORDIS_CONFIG),配置相关的变量名改为通用规则说明 - 新增「走 pi 插件配置多 provider」:自定义组合追加 settings/credentials/llm-pi-ai 三插件,~/.dsh/settings.yaml 的 llm-pi-ai 段配 provider 列表(apiKeyEnv 只引用变量名),含休眠/热加载行为与沙箱下 sandboxPaths.readOnly 注意事项 - 自定义路由示例泛化为占位值,文档不出现具体 provider 端点与 key 名 - 快速接入 provider 行与 pi 章节交叉引用,消除「不支持更换 provider 路由」的表面矛盾 - 安装章节补充 Python >= 3.10;开头补 cordis 组合白话注释
|
评审意见已逐条修订,推了两个 commit(bffd0b7f、49077265): 1)沙箱下 per-bot env(安全相关):已删除「沙箱下 per-bot env 可能不传递」的 caveat 和对应 FAQ。核对启动链确认结论相反:worker 始终把 2)默认组合:自定义组合章节改为先原样贴出 3)daemon 重启: nits:
另外补充了「走 pi 插件配置多 provider」一节:自定义组合追加 麻烦再复核一遍~ |
deepcoldy
left a comment
There was a problem hiding this comment.
复核了更新后的版本(head 4907726),先前 review 提的 3 项 + 2 个 nit 都已按预期处理,逐条对源核过:
- 沙箱 per-bot env:已更正为「沙箱模式下同样生效——worker 把
env作为injectEnv(PTY 并入子进程环境 / tmux 走 pane 内/usr/bin/env),bwrap 不清理环境,key 一路继承」,与实现一致;并补了「DSH_CORDIS_CONFIG需在文件沙箱可见范围,否则existsSync判空静默回退内置组合」这个真正该提醒的点。 - 默认组合 YAML:现与
src/dsh-runner.ts的VENDORED_CONFIG逐字一致(4 个config子树已补全),zen/go 改成占位示例 + 明确「只调整llm-deepseek段、其余保持默认」并说明删掉sessions.root/cwd的后果。 - 重启命令:已改为
botmux restart(checkout 内pnpm daemon:restart),并说明为何不要用pm2 restart --update-env。
nit:/api/cli-options 措辞已改成「id: dsh 条目的 available」;「安装 dsh 运行时」已注明 Python >=3.10;安装命令保持不加 --pre(正确——当前只有 pre-release 时裸 pip install 会解析到该 rc)。
另:新增的「走 pi 插件配置多 provider」一节,botmux 侧的集成点我核对无误——sandboxPaths.readOnly 是真实 bot 配置字段(src/types.ts)、适配器只声明了 ~/.botmux/dsh 为 authPaths(所以 ~/.dsh 默认不在沙箱内、需显式加进 sandboxPaths.readOnly 的提醒正确)。该节里 dsh 自身插件的行为(dsh-settings-file / dsh-credentials-local / llm-pi-ai 的挂载语义、settings.yaml 的 llm-pi-ai: / agent-default-model: 段、热加载与「默认休眠」)属于 dsh 运行时范畴,botmux 代码内无从核对——建议对照 dsh 自身的插件文档再确认一遍这几个名称与字段。
我这边先前的意见都已解决,LGTM。
|
感谢复核 🙏 pi 一节里 dsh 侧的名称与字段已对照本地安装的 dsh 插件文档逐项确认(
均与文档措辞一致,无需再改。 |
deepcoldy
left a comment
There was a problem hiding this comment.
更新:撤回上一条 approve,改为 request changes。
R2 里我确认的前三项修订(沙箱 per-bot env、默认组合 YAML 逐字对齐、重启命令)仍然成立。问题出在新增的「走 pi 插件配置多 provider」一节——把它拿真实发行版跑下来,有两个硬阻断,照文档做会让 bot 起不来 / 承诺的能力实际不存在。
阻断 1:按文档装到的运行时加载不了这份三插件组合
当前 PyPI 只有 deepseek-harness-sdk / deepseek-harness-runtime-bin 的 0.1.0rc6。装上后用打包的 dsh-jsonrpc-agent 逐个插件做启动探针(这正是 src/dsh-runner.ts 实际的加载方式):
@deepseek-ai/dsh-llm-pi-ai→ 能解析(随后因最小探针缺 llm seam 而 pending,说明插件确实在发行闭包里)@deepseek-ai/dsh-settings-file→ERR_MODULE_NOT_FOUND: Cannot find package@deepseek-ai/dsh-credentials-local→ERR_MODULE_NOT_FOUND- 文中
agent-default-model:段隐含依赖的@deepseek-ai/dsh-agent-default-model→ERR_MODULE_NOT_FOUND
发行闭包里实际存在的是 @deepseek-ai/dsh-settings、@deepseek-ai/dsh-credentials(不带 -file/-local 后缀)。所以文档让用户把 dsh-settings-file / dsh-credentials-local 加进 cordis 后,dsh 会在握手前直接 plugin tree failed to load,settings.yaml 根本没机会生效——而且这是单文件 wheel 的既定发行闭包,无法靠“另外 npm install”补救。
阻断 2:agent-default-model: 不会替 botmux 选 provider/model,「多 provider」在当前适配器里不成立
- botmux
src/dsh-runner.ts:650固定发送initialize { provider: "deepseek-official", model }——provider是写死的字面量,不从任何 config/env/model 派生。 - dsh 官方 JSON-RPC server(
packages/sdk/server/src/server.ts:117-118, 224-231)把这两个显式参数原样存下并用来创建每个 Agent。 - 官方
agent-default-model的语义(其 README):deployment default「an Agent entry point uses only when a session has no selection of its own」。botmux 每次都传显式provider+model,session 始终有 selection,所以agent-default-model永远不会被查到——不是“server 忽略它”,而是当前 botmux 的调用路径结构上就绕过它。
所以文档里「在 agent-default-model: 段选择会话默认 provider/model」是事实错误;顶部与该节的「多 provider」承诺也超出当前 botmux 能力。今天 model 只能是 deepseek-official 路由下的模型,无法把会话切到 pi 的其它 route。
建议二选一
- 本 PR 维持纯文档(推荐,快):删掉整段「走 pi 插件配置多 provider」及前文的相关跳转,明确当前 botmux 仅支持
deepseek-official;自定义组合只讲现有llm-deepseek的 key / baseURL / model。这样 PR 立刻是准确、可合的纯文档。 - 真正支持多 provider(另开功能 PR):给 dsh adapter/runner 增加 provider 配置并传入 JSON-RPC
initialize、处理 dashboard 模型候选,同时要求 dsh runtime 把 settings / credentials 插件纳入发行闭包;用真实 wheel 做启动 + 选路集成测试。不要用agent-default-model兜底——它不是这个 JSON-RPC 入口的选择源。
(附:若将来确实保留 credentials 文件方案,credentials-local 要求凭据文件 chmod 600,否则会拒绝启动,值得在文档里点一句。)
前三项已经修得很好,这节删掉或降级后我再复核一遍。
改动
新增
docs/dsh.md:DeepSeek Harness(dsh)适配器的接入指南,覆盖:~/.dsh全局配置不生效,凭据只能通过环境变量注入;两种注入方式及沙箱注意事项DSH_CORDIS_CONFIG覆写行为、默认组合内容与 zen/go 网关示例为什么
dsh 适配器(#858)引入后缺少面向用户的接入文档。dsh 在 botmux 里的凭据链路(不读
~/.dsh)和默认组合覆写行为与单独使用 dsh 时差异较大,实际接入容易踩坑,整理成文档便于按步骤接入与排错。影响面
纯文档新增,无代码变更,不影响任何运行时行为。
验证
src/adapters/cli/dsh.ts、src/dsh-runner.ts实现逐项核对(环境变量名、默认组合、provider 路由、model 选项、会话目录)docs/riff.md