前言¶
在 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。