前言¶
在 DeepSeek Harness(DSH)裏跑編碼 Agent,文件編輯往往是 token 消耗和出錯的重災區。常見的 str_replace 或按行號定位,要求模型在輸出裏逐字複述要被替換的舊代碼——這部分是輸出 token,計費通常是輸入的約 5–6 倍。上方多插入一行,下方行號整體偏移,改錯行的風險隨之上升,且工具側往往缺少「這段範圍是否就是模型剛纔看到的內容」的校驗。
下面介紹 dsh-better-edit(維護者 Rianico)。它爲 DSH 提供基於內容哈希(hashline)的 read、edit、undo_last_edit 工具:每行分配一個 3 字符哈希作爲地址,編輯時只傳起止哈希和替換文本,不回顯舊內容;範圍在寫入前對照模型已讀狀態校驗,過期或未見行直接拒絕並回傳新錨點。項目採用 MIT 許可證,npm 當前版本爲 0.4.0,GitHub 約 15 stars。
這是什麼¶
dsh-better-edit 是 DSH 的客戶端插件,分類爲「客戶端」。它通過 cordis.patch.yml 掛載到 DSH 運行時,在 agent/session-start 時將 hashline 版 read/edit 註冊到 agent 作用域,從而替換 preset 內置的同名工具,並保留內置 write。
與按行號或全文搜索替換不同,hashline 把每一行當作內容尋址:哈希由行內容推導,上方編輯不會使下方未改動行的錨點失效。插件在 SkillHub 社區目錄(skillhub.cn/plugins/Rianico/dsh-better-edit)可檢索;該目錄爲獨立社區站點,與 DeepSeek / 幻方無官方從屬關係。
核心功能¶
三個工具¶
| 工具 | 作用 |
|---|---|
read |
以 HASH│內容 返回文件,支持 offset(1 起始)、limit 分頁 |
edit |
按 remove_from / remove_to 哈希範圍替換;同文件最多 32 條編輯原子批量 |
undo_last_edit |
撤銷指定路徑的上一次 hashline 編輯,重啓後仍可用 |
read 展示過的行、diff 回顯行、拒絕並回傳(reject-and-serve)的行,都計入「已提供」狀態。edit 寫入前逐行校驗:從未展示的行觸發 [E_RANGE_UNSERVED],磁盤內容與錨點不一致觸發 [E_RANGE_STALE],批次中任一項失敗則整批不寫([E_BATCH_ABORT])。
相對 str_replace 的差異¶
README 中的對比要點如下,均來自項目文檔與可復現基準,而非第三方案例:
- 編輯調用不回顯被替換文本,只傳兩個 3 字符哈希加新內容
- 錨點爲內容地址,連續編輯時未改動行哈希保持有效,diff 輸出帶新錨點,通常不必每次改完都
read - 範圍與模型所見逐行覈對;錯錨點、過期內容在寫入前硬拒絕,並回傳帶新哈希的當前行供重試
- 對 ASCII 空白變化有一定容忍(如
prettier、black介入後錨點仍可解析);字符串字面量內的空白不在此列
項目在固定 103 行語料、12 次編輯的 token 基準中報告:相對 str_replace,hashline edit 輸出 token 約省 31%(多行範圍 29–47%);同一外部漂移重構任務中,工具調用約 3 次 vs 6 次(對比 OMP 封裝,方法說明)。確定性正確性電池爲 23/23。本地可運行 npm run benchmark 復現計數部分。
存儲與撤銷¶
哈希快照、已提供狀態、撤銷歷史默認存放在 central 模式:
$DSH_HOME/plugins/dsh-better-edit/runtime/<name>-<hash8>/hash-store.sqlite
DB 爲可丟棄緩存,刪除後下次 read 會按文件內容重建哈希。撤銷默認 TTL 7 天(undo_ttl_s: 604800,-1 爲永久)。
安裝與啓用¶
環境要求:Node ^22.19.0 || >=24.0.0(DSH 要求,存儲依賴 node:sqlite);已有一個 dsh profile。
任選一種安裝方式:
npx @deepseek-ai/dsh plugin --profile web add github:Rianico/dsh-better-edit # 從 GitHub
npx @deepseek-ai/dsh plugin --profile web add dsh-better-edit # 從 npm
npx @deepseek-ai/dsh plugin --profile web add /path/to/dsh-better-edit # 從本地源碼
無需額外配置。該 profile 的下一次會話即加載 hashline 工具。驗證插件層是否生效:
dsh --profile <name> --dump-config # 輸出中應出現 "# == dsh-better-edit" 層
可選配置寫在 $DSH_HOME/plugins/dsh-better-edit/config.yaml,例如存儲位置、撤銷 TTL、central 清理策略。環境變量 DSH_BETTER_EDIT_STORE_DIR、DSH_BETTER_EDIT_AUTO_GITIGNORE 可覆蓋 yaml。首次啓動時若文件不存在,插件會生成帶註釋的默認配置,不覆蓋已有文件。
典型用法¶
讀取:每行帶哈希前綴¶
read 返回的每一行,行首哈希即該行地址:
ve7│function hello() {
szJ│ console.log("world");
kQm│}
編輯:按哈希範圍定位¶
下面示例把 szJ 這一行替換爲新內容:
{
"path": "src/main.ts",
"edits": [["szJ", "szJ", " console.log('hi');"]]
}
工具返回 diff,並附帶新錨點,便於鏈式編輯:
- szJ │ console.log("world");
+ a3m │ console.log('hi');
kQm │ }
同一文件可一次提交多條編輯,全部成功才寫入:
{
"path": "src/main.ts",
"edits": [
["a1b", "a1b", "new line 1\n"],
["c3d", "c3d", "new line 2"]
]
}
撤銷¶
對剛改過的文件調用 undo_last_edit,傳入 { "path": "src/main.ts" }。僅當磁盤內容與上次編輯後快照一致時生效;若中間被外部修改,返回 [E_UNDO_STALE]。
適用場景與注意¶
適合:
- 長會話中的結構性改動,需要連續多次編輯且不能落錯行
- 希望減少編輯相關輸出 token、降低
str_replace式複述成本 - 文件可能在編輯間隙被格式化工具或外部進程改動,需要過期檢測而非靜默覆蓋
不太適合:
- 單行微調(token 節省接近持平,README 有說明)
- 新建文件(繼續用內置
write;插件會在write後自動read以建立錨點)
安裝前請注意:
- 插件以當前 dsh 進程權限讀寫工作區與
$DSH_HOME下的存儲,安裝前應閱讀 源碼 與 MIT 許可證 - DSH 仍處於開發者預覽階段,插件 README 註明當前針對特定 dsh 版本接線,升級 DSH 後宜重新覈對兼容性
- 基準數字衡量的是請求負載 token,未完全建模轉錄失敗重試等真實會話成本;正確性優勢需結合具體工作流評估
鏈接¶
- 社區目錄:skillhub.cn/plugins/Rianico/dsh-better-edit
- 源碼與文檔:github.com/Rianico/dsh-better-edit
- 中文 README:README.zh.md
若你已在 DSH 裏反覆遇到行號漂移或 str_replace 複述出錯,可以先按上文命令裝入 profile,用 read → edit → 看 diff 新錨點走一遍最小閉環,再決定是否用於日常 Agent 會話。