用 dsh-stall-guard 给 DeepSeek Harness 装上任务看门狗

前言

把长任务交给 DeepSeek Harness(DSH)跑的时候,最难判断的往往不是「慢」,而是「还在不在动」。一次编译可能要十分钟,一次长文本生成也可能一直没有新的界面反馈;与此同时,LLM 请求挂起、工具调用空等、循环空转,看起来同样像卡住。如果看门狗只按墙钟时间杀任务,长操作会被误伤;如果完全不管,会话又会在真静默里耗下去。

dsh-stall-guard 要解决的就是这件事:跟踪每个会话的最后活动时间和在飞操作,只有「运行中、没有任何事件、也没有任何在飞调用」才判定为真卡死,然后用「排查 → 修复 → 换方向」的阶梯消息把 Agent 推回去。仓库 README 把这一点写得很死:全程不终止任何任务

本文按插件目录页、GitHub 仓库 README、package.jsonlib/index.js 交叉核对后整理:它是什么、怎么判定卡住、如何安装配置,以及查看状态时该看哪些文件。

这是什么

dsh-stall-guard 是一款面向 DeepSeek Harness 的任务看门狗插件,由 GitHub 用户 akira399 维护,仓库地址是 akira399/dsh-stall-guard。社区目录把它归在「会话与消息」分类,许可证为 MIT,主要语言是 JavaScript。写作时(2026-08-18)GitHub 显示 3 颗星,package.json 版本为 1.3.0,要求 Node.js >=20,零 npm 依赖。

它解决的不是「给 Agent 加一个停止按钮」,而是这三类现场:

  • 会话显示 running,但长时间既没有 turn/step/tool/LLM 事件,也没有在飞操作
  • 长构建、长生成这类「看起来很久、其实还在干活」的任务,不能被当成卡死
  • 真静默发生后,需要可复现的引导,而不是直接掐掉当前任务

DeepSeek Harness 官方仓库的定位是「一切皆插件」:模型、工具、会话、循环等能力都由插件组合。dsh-stall-guard 走的是社区插件这条路,收录在独立站点 DeepSeek Harness 插件库;该目录与 DeepSeek / 幻方没有官方从属关系,安装前应把它当成第三方源码来审查。

需要提前说清一处文案差异:目录页的一句话简介仍写「只在真正静默时轻推或终止」。对照仓库 README、package.json 描述和 1.3.0 源码,当前实现没有 terminate 选项,也不会发出终止指令;状态字段里虽然还留着 terminated,注释写明只是兼容保留、不会再被置位。下文以仓库一手资料为准。

核心功能

监控 → 判断 → 继续 / 修复 / 换方向

插件挂上 agent/statussession/event,为每个会话维护「最后活动时间」和「在飞操作计数」。周期扫描的间隔由 checkIntervalMs 控制(默认 5 秒)。判定逻辑可以压成一张表:

任务情况 判定 行为
持续有事件(步骤 / 工具 / LLM 流在动) 推进中 不干预;任何活动都会把阶梯重置回第 1 级
单个长操作在飞(如 10 分钟构建、长文本生成) 推进中(busy > 0 不引导;超过 busyTimeoutMs 只记一条 LONG_RUNNING
无事件 + 无在飞,静默超过 stallThresholdMs 真卡死 阶梯式引导:诊断 → 修复 → 换方向循环

默认真静默阈值是 120000 ms(2 分钟)。在飞观察窗口默认 600000 ms(10 分钟);把 busyTimeoutMs 设为 0 可以关掉 LONG_RUNNING 记录,但不会因此开始引导——有操作在飞时,源码直接 return

三级阶梯,只注入消息

policy 默认是 auto。真静默确认后,插件通过会话的合法通道注入一条 user/message,按冷却间隔(默认 30 秒)升级:

  1. 第 1 级 DIAGNOSED(排查):请 Agent 说明自己在等什么、是否有操作失败或挂起。
  2. 第 2 级 FIXING(修复):请它针对卡点重试、完成挂起调用或修好出错步骤,然后继续。
  3. 第 3 级及以后 REDIRECTING(换方向):请它放弃当前方法、改用替代方案,并保留已完成成果。第 3 级之后按同一冷却间隔循环,没有终止档。

默认文案写在 lib/index.js 里,每条都会再附一行看门狗自己的诊断,格式类似:

[看门狗诊断] 最后活动:tool/call;位置:第 2 轮第 5 步;已静默 125000ms。

如果只想记日志、不向 Agent 说话,把 policy 改成 report 即可。

在飞豁免与运行状态

「有操作在飞 = 推进中」靠事件对来计数:

  • tool/calltool/code-dispatchtool-workflow/run-startrequest/headerbusy + 1
  • tool/resulttool-workflow/run-endassistant/messagebusy - 1(不会减到 0 以下)
  • step/endturn/end:把 busy 清零,避免计数漂移

运行中状态由 turn/start / turn/end 驱动,同时也监听 agent/status。README 特别写了:即使错过 agent/status,turn 一打开就会开始监视。覆盖的无进展场景包括 LLM 调用挂起、工具调用挂起、循环空转。

还有一条设计边界必须知道:如果 Agent 卡在一个永不返回的 await 上,注入的消息会排队到该步骤结束后才被处理。插件此时不会杀任务,只会按冷却继续下一级引导。

事件落盘和状态接口

每次检测或引导都会追加到 $DSH_HOME/stall-guard/events.jsonl(未设置 DSH_HOME 时等价于 ~/.dsh/stall-guard/events.jsonl)。事件类型只有:

  • STALL:真静默检测(默认每 60 秒最多记一次,避免刷屏)
  • LONG_RUNNING:在飞过久,仅记录
  • DIAGNOSED / FIXING / REDIRECTING:阶梯注入是否成功

README 强调:永远没有终止类事件。若本机开了 Web UI,还可以查实时状态:

GET http://127.0.0.1:3080/api/dsh-stall-guard/status

返回当前配置、各会话的 ladderStage、以及最近 50 条事件。GUI 通知在 README 里被标成后续增强,当前版本没有这一项。

安装与启用

目录页给出的安装命令如下,在 DeepSeek Harness 终端里运行即可:

dsh plugin add github:akira399/dsh-stall-guard

如需可复现安装,按目录页说明固定 commit。写作时 main 分支最新提交是 db5b2147ccd60c0a0f9305f12402fb84491e919d(对应 1.3.0):

dsh plugin add github:akira399/dsh-stall-guard#db5b2147ccd60c0a0f9305f12402fb84491e919d

仓库 README 另给了一条带 profile 的写法,适合用 npx 拉 CLI、并明确装进 web profile 的场景:

npx -p @deepseek-ai/dsh dsh plugin --profile web add github:akira399/dsh-stall-guard

安装后需要重启 DSHcordis.patch.yml 会把插件插入当前 profile 的组合配置,默认启用(opt-out)。修改 settings.yamlstall-guard 段之后热生效,不必再重启。

目录页的安全提示同样适用:插件以当前 dsh 进程的权限运行,安装时可能执行代码。安装前请检查源代码仓库和许可证。

典型用法

1. 使用默认阈值,只在真静默时引导

装好并重启后,默认配置已经是「开着、2 分钟真静默、auto 阶梯」。适合大多数「偶尔会挂、但不希望长任务被碰」的编码 Agent。你不需要先写配置;只要会话处于 running,插件就会从 turn 打开开始监视。

2. 把静默阈值改短,并确认是 auto 策略

如果本地任务通常几分钟内就会有工具回包,可以把阈值改到 60 秒,扫描间隔改到 3 秒。仓库 README 给的示例是:

stall-guard:
  stallThresholdMs: 60000
  checkIntervalMs: 3000
  policy: auto

保存后配置热生效。想先观察、不注入消息时,把 policy 改成 report

3. 看日志,确认引导而不是误杀

真静默发生后,打开事件文件,确认出现的是 STALL 和阶梯事件,而不是对长操作动手:

tail -n 20 ~/.dsh/stall-guard/events.jsonl

同时请求状态接口,核对 busyidleMsladderStage

curl -s http://127.0.0.1:3080/api/dsh-stall-guard/status

如果某次构建已经跑了很久,但 busy > 0,状态里不应出现阶梯升级,日志里最多只有 LONG_RUNNING。这就是 README 说的:「任务执行时间长」不等于「卡住」。

4. 自定义三级文案(可选)

diagnoseMessagefixMessageredirectMessage 都可以改。留空或不写时,源码会回退到内置中文默认句。每条仍会自动拼接 [看门狗诊断] 那一行,自定义文案不用自己拼现场信息。

仓库提供了自检命令,覆盖语法、默认配置、在飞豁免、阶梯循环不终止、活动重置阶梯、STALL 节流和状态路由等:

pnpm verify

适用场景与注意事项

适合:

  • 经常把编译、测试、长生成交给 DSH,又担心会话在无事件时悄悄停住
  • 需要一份可审计的卡顿记录(JSONL + 状态接口),而不是只看聊天窗口
  • 希望干预手段仅限于「给 Agent 再写一句话」,不要由插件结束任务

需要注意:

  1. 插件以当前 dsh 进程权限运行,安装时可能执行代码。使用前阅读 akira399/dsh-stall-guard 源码和 MIT 许可证;生产环境建议固定 commit。
  2. 它不是硬中止。卡在永不返回的 await 时,消息会排队;此时仍要靠宿主界面的停止能力或人工介入。
  3. 在飞计数依赖特定事件类型。若某个工具或工作流不走 README 列出的那几对事件,busy 可能不准,表现为该豁免或不该豁免。
  4. Web 状态路由依赖 webServer 服务;没有 Web UI 时,仍可看 events.jsonl 和插件日志。
  5. 社区目录不是官方应用商店。DSH 仍处于开发者预览,核心 API 会继续变,插件行为以当时安装的 commit 为准。

结尾

dsh-stall-guard 把「慢」和「死」拆开:有事件或有在飞操作就当作推进中;只有真静默才按排查、修复、换方向循环轻推,并且把每次判定写进日志。对长时间跑任务、又不想被看门狗误杀的 DSH 用户,这是一套边界写得很清楚的社区方案。

目录页:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-stall-guard/

GitHub:https://github.com/akira399/dsh-stall-guard

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

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

小夜