dsh-recall-plugin
Recall any user message: rolls the conversation (official session fork) and workspace files (per-message shadow git snapshots) back to before it, with a diff-preview confirmation panel.
Install
dsh plugin --profile web add dsh-recall-plugin
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-recall-plugin 
简体中文 | [English](README.en.md)



在任意一条你发过的消息下方点「↶ 撤回」——工作区文件和对话历史一起回到那条消息发出之前的状态。
每条消息发送时,工作区先被快照进一个独立的影子 git 仓库(不碰项目自身的 git);撤回时按快照恢复文件,并经 DSH 官方 sessions.fork 把对话切回该消息之前的 turn 边界,原会话归档保留、随时可找回。被撤回消息的文本与附件自动放回输入框,改完即可重发;也可以点消息旁的「✎ 编辑」就地改完直接重发(不动文件),同一段对话的多个版本经 ‹ X/N › 翻页器来回切换。快照存储默认落在 $DSH_HOME 下。最主要的边界:快照只在消息发送时创建,插件启用前的历史消息没有快照、不显示撤回按钮。
[更新日志](CHANGELOG.md)
目录
- [界面预览](#界面预览)
- [功能亮点](#功能亮点)
- [技术栈与依赖](#技术栈与依赖)
- [已知限制](#已知限制)
- [安装](#安装)
- [使用](#使用)
- [配置项](#配置项)
- [快照维护与清理](#快照维护与清理)
- [常见问题](#常见问题)
- [工作原理](#工作原理)
- [事件契约(供同宿主插件监听)](#事件契约供同宿主插件监听)
- [参与贡献](#参与贡献)
- [License](#license)
界面预览
撤回按钮 · 确认面板 · 变更文件清单
 · 
- 设置页 · 插件配置卡片(配置表单 / 排除表 / 快照管理,保存即热生效)
功能亮点
带括号版本号的能力需要该版本或更高;其余无特殊版本要求。
- 文件 + 对话,整段回退:撤回的不只是聊天记录,agent 改过的文件也一并回到原样;不受项目
.gitattributes转换影响,换行与二进制内容字节级保真(2.1.1+)。 - 只想重来对话?文件可以不动(2.3.24+):确认面板可二选一撤回范围——默认「回退文件与对话」为完整回退;「仅撤回对话」则项目文件一个字节都不动(也不打安全快照),适合对回复不满意、但文件改动正是想要内容的场景。
- 不碰项目自身的 git,目录保持干净:快照存在独立的影子 git 仓库,分支、暂存区、未提交改动统统不受影响;存储默认落在
$DSH_HOME下、与会话沙箱权限无关(workspace-write / read-only 照常工作),仅当 home 不可写才降级到项目内.dsh-recall-snapshots。 - 先看清单再动手,可反复后悔:撤回前展示将变更的文件清单(修改 / 恢复 / 删除),确认后才执行;撤回后还能再撤到更早,被覆盖的文件一直找得回来。
- 撤回完就能重发(2.3.15+):消息的文本与附件(图片、文件)一起放回输入框,改完直接发送,不必重新挑一遍附件。
- 只改一个字也不用三连(2.5.0+):消息旁的「✎ 编辑」在该消息位置长出一张与官方输入框同款的编辑卡(预填原文、随内容增高),底部输入框保持原样;卡内可改字、粘贴/拖入附件,按 Enter 或点发送即新建会话、把改后的文本自动发出(原会话照常归档可找回),但只回退对话、不动项目文件。原消息附件以可移除的标签显示,权限以只读标签展示,模型与推理等级可在卡内按官方同款菜单切换(同步到底部输入框);
Esc取消。不想立刻发可在设置里关掉「编辑后自动发送」,改为只回填输入框。 - 同一句话的多个版本可以来回翻(2.5.0+):每次撤回或编辑重发都会 fork 出新会话,最后一轮回答的操作区出现
‹ X/N ›——点一下切到别的版本,侧栏始终只留当前那个(其余自动归档),切回时视口停回原位置。消息区因模型插件缺失等原因无法渲染时,会话头仍保留同一组翻页按钮;切换失败不会把当前版本困在归档区。 - 撤回全程有防护(2.0+,救援 2.1+):预览后出现新快照会强制重新预览;执行前自动打「回退前」安全快照,回退失败自动救援,救援失败给出可直接复制执行的手动恢复命令。
- 磁盘友好、自动维护:快照走 git delta 增量压缩,大文件自动跳过(阈值可配);定期无损
git gc、会话删除联动清理、按条数与保留天数自动清理;设置页提供工作区 → 会话 → 快照三级树形管理,支持搜索与分级删除。 - 失败不静默、能自愈(自愈 2.1+):失败按根因分类(git 缺失 / 磁盘满 / 无权限 / 锁冲突 / 目录冲突)给出可行动提示,同类故障 10 分钟只打扰一次,原因进设置卡片「最近错误」;自动清理残骸、连续 3 次失败指数退避、多实例按心跳互让;无法索引的路径跳过并告知,不中断整条快照(撤回时也不触碰它们)。
技术栈与依赖
本插件是 DSH bundle 形态:host 半跑在 DSH 进程内(Node ESM),client 半跑在浏览器会话页内,两侧同出一个 npm 包,包本体零运行时 dependencies。
- 运行时:Node.js ≥ 20、git CLI;Windows 走 PowerShell 5.1/7,Linux/macOS 走 bash(按平台自动分叉)。
- 语言与构建:TypeScript + ESM;
npm run build经 esbuild 产出lib/(host 逐文件转译、client 打包为单文件),产物随源码提交。 - 测试与门禁:vitest(纯逻辑单测、jsdom client 组件测试、官方 API 字段探针)+
tsc --noEmit类型门禁 + 装配门禁脚本,详见「参与贡献 → 测试」。 - 宿主依赖(peerDependencies,随 DSH 安装提供,无需单独安装):
@deepseek-ai/cordis4、@deepseek-ai/dsh-*(host-webserver / sandbox-policy / session / session-query / settings / shell)、@deepseek-ai/schemastery3.18;react18 为可选 peer(client 由宿主注入)。
已知限制
设计上接受的边界与尚未覆盖的极端情形,使用前值得先确认。
- 快照在消息发送时创建:插件启用前的历史消息没有快照,不显示撤回按钮。
- 快照是尽力捕获:从收到消息到
git add之间有约 0.5–1.5 秒窗口(Windows 上仅一次 PowerShell 启动就占约 0.4 秒)。秒级任务若在这个窗口内改完文件,该快照会连带捕获本轮改动——撤回时文件回退成为空操作(预览面板显示「共 0 个文件将变更」),对话回退不受影响。 - 会话第一条用户消息无法回退对话(仅文件回退),因为 fork 需要更早的 turn 边界;「编辑并重发」同样受此限制——没有更早的切点时会明确拒绝,而不是静默降级成只回填。
- 版本翻页器只识别本插件产生的版本(撤回 / 编辑重发);会话列表里手动 fork 出来的会话不计入家族。版本登记存在浏览器
localStorage,换浏览器或清缓存后翻页器不再显示历史版本(会话本身与归档不受影响)。会话头兜底入口能找回版本,但若目标会话内容依赖已卸载的模型 provider,恢复该 provider 前内容仍无法正常显示。 - 目标工作区的 agent 正在运行时无法发起撤回(防护设计,先停止 agent 再撤回)。
- 支持 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)无法索引:其余部分快照照常(fail-open,页面会提示跳过了哪些路径),但其内容不参与回退。 - Windows 保留设备名(如
nul、aux、con、com1,含扩展名形式)无法由 Git 索引,默认不参与快照与回退;这些路径保持原样,也不会反复产生跳过提示。此排除仅适用于 Windows。 - 工作区根路径自身超过 260 字符时不支持撤回:这是 Windows
MAX_PATH的硬限制——git 拒绝索引这类目录(\\?\扩展路径只能救工作区内部的深文件,救不了根前缀本身;实测根长 259 字符起就失败)。这种工作区的快照会失败,「最近错误」里提示把项目移到更短的路径。工作区内的深文件(根短、文件路径超 260)不受影响,照常快照与回退。 - 工作区内的目录重解析点(junction / 目录符号链接)默认不参与快照:它们指向的子树不会被索引,因此那部分内容不参与回退。win32 上这是必需的——git for Windows 把 junction 当普通目录递归,自引用 junction 会让索引膨胀到 Windows 的 31 层重解析点上限(实测 2 个文件的工作区产出 64 条索引);POSIX 侧符号链接照常进快照(git 记成
120000条目,不递归进目标)。确需把某个良性 junction(指向工作区外、非自引用)纳入快照时,可在排除配置里追加!路径/(如!ext-link/)反选恢复——用户排除行在机器生成行之后生效;切勿对自引用 junction 使用(爆炸根因)。 - 文件名含换行/TAB 的极端情形超出 diff 清单的解析能力(概率可忽略)。
- 与 dsh-routing-suite(渐进式工具披露路由)的交互:同时启用其 router-standard 预设时,撤回经
sessions.fork出新会话会把路由阶段重置为默认(工具面临时收窄)。现象、成因与解决方案见 [docs/routing-interplay.md](docs/routing-interplay.md)。
安装
前置:
- git CLI:未安装时撤回按钮不出现(页面顶部会提示安装 git),不影响 DSH 运行。
- shell:Windows 上 PowerShell 5.1 / 7 均可;Linux/macOS 需 bash。
- DSH 版本:
0.1.2-alpha.1至0.2.2-rc.1;已核验 minor 线内的后续版本自动放行,未核验的新 minor 线会被启动期兼容门禁拦截(开窗机制见下方折叠块)。 - 0.1.7-alpha.1 是破坏性版本(shell 执行与 settings 面接口更换),插件内置双分支共存适配:同一发布同时兼容 0.1.2–0.1.6 各线与 0.1.7+,老版本 DSH 上行为不变。
0.1.1-rc.2及更早不支持:那条线的客户端运行时没有sessions/workspaces/uiWorkspace服务,插件 UI 会静默不渲染。
<details>
<summary>peer 版本开窗机制(升级 dsh 前可看)</summary>
peerDependencies 按 minor 版本线开窗,与 dsh.compatibility.dshReleases 声明一致:
>=0.1.2-alpha.1 <0.1.3 || >=0.1.3-alpha.1 <0.1.4 || >=0.1.5-alpha.1 <0.1.6 || >=0.1.6-alpha.1 <0.1.7 | …(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::71,最后更新 2026-11-05