前言¶
在 DeepSeek Harness(DSH)里,若启用了 @deepseek-ai/dsh-fs-observation-policy,文件版本只来自受 instrumentation 的读写操作(会发出 fs/observed)。dsh-tool-bash、dsh-shell、dsh-subprocess-local 等工具不会上报这类事件;DSH 文档也写明:只有受 instrumentation 的文件系统操作会在这里报告,操作系统层面不会被监视。
因此,智能体用 bash 或 shell 改动了它之前「观测过」的文件后,内存里的观测版本会滞后;紧接着再用 DSH 自带的 edit 改同一文件,常会收到 FS_STALE_VERSION——错误来自本会话自己的 shell 写入,而不是外部进程。关掉观测策略可以消除这类报错,但第三方改写文件时也会失去保护,最坏情况是静默数据丢失。
下面介绍社区插件 dsh-fs-reobserve(维护者 lucagiftzek,npm 包 @lucagiftzek/dsh-fs-reobserve,当前版本 1.0.0,MIT 许可证)。它在「严格策略」与「完全关闭」之间补一层:仅在本会话自己的 bash/shell 调用结束后,重新 stat 本会话曾观测过的路径并再次发出 fs/observed;他人或外部进程造成的变更仍保持旧观测,下一笔 edit 仍会正确触发 FS_STALE_VERSION。
这是什么¶
dsh-fs-reobserve 是 DSH 工作流类插件,定位为 @deepseek-ai/dsh-fs-observation-policy 的补充中间方案:消除「自伤式」陈旧文件错误,同时保留对第三方写入的 stale 检测,并继续强制执行「先 read 再 edit」相关的 FS_NOT_OBSERVED 约束。
背景:三种取舍¶
README 用表格对比三种模式,核心差异如下。
| 行为 | 严格策略 | dsh-fs-reobserve | 关闭策略 |
|---|---|---|---|
| 本会话 bash 写入导致的 stale | 会报错 | 不再误报 | 不报错 |
| 第三方写入导致的 stale | 会报错(正确) | 会报错(正确) | 被压制(不安全) |
FS_NOT_OBSERVED |
强制 | 强制 | 不强制 |
| 最坏失败 | 浪费一次调用 | 浪费一次调用 | 静默数据丢失 |
插件不会为未发生的变更重新观测:cron、其他智能体或桌面编辑器改写的文件仍保留旧观测,智能体仍需 re-read,这是刻意保留的保护。
核心功能¶
在本会话的一次 bash 或 shell(可配置)调用 settle 之后,插件对该会话曾观测过的目标重新 stat,并通过 ctx.fs.stat 作为唯一合法来源再次发出 fs/observed,覆盖三种状态迁移:
- 存在 → 存在(新版本):命令重写了文件。
- 存在 → 不存在:命令删除了文件。
- 不存在 → 存在:命令创建了此前 read 已确认不存在的文件。
版本号不会被凭空制造。默认监听的工具为 bash 与 shell;可选在工具结果上附加说明(notify),便于智能体知道发生了 re-observe。
安装与启用¶
需要 Node 22.5 及以上,以及自带 @deepseek-ai/dsh-fs-observation-policy 的 DSH 构建(README 写明在 DSH 0.1.5 与 0.2.1 上使用)。包声明了 dsh.bundle,dsh plugin add 会写入 dsh.profile.bundles 并由插件自带的 patch 插入 fs-reobserve 条目,不要再手工添加重复的 insert 行。
官方安装方式:
dsh plugin --profile web add @lucagiftzek/dsh-fs-reobserve
# or from GitHub: dsh plugin --profile web add github:lucagiftzek/dsh-fs-reobserve
# then restart `dsh web`; the log shows "fs-reobserve: armed ..." once
本地 checkout 也可用 link 方式安装:
dsh plugin --profile web add link:/absolute/path/to/dsh-fs-reobserve
安装后重启 dsh web;日志中出现一次 fs-reobserve: armed ... 表示已就绪。
配置¶
选项从插件 loader 条目读取(profile 的 cordis.patch.yml 里 fs-reobserve 那一行),不会读取 settings.yaml 段。示例见仓库 docs/TROUBLESHOOTING.md。
| 键 | 默认值 | 含义 |
|---|---|---|
tools |
[bash, shell] |
需要在其结束后触发 re-observe 的工具 |
notify |
true |
是否在工具结果上附加说明 |
maxNotifyPaths |
4 |
说明中列出的路径数量上限,超出则省略 |
临时关闭而不卸载:在 ~/.dsh/profiles/web/cordis.patch.yml 增加:
- id: fs-reobserve
disabled: true
典型用法与排错¶
日常用法即:在 web profile 安装插件并重启 DSH web,继续让智能体用 bash/shell 改文件后再用 instrumentation 的 edit;自伤式 FS_STALE_VERSION 应消失,外部改写仍应触发 stale。
出问题时:
- 可将仓库中的
skills/fs-reobserve-doctor复制到~/.dsh/skills/(该版本不会自动注册该 skill),再让智能体加载fs-reobserve-doctorskill。 - 按症状查阅 docs/TROUBLESHOOTING.md。
- 错误码与日志行见 docs/ERRORS.md。
包内测试:npm test(node --test test/*.test.mjs)。
适用场景与注意¶
适合在 web profile 下长期启用文件观测策略、且智能体频繁通过 shell 改工作区文件的开发流程。不适合期望「关闭所有 stale 检测」或「对外部改写也自动刷新观测」的场景——后者与安全模型相悖。
插件与 DSH 进程同权限运行;安装前请自行查看 GitHub 仓库 源码与 MIT 许可证。DSH 生态强调「一切皆插件」;社区目录 skillhub.cn 为独立站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-fs-reobserve 把「本会话 shell 写入」与「他人改写」区分开:前者在命令结束后自动刷新观测,后者仍迫使 re-read。需要安装命令、配置与排错细节时,可看目录页 skillhub.cn/plugins/lucagiftzek/dsh-fs-reobserve 与 GitHub github.com/lucagiftzek/dsh-fs-reobserve。