前言¶
在 DeepSeek Harness(DSH)裏跑智能體時,工具層可以寫文件、跑 shell。很多倉庫會在 AGENTS.md 或團隊規範裏寫一句:臨時目錄、日誌、探針文件不要堆在倉庫根目錄,統一放進 tmp/<任務名>/。規範寫在文檔裏,模型或腳本仍可能在根目錄創建 _tmp_probe/、build.log、.tmp 等條目,事後要靠人工或 CI 清理。
dsh-root-temp-guard 是 DSH Host 側的工作流類插件,在工具調用管線裏攔截「在工作區根目錄創建臨時目錄 / 臨時文件」,並可在回合結束時把漏網的根目錄臨時項移入隔離目錄。下面介紹它的定位、三層機制、安裝方式與配置要點。
這是什麼¶
維護者 lizhijie429,倉庫 lizhijie429/dsh-root-temp-guard,npm 包名 dsh-root-temp-guard(資料中版本 0.6.0),許可證 MIT。DSH 引擎要求:>=0.2.1-0 <0.3.0。
一句話定位:在 Host 插件層把「臨時產物統一放臨時目錄」的項目約定,從文字規則升級爲執行期攔截;工作區根目錄隨會話解析(session-root aware),規則與文案可配置。
務必區分邊界:這是衛生 / 約定守衛,不是安全邊界。文件類工具走參數解析與 fs-intent 兩層判定,命令類只做啓發式文本匹配;惡意或複雜 shell 仍可繞過,真正邊界仍是 DSH 沙箱。
社區目錄頁:SkillHub 插件頁(與 DeepSeek / 幻方無官方從屬,屬社區收錄)。
核心功能:三層攔截¶
插件 README 將機制歸納爲三層,且三層在插件內部異常時均爲 fail-open(放行並寫日誌,不卡死工具調用)。
1、工具參數層¶
通過 ctx.tools.guard() 在工具執行前運行,結合工具參數與會話當前工作目錄(workingDirectory.get(session))判定。即便模型先 working_directory { cd: "tmp" } 再寫 ../_tmp_x,也會按真實 cwd 解析並攔截。
2、已解析目標層¶
監聽 DSH 的 fs/write-intent / fs/edit-intent waterfall(write、edit、str_replace_editor 均會觸發),在路徑解析完成、寫盤前判定。該層使用 realpath 身份,因此通過 tmp/link 等 junction/symlink 把根目錄臨時項藏進允許的 tmp/ 也會被拒絕。
3、回合結束清掃¶
監聽 session/event 的 turn/start / turn/end:把本輪新出現且名字像臨時項的根目錄條目移動(不刪除)到 tmp/_quarantine/<timestamp>-<name>,便於人工恢復。這是對命令類啓發式繞過的兜底;turn/start 之前已存在的條目不會被被動處理。
默認覆蓋的工具類型(資料原文):
- 文件類:
write、edit、str_replace_editor(view只讀放行) - 命令類:
pwsh、bash、terminal_send(解析command/text;workdir按當前 cwd,cd/Set-Location後的相對路徑按新目錄解析)
默認規則示例:根下的 _tmp_probe/、scratch/、test-out/、_tmp_notes.md、build.log、x.tmp 等會拒絕;配置的統一臨時目錄(默認名 tmp)下的路徑允許;工作區外路徑不干預,交給沙箱策略。
安裝與啓用¶
本插件是 DSH profile 組合包(bundle):package.json 的 dsh.bundle.patch 指向 cordis.patch.yml,安裝後 DSH 會自動插入 root-temp-guard 行(默認 tmpDirName: tmp、quarantine: strict)。
CLI profile(推薦)¶
npm 發佈後,在 web / headless 等由 CLI 管理的 profile 上執行:
dsh plugin --profile web add dsh-root-temp-guard
安裝後可用下面命令確認 patch 是否生效:
dsh --profile web --dump-config | Select-String -Context 0,6 'dsh-root-temp-guard'
發佈前從本地目錄安裝(資料示例,無構建步驟):
dsh plugin --profile web add "file:$env:USERPROFILE\.dsh\plugins\dsh-root-temp-guard"
桌面端 profile¶
desktop profile 由 Electron 管理,dsh plugin 不直接改它。需在 %USERPROFILE%\.dsh\profiles\desktop\cordis.patch.yml 末尾按絕對路徑插入 root-temp-guard 條目(字段見 README「方式二」)。純 config 改動在默認 patchReload: live 下可熱生效;改 index.mjs / lib/guard.mjs 可能受 ESM 緩存影響,需重啓 DeepSeek Harness。
臨時驗證(不改 profile)¶
dsh headless --patch <含 root-temp-guard insert 的 yaml> "hello"
安裝插件會以當前 DSH 進程權限運行 Host 代碼;啓用前應自行查看倉庫源碼與 MIT 許可證,確認符合你的環境策略。
典型配置¶
config: 塊全部可選。常見字段如下(默認值以 README 爲準):
| 字段 | 默認 | 說明 |
|---|---|---|
enabled |
true |
總開關 |
mode |
deny |
deny 拒絕;warn 只記 would-deny 並放行(灰度) |
tmpDirName |
tmp |
統一臨時目錄名(單路徑段) |
allowRootNames |
[] |
額外放行的根目錄名 |
quarantine |
strict |
回合結束清掃;off 關閉 |
reasonTemplate |
見 README | 拒絕文案,支持 {name}、{tmpDir} |
在 profile 的 cordis.patch.yml 裏按 id: root-temp-guard 覆蓋 config 會整體替換該行的 config。資料中的灰度示例:
- insert:
- id: root-temp-guard
name: 'C:\Users\<你>\.dsh\plugins\dsh-root-temp-guard\index.mjs'
config:
mode: warn
tmpDirName: scratchpad
reasonTemplate: '臨時產物請寫入 {tmpDir}/<任務名>/,不要污染倉庫根目錄:{name}'
日誌默認寫在 <插件目錄>/state/root-temp-guard.log,超過 5MB 會輪轉一次爲 .1。拒絕、隔離移動、掛載/dispose 等事件會寫入該文件。
適用場景與注意¶
適合誰
- 已在 AGENTS.md 或團隊規範里約定「臨時文件進
tmp/」,希望 Host 層自動擋掉根目錄_tmp*、.log、.bak等常見污染。 - 需要先用
mode: warn觀察誤報,再切deny上線的工作流團隊。
不要指望它做什麼
- README「已知限制」明確:
node -e "fs.mkdirSync(...)"、複雜拷貝、管道、別名、腳本間接建目錄等可繞過命令類啓發式。 - 無 session 的 agentless 調用拿不到工作區上下文,守衛直接放行。
- 子代理 / workflow / PTC 機制上走同一註冊表,但未做端到端集成驗證。
- 其它插件直接調用
ctx.fs且不觸發 intent 的路徑不在 fs-intent 層覆蓋範圍內;可通過extraWriteTools/extraShellTools擴展工具名。
非法配置會寫 config.warning 到日誌,而不是靜默失效。
結尾¶
dsh-root-temp-guard 把倉庫根目錄臨時項的約定落到 DSH 工具管線:參數守衛、寫盤 intent、回合隔離清掃三層配合,配置驅動且隨會話工作區根切換項目。若你的 profile 已由 CLI 管理,優先用官方 npm 安裝命令接入 bundle。