前言¶
在 DeepSeek Harness(DSH)里跑智能体,常见做法是本机一个实例:工单、策略、评估和会话都在同一进程里。当你有多台机器——公司笔记本、宿舍电脑、一台常驻服务器——希望「在一个地方说话、在对应机器的工作区里干活」,而又不想在每台设备上各维护一套账本,就会遇到路由与状态一致性的问题。
下面介绍社区插件 dsh-foreman(维护者 niechao136)。它在服务器侧保留唯一账本(Engine、SQLite、Policy、Tickets、Evals、设备表),通过 Hub 与 Selector 把工单派到远端设备上完整运行的 DSH;设备侧用配套的 dsh-foreman-node 只接单、本地执行并回报,不建工单、不持策略、不打开数据库。项目标注为早期开发中,MIT 许可;不是 DeepSeek 官方产品。
这是什么¶
一句话定位(摘自项目 README):一个常驻的主 loop,把工单派给多台在线设备上各自完整运行的 DSH,账本只有一份。
架构上,服务器跑 dsh-foreman,每台个人机器装 dsh-foreman-node;设备通过 wss 主动连 Hub。本机也可 target.kind === 'local',行为与不接设备时相同。
当前 package 版本为 0.5.1(以仓库 package.json 为准)。运行时要求 Node ^22.19.0 || >=24.0.0,DSH ^0.2.1-alpha.2。
核心功能¶
单账本与双层角色¶
服务器侧集中持有工单、策略与评估;每个项目一条主会话入口,操作者在此对话,主会话负责路由,Worker 在具体工作区目录执行。设备侧插件不承担账本职责。
Selector 与派单时机¶
accept 工单时,prepareTicket 即选定设备并写入 Ticket.target,再由 newAssignment 复制到 Assignment.target——不是 Executor 选型(Executor 没有写库通道)。
- 远端目标:以
assign帧发给对应设备;设备不在线则报blocked,不伪造 failed,也不悄悄改成本机跑。 - 本地目标:交给本机
DshExecutor。
断线不会自动重派(避免同活执行两遍);超时转为 blocked,由人处理。
已落地的模块(项目自述)¶
README 写明:设备注册表、Selector、ForemanExecutor、Hub、回报规则、设备侧插件、文本渲染、迁移脚本、面板设备页、飞书群路由等已实现,测试 1332 项。设计、实现计划与交接见仓库内 docs/superpowers/ 与 HANDOFF.md。
与上游的关系¶
代码以 dsh-superagent-local 为起点,思想来自 DeepSeek Harness 团队的 Super-agent 原型与研究文档;本项目在多设备与迁移方向上做重写与扩展,并对文中未解问题(如 A2A、安全)采用明确取舍,而非声称已全部解决。
安装与启用¶
dsh-foreman 在 npm 上以包名 dsh-foreman 发布,并在 package.json 中声明 dsh.bundle(profile bundle)。安装前请确认本机 pnpm 在 PATH 中;社区插件以当前 DSH 进程权限运行,安装前建议自行审阅源码与许可证。
装入 web profile(常见本机 / 面板场景)¶
生态目录 dsh.works 给出的安装方式为:
dsh plugin --profile web add dsh-foreman
安装或更新 bundle 后需重启对应 profile 的 DSH Web。可用下列命令确认 bundle 层已生效(以你实际使用的 profile 名为准):
dsh --profile web --dump-config
输出中应能看到 dsh-foreman 相关 bundle 层。
独立主 loop 实例(服务器部署示例)¶
若要把主 loop 与原有 DSH 实例隔离(独立 DSH_HOME、profile、端口),仓库 runbook docs/deploy-loop-instance.md 建议在主 loop 所在 profile安装 foreman,不要在同一实例混装 node 包。示例:
export DSH_HOME=/home/ubuntu/.dsh-loop
dsh --profile loop --dump-config > /dev/null
dsh plugin --profile loop add "github:niechao136/dsh-foreman"
验收时,--dump-config 里应只有 dsh-foreman,不应出现 dsh-foreman-node:
dsh --profile loop --dump-config | grep foreman
设备侧¶
被派活的笔记本、宿舍电脑等应安装 dsh-foreman-node(npm 包名 dsh-foreman-node)。设备侧安装命令见 dsh-foreman-node 目录条目(示例:dsh plugin --profile web add dsh-foreman-node)。服务器主 loop 实例上只装 foreman,不装 node。
与本插件相关的配置项(独立实例 runbook)¶
将 examples/profile.cordis.patch.yml 复制到目标 profile 的 cordis.patch.yml 后,runbook 中与 foreman 直接相关的键包括:
- id: dsh-foreman
config:
stateDir: /home/ubuntu/.dsh-loop/state/superagent
hubPort: 8790 # 设备连入的环回端口;0 表示不开 Hub,工单仅本机
hubIdleMs: 600000 # 设备无心跳多久视为 blocked
hubPort 默认只监听 127.0.0.1;对外常配合隧道(如 cloudflared)使用稳定域名。迁机与更多部署细节见 docs/migration.md。
典型用法¶
1. 在主 loop 登记设备¶
runbook 推荐在 Web 面板「设置 › 设备」中登记 id、显示名、可接项目及该机器上的路径,获取 url、deviceId、token(令牌仅展示一次)。
headless 环境可用仓库脚本(路径以 runbook 为准):
cd /path/to/dsh-foreman
export DSH_HOME=/home/ubuntu/.dsh-loop
node scripts/add-device.mjs add --home "$DSH_HOME" --id laptop --name 公司笔记本 --label intranet --root shop='D:\工作\shop'
2. 在设备上配置 node 并连通 Hub¶
在设备 DSH 的「设置 › 插件 › dsh-foreman-node」中配置 SSH 隧道或 wss:// 枢纽地址,填入主 loop 下发的 deviceId 与 token,映射项目路径后保存并重启设备侧 DSH。主 loop 侧无需因登记而重启。
3. 接受工单时的行为预期¶
工单 accept 后,若目标设备离线或超时,状态为 blocked,不会自动改派或静默回落本机。确认设备未在执行后,再由人工重试。
4. 飞书群路由(可选)¶
整台服务器可配置一个飞书机器人,用群区分项目;Policy 中 routing.chats 可同时约束工作区与设备 labels,Selector 只选带匹配标签的设备,选不到则 blocked。示例结构见 runbook 中的 JSON 片段。
适用场景与注意¶
适合谁: 需要在多台机器上保留各自工作区与执行环境,又希望工单、策略、评估与主会话入口集中在一台(或一组)主 loop 上的 DSH 用户;需求主要来自本机操作者主会话,而非仅 GitHub/飞书触发(虽也支持飞书群路由等能力)。
注意事项:
- 项目处于早期开发,API 与部署方式可能变动;重大部署前阅读
HANDOFF.md与设计文档。 - 同一 DSH 实例不宜同时装 foreman 与 foreman-node 作为主 loop 验收标准所描述的那样混用;多实例应使用不同
DSH_HOME。 - 插件与 node 均为第三方代码,安装即在本机执行;请核对 MIT 许可与仓库源码。
- SkillHub、dsh.works 等目录为社区站点,与 DeepSeek / 幻方无官方从属关系;星标在目录快照中可能为 0,不代表质量结论。
结尾¶
dsh-foreman 把「一个主 loop、一份账本、多台 Worker」落到可部署的 bundle:派单在 accept 时写入 target,远端不在线则明确 blocked,断线不重派。若你要从单机构型扩展到多设备协同,可从 npm 或 GitHub 安装 foreman,再按 runbook 配 Hub 与设备表。