前言¶
在 DSH 里让模型改代码,常见路径是 write 和 edit 工具直接落盘。一旦连续多轮改动,单靠 Git 或手动对照聊天,很难快速回答「这一轮到底动了哪几个文件、撤一步会不会盖掉我后来手改的内容」。社区插件 dsh-file-undo(维护者 QinLuza,分类:记忆)针对的就是这一类问题:在每次文件写入/编辑前抓全文快照,用侧栏红绿 diff 逐条审查,并支持 /undo 与两阶段确认撤销。当前版本 0.2.0,许可证 MIT。
这是什么¶
dsh-file-undo 是 DSH 插件,定位是撤销 agent 对文件的 write / edit 操作。实现上不存反向补丁,而是在落盘前保存 before 全文,撤销时整文件写回;diff 在现场计算,与存储解耦。除聊天命令外,还提供 Web 侧栏「撤销」面板(带未撤销计数徽章),并可在同一项目树下切换会话、自动跟随当前查看的会话。
核心功能¶
可视化审查面板¶
侧栏底部进入审查面板后,大致包含:
- 历史列表:时间、工具类型(write / edit / create)、文件名、恢复/移除行数、模型轮次;失败调用也会留痕。
- 撤销视角 diff:绿行表示撤销将恢复的内容,红行表示将移除的当前内容;超长内容默认截断,约 800 行后可「显示全部」。
- 自动预检:打开条目即判断能否安全撤销,并给出分类原因(见下文安全模型)。
- 两阶段确认:首次点击为武装(约 3 秒自动解除),再次点击才执行。
- 会话切换器:列出当前目录及其父子目录下的会话,默认跟随当前查看会话;headless 等环境下可静默降级。
安全模型¶
Host 侧裁决能否改文件,UI 只展示结果。预检(preview)为只读分类,常见原因包括:file_creation(撤销创建类操作会删文件,需内容与 hash 双闸及确认)、external_modified(快照后文件被手工改过,避免吞掉人工编辑)、superseded_by_later_ops(其后还有同文件的编辑,引导「回退到此状态」)、already_reverted、file_missing、stale 等。提交(apply)携带 expectedCurrentHash 乐观锁,预览后文件再变则拒绝。还支持 RewindTo(选中历史条目原子写回,并明示将丢弃的后续步数)以及级联恢复/重做,状态在 recorded → reverted → reapplied 间闭环。聊天里的 /undo 不做 external_modified 拦截,保留强制撤销语义。
命令¶
| 命令 | 作用 |
|---|---|
/undo |
撤销最近一次文件写入/编辑 |
/undo list |
查看当前会话已记录的操作历史 |
/undo <n> |
撤销指定索引的操作 |
/undo sessions |
列出同项目树会话(与面板切换器同源 API) |
/undo prune [days] |
清理 N 天前的快照(默认 7),只缩回退深度,不动当前文件 |
/undo git [n] |
从 git 归档恢复第 n 个快照(0 = 最新) |
/undo git-status |
git 归档健康状态 |
快照存储与归档¶
快照目录结构(用户主目录下):
~/.dsh/file-undo/
<workspace-key>/ # 由会话 cwd 规范化派生
<chat-key>/ # 会话 id
snapshots.jsonl # append-only
git-archive/ # 每条快照一个 commit,可静默降级
插件加载时按 7 天惰性清理;也可用 /undo prune 手动清理。路径写法不同但指向同一目录时,会规范化为同一 workspace 键。
安装与启用¶
插件以当前 DSH 进程权限运行,安装前建议阅读 GitHub 仓库 源码与 MIT 许可证。社区目录页:skillhub 插件页(独立站点,与 DeepSeek / 幻方无官方从属关系)。
方式一:本地构建(link)——在仓库目录执行 pnpm install && pnpm build,在 profile 的 package.json 中加入 link: 依赖后,于 profile 目录 pnpm install 并重启 DSH。README 中的完整步骤含 git clone 获取源码,见官方文档。
方式二:npm(发布后):
dsh plugin --profile web add dsh-file-undo
纯 client 侧改动在 link 模式下通常只需浏览器硬刷新;host 侧变更需重启 DSH。
典型用法¶
- 安装并重启 DSH(或按 link 方式配置 profile)。
- 在 Web 界面让 agent 通过
write/edit修改文件;每次落盘前会自动进入时间线。 - 打开侧栏底部「撤销」图标,在历史列表中选一条,查看预检结果与红绿 diff,两阶段确认后撤销;或于聊天输入
/undo、/undo list、/undo 2等。 - 若预检提示
superseded_by_later_ops,按面板引导使用「回退到此状态」,并确认将丢弃的后续步数。 - 定期或按需执行
/undo prune 7清理旧快照;需要时可用/undo git-status与/undo git [n]查看或从 git 归档恢复。
适用场景与限制¶
适合:频繁让 agent 改同一仓库、需要按轮次审查 diff、希望在误改后快速整文件回滚,且主要改动来自 DSH 的 write / edit 的场景。
注意:
- 只覆盖
write/edit;在 shell 里直接改文件(重定向、Set-Content等)不会进入时间线。 - 「回退到此状态」会丢弃其后改动,不做旧基线重放。
- 面板与会话跟随依赖 Web 界面;headless 下聊天命令仍可用。
- HTTP API 为
POST /file-undo/api/*,带 Host 头与 Origin 等信任围栏,仅供本地/受信环境使用。
结尾¶
dsh-file-undo 把 agent 文件改动做成可审查的时间线:全文快照、侧栏 diff、预检加乐观锁提交,以及 /undo 与回退/重做闭环。若要试用或贡献代码,可从目录页与仓库入手:
- 目录页:https://www.skillhub.cn/plugins/QinLuza/dsh-file-undo
- GitHub:https://github.com/QinLuza/dsh-file-undo