dsh-recall-plugin
Recall Plugin
在 DSH 中撤回自己发过的消息:工作区文件与对话历史一起回到那条消息发出之前,消息的文本与附件自动放回输入框,改完即可重发。文件走独立影子 git 快照(不碰项目自身的 git),对话走官方 sessions.fork,原会话归档可找回。
插件会安装到这里;不确定时保持 web。
npx -y @deepseek-ai/dsh plugin --profile web add dsh-recall-plugin@2.3.24


dsh-recall-plugin
在 DSH 中撤回自己发过的消息:工作区文件与对话历史一起回到那条消息发出之前,消息的文本与附件自动放回输入框,改完即可重发。文件走独立影子 git 快照(不碰项目自身的 git),对话走官方 sessions.fork,原会话归档可找回。
插件会安装到这里;不确定时保持 web。
npx -y @deepseek-ai/dsh plugin --profile web add dsh-recall-plugin@2.3.24


Recall Plugin 以 dsh-recall-plugin 发布,当前版本为 2.3.24。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。
简体中文 | English
撤回时文件与对话一起回退:工作区先被快照进一个独立的影子 git 仓库,撤回就用它把文件恢复到那条消息发出之前;对话通过 DSH 官方的 sessions.fork 切到该消息之前的 turn 边界,原会话归档保留、随时可找回。撤回后,这条消息的文本与附件会自动放回输入框,改完即可重发。快照全程不触碰项目自身的 git,存储默认落在 $DSH_HOME 下。最主要的边界:快照只在消息发送时创建,插件启用前的历史消息没有快照、不显示撤回按钮。
| 撤回按钮 | 确认面板 · 变更文件清单 |
|---|---|
| 悬停出现撤回按钮 | 确认面板 · 变更文件清单 |
带括号版本号的能力需要该版本或更高;其余无特殊版本要求。
.gitattributes 转换影响,换行与二进制内容字节级保真(2.1.1+)。$DSH_HOME 下,与会话的沙箱权限无关(workspace-write / read-only 照常工作),仅当 home 不可写才降级到项目内 .dsh-recall-snapshots。git gc,会话删除联动清理,可按条数与保留天数自动清理;设置页提供工作区 → 会话 → 快照三级树形管理,支持搜索与分级删除。设计上接受的边界与尚未覆盖的极端情形,使用前值得先确认。
git add 之间有约 0.5–1.5 秒窗口(Windows 上仅一次 PowerShell 启动就占约 0.4 秒)。秒级完成的琐碎任务若在这个窗口内改完文件,该快照会连带捕获本轮改动——撤回时文件回退成为空操作(预览面板显示「共 0 个文件将变更」),对话回退不受影响。.git)无法索引:快照对其余部分照常(fail-open,页面会提示跳过了哪些路径),但其内容不参与回退。sessions.fork 出新会话,导致路由阶段重置为默认(工具面临时收窄)。现象、成因与解决方案见 docs/routing-interplay.md。前置:git CLI(未装时撤回按钮不出现,页面顶部会提示安装 git,不影响 DSH 运行);Windows 上 PowerShell 5.1 / 7 均可,Linux/macOS 需 bash + git;DSH 0.1.2-alpha.1 至 0.1.6-alpha.2(peerDependencies 为按 minor 版本线开窗 >=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,与 dsh.compatibility.dshReleases 声明一致;每条线以首个核验版本为下限、开一条上界到下一 minor 的区间,同线内后续 prerelease/正式版自动放行、无需改 peer 声明,未验证的新 minor 线(如 0.1.7)仍被拦截)。0.1.1-rc.2 及更早不再声明支持:那条线的客户端运行时没有 sessions/workspaces/uiWorkspace 服务,插件 UI 会静默不渲染。
dsh plugin --profile web add dsh-recall-plugin
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
dsh web # 前台运行
pm2 restart <your-dsh-name> # 由 pm2 托管
验证:重启后硬刷新页面(Ctrl+Shift+R),悬停任意一条插件启用后发送的用户消息——复制按钮旁出现「↶」即生效。没有按钮?九成是没重启 DSH 进程,或 git CLI 不在 PATH 里。
卸载:同时移除依赖与挂载,快照数据保留在 home 下 dsh-recall-snapshots/,想彻底清除手动删掉该目录即可。
dsh plugin --profile web remove dsh-recall-plugin
全部配置可在「设置 → 插件配置 → 撤回插件」卡片可视化修改(保存即热生效,无需重启),也可在 profile 的 cordis.patch.yml 按 id: recall 重述 insert 行改写;env 变量仅覆盖 gc 两项且优先级最高(设了 env 的字段在卡片里锁定)。
| 配置项 | 默认值 | 说明 |
|---|---|---|
gcSnaps | 50 | 每积累多少条快照触发一次 git gc(env DSH_RECALL_GC_SNAPS 可强制覆盖) |
gcHours | 24 | 距上次 gc 超过多少小时触发(与条数先到先触发;env DSH_RECALL_GC_HOURS) |
maxFileBytes | 104857600(100MB) | 超过该大小的文件不进快照、不被回退触碰 |
maxSnapshotsPerWorkspace | 500 | 每个工作区保留的最大快照数,超限自动删除最旧的;0 = 不限制 |
retentionDays | 0 | 按天数保留快照,超期自动删除;0 = 不启用(与条数上限各自独立生效) |
baseExcludes | .git、node_modules/、.dsh-recall-snapshots/、dsh-recall-snapshots/ | 基础排除表(gitignore 语法,优先级低于 exclude.txt) |
refillDraft | true | 撤回后把被撤回的消息(文本与附件)回填到输入框 |
snapshotEnabled | true | 快照总开关(关闭只冻结新建,已有快照仍可撤回) |
archiveOriginal | true | 撤回后归档原会话(关闭后原会话保留在会话列表中) |
设置卡片另提供「恢复默认」(一键重置全部字段)与「最近错误」查看/清空。
插件自动控制磁盘占用,无需手动管理:
定期 gc:每 50 条快照或距上次 gc 24 小时(先到先触发,阈值可配),后台执行 git gc 把 loose 对象压成 pack。无损操作——所有快照照常可回退。节流凭据写在影子仓库内的 gc.stamp,重启 DSH 不会重置周期。
条数上限与保留天数:每工作区快照默认上限 500 条(超限清最旧);也可按 retentionDays 设保留天数,两者独立触发、都可在配置卡片调整或关闭。
会话删除联动清理:会话被彻底删除(会话日志从磁盘消失)后,下一次维护会自动删除该会话的全部快照并释放空间。归档不算删除——撤回功能自己归档的原会话日志仍在,快照保留、随时可从归档找回。判断很保守:会话只是冷着(不内存里)不会误清;无法核实日志状态时宁可不清。
用户自定义排除:打开「设置 → 插件配置 → 撤回插件」卡片(默认收起,点卡片头展开)即可可视化编辑快照排除项——输入路径或模式回车即加、常用模式(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/ 里对应项目的哈希目录。
树形快照管理:打开「设置 → 插件配置 → 撤回插件 → 快照管理」可看到树形列表——第一级工作区(文件夹名)、第二级会话(会话标题,撤回链聚成版本家族)、第三级快照(时间 + 消息内容摘要,悬停看完整内容)。支持搜索与「加载更多」;工作区和会话节点可展开/折叠;每一级右侧都有删除按钮,删除前会二次确认。删除工作区 = 清掉该工作区全部快照;删除会话 = 清掉该工作区内该会话的全部快照;删除叶子 = 只删那一条快照;顶部另有带确认的「全部删除」。
每条用户消息发送时(agent 动文件之前),工作区被快照进一个独立的影子 git 仓库;撤回时先打「回退前」安全快照、再用 git archive 恢复文件、通过 DSH 官方 sessions.fork 机制把会话切到该消息之前。二进制与换行符安全,全程不触碰项目自身的 git 状态。
快照存储:home 下 dsh-recall-snapshots/<SHA256(项目绝对路径)>/,内含影子 git 仓库(git/,tag 名为 snap-<消息ID>)、索引文件 index.json(消息 ID → 快照时间 / 会话)与撤回链 lineage.json。Windows 上脚本走 PowerShell,Linux/macOS 走 bash(按平台自动分叉)。
Windows 上宿主把 shell 配成 bash 也照常工作(2.3.22+):官方 shell 由 profile 注册,win32 上可以只启用 bash-sandbox——此时 pwsh 脚本会被 bash 执行而全盘失败。插件首次执行命令前会先探测执行器能否跑 pwsh(哨兵命令),确认是 bash 后改用系统 PowerShell 5.1 直连执行,快照与撤回不受影响;ctx.shell 即 pwsh 的常规部署行为不变(探测一次、判为 pwsh 后一切照旧)。
想直接翻历史快照:
git --git-dir="<store>\git\.git" tag -l
git --git-dir="<store>\git\.git" ls-tree -r --name-only snap-<消息ID>
把 profile 对本包的依赖改成 link: 指向克隆目录;DSH 加载的是工作区 lib/ 构建产物(源码在 src/),改 src/ 后先 npm run build 再重启 DSH 生效,无需复制或发布:
# 1. 编辑 $env:USERPROFILE\.dsh\profiles\web\package.json:
# "dependencies" 里 "dsh-recall-plugin": "link:<你的克隆路径>\dsh-recall-plugin"
# "dsh.profile.bundles" 已含 "dsh-recall-plugin"(官方命令装过一次即可)
# 2. 在 profile 目录安装并重启
cd $env:USERPROFILE\.dsh\profiles\web
pnpm install
# 3. 重启 DSH + 硬刷新页面(Ctrl+Shift+R)
注意:全部源码在 src/(Host 在 src/host/、浏览器端在 src/client/、共享类型在 src/types/),lib/ 是纯构建产物目录——npm run build 经 esbuild 生成(逐文件转译 host 产物 + 打包 lib/client.js),产物随源码提交。改任何 src/ 后必须跑 npm run build,否则运行的是旧产物(CI 有产物新鲜度统一校验)。
npm test:纯逻辑单测(vitest,28 个文件 361 例,无 DSH 依赖,CI 与本地同跑)——配置解析、快照解析器、救援编排、错误分类、脚本模板同名导出契约、客户端纯函数、发布包内容布局、快照索引持久化、存储上限与保留天数等;npm run test:probe:官方 API 字段探针(依赖本机 dsh 安装;dsh 升级后本地必跑)——钉住 renderMessageImages/node/cwd、sessions.fork 的 atSeq/increaseTitle、listSessions 记录结构、AgentRegistry 等字段,违反即红;npm run verify:host:装配门禁(依赖本机 dsh 安装)——用真实 cordis 起插件,断言 inject 声明、端点注册、Config schema、卸载清理,装配回归发版前即可拦截;npm run build:host+client 全量打包(改任何 src/ 后必跑);npm run check:dsh:dsh 版本巡检(发布前)。npm ci --legacy-peer-deps + npm run typecheck + npm test + 产物新鲜度统一校验(npm run build && git diff --exit-code lib/;探针与装配门禁只在有 dsh 的机器跑)。MIT