在 DSH 用户消息旁加「撤回」按钮,把项目文件与对话历史一并回退到该消息发送之前;底层用影子 git 仓库快照+官方 sessions.fork。
- 语言
- JavaScript
- License
- MIT
- 分支
- main
安装
$ dsh plugin --profile web add github:limbo947/dsh-recall-plugin在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 limbo947/dsh-recall-plugin:先查看仓库 https://github.com/limbo947/dsh-recall-plugin.git 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
在 DSH 的用户消息气泡旁加「↶ 撤回」按钮,点一下就把工作区文件和对话历史一起回退到该消息发送之前;底层用独立的影子仓库做文件快照,用官方 sessions.fork 切会话。
核心能力
- 一键回退整段交互:撤回时把项目文件恢复、对话切到该消息之前、新会话打开、原会话归档可随时找回
- 文件与对话双轨同步:先弹文件清单确认(修改 / 恢复 / 删除),确认后才动手,不会盲目覆盖
- 影子 git 仓库存储:快照存在 home 下的独立 git 仓库(
~/.dsh/dsh-recall-snapshots/<工作区路径 SHA256>/),不污染项目自带的 git、不动暂存区、不动未提交改动 - 自动维护磁盘:每积累 50 条快照或 24 小时后台跑
git gc压缩;会话日志彻底删除后该会话的全部快照自动清理 - 可视化排除配置:设置页编辑
exclude.txt(gitignore 语法),保存后下一次快照/回退即时生效;超过 100MB 的大文件自动跳过 - 树形快照管理:设置页按 工作区 → 会话 → 快照 三级树形展示与删除,叶子显示对应消息内容摘要
技术实现
- 语言: 纯 JavaScript(ESM,零构建步骤)
- 关键依赖:
@deepseek-ai/cordis(插件框架)、@deepseek-ai/dsh-shell(PowerShell/bash 执行器)、@deepseek-ai/dsh-session-query(冷日志读取)、@deepseek-ai/dsh-sandbox-policy(会话 cwd 解析) - 架构模式: 双 bundle 持久挂载:Host 半通过
cordis.patch.yml的 insert 行注入,注册/api/recall/*HTTP API 给前端调用;Client 半通过dsh.clientbundle 注入浏览器,注册conversation.chat.node渲染槽(priority -1 起、负向递减重试到 -3)渲染用户消息气泡 - 入口文件:
lib/index.js(Host 主入口,791 行装配各域模块) /lib/client.js(Client 主入口,UI 注入 927 行) /lib/snapshots.js(快照域:captureSnapshot / diffFor / rollbackFor / resolveCutSeq)
适用场景
AI 帮你改了一堆文件后发现方向不对、想回到"这条消息之前"的状态继续——传统做法是手动 git stash 或丢弃改动,但还得保留对话上下文继续推进。本插件让"撤回到某条消息"成为一次点击的操作,且文件与对话同时回到那一刻。适合用 DSH 长时间迭代、改动频繁、回退需求多的开发场景。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | >= 0.1.0-rc.8 | peerDependencies 中 cordis ^4.0.1、dsh-session/shell/sandbox-policy/session-query/host-webserver/client-web-react 均 ^0.1.0-rc.8 |
| Node.js | >= 20 | engines.node 声明 |
| git | 任意可执行版本 | 探测不到时撤回按钮不出现、页面顶部提示 gitMissing,DSH 本身不受影响 |
| Windows | PowerShell 5.1 / 7 | 脚本模板用 [Text.Encoding]::UTF8 与 SHA256::Create() 兼容 PS 5.1 |
| Linux / macOS | bash 3.2+ | POSIX 模板与 pwsh 模板同名导出,按平台在 store.js 单选 |
| React | ^18.2.0 | Client 半的 peerDependency |
安装方式
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
安装后需重启 DSH 进程(dsh web 前台重启或 pm2 restart <你的dsh进程名>),然后硬刷新浏览器页面(Ctrl+Shift+R)——悬停任意一条插件启用后发送的用户消息,复制按钮旁出现「↶」即生效。
配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
gcSnaps | 整数 | 每积累多少条快照触发一次 git gc | 50 |
gcHours | 整数 | 距上次 gc 超过多少小时触发(与条数先到先触发) | 24 |
maxFileBytes | 整数(字节) | 超过该大小的文件不进快照、不参与回退 | 104857600 (100MB) |
baseExcludes | 字符串数组 | 基础排除表(gitignore 语法),对所有项目生效 | ['.git', 'node_modules/', '.dsh-recall-snapshots/'] |
DSH_RECALL_GC_SNAPS(环境变量) | 整数 | 同 gcSnaps,但优先级高于上述配置 | — |
DSH_RECALL_GC_HOURS(环境变量) | 整数 | 同 gcHours,但优先级高于上述配置 | — |
配置写在 profile 的 cordis.patch.yml 里按 id: recall 重述整行即可覆盖默认值;最常用的「加一项排除」请直接编辑 exclude.txt 或设置页,无需重启。
常见问题
Q: 撤回按钮没出现怎么办?
A: 九成是 DSH 进程没重启,或 git CLI 不在 PATH。重启后硬刷新页面(Ctrl+Shift+R)即可。插件启用之前发送的消息也没有快照,按钮不会出现在那些消息上。
Q: 撤回会污染项目自己的 git 仓库吗?
A: 不会。快照存放在 home 下的独立影子 git 仓库(~/.dsh/dsh-recall-snapshots/<SHA256>/git/),不会动你项目内的 .git、暂存区、未提交改动;.git、node_modules 已被默认排除。
Q: home 不可写时数据存哪里?
A: 降级到项目内 .dsh-recall-snapshots/,页面顶部会一次性弹降级提示。home 恢复可用后,下一条快照前会自动把项目内数据迁回 home 并清理干净。
Q: 如何把某个目录排除出快照?
A: 设置 → 插件 → 撤回设置 可视化编辑 exclude.txt(gitignore 语法,一行一条),保存后下一次快照/回退即时生效;或直接编辑 home 下 dsh-recall-snapshots/exclude.txt。回退到更早快照时,当时尚未排除的文件仍会被恢复(这是回退的语义)。
Q: 会话被删除后快照还在吗?
A: 归档不算删除——撤回功能自己归档的原会话快照保留可找回;只有会话日志从磁盘真正消失时,下次维护才会自动清理该会话的全部快照。判断保守:冷着的会话不会被误清。
Q: 撤回错了能找回来吗?
A: 能。回退前会自动打一个 snap-pre-rollback-<时间戳> 安全快照 tag(不进 index 列表,但 git tag -l 仍能看到),从该 tag 恢复即可——这是堵住"撤回是唯一不可逆操作"的兜底。
Q: 卸载后快照数据会一起删吗?
A: 不会。dsh plugin --profile web remove 仅移除依赖与挂载层,快照数据保留在 home 下 dsh-recall-snapshots/;想彻底清除手动删除该目录即可。
上手难度
入门 — 安装重启即可用,无强制配置;进阶用法(自定义排除、手动 gc、批量删除快照)全部在设置页可视化完成。
已知问题与限制
- 仅快照启用后发送的消息:插件启用之前的历史消息没有快照,自然不显示撤回按钮(README.md:44)
- 首条消息仅回退文件:会话第一条用户消息无法回退对话,因为
sessions.fork需要更早的 turn 边界(README.md:45) - macOS 尚未真机实测:脚本按 bash 3.2 兼容编写,但目前只跑了 Windows 真机与 WSL2 Ubuntu(bash 5.3 + git 2.53)的全流程(README.md:46)
- 嵌套 git 仓库不进快照:工作区子目录里自带
.git的子仓库(gitlink)内容不参与快照与回退(scripts.pwsh.js:36-39) - 文件名含换行/TAB 解析异常:diff 清单的解析按 TAB 切分,文件名含这两种字符的极端情况会被错乱解析(scripts.pwsh.js:191-194)
- 撤回需 git CLI:未装 git 时撤回按钮不出现、页面顶部一次性提示,DSH 本身不受影响(README.md:52)
- fork 不继承原标题递增:已经修复——多次撤回新会话不会变「xxx 2/3/4」(CHANGELOG.md:84-85, lib v1.2.2)
撤回一条消息,项目文件也一起回去。
简体中文 | English
在任意一条你发过的消息下方,点「↶ 撤回」,工作区文件和对话历史一起回到那条消息发出之前的状态。
界面预览
- 撤回按钮位置

| 确认面板 · 变更文件清单 | 确认面板 · 变更文件清单 |
|---|---|
![]() | ![]() |
- 设置页 · 排除项快速编辑(设置 → 插件 → 撤回设置)

功能亮点
- 文件 + 对话,整段回退:撤回的不只是聊天记录,agent 改过的文件也一并回到原样。
- 不碰你项目自己的 git:快照存在独立的影子 git 仓库里,你的分支、暂存区、未提交改动统统不受影响;
.git、node_modules自动排除。 - 项目目录保持干净:快照始终存在
$DSH_HOME下,不会往项目里塞任何东西;与会话的沙箱权限无关(workspace-write / read-only 会话照常快照与回退),仅当 home 本身不可写(如指到只读盘)才降级到项目内.dsh-recall-snapshots(降级时页面会提示),home 恢复后自动迁走、清理干净。 - 可以反复后悔:只要会话还在(含归档),快照全量保留、不修剪。撤回一次后还能再撤到更早;撤回时被覆盖的文件也一直找得回来。会话被彻底删除后,其快照随之清理(见下)。
- 先看清单再动手:点撤回先弹出将变更的文件清单(修改 / 恢复 / 删除),确认后才执行,不会稀里糊涂覆盖。
- 磁盘友好:快照走 git delta 压缩,是增量不是整目录拷贝;超过 100MB 的大文件自动跳过。
- 自动瘦身:定期
git gc把 loose 对象压 pack(无损,快照一个不丢);会话删除后其快照自动清理;构建产物可经exclude.txt全局排除(见下)。 - 树形快照管理:设置页「快照管理」按 工作区 → 会话 → 快照 三级树形展示,支持展开/折叠;每级右侧都有删除按钮,可一次清掉整个工作区或某个会话的全部快照,叶子显示该快照对应的消息内容摘要,方便定位“这条消息当时改了什么”。
已知限制
- 快照在消息发送时创建,插件启用前的历史消息没有快照,不显示撤回按钮。
- 会话第一条用户消息无法回退对话(仅文件回退),因为 fork 需要更早的 turn 边界。
- 支持 Windows(PowerShell 5.1/7 + git CLI)与 Linux/macOS(bash + git CLI)。Windows 真机验证充分;Linux 已在 WSL2(Ubuntu 26.04,bash 5.3 + git 2.53)实测全流程(含中文路径、home 降级、会话清理、gc);macOS 侧脚本按 bash 3.2 兼容编写,尚未真机实测。
- 工作区内嵌套的其他 git 仓库(子目录自带
.git)不进快照,其内容不参与回退。 - 文件名含换行/TAB 的极端情形不在 diff 清单的解析能力内(概率可忽略)。
安装
前置:git CLI(未装时撤回按钮不出现,页面顶部会提示安装 git,不影响 DSH 运行);Windows 上 PowerShell 5.1 / 7 均可,Linux/macOS 需 bash + git;DSH 0.1.0-rc.x(依赖版本见 peerDependencies)。
- DSH 官方插件命令:安装并自动挂载进 web profile
dsh plugin --profile web add dsh-recall-plugin
- 也可从 git 直接安装(纯 JS 无构建,免 prepare/allowBuilds):
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
- 重启 DSH 进程(按你的启动方式,任选其一)
dsh web # 前台直接启动
pm2 restart <你的dsh进程名> # 若用 pm2 托管
验证:重启后硬刷新页面(Ctrl+Shift+R),悬停任意一条插件启用后发送的用户消息——复制按钮旁出现「↶」即生效。没有按钮?九成是没重启 DSH 进程,或 git CLI 不在 PATH 里。
卸载:dsh plugin --profile web remove dsh-recall-plugin(同时移除依赖与挂载层),快照数据保留在 home 下 dsh-recall-snapshots/,想彻底清除手动删掉该目录即可。
使用
- 鼠标悬停任意插件启用后发送的用户消息,复制按钮左侧出现「↶ 撤回」。
- 点击 → 确认面板展示将变更的文件清单(修改 / 恢复 / 删除)。
- 点「确认回退」→ 文件恢复到该消息发送前的状态;视图切到新会话(该消息及之后的对话移除),原会话归档、随时可找回。
快照维护与清理
快照全量保留的前提是「会话还有找回的可能」,在此之上插件自动控制磁盘占用,无需手动管理:
-
定期 gc:每 50 条快照或距上次 gc 24 小时(先到先触发),后台执行
git gc把 loose 对象压成 pack。无损操作——所有快照照常可回退。节流凭据写在影子仓库内的gc.stamp,重启 DSH 不会重置周期。两个阈值可用环境变量覆盖(一般用不着):DSH_RECALL_GC_SNAPS、DSH_RECALL_GC_HOURS。 -
会话删除联动清理:会话被彻底删除(会话日志从磁盘消失)后,下一次维护会自动删除该会话的全部快照并释放空间。归档不算删除——撤回功能自己归档的原会话日志仍在,快照保留、随时可从归档找回。判断很保守:会话只是冷着(不内存里)不会误清;无法核实日志状态时宁可不清。
-
用户自定义排除:打开「设置 → 插件 → 撤回设置」即可可视化编辑快照排除项——输入路径或模式回车即加、常用模式(
dist/、*.log、.env等)一键追加、保存后下一次快照/回退立即生效,无需重启。也可以直接编辑 home 下dsh-recall-snapshots/exclude.txt(即$DSH_HOME/dsh-recall-snapshots/exclude.txt,未设置时为~/.dsh/dsh-recall-snapshots/exclude.txt;UTF-8),一行一条 gitignore 风格 pattern(#开头为注释),两种方式编辑的是同一份配置,例如:# 构建产物不进快照 dist/ build/ *.log对所有项目生效(home 不可写而降级到项目内存储时,该工作区有独立的排除配置,设置页会分卡片列出)。新增排除只影响之后的快照;回退到更早的快照时,当时尚未排除的文件仍会被恢复(回到当时的状态,这正是回退语义)。想彻底清掉已进快照的目录,可手动删除 home 下
dsh-recall-snapshots/里对应项目的哈希目录。设置页标签依赖 DSH 自带设置页(0.1.0-rc.x 均含);极旧版本看不到该标签时,直接编辑文件等效。 -
树形快照管理:打开「设置 → 插件 → 撤回设置 → 快照管理」可看到树形列表——第一级工作区(文件夹名)、第二级会话(会话标题)、第三级快照(时间 + 消息内容摘要,悬停看完整内容)。工作区和会话节点可展开/折叠;每一级右侧都有删除按钮,删除前会二次确认。删除工作区 = 清掉该工作区全部快照;删除会话 = 清掉该工作区内该会话的全部快照;删除叶子 = 只删那一条快照。
工作原理
每条用户消息发送时(agent 动文件之前),工作区被快照进一个独立的影子 git 仓库;撤回时用 git archive 恢复文件、通过 DSH 官方 sessions.fork 机制把会话切到该消息之前。二进制安全,全程不触碰项目自身的 git 状态。
-
快照存储:home 下
dsh-recall-snapshots/<SHA256(项目绝对路径)>/,内含影子 git 仓库(git/,tag 名为snap-<消息ID>)与索引文件index.json(消息 ID → 快照时间 / 会话)。Windows 上脚本走 PowerShell,Linux/macOS 走 bash(按ctx.shell平台层挂载的执行器自动分叉)。 -
想直接翻历史快照:
git --git-dir="<store>\git\.git" tag -l git --git-dir="<store>\git\.git" ls-tree -r --name-only snap-<消息ID>
本地开发(无需发布)
# 把包目录放进 web profile 的 node_modules,并登记到 bundles
$pkg = '<你的仓库克隆路径>\dsh-recall-plugin'
$profile = "$env:USERPROFILE\.dsh\profiles\web"
Copy-Item -Recurse -Force $pkg "$profile\node_modules\dsh-recall-plugin"
# 手动编辑 $profile\package.json:
# dependencies 加 "dsh-recall-plugin": "1.0.0"
# dsh.profile.bundles 加 "dsh-recall-plugin"
# 然后重启 DSH 并硬刷新页面
License
MIT
收录徽章
[](https://deepseek-plugin.org/plugins/limbo947/dsh-recall-plugin)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。

