前言¶
在 DeepSeek Harness(dsh)裏跑長任務時,常見一種現象:界面上的 turn 一直顯示 running,日誌和輸出裏卻沒有任何報錯。模型側有流式 idle 超時(DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000,由 idleWatchdog 按 chunk 重載),因此「長時間無輸出」往往指向工具調用卡住,而不是模型卡住。社區討論 #7339 描述的就是這類 long-horizon 任務靜默掛起。
根因之一在於工具定義:ToolDefinition.timeoutMs 是可選字段,說明爲「Cooperative tool-call timeout budget in milliseconds. Omit for no deadline」。核心策略包 @deepseek-ai/dsh-tool-call-timeout-policy 在 timeoutMs === undefined 時直接 return next(),不會掛定時器、不會發信號、也不會寫診斷。在 dsh v0.1.6-alpha.2 中,調用 defineTool( 的 40 個非測試源文件裏,有 26 個完全沒有 timeoutMs,其中包括 tool-subagent、tool-terminal、mcp-resources 以及若干 fs 與工作流相關工具——恰恰是委託子進程、跨網絡 MCP 等容易長時間阻塞的路徑。
下面介紹社區 Cordis 插件 @argszero/cordis-plugin-tool-deadline-guard(GitHub:argszero/cordis-plugin-tool-deadline-guard),它在 tools/execute 與 tools/pre-execute 瀑布上爲「未自行聲明 deadline」的調用補上可配置的部署級預算,超時後把靜默掛起變成模型可見的結構化錯誤,便於重試或改策略。
這是什麼¶
@argszero/cordis-plugin-tool-deadline-guard 由維護者 argszero 發佈,分類屬於 DSH 生態中的工作流向插件(SkillHub 目錄:argszero/cordis-plugin-tool-deadline-guard)。它不替換工具自身實現的 timeoutMs,而是在 harness 未武裝任何 deadline 時爲工具執行體與派發前階段分別計時;到期則返回插件自有錯誤碼,與核心策略的 TOOL_TIMEOUT 區分開,便於區分「工具聲明瞭預算卻超時」與「部署策略補上的預算超時」。
核心功能¶
執行體階段(tools/execute)¶
插件掛在與核心 timeout policy 相同的公開 seam tools/execute 上。對每個 dispatch:
- 通過
ctx.tools.get(exec.name, exec.agent)解析工具定義,決定是否武裝 deadline;未知工具仍由 registry 處理(UNKNOWN_TOOL)。 - 武裝一個 timer 與一個
AbortController,經exec.signal向工具提供AbortSignal.any([caller, own]),與核心 policy 的做法一致。 - 在
finally中恢復調用方 signal,避免後續 wrapper 看到本 mount 可能已 abort 的 signal。 - 僅當本 mount 的 timer 先觸發時才替換結果;在預算內正常結束則原樣返回工具結果,不二次 dispatch。
- 超時結果形態爲
isError: true,且error.info.code === 'TOOL_DEADLINE_EXCEEDED'(非核心的TOOL_TIMEOUT),模型側可據此行動。README 中的示例如:對subagent的調用在超過600000ms且工具未聲明timeoutMs時,返回明確說明 deadline 來源的錯誤文本。
默認情況下,凡未在工具定義裏寫 timeoutMs 的調用,會被 bound 在 10 分鐘(600000 ms);已聲明 timeoutMs 的工具在默認 applyTo: undeclared 下仍交給核心 policy,本插件不改動。
派發前階段(tools/pre-execute,0.2.0)¶
timeoutMs 只約束工具體;tools/pre-execute 瀑布在覈心 tools/execute wrapper 之前完成。若某 listener 在此階段 await 無界工作,整個 session 的工具調用都會堵在後面,而只掛在 tools/execute 上的 deadline structurally 看不到該階段。README 以 @deepseek-ai/dsh-workspace-changes 在 pre-execute 中等待 turn recorder 快照隊列爲例,並指向討論 #9515。
0.2.0 起,同一插件也掛載 tools/pre-execute。該階段超時使用不同錯誤碼 TOOL_PRE_EXECUTE_DEADLINE_EXCEEDED,形態爲 deny(調用未被 dispatch),與執行體超時區分:便於判斷是「跑太久」還是「根本沒跑起來」。
配置項¶
無配置時:對所有未聲明 timeoutMs 的工具使用 10 分鐘默認預算,其餘調用原樣放行。
| field | default | meaning |
|---|---|---|
mode |
auto |
auto 武裝 deadline;observe 只報告將會 bound 的內容並原樣 dispatch;off 不註冊 |
defaultTimeoutMs |
600000 |
未聲明 timeout 的工具的預算(10 分鐘) |
perTool |
{} |
按解析後的工具名覆蓋預算,優先於 defaultTimeoutMs |
exempt |
[] |
永不 bound 的工具名 |
applyTo |
undeclared |
undeclared 不碰已聲明 timeoutMs 的工具;all 對所有已知工具 bound |
onExpiry |
cooperative |
到期行爲;README 指向 Honest limits 小節 |
preExecute |
true |
是否 bound 派發前階段 |
preExecuteTimeoutMs |
defaultTimeoutMs |
派發前階段預算 |
warnLimit |
5 |
每個 mount 發出的診斷條數;0 關閉 |
預算須爲正有限數且 ≤ 2147483647(setTimeout 飽和上限);更大值會立即觸發,因此「無 deadline」應通過 exempt 或 mode: off 表達,而非設極大數值。
安裝與啓用¶
先在項目中安裝 npm 包(版本以 registry 爲準;package.json 中當前爲 0.2.0):
npm install @argszero/cordis-plugin-tool-deadline-guard
在 cordis.yml 或 profile bundle 中增加一行(也可合併包內自帶的 cordis.patch.yml,內容等價):
- insert:
- id: tool-deadline-guard
name: '@argszero/cordis-plugin-tool-deadline-guard'
安裝後無需額外配置即可生效:未聲明 timeoutMs 的工具默認 10 分鐘上限。需要更長或更短等待時,在 Cordis 插件配置裏調整 defaultTimeoutMs 或 perTool;對必須允許長時間阻塞的工具(例如特定 MCP),將其名加入 exempt。
上線前可用 mode: observe 觀察本 mount 將會 bound 哪些調用,確認名單後再切回 auto。
典型用法示例¶
僅收緊 subagent 與 terminal,其餘仍用默認 10 分鐘:
在插件實例上配置(字段名以 README 爲準):
defaultTimeoutMs: 600000
perTool:
subagent: 900000
terminal: 300000
exempt:
- ask-user
關閉派發前階段 bound(只 guard 執行體):
preExecute: false
對某第三方 MCP 工具完全豁免:
exempt:
- mcp_some_server_long_poll
超時後模型會看到類似 README 中的 tool_result [error],其中說明 exceeded 的毫秒數與 deadline 來自 tool-deadline-guard mount,而不是工具自帶的 timeoutMs。
適用場景與注意¶
適合誰: 在生產或長時間自動化任務中使用 dsh,且依賴 subagent、終端、MCP、工作流類工具;希望 turn 不會因單個 wedged 調用無限 running,又需要與核心 TOOL_TIMEOUT 區分運維語義(部署策略 vs 工具自聲明預算)的團隊。
協作式默認: onExpiry 默認爲 cooperative;README 強調插件不會強行拋棄工具本身不願結束的調用,並在可選 replace 模式下明確說明限制。需要更激進行爲時應閱讀 README 的 Honest limits。
權限與安全: 插件隨當前 dsh 進程權限運行,掛載在 harness 公開 waterfall 上,不單獨降權。安裝前請閱讀 GitHub 倉庫 源碼與 MIT 許可證,確認與您的合規要求一致。peer 依賴範圍在 package 說明中審計爲 dsh 0.1.2-rc.1 至 0.2.1-alpha.2 的 npm/pnpm prerelease 讀法;與您實際 dsh 版本不匹配時應在測試環境驗證。
生態說明: DSH 採用「一切皆插件」的 Cordis 組合方式;SkillHub 等社區目錄獨立於 DeepSeek / 幻方,並非官方應用商店。本插件星標數爲 0(截至目錄抓取),選用時以 README 與 issue 跟蹤維護狀態即可。
結尾¶
tool-deadline-guard 解決的是 harness 對「未聲明 timeoutMs」工具默認不設 deadline 的空白:把靜默 wedged 的工具調用轉成 TOOL_DEADLINE_EXCEEDED 或 TOOL_PRE_EXECUTE_DEADLINE_EXCEEDED,讓模型和運維都能看見原因。目錄頁:https://www.skillhub.cn/plugins/argszero/cordis-plugin-tool-deadline-guard;源碼與完整配置說明:https://github.com/argszero/cordis-plugin-tool-deadline-guard。