dsh-plugin-loud-failure:把靜默的工具失敗變成響亮的失敗

前言

跑智能體的同行大概都遇到過這類失敗:一次工具調用退出碼是 0,輸出看起來也正常,模型據此繼續往下走,幾步之後才從各種跡象裏拼出真相——最初的調用其實已經失敗了。pandoc 丟一個字形只打警告,PDF 照樣寫出;管道把 Python 的 traceback 捲走,退出碼由 tail 提供;; 鏈讓 command not found 混在一堆正常輸出後面。退出碼說成功,模型讀到成功,錯誤沿下游傳播。

事後翻 session 日誌當然能找到原因,但更好的時機是失敗發生的當下。DSH 的理念是一切皆插件,工具執行鏈上留有 tools/post-execute 這樣的擴展點。本文介紹的 dsh-plugin-loud-failure 就掛在這個點上:在結果送達模型之前匹配警告簽名,把靜默失敗顯式化。

這是什麼

dsh-plugin-loud-failure 是一個 DeepSeek Harness 插件,由 Rhymer-Lcy 維護,MIT 許可證。一句話定位:一個 tools/post-execute 策略,在成功的工具輸出裏匹配警告簽名,命中後阻止該結果或附加一條通知。它不改動任何工具與循環。

版本與依賴寫全:

  • 插件版本 0.1.1;
  • 要求 DeepSeek Harness 0.1.0-rc.6(其中 @deepseek-ai/dsh-tools@deepseek-ai/dsh-llm 固定在 0.1.0-rc.6);
  • Node.js 20+。

作者說明這是唯一測試過的版本,peer 範圍按發佈固定。升級 harness 後,需要留意插件是否跟進發版。

工作原理

核心是一個註冊在 tools/post-execute 的瀑布監聽器,按下面的順序工作:

1、加載時,把內置規則與用戶配置的 rules 合併(與內置規則同 id 的用戶規則就地替換),並編譯所有正則。規則表不可用——非法正則、重複 id、stateful 標誌、空 message——會攜帶違規規則 id 拒絕插件加載。壞配置在啓動時就失敗,而不是等到第一次工具調用。

2、每次 tools/post-execute,把結果的文本塊(可選還包含成功 canonical value 的 JSON)與適用規則匹配。when: success 的規則對已帶失敗標記的輸出保持安靜:非零的 [exit code: N] 行、非零退出碼的 [status: ...] trailer、[sandbox: file access denied ...]。這些模型本來就看得到,不算靜默失敗。

3、任一命中規則的 actionerror 時,監聽器返回 { kind: 'block' }。註冊表將其轉爲 isError 結果:內容以說明頭部開頭,原始輸出原樣保留;canonical value 不復存在,Code Mode 程序也無法消費被污染的值。

4、只有 actioncontext 的規則命中時,監聽器放行,並向決策的 additionalContexts 追加一條 UserMessage 通知,來源爲 { kind: 'plugin', plugin: 'loud-failure', form: 'notice', summary },Web UI 顯示爲摺疊的一行。

5、無命中則 next() 放行。action: off 的規則永不運行。

監聽器通過 ctx.on 註冊,隨插件卸載;配置變更會重載插件並註冊新監聽器。

內置規則覆蓋的靜默失敗

內置規則表全部來自實際觀察到的、藏在成功退出碼後面的失敗:

觀察到的調用 模型看到 實際發生
pandoc ... --pdf-engine=xelatex 打印 Missing character: There is no ₂ in font ... PDF 已寫出,退出碼 0 SpO₂ 的下標被從 PDF 裏默默丟掉
python script.py \| tail -n 20 最後 20 行,退出碼 0 traceback 已滾過,退出狀態由 tail 提供
pandocc in.md -o out.pdf; ls -l out.pdf bash: pandocc: command not found 加一段列表,退出碼 0 什麼都沒構建,退出狀態由 ls 提供
python calc.py 打印 RuntimeWarning: invalid value encountered in divide 一個數組,退出碼 0 數組裏是 nan
PowerShell 5.1 命令加了 2>&1 NativeCommandError$? 爲 false 程序其實退出 0,stderr 被 PowerShell 包裝
Windows 控制檯打印 ��� 文本,退出碼 0 GBK/UTF-8 代碼頁不匹配,文本已損壞

如果你的工作流裏這類場景常見,內置規則開箱即用;命中後要麼得到一個 isError 結果,要麼在下一輪請求裏看到一條通知。

安裝與啓用

下面按從簡到繁給出三種方式。

從 release tarball 安裝

無構建步驟、無需構建授權,命令如下:

dsh plugin --profile web add https://github.com/Rhymer-Lcy/dsh-plugin-loud-failure/releases/download/v0.1.1/dsh-plugin-loud-failure-0.1.1.tgz

安裝後確認配置裏出現了插件層:

dsh --profile web --dump-config

輸出中應能看到一個 # == dsh-plugin-loud-failure 層。

另外,dsh plugin add 打印 @deepseek-ai/* 的 peer 依賴警告屬預期:profile 從 harness 安裝中解析這些包,而不是在插件旁安裝。

從 GitHub 固定 commit 安裝

dsh plugin --profile web add github:Rhymer-Lcy/dsh-plugin-loud-failure#<commit-sha>

git 安裝會拉取源碼,pnpm 需要被允許運行本包的 prepare 腳本(內容是 tsc)。首次 add 會失敗並打印需要允許的完整 key,把它追加到 profile 的 pnpm-workspace.yaml 後重試:

# $DSH_HOME/profiles/web/pnpm-workspace.yaml(key 從 pnpm 的提示裏複製)
allowBuilds:
  "dsh-plugin-loud-failure@https://codeload.github.com/Rhymer-Lcy/dsh-plugin-loud-failure/tar.gz/<commit-sha>": true

從源碼 checkout 直接運行

先構建:

git clone https://github.com/Rhymer-Lcy/dsh-plugin-loud-failure.git
cd dsh-plugin-loud-failure && pnpm install && pnpm run build

然後在 overlay.yml 裏插入一行,指向 lib/index.js

# overlay.yml
- insert:
    - id: loud-failure
      name: /absolute/path/to/dsh-plugin-loud-failure/lib/index.js
dsh web --patch ./overlay.yml

卸載

dsh plugin --profile web remove dsh-plugin-loud-failure

配置

安裝後,bundle 會插入 id: loud-failure 的一行,帶上 schema 默認值。已覈實的配置鍵有兩個:

  • rules:用戶規則數組,默認爲空。與內置規則同 id 就地替換,新 id 按順序追加;兩個用戶規則同 id 會導致加載失敗。
  • shellTools:指定被檢查的工具,默認 [bash, pwsh, job_output]

覆蓋配置時有一個容易踩的坑:patch 替換的是整行 config。如果你在自己的 profile 的 cordis.patch.yml 裏覆蓋 loud-failure 的配置,必須重述所有要保留的鍵。

適用場景與注意事項

適合誰:

  • 工作流裏有大量 shell 類工具調用、被靜默失敗坑過的人,上面六種場景內置規則直接覆蓋;
  • 想把團隊自己的警告簽名沉澱成規則的人:rules 可配置,action 支持 errorcontextoff 三種結果。

使用前注意:

1、版本耦合。要求 DeepSeek Harness 0.1.0-rc.6 與 Node.js 20+,插件僅在該版本測試過。

2、git 安裝的授權要當回事。允許 prepare 腳本,意味着倉庫代碼會在安裝時於任何 agent 沙箱之外運行;務必固定 commit。release tarball 安裝沒有這個環節。

3、插件以當前 dsh 進程的權限運行,安裝任何第三方插件前應先檢查源碼與許可證。本插件許可證爲 MIT,源碼公開在 GitHub。

結語

這個插件的思路很剋制:不改工具、不改循環,只在 tools/post-execute 一個環節上,把退出碼 0 背後的警告簽名變成模型無法忽略的 isError 結果,或者一條可見的通知。對長期跑鏈式工具調用的人來說,它把「幾步之後才發現」提前到「當下就看到」。

  • GitHub 倉庫:https://github.com/Rhymer-Lcy/dsh-plugin-loud-failure
  • 社區目錄頁:https://www.skillhub.cn/plugins/Rhymer-Lcy/dsh-plugin-loud-failure

目錄爲獨立社區站點,與 DeepSeek / 幻方無官方從屬關係。

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

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

小夜