逐工具调用的工作区检查点:记录工作区内每一次文件改动(默认排除 .git 与 node_modules),包括由 shell 命令而非 write/edit 造成的改动,并把每个被改路径的旧内容存进工作区之外的内容寻址库。恢复有两种模式——撤销单条记录,或回到某个时间点——带行级 diff 预览、默认 dry run,且每次恢复前都先写保护快照,所以恢复本身也能被撤销。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:BOWLUNA/dsh-zcode-rewind
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 简体中文
面向 DeepSeek Harness 的逐工具调用工作区检查点——连 shell 副作用一起捕获。
为什么做这个
我们能找到的检查点实现,都只追踪「文件编辑工具」造成的改动。Claude Code 官方文档把话说得很直:
「检查点不追踪被 Bash 命令修改的文件」——rm file.txt、mv old.txt new.txt、
cp source.txt dest.txt 都无法通过 rewind 撤销。Cline 确实能捕获命令副作用,代价是每次工具调用后
把整个仓库提交进一个 shadow git,而它自己的文档提醒:大仓库会明显吃存储、明显变慢。
DSH 自己的市场也一样:我们读过的四个回滚插件(dsh-rewind-plugin、@anionex/dsh-turn-rewind、
dsh-undo-savepoint、dsh-recall-plugin)要么只解析 write/edit 的 file_path 参数,
要么只在 turn 边界打快照——所以一个 turn 中途的 sed -i,它们全都看不见。
它捕获什么
- 每一次会改动文件的工具调用:
bash、pwsh、write、edit、MCP 工具、子代理工具。 - 删除、新建、修改——每个路径都带一个可还原的改动前内容哈希。
- 内容寻址的文件内容,跨会话、跨工作区去重。
- 一份持久账本:谁在什么顺序上改了什么,重启后仍在。
工作原理
tools/execute (before) ──> 登记 pending;首次捕获写一份全量基线
│ (工具执行: bash rm/mv/sed、write、edit、MCP …)
tools/post-execute ─────> 指纹差分 → 读变化文件 →
内容寻址 blob 库(sha-256,去重)→
追加式账本记录
指纹是整棵工作区的 路径 → 大小 + mtime。每次捕获的成本是一次 O(文件数) 的 stat 遍历,
加上只对真正变化的文件读内容——3000 个文件实测 88 ms;首次全量基线 2936 ms,
而零变更捕获只要 86 ms。
安装
dsh plugin --profile web add dsh-zcode-rewind
重启 DSH——bundle 插件在启动装配期生效。用
dsh --profile web --dump-config | grep workspace-rewind 验证合成树。快照库在工作区之外,
位于 $DSH_HOME/workspace-rewind/,绝不碰你的 git 仓库。
工具
| 工具 | 作用 |
|---|---|
rewind_now |
立即手动建检查点,比如危险操作之前 |
rewind_list |
最近记录(新→旧):id、时间、工具、+新增 ~修改 -删除、示例路径 |
rewind_diff |
恢复计划 + 行级 unified diff,不改动任何文件 |
rewind_restore |
mode=revert 撤销单条记录;mode=asof 回到某个时间点 |
rewind_undo |
撤销最近一次恢复——反复执行即 undo/redo 来回切 |
rewind_status |
快照库状态:记录数、blob、占用、配额、当前配置 |
配置
- insert:
- id: workspace-rewind
name: 'dsh-zcode-rewind'
config:
capture: all # all | fileTools | off
maxFileBytes: 8388608 # 超过此大小的文件只记事件
maxFiles: 20000 # 单次遍历文件数上限
maxTotalBytes: 536870912 # 快照库配额;超限淘汰最旧未引用 blob
keepRecords: 500 # 账本裁剪阈值
excludes: ['.git', 'node_modules', 'dist']
secretNames: ['.env', '*.pem', '*.key']
恢复语义
| 模式 | 含义 |
|---|---|
revert |
只抵消某一条记录的增量——「撤销刚才搞坏的东西」用这个 |
asof |
把工作区回到某条检查点记录的状态:折叠账本,并正确处理 target 之后新建的文件 |
安全
- 恢复默认 dry-run;必须显式
apply=true才会动文件系统。 - 每次恢复前先写一条 rescue 保护记录,所以
rewind_undo能撤销它——而且可以反复撤销。 - restore / rescue 记录豁免配额淘汰:撤销链永远不会被清掉。
- 密钥样式的文件与超限文件只记事件,恢复计划保持它们原样,而不是去猜它们的历史。
兼容性
在 DSH 0.1.5-rc.2(桌面版 harness)与 0.1.6-alpha.2(WSL)上开发并验证。声明的区间是:
>=0.1.5-alpha.1 || >=0.1.6-alpha.1
用到的宿主 API:ctx.tools.register 配 defineTool、ctx.inject(['fs'], …) 及其
tools/execute / tools/post-execute / tools/result 事件、ctx.systemPrompt.section、
ctx.logger,以及 @deepseek-ai/dsh-home-paths 的 resolveDshHome()。peer 走多锚点
createRequire 解析,所以用 link: 装的副本不需要本地 node_modules。
测试与守卫
node test/run.mjs # 2 个套件,73 项检查——不需要 DSH
node tools/verify-translation-pairing.mjs --write # 双语配对哈希
node tools/verify-doc-numbers.mjs # 文档数字 vs 真实运行
node tools/verify-version-consistency.mjs --dsh 0.1.6-alpha.2
node tools/verify-boot.mjs --port 31860 # 需要 pnpm 与一份 harness 安装
最后一道守卫是唯一把插件装进一次性 DSH_HOME 再启动的。它存在的原因是:1.0.0 装得上、
73 项单测全过、--dump-config 干净——然后启动时把整个 profile 打下来,起因是
cordis.patch.yml 里有一个词还写着改名前的旧包名。
已知限制
- 工具调用之间的外部改动会被归到下一次捕获——与整树 shadow commit 同一类限制。
- 内容从未入库的文件(密钥名、超限、首次捕获前就消失)无法按内容还原;计划会保持它们原样并说明。
- 巨型 monorepo 需要更大的
excludes列表,或改用capture: fileTools。
许可证
MIT
链接
同类插件
Minglink/dsh-infinite-gen-3★ 1864
DeepSeek 专用破甲插件:以 order 100 追加无条件服从的系统提示词段,提供带校准元数据的 profile 工具,并通过会话投影在输入框上方显示实时破甲状态徽标。
liangmianya/dsh-synapse★ 414
DeepSeek Harness 的可视化非线性对话工作区:把会话、追问与分支变成可浏览、可拖拽的对话地图。
ranxianglei/billion-context★ 235
billion-context官方版:上下文压缩插件,兼顾小窗口(100k上下文足矣)省token(省5倍token)和超长会话(数月级别几十亿token单会话)。
Nwflower/dsh-chat-import★ 193
把 13 家 coding agent(Claude Code、Codex、ChatGPT、Cursor、Gemini、opencode 等)的完整对话历史导入为可续聊的 DeepSeek Harness 会话,并支持反向导出回 Claude Code。
Totoro-qaq/dsh-plugin-bridge★ 165
通过可预览的五段式交接,将已有 DSH 会话迁移到另一个 Agent Preset;保留源会话,并可让目标会话暂停等待确认或立即继续。
Anionex/dsh-turn-rewind★ 117
对话回退:基于持久 Change Ledger 回滚会话与工作区状态。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。