Skip to content

About

DSH 命令行工具:跨模式派活 —— 让 AI 开一个换了工具集的独立会话去干活,再把结果取回来。

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

CI License: MIT

dsh-delegate —— DSH 跨模式派活

只想要“照着做一遍”的封装版本(含安装、配置与排错表),见同名技能包 agent-cross-preset-delegation;本仓库是代码本体。

让 AI 自己开一个独立会话去干活,并且可以把结果收回来。

和原生子代理的分工

原生 subagent / subagent_fork dsh-delegate
换模式(agentPreset) 不行,继承当前模式 可以,十个预设任选
选渠道模型 可以 可以,任意已注册渠道
结果回传 自动回、有通知、可续追问 等它跑完取回,也可续聊
上下文 干净隔离 完全独立的新会话

一句话:原生子代理换不了模式,它能。

两者的上下文差在哪(实测)

用同一个模式分别跑原生子代理和一个 delegate 新会话,让它俩各自清点自己收到了什么,结论是:

项 原生子代理 delegate 新会话
系统提示章节 同一套 同一套
长期记忆 / 用户档案 / 项目关键记忆 都有 都有
技能目录 有 有
工具集 同一批 同一批
会话 ID 各自的 各自的
工作目录 继承父会话 跟随调用方会话

所以"新对话"并不比原生子代理更干净或更脏——系统提示、记忆、工具是同一份。真正改变上下文的是换模式:换了模式才换掉整套提示、工具和技能目录。

剩下的实际差别只有三点:

  1. 对话历史——原生 subagent 看不到当前对话,subagent_fork 能看到已完成轮次,delegate 两者都看不到。
  2. 可见性——delegate 出来的会话在界面上独立可见,用户能点进去接着聊;原生子代理是挂在本会话下的隐藏子会话。
  3. 回传方式——原生把结果直接放进当前上下文;delegate 由工具读回来打印。

快速开始

cd dsh-delegate

node delegate.mjs presets                     # 有哪些模式可选
node delegate.mjs providers                   # 有哪些渠道
node delegate.mjs where                       # 新会话会落在哪个工作目录
node delegate.mjs run --task "任务书" --preset code --timeout 900
node delegate.mjs sessions --limit 10         # 看派出去的会话
node delegate.mjs read <sessionId>            # 取结果
node delegate.mjs send <sessionId> --task "再补充..."   # 续聊

带渠道模型:

node delegate.mjs run --task "..." --preset academic `
  --provider siliconflow --model "moonshotai/Kimi-K2.7-Code" --effort high

长任务后台派、稍后取:

node delegate.mjs run --task "..." --preset ops --no-wait --title "运维巡检"

参数

参数 说明
--task 必填。新会话看不到当前对话,任务书必须自包含
--preset academic / code / draw / dsh-codex / mail / mcp / mcu / null / ops / shopping
--provider --model 必须成对给。模型 id 见 <DSH_HOME>\settings.yaml 的 llm-pi-ai.providers
--effort high / max / low;硅基的 Kimi 系不支持,传了会报错
--cwd 不给就跟随调用方会话的工作目录(读 DSH_SESSION_ID 反查)
--title 新会话的显示标题,便于在界面里认出来
--timeout 等待上限(秒),默认 900。超时不杀任务,之后可 read 取
--no-wait 只派活,立即返回 sessionId
--json 结构化输出

它是怎么绕过鉴权的

DSH 的 /api 由两层把关:先查「请求来路是否可信」,再查「浏览器会话签名 cookie」。 本机其他进程直接调用会拿到 401,所以以前那套直接 POST /api/session.create 的脚本在 DSH 升级后全部失效了。

delegate.mjs 的做法是:读取 DSH 自己存在 %DSH_HOME%\.credentials.yaml → records.'client-connection/browser-session'.payload.secret 里的会话签名密钥,按 DSH 的算法(v1.<base64url(payload)>.<HMAC-SHA256 签名>)离线生成合法 cookie 再调用接口。

全程在本机完成,不联网、不外发、不修改 DSH 的任何文件。

该密钥随每次 dsh web 重启轮换,工具每次运行自动重取,无需人工处理。

实现要点(改这个工具时要知道)

  • 接口返回的 turnOutline.response 是摘要,长回复会被截断成一句带省略号的预览。取完整回复必须走 session/page 读事件流,从 assistant/message 的 content 里挑 type: 'text' 的段(同一轮取最后一条非空的)。
  • session/page 需要 throughSeq,取自 session/list 里该会话的 projections.asOfSeq。
  • RPC endpoint 是 namespace/method 斜杠格式(session/create),不是点号;body 是 {type:'client-request', rpcId, method, payload:{args:{...}}}。
  • 参数名因方法而异(request / _request / 无参),工具按错误提示自动适配。
  • Windows 上不要用 process.exit() 收尾——会触发 libuv 断言并打印噪音;只设 process.exitCode 让进程自然退出。

排查

现象 处理
401 dsh web 没在跑,或刚重启;确认端口 3080 后重试
404 DSH 升级后接口改名。到 node_modules\@deepseek-ai\dsh\node_modules\@deepseek-ai\*\lib\typert.host.js 里核对 namespace / method
args fields do not match 该方法参数名不是 request。工具已自动适配三种形态,若仍报错按提示里的 missing "X" 补
一直不返回 那轮还没跑完,用 read <sessionId> 看进度

注意

  • 派出去的会话会真实留在会话列表里,目前 DSH 没有删除会话的接口——清理要手动在界面里做,别拿它做试验性乱派。
  • 相关技能:dsh-cross-mode-delegation(告诉 AI 什么情况下该用它)。

测试

node test.mjs     # 语法检查 + 帮助入口冒烟 + 文档与实现一致性(不需要 DSH 在运行)

CI 跑的就是这一条命令,任何 Node ≥18 的机器上都能跑通。 涉及真实派活的命令(run / send / read / sessions / presets / providers)需要 DSH 正在运行, 因此不放进 CI——它们会真的开新会话,而 DSH 目前没有删除会话的接口。

许可

MIT。

About

DSH 命令行工具:跨模式派活 —— 让 AI 开一个换了工具集的独立会话去干活,再把结果取回来。

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages