用 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

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

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

小夜