用 dsh-tool-diff 給 DeepSeek Harness 裝上結構化差異比較

前言

智能體要對比兩份內容時,常見路徑是起一個 bash 進程去調系統 diff,或者自己寫一段比較邏輯。配置片段、API 響應、表格、文檔修訂都經常碰到這件事。系統 diff 只看整段文本:JSON 裏改了 $.user.name,輸出往往是大塊加減行,看不出路徑;CSV 引號裏的逗號、Markdown 標題改名,手寫比較又容易漏。Windows 上每次起進程的開銷也更明顯。

DeepSeek Harness(dsh)把模型、工具、會話和界面都做成插件,官方倉庫的說法是 Everything is a Plugin(一切皆插件)。社區因此補了一批給模型調用的確定性工具。dsh-tool-diff 做的事情很具體:在進程內對文本、JSON、CSV、Markdown 做結構化比較,輸出 unified diff 或帶路徑的變更列表,不讀盤、不寫盤、不聯網。

需要先分清來源。DeepSeek Harness 本體在 deepseek-ai/deepseek-harnessdeepseek-harness-plugin.com 是獨立的社區插件目錄,About 頁寫明與 DeepSeek / 幻方沒有官方從屬關係,不能當成官方應用商店。本文按目錄詳情頁、GitHub 倉庫 README / package.json / LICENSE,以及官方 Harness 倉庫交叉覈對,覈實日期爲 2026-08-18

這是什麼

dsh-tool-diff 是一款「工具與能力」插件,由 GitHub 組織 omdsh-dev 維護,源碼在 omdsh-dev/dsh-tool-diff,許可證 MIT,主要語言 TypeScript。查閱時目錄頁與 GitHub 均顯示 4 星;package.json 裏的包名是 @deepseek-ai/dsh-tool-diff,版本 0.0.1,並標了 "private": true,安裝走 GitHub 源,不是公開 npm 包。engines 要求 Node.js ^22.19.0 || >=24.0.0

它向模型註冊名爲 diff 的工具,profile 裏的 row id 是 tool-diff。輸入是兩段字符串 before / after,按 action 走不同比較器,統一吐出一段 JSON 文本信封。倉庫 README 把定位寫成:零依賴、純函數、只讀。

它要解決的是這三類麻煩:

  • 不要爲一次比較再起系統進程
  • 讓 JSON / CSV / Markdown 的變更落到路徑或行列上,而不只是整段文本 diff
  • 比較邏輯可復現、有邊界:輸入超限直接報錯,輸出超限截斷並置 truncated

README 寫明已在 @deepseek-ai/dsh@0.1.0-rc.6 的隔離 consumer 裏做過全鏈路驗證:配置 dump 能看到該插件 row,工具能註冊並執行。這是倉庫自己的驗證記錄,不是第三方評測。

核心功能

安裝後只有一個工具:diff。用 action 區分五種比較,所有 action 的信封都帶 { equal, truncated, beforeBytes, afterBytes, changes }

action 作用 輸出要點
text 行級 Myers diff 默認 unified diff(--- before / +++ after / @@ hunk,無時間戳)加統計;format=structured 則給帶行號的操作列表
json 遞歸比較兩個 JSON 值 $ 路徑化變更,如 $.user.name$.items[0]$['a.b'],並彙總 add / remove / replace
csv 按 RFC 4180 解析後再比 addedRows / removedRows / changedRows(列級)/ duplicateKeys / 列集合變化
markdown 輕量塊級 tokenizer headingChanges(含 rename)/ blockChanges(如 h2[1]/p[0])/ codeBlockChanges,外加全文 diff
patch 生成 unified diff 並在內存中校驗 patch 文本 + valid / hunks / targetMatchesAfter / hunk 級錯誤

常用參數如下,均來自倉庫 README:

  • before / after:兩側內容,任意 action 都要給
  • formatunified(text / patch 默認)、structured(json / csv / markdown 默認)、both
  • context:unified 上下文行數,默認 3,範圍 0..20
  • key:CSV 主鍵列名或從 1 起的列號;不給就按行號位置比較
  • delimiter:CSV 分隔符,默認 ,,也可寫 tab
  • ignoreWhitespace / ignoreCase:比較時忽略空白或大小寫;patch 會拒絕這兩個選項,因爲補丁必須是精確文本協議
  • sortKeys:JSON 鍵排序,默認 true,讓變更列表穩定
  • maxChanges:最多報告多少條變更,默認 1000,硬頂 10000

安全模型是這條插件的重點,README 寫得很死:

  • 零依賴:Myers 行級 diff、RFC 4180 解析、JSON 遞歸比較都是手寫實現,不拉第三方比較庫
  • 只讀:不讀文件、不寫文件、不聯網、不調 git;patch 只在內存裏生成並校驗補丁,絕不落盤
  • 預算:單側輸入 ≤ 256 KiB(超限直接報錯);輸出 ≤ 64 KiB(超限按 maxChanges 和字節預算截斷,並置 truncated);行數 ≤ 50K;JSON 嵌套 ≤ 64 層;CSV ≤ 50K 行 / 512 列;timeoutMs: 2000
  • Myers 還有 diagonal 預算 2000、蛇步總預算 2000 萬、公共前後綴修剪和 4000 行規模上限,避免惡意重複或全異文本把進程拖死
  • 工具參數會記入會話日誌,不要把密鑰、token 這類敏感數據當作 before / after 傳進去

設計上還有幾條邊界,用的時候會對上輸出:

  • CSV 給了 key 且有表頭,就按主鍵比,行順序無關;否則按數據行號。兩側重複 key 都進 duplicateKeys,且 equal=false,這些行不參與匹配
  • JSON 在 JSON.parse 前先做非遞歸括號掃描,超過 64 層直接報錯;重複鍵由狀態機掃出來,寫進 duplicateKeys.before/after,不會靜默丟掉
  • Markdown 按塊類型做 Myers:同型塊內容變化是 replace,結構增刪是 add/remove;同路徑同級別標題文本變化記爲 rename
  • patchequal 只表示兩側在精確行和末尾換行語義下相等,和 valid 無關;valid 只表示生成的 patch 能從 before 應用到 after。補丁被截斷時是 valid:falsepatchComplete:false
  • 入口會拒絕孤立 surrogate,報 invalid Unicode
  • unified diff 不帶時間戳,方便復現

倉庫 README 寫明測試用 vitest,當前有 124 個用例。peer 依賴是 @deepseek-ai/cordis ^4.0.1@deepseek-ai/dsh-tools@deepseek-ai/dsh-invariants>=0.0.1-rc.1 <0.2.0),由 profile 的 profiles/node_modules 回退安裝提供,插件自身不再依賴未加 scope 的 cordis

安裝與啓用

目錄頁給出的安裝命令如下,在 DeepSeek Harness 終端裏運行即可:

dsh plugin add github:omdsh-dev/dsh-tool-diff

目錄頁同時寫了:插件以當前 dsh 進程的權限運行,安裝時可能執行代碼。安裝前請檢查源代碼倉庫和許可證;需要可復現安裝時,固定 commit 哈希。寫法是把 #commit 換成倉庫裏的完整哈希。查閱時 main 最新提交是 73c142e262275c5a278dc31e80bac7966fba168e(2026-08-14):

dsh plugin add github:omdsh-dev/dsh-tool-diff#73c142e262275c5a278dc31e80bac7966fba168e

倉庫 README 推薦按 profile 安裝。web 是交互式界面,headless 給 dsh run 用,兩者互不覆蓋:

# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-diff

# 一次性任務(headless)profile —— dsh run 默認使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-diff

也可以先 npm pack 再裝本地 tarball:

git clone https://github.com/omdsh-dev/dsh-tool-diff
cd dsh-tool-diff
npm install && npm pack
dsh plugin --profile web add ./deepseek-ai-dsh-tool-diff-*.tgz
dsh plugin --profile headless add ./deepseek-ai-dsh-tool-diff-*.tgz

包內 dsh.bundle.patch(對應倉庫裏的 cordis.patch.yml)會在安裝後把插件插入 profile 的 layer stack,id 爲 tool-diff。Windows 路徑要用正斜槓,例如 C:/...

驗證安裝:

dsh --profile web --dump-config | grep tool-diff

README 給的運行驗證句是:

dsh run "使用 diff 工具對比兩段文本"

注意:dsh run 默認走 headless。只裝了 web、沒裝 headless 時,這條命令看不到工具。README 還提示啓動用 npx -p @deepseek-ai/dsh@0.1.0-rc.6 dsh web,不要 npm install -g 全局安裝。手動改 profile 層、本地 junction / symlink 只適用於源碼貢獻或舊 snapshot,日常安裝用上面的 bundle 即可。

典型用法

裝好之後,模型調用 diff,把 actionbeforeafter 傳進去。倉庫沒有再給一套逐步點擊的界面教程,下面的輸出和驗證句都直接來自 README。

1. JSON 路徑級變更

action=json 時,默認 format=structured。README 的示例信封如下:

{"kind":"json","equal":false,"beforeBytes":42,"afterBytes":58,"changes":[
  {"op":"replace","path":"$.tags[1]","before":"b","after":"c"},
  {"op":"add","path":"$.user.email","after":"b@x.com"},
  {"op":"replace","path":"$.user.name","before":"Alice","after":"Bob"}],
 "summary":{"added":1,"removed":0,"replaced":2,"moved":0}}

對照這份輸出可以讀出三件事:$.tags 數組第 1 項從 b 換成 c$.user 下新增 emailname 從 Alice 換成 Bob。系統 diff 通常只會給你前後兩段 JSON 的行級加減,不會給出這些路徑。

sortKeys 默認打開,同一組變更的列表順序穩定,方便寫斷言或把結果再交給後續步驟。

2. 文本 unified diff

action=text 默認 format=unified。輸出是標準 unified diff,文件頭固定寫成 --- before / +++ after,hunk 帶 @@,沒有時間戳。需要給模型看「第幾行發生了什麼」時,把 format 改成 structured。上下文行數用 context 控制,默認 3 行。

只關心邏輯是否相同、空格和大小寫可以忽略時,打開 ignoreWhitespaceignoreCase。這兩個開關對 text / csv / markdown 有效;patch 會拒絕,不要混用。

3. CSV、Markdown 和內存補丁

表格對齊用 action=csv。有穩定主鍵(例如 id 列)時把 key 設成列名,行被打亂也能對上;沒有主鍵就按行號比。分隔符不是逗號時改 delimiter,製表符寫 tab

文檔修訂用 action=markdown。它先按標題、代碼塊、列表、引用、表格切成塊,再做塊級 Myers:標題改名會進 headingChanges 的 rename,代碼塊的語言、行數或內容變化進 codeBlockChanges

需要一張能從 before 應用到 after 的補丁、但又不想改磁盤文件時,用 action=patch。返回值裏看 validhunks;被輸出預算截斷時不要拿這份 patch 當真補丁。README 明確寫了:補丁只在內存中生成和校驗,不會落盤,也不會調用 git。

日常冒煙可以用倉庫給的這一句,確認工具已註冊:

dsh run "使用 diff 工具對比兩段文本"

適用場景與注意事項

適合這些情況:

  • 智能體要對比配置片段、API 響應、CSV 導出或 Markdown 文檔,需要路徑 / 行列級變更,而不是整段文本 diff
  • 希望比較發生在 dsh 進程內,不額外起 diff / git 子進程
  • 需要 unified diff 或內存中的 patch 校驗,但不允許插件改工作區文件

使用時注意下面幾條,都來自目錄頁或倉庫 README,不是額外發揮:

  1. 先看源碼和許可證再裝。 目錄頁寫明:插件以當前 dsh 進程的權限運行,安裝時可能執行代碼。本插件自稱只讀,仍應按第三方代碼對待。
  2. 社區目錄不等於官方商店。 deepseek-harness-plugin.com 是獨立站點,與 DeepSeek / 幻方無從屬關係。
  3. web 和 headless 要分別裝。 只給 web 裝,dsh run 默認的 headless profile 裏沒有這個工具。
  4. 輸入輸出都有硬頂。 單側超過 256 KiB 會直接失敗;輸出超過 64 KiB 會截斷。大文件應先自己切片,不要指望一次塞進工具。
  5. 不要傳入敏感數據。 參數會進會話日誌。
  6. patch 不是落盤補丁工具。 它不寫文件、不調 git;ignoreWhitespace / ignoreCase 也不能用在 patch 上。
  7. 運行時版本。 README 驗證線是 @deepseek-ai/dsh@0.1.0-rc.6package.json 要求 Node.js 22.19+ 或 24+。更舊的 snapshot 可能要走倉庫說的手動安裝路徑。
  8. 包名帶 @deepseek-ai/,並不表示官方插件。 這是社區倉庫 omdsh-dev/dsh-tool-diff 的 npm 包名,且 private: true

小結

dsh-tool-diff 給 DeepSeek Harness 註冊了一個只讀的 diff 工具:文本走 Myers 行級比較,JSON 給出 $ 路徑,CSV 按主鍵或位置對齊,Markdown 按塊對齊,需要時再在內存裏生成並校驗 unified patch。比較邏輯零依賴、有輸入輸出預算,不碰磁盤和網絡。對經常讓智能體覈對配置、接口返回和文檔修訂的人來說,它補的是「系統 diff 看不懂結構、手寫比較又難驗證」這一截。

目錄頁與源碼:

  • 插件目錄:https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-tool-diff/
  • GitHub 倉庫:https://github.com/omdsh-dev/dsh-tool-diff
  • DeepSeek Harness 官方倉庫:https://github.com/deepseek-ai/deepseek-harness
羽毛球分组比赛记分
小程序二维码

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

小夜