dsh-tool-call-leak-fix:攔截工具調用泄漏與 turn 靜默失敗

前言

在 DSH(DeepSeek Harness)裏跑帶大段代碼或 HTML 的工具調用時,有時會出現一種很誤導人的現象:界面顯示 turn 已正常完成,實際上沒有任何工具被執行,而 <invoke>、<parameter> 或帶 antml: 前綴的調用標記卻混進了 assistant 正文。Harness 不報錯,agent 循環直接當作 {kind:'completed'} 結束。壞樣本還會留在歷史裏,模型容易繼續模仿同一格式;fork 會把父會話裏的損壞輸出一併繼承。社區裏也有人把這類連鎖失敗叫作 chain reaction。

dsh-tool-call-leak-fix 是維護者 IRwDONE 發佈的工作流類宿主插件(GitHub 倉庫 IRwDONE/dsh-tool-call-leak-fix,npm 包 @irwdone/dsh-tool-call-leak-fix,當前資料中的版本爲 0.5.1,MIT 許可證,零運行時依賴)。它針對「調用標記泄漏爲正文、調用未執行卻 turn 靜默關閉」這一類失敗,在分發前攔截、在同一 turn 內糾偏、fork 時簡報、並在模型可見面上作廢已進入歷史的損壞輸出。下面介紹它解決的問題、機制、安裝方式與配置邊界。

這是什麼

一句話:DSH 宿主插件,把「工具調用沒跑、標記卻進正文、turn 像成功一樣關掉」從靜默 no-op 變成可感知、可糾正的行爲,並在 fork 與上下文回放側儘量切斷壞樣本對後續模型的影響。

維護者 IRwDONE;分類爲工作流;插件在 SkillHub 目錄頁爲 dsh-tool-call-leak-fix。實現爲純 ESM JavaScript,僅使用 Node 內置模塊,不需要額外構建或前端半邊。

故障長什麼樣

README 裏保留了一段真實形態的節選:思考內容裏模型甚至意識到該用 antml: 前綴,但整段調用仍作爲正文輸出,隨後 turn 結束且沒有工具卡。常見形態包括:

  1. V1 結束序列增殖:調用尾部結束標記重複出現。
  2. V2 開場標記缺失:只剩參數開場,沒有外層 invoke 開場。
  3. V3 泄漏爲正文:調用信封混進 assistant 正文,未被識別爲真正工具調用。
  4. V4(相關):容錯 JSON 解析把非法參數降級爲 {},工具帶着空參數執行。

泄漏方言既有裸標籤(<invoke / <parameter),也有 antml: 前綴形式;還有「僞造工具結果」——正文出現結果形標記但該步並未調用工具。三種核心形態都是靜默失敗:不執行、不報錯,turn 正常關閉。

用戶在對話裏讓模型自行修復、僅 fork、或 compact,往往不能從根上去掉歷史裏的壞樣本;README 說明裝上本插件後,fork 之後損壞輸出可在模型可見面上被作廢,後續對話可不再出現同類泄漏型失敗(具體還依賴 M9 等開關,見下文配置)。

核心功能

插件 README 將能力歸納爲多條守衛(平時不主動打擾用戶):

攔截(M2)

工具調用分發前掃描已解析參數。若某字符串參數邊界已損壞(例如尾部結束序列增殖、結構中途截斷),且體量達到閾值(默認 ≥2000 字符或 ≥20 行),則拒絕本次調用並給出可操作說明(如建議拆成 ≤100 行分塊重發)。同時處理「聲明必填卻收到空 {}」的情況。已現場驗證:真實會話中 22 行以上且結構截斷的參數在分發前被拒,目標文件未被創建。

糾偏(M3)

寫入類工具執行後,若結果中有機器可讀的空轉證據(如 noop: true、status: "noop"、written: 0 且確實帶了內容),在結果後補一句短提示,不做自由文本猜測。由配置項 noopCheck 控制總開關。

自愈(M4)

觀察已提交的 assistant 消息:若某步輸出損壞且該步沒有任何工具調用,在 turn 即將關閉時注入糾正,保持 turn 打開、讓模型在同一 turn 內重發。糾正次數有上限,由 maxCorrectionsPerTurn 控制;本 bundle 的 patch 將默認改爲 2,以便「第一次糾正後又寫壞」時還能再給一次更硬的指令。到頂即停,避免循環。已現場驗證 turn 不關閉並繼續的完整鏈條。

fork 簡報(M7)

fork 會話繼承父歷史且歷史本身難以改寫(README 稱凍結請求 D-8)。插件在 fork 的第一個模型步之前注入一次代碼生成的簡報:把歷史裏「沒有對應工具卡的孤立調用標記」標爲損壞、未執行,請模型勿模仿。每個會話只放一次;非 fork 零開銷。由 forkBrief 控制。

上下文修復(M9)

已進入歷史的壞樣本仍會被逐字回放。插件在模型可見 surface 上遮蔽損壞步驟(該步損壞且無工具調用),換成靜態說明(「此處原爲損壞輸出、已作廢,請勿模仿」),日誌原始事件保留,零模型調用。啓用前用自建探針自檢 surfaceOp.replace 語義;自檢失敗則整個會話故障關閉。fork 繼承的損壞步驟可在每會話第一次 turn 結束時一併掃描遮蔽。由 repairContext 控制,設爲 false 可完全停用。

裝上之後的行爲對比(摘要)

以前 現在(插件生效時)
壞調用不執行、不報錯 分發前攔截並說明原因
泄漏後 turn 靜默關閉 turn 保持打開,同 turn 內糾正重發
寫入工具自報成功卻無改動 結果後補空轉提示(M3)
歷史壞樣本持續被模仿 當場機制縮短故障窗口;不能改寫已寫入的歷史(見邊界)

README 明確:刻意不做 system-prompt 規則塊注入,也不做「強制小塊寫入工具」。

安裝與啓用

用 Harness 自帶的插件管理器安裝,不要手改 profile 來「假裝掛上」。三種方式任選其一。

方式 A:在插件市場 / 插件管理器搜索 dsh-tool-call-leak-fix 或 @irwdone/dsh-tool-call-leak-fix,點擊安裝。

方式 B:一條命令安裝時使用 npm 包名或 GitHub 地址(資料原文如下,勿自行拼接其它 install 語法):

@irwdone/dsh-tool-call-leak-fix

或(倉庫需公開):

https://github.com/IRwDONE/dsh-tool-call-leak-fix

方式 C:克隆倉庫後,對 install_bundle 的 target 填倉庫根目錄(含 package.json),不要填到 plugin/ 子目錄。

安裝之後:

  1. install_bundle 返回 application: "applied" 即表示已生效;若提示重啓則重啓 Harness。
  2. 判活:插件管理器列表,或 Config 中出現 include:tool-call-leak-fix;更硬判據是是否真的注入了糾正。
  3. 不要僅通過 grep ~/.dsh/profiles/<profile>/cordis.patch.yml 判斷——bundle 自帶 patch(plugin/cordis.patch.yml,由 package.json 的 dsh.bundle.patch 聲明),該行本就不一定出現在 profile 的 patch 裏。
  4. 停用:管理器禁用,或將該行 config.enabled 設爲 false。

配置

config 會校驗並歸一化;非法值回退默認。數值閾值須爲整數且 ≥1(僅 maxCorrectionsPerTurn 允許 0)。

鍵 默認 含義
enabled true false 時不註冊任何監聽器
maxLines 100 單字符串葉子行數上限(過長預警)
maxChars 20000 單字符串葉子字符數上限
closingTagCount 8 </ 出現次數作「密集」證據,不單獨導致攔截
endSequenceRepeats 2 尾部連續結束序列達到幾個判損壞
maxCorrectionsPerTurn 1 每 turn 最多自愈次數;本 bundle patch 設爲 2
lang zh 注入文案語言:zh / en
noopCheck true M3 空轉檢查總開關
debugLog false 診斷日誌;false 時不寫文件
debugLogPath '' 空串由系統臨時目錄推導
contextGuard false 內部保留、未接線
contextGuardNote '' 內部保留、未接線
forkBrief true M7 fork 首步前簡報
forkBriefNote '' 空串用內置中英文簡報
repairContext true M9 模型可見面遮蔽損壞步驟

典型用法與適用場景

本插件沒有單獨的「業務 API」:安裝並啓用後,守衛在工具分發、turn 關閉、fork 首步、會話 surface 替換等接縫上自動工作。典型適用場景包括:

  • 經常通過 DSH 調用「大段 code / HTML / JSX」類參數的工具,且遇到過 invoke/parameter 標記出現在正文裏。
  • fork 父會話後繼續開發,希望 inherited 歷史裏的損壞調用標記被簡報或 M9 作廢,減少模仿。
  • 需要把靜默 no-op 變成帶原因的攔截或同 turn 重試,而不是誤以爲任務已完成。

注意:

  • 插件以當前 DSH 進程權限運行;安裝前請自行閱讀倉庫源碼與 MIT 許可證,確認可接受其行爲(含 M9 自檢失敗時關閉整個會話等策略)。
  • README「已知邊界」:不能改寫歷史(M5 / D-8);壞樣本「不洗白過去」,只能縮短故障窗口。繞法包括新開會話,或明確讓模型忽略某段損壞內容。
  • M2 攔截、M4 自愈、M7 fork 簡報、M9 上下文修復在 README 中標註爲已現場驗證;做不到的部分以倉庫「已知邊界」爲準。

結尾

dsh-tool-call-leak-fix 把 DSH 裏一類常見的工具調用靜默失敗——標記泄漏、turn 假完成、歷史污染——拆成攔截、同 turn 自愈、fork 簡報與模型可見面作廢四層處理,零依賴、僅依賴 Host 半邊接縫。社區目錄頁:SkillHub · dsh-tool-call-leak-fix。源碼與完整說明:GitHub · IRwDONE/dsh-tool-call-leak-fix。

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

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

小夜