鱼皮AI导航
鱼皮AI导航
  • 主页
  • 社区
  • AI工具
  • AI知识库
  • AI提示词
  • MCP
  • Skills
  • AI学习资源
  • AI资讯
  • GitHub开源
登录/注册

dsh-filesnap

同步回退 DeepSeek Harness 的对话与工作区,不碰 Git:每次回退都是一个 fork,/redo 可撤销,Rust 引擎毫秒级快照。

会话消息
访问 GitHub
文档README

dsh-filesnap — 同步回退 DSH 对话与文件

English | 中文

参与讨论 · 报告问题

为 DeepSeek Harness 同步回退对话与工作区文件,不碰 Git。每次回退都发生在一个新的 fork 中,因此改变主意时 还可以用 /redo 回去。由一个快得离谱的 Rust 🦀 引擎驱动。

dsh-filesnap:对话与工作区一起回退

▼
console
复制代码
> /rewind 2 Rewound to turn 2 (把限流改成按租户维度). Files: 7 written, 1 deleted. The conversation continues in session-9f3c1a04-…. Run /redo there to reverse this rewind.

快速开始

环境要求

  • 带有 web 或 headless profile 的 DeepSeek Harness
  • Node.js ^22.19 或 >=24
  • x64 或 arm64 架构的 Linux、macOS 或 Windows

原生 filesnap 二进制会随插件 一起安装,不需要另装 Rust、Git 或其他运行时。

[!IMPORTANT] dsh 目前没有为仓库外插件提供正式的事件类型注册接口,因此 dsh-filesnap 会在加载时 注册自己的 session 事件。如果卸载插件,它捕获过的会话将暂时无法打开,重新安装后 即可恢复访问。 会话数据仍完整保留在磁盘上。插件装着但用源码 checkout 的 pnpm dsh 启动时也会出现同样的拒绝——请用构建版 CLI 或 npm 安装的 dsh;见 排障和 架构限制。

1. 安装

▼
console
复制代码
$ dsh plugin --profile web add dsh-filesnap

安装到此为止:本包声明了 dsh.bundle,启动器会自己把它挂进 profile。headless profile 把 web 换成 headless 即可。

[!WARNING] 从 0.2.1 或更早升级? 那些版本要求你在 ~/.dsh/profiles/<profile>/cordis.patch.yml 里手动加一行 id: filesnap。在 0.2.2 上启动 dsh 之前,先删掉那一行。 现在 bundle 会提供同一行,loader 拒绝两个同 id 的条目,dsh 会起不来: plugin tree failed to load: … duplicate loader entry id: filesnap。

2. 验证并使用

▼
console
复制代码
$ dsh --profile web --dump-config | grep -A 1 filesnap - id: filesnap name: dsh-filesnap

重启 profile,完成一轮 agent 任务,然后输入 /rewind。如果组合后的 profile 中没有 插件,或浏览器控件没有出现,请看排障指南。

第一次回退,一步一步来

截图来自 web profile 上 0.2.2 的真实会话。

1. 跑一轮会改文件的任务,然后悬停到回复上。 每条完成的 assistant 回复旁边,复制和 分支的旁边,就是回退控件。tooltip 写着它会回到哪一轮、这次快照覆盖了什么。

assistant 回复下方的回退控件和它的覆盖范围 tooltip

2. 或者直接输入 /rewind。 输入框会提示参数:轮次编号或点 id,--into 指向你已经 建好的 fork,或者 status。刻意没有"往回三步"这种写法——你指的是眼前看到的那个点。

输入框里的 /rewind 命令及其参数

3. 选一轮。 文件回到那一轮之前的样子,对话在那里 fork,结果里写着你现在所在的子会话。 你离开的那个对话没有被改写。

两次回退的结果:写入和删除的文件数,以及各自继续的会话

4. 会话列表能分清这一对。 你回退离开的那个对话带一个箭头标记,fork 不带。

会话列表里两条带标记的被回退会话

5. 改主意了?在 fork 里 /redo。 它反转这次回退,把你交还给原来的对话,标记随之消失。

/redo 的结果:回退已反转,回到原会话继续

6. 随时 /rewind status。 本工作区记录占的磁盘、共享内容存储占的磁盘,以及这里哪些 文件没有被保护、为什么。

转录里的 /rewind status 输出

为什么选择 dsh-filesnap

意味着什么
对话 + 文件在选中的轮次 fork 对话,并把工作区恢复进同一个 fork。
不依赖 Git在 Git 仓库和普通目录中都能工作,不改变 commit、branch、stash 或 worktree 状态。
回退也能撤销在还原写入前先创建救援点,/redo 可以撤销这次回退。
覆盖面更完整支持二进制文件、被 Git 忽略的文件,以及经 ctx.fs 发生在项目目录外的编辑。
原生引擎有界扫描、内容寻址和还原运行在独立的 🦀 Rust 小型二进制中,不占用会话的 Node 进程。
范围可检查/rewind status 会报告存储占用,以及哪些文件未被保护和对应原因。

这套设计不会把版本控制当作快照仓库。带版本日期和源码审计的完整对比见 插件对比。

命令

命令结果
/rewind列出每轮开始前捕获的工作区状态。
/rewind <turn>在该轮 fork 对话,并恢复对应文件。
/redo撤销落在当前会话中的回退。
/rewind status报告存储内容和当前未受保护的文件。

/rewind 接受列表中显示的轮次编号或 point id。它刻意不支持“往回三轮”这样的相对 寻址:还原会覆盖文件,因此目标必须明确。

这两个命令都不会触发模型轮次。回退是用户对对话执行的操作,不应该再经过被回退的对话。

哪些文件会被保护

每次模型 step 之前,dsh-filesnap 会捕获三个有界集合的并集:

  • 工作区已知的文件,包括 Git 报告的 tracked 文件名;
  • 在 ctx.fs 写入或编辑之前观察到的路径,即使路径位于项目目录之外;
  • 最近发生变化的工作区文件的有界扫描,用来覆盖 shell 命令造成的写入。

内容按哈希寻址,因此未变化的文件会被复用,不会每轮复制一份。.filesnapignore 是 对称的:被忽略的路径不会被存储、恢复,也不会被还原操作删除。只有目标快照明确记录某个 路径当时不存在,还原才有权删除它。

/rewind status 会重新扫描当前目录,并列出超出覆盖范围的项目,例如无法读取、过大或 不是普通文件的路径。覆盖细节与还原不变量见架构说明。

性能

引擎运行在模型请求之前,而模型请求通常需要数秒。当前在 warm page cache 下得到的初步 测量是:

工作区捕获文件数首次捕获重复捕获
本仓库8420 ms8 ms
DeepSeek Harness monorepo磁盘上 70,918 个文件中的 7,995 个1.75 s268 ms

这些数字只描述原始测量机器,不是对所有设备的承诺。跟踪集合是有界的,不会每轮遍历 70,918 个文件;重复捕获还会复用未变化的内容。测量方法、尚缺的机器元数据和复现命令见 基准测试。

浏览器体验

可选的 ./client export 会增加:

  • 每条已完成 assistant 消息旁边的回退操作;
  • header 中的 redo 和存储状态操作。

转录本身已经是轮次列表,所以插件不会再增加一个重复的 checkpoint 面板。在浏览器中, 部署先创建正确组合的子会话,host 把文件还原进去,client 再打开该子会话。headless 场景 则由 host 插件自行 fork。

浏览器 bundle 会在发布流程中完成类型检查和构建,但目前还没有自动化浏览器内测试。

配置

默认值适用于普通本地部署。

字段默认值用途
command自动解析指向另一个引擎构建,或由远程 subprocess provider 解析的裸命令。
dataDir平台数据目录存储位置,永远不在项目目录中。
timeoutMs120000单次引擎调用的墙钟上限。
graceMs2000取消或超时后从 SIGTERM 到 SIGKILL 的宽限时间。
maxOutputBytes1048576每条输出流的内存上限。
declareEditstrue在编辑之前立即记录文件 pre-image。

未知字段和不可用值会在插件加载时失败,不会等到某次回退点悄悄消失后才暴露。

当前限制

  • 卸载插件后,包含其事件类型的会话在重新安装前无法读取;不会删除任何会话数据。
  • 在 web 输入框中键入 /rewind 只会报告子会话 id,不会自动跳转;逐轮浏览器操作会完成跳转。
  • host 自行执行的 headless fork 会继承模型 route 和 preset,但不会继承部署的 per-agent 模型选择或 workspace 挂载。
  • shell 在工作区外、大小边界之外或近期变化预算之外创建的文件,需要同时被文件系统写入 事件观察到才能覆盖。
  • 引擎已经支持 gc、doctor 和删除 session,但插件还没有把它们暴露为 /rewind 子命令。

事件注册限制见架构说明,操作问题见 排障指南。

文档

文档回答什么问题
架构说明何时捕获、fork 与还原的顺序,以及记录了什么。
插件对比不同 dsh rewind 设计的区别,并标明审计版本。
基准测试已发布的时间数据意味着什么,以及如何复现。
排障指南安装、profile、client bundle 和存储诊断。
参与贡献本地开发、构建和四层测试。

快照引擎也可以脱离 dsh 使用:通过 Rust(cargo add filesnap)或其带版本的 JSON Lines CLI 集成。本仓库完整的 subprocess adapter 是 src/cli.ts。

参与贡献

欢迎用中文或英文参与:

  • Discussions:问题、想法和使用案例;
  • Issues:bug 和明确的改进项;
  • Pull requests:已经实现的修改。

修改 host/engine 边界前请阅读 CONTRIBUTING.zh.md。安全问题请通过 SECURITY.md 中的私有渠道报告,不要创建公开 issue。

许可证

Apache-2.0,见 LICENSE。它使用的 filesnap 引擎采用同一许可证。

会话消息

快捷安装

复制到终端去安装插件

dshplugin--profilewebaddgithub:extracurricular-ai/dsh-filesnap

温馨提示

装插件等于在本机跑第三方代码,权限与你相同,能读文件、用凭据、访问网络,工具审批管不到。请只装可信来源,并尽量锁定 commit。

站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
🔥热门工具
朱雀AI检测朱雀AI检测
朱雀AI检测助手朱雀AI检测助手
LovartLovart
老鱼简历老鱼简历
WritePass官网WritePass官网
面多多面多多
CursorCursor
星月写作星月写作
零感AI零感AI
墨得问题墨得问题
dsh 插件推荐
dsh-btw
提供 /btw 一次性上下文旁问,不执行工具;回答显示在可复制、折叠或关闭的独立气泡中,不写入主对话。
billion-context
billion-context官方版:上下文压缩插件,兼顾小窗口(100k上下文足矣)省token(省5倍token)和超长会话(数月级别几十亿token单会话)。
dsh-conversation-archive
在 Windows 上管理 DSH 已归档会话,支持搜索、批量取消归档与删除、AI 辅助文件保留,以及经过校验的本地或网络目录备份。
dsh-auto-continue
回答因达到单次输出 token 上限被截断时自动发送"继续"续写,无需手动操作;面向自部署 Ollama 等小输出上限场景。
dsh-branchmark#dsh-branchmark
Vibe Coding 时,如果突然想到另一个问题,或者看到一段以后还会用到的回答,可以先保存下来、在 Side Chat 里快速问清楚,或另开一个相关会话继续研究,不打断当前任务的开发思路和注意力。