dsh-retrace
撤回/编辑重发/重新生成,加上单会话版本化:每次回退的时间线、产物回退(git 优先、快照兜底)、分叉图、会话谱系,以及实时看门狗(并发写入第一时间快照日志)。编辑前自动停止运行中的 agent(官方 cancel/whenIdle),回退不会损坏持久化日志、也不会破坏 /compact。
安装
dsh plugin --profile web add dsh-retrace
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✗ |
| 2 列装 | — |
| 3 挂载 | — |
| 4 启动 | — |
dsh: initialized profile web at /home/node/.dsh/profiles/web四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
<div align="center">
🧭 dsh-retrace
撤回 · 重发(从这条重开)· 重新生成,加上写安全的会话版本化 —— DeepSeek Harness 的
Agent 业务层(生产级保证) 实现。




简体中文 · [English](./README.md)
</div>
撤回 / 重发 / 重新生成 —— 每个会话都该有的三个操作。但回退不只是「撤掉一条
消息」:DeepSeek Harness 把对话存在 append-only 事件日志里,撤回只回退上下文,改过的
产物文件不会自动还原。dsh-retrace 把对话和它的产物一起版本化,并保证
每一次新的回退都合法——不会弄脏日志,新写入的 marker 不产生 token-meter 配对债
(两段原子对按构造即通过)。
⚠️ 诚实的边界(与配套契约自己的说明一致):旧版本留下的单段 marker 是
已知设计债。压缩前请用配套check体检并fix --remove-markers清理,否则宿主的
压缩前自检会挡住 /compact。新的回退不会增加这笔债。
🛡️ 写安全 · 🔍 深层体检 · 🔄 检测→修复→守护 —— 详见下方「生产级保证」。
版本索引:[VERSIONS.md](./VERSIONS.md)
0.4.139 已发布到 npm——安装/固定版本请用当前 npm latest0.4.135(见 [VERSIONS.md](./VERSIONS.md));下文的dsh-retrace@0.4.139示例在该版本发布后适用。
⚡ 一分钟安装
需要带 dsh CLI 的 DeepSeek Harness;装完重启 DSH 生效(运行中的应用不会热加载)。
dsh plugin --profile desktop add dsh-retrace # DSH 桌面版 # 或 Web 部署:dsh plugin --profile web add dsh-retrace # 或从解压后的检出 / ZIP: # dsh plugin --profile desktop add ~/plugins/dsh-retrace
没有命令行? 先装一次社区插件市场,再在 设置 → Plugin Market 搜
dsh-retrace 一键安装:
dsh plugin --profile desktop add dshmarket # 只需一次
重启后,悬停任意助手回复 → ↩ / ↻;任意用户消息 → ✎。详细步骤见
[📦 安装](#-安装)。
🛡️ 生产级保证(0.4.x 全部已上线)
· 能力 · 说明
🛡️ · 写安全 · 每次回退过三层写前契约校验;运行中的 agent 自动停止(官方 cancel/whenIdle,带等待上限);轮次间 marker 用临时 step 包裹 —— 新的回退不会弄脏日志,新 marker 不产生 token-meter 配对债;旧单段 marker 是已知设计债(压缩前先 check + fix --remove-markers)
🔍 · 深层体检 · 配套 dsh-log-contract 30+ 条契约规则(token-meter 配对 / 跨 step 引用 / 物理序 / inbox 重放),用真实损坏会话当测试集 —— 能找出让 /compact 永久失效的那类问题
🔄 · 检测→修复→守护 · 看门狗在并发写入第一时间快照日志;离线 fix 原地中和问题 marker、裁剪跨 step 引用;写前校验在坏事件落盘前拦住
✨ 功能
操作 · 入口 · 效果
↩ 撤回 · 悬停任意助手回复;或用户消息下方的操作行 · 先弹二次确认(破坏性动作:本条及其后的对话将离开会话)。确认后,若本轮仍在运行,插件先通过官方停止入口暂停在途轮次并等待(有上限);暂停失败/超时也照常撤回,并给出可见提示。随后整轮(该条输入及其输出、工具行)从模型上下文与对话视图中一并移除,输入原文回显到输入框方便立即修改后重发;一条短暂提示标记回退点,你继续输入后自动消失。
✎ 重发(从这条重开) · 用户消息下方的操作行 · 主语义是从这条重开:本条及其后被回退,并用新文本重发,对话进入新的时间线分支。若该范围被守卫拒绝(过大、无法原地改写),错误提示里给出兜底动作 —— 「仅改文本(保留后续)」。新消息下方有一个折叠的「原输入」对照,点击展开、可配置关闭。
↻ 重新生成 · 悬停任意助手回复 · 回退并隐藏该回复及其后内容,重新发送原提问,让智能体重新作答。
撤销一次撤回
操作 · 作用面 · 效果
↺ 恢复显示 · 只改界面 · 把该标记隐藏的行重新显示回对话视图。日志只增不减、模型上下文不变,撤回痕迹保留。入口在该标记行上。
⏪ 真正恢复 · 改日志 · 原地中和这两段标记(不改 seq 编号),让被撤回区间回到模型面,该区间的重发 / 撤回入口复活。要求会话空闲、且不是你当前正在查看的会话;成功后需切走并重开该会话(或刷新页面)才看到恢复后的内容。被拒时给出可执行的下一步(会话运行中 / 文件被其他进程持有 / 已被更晚的标记重新遮蔽 / 当前宿主未装配该能力)。
读档点与回档(0.4.x 已上线) —— 每次回退都会被记录为一个读档点:
· 能力 · 说明
🕘 · 读档点 · 对话视图里的「读档点」Tab:每个改动(类型/时间/消息数/文件变更徽标),经 session/projection 推送帧实时更新(零轮询),大列表窗口化;嵌套历史按大纲逐层展开
↩️ · 产物回退 · 仅对话 / 仅产物 / 两者,先干跑预览再执行;git 优先 + 内容寻址快照兜底;回退本身是新读档点(restore)。预览在会话运行中直接拒绝(不会出现「预览说可以、确认时才被拒」),预览/回档失败都会在界面上显示,不静默
🧬 · 谱系标识 · 新建会话自动分配稳定谱系标识;侧栏每个会话只显示一个标识(刷新不重复)
🧭 · 跳转对话 · 从读档点一键跳转到对应位置(自动翻页加载更早历史 + 锚点高亮);该点超出自动加载预算时,给出可诊断原因,而不是点了没反应
🧹 · 存储有界 · 快照只保留最近 N 个读档点(默认 50);节流后台扫掠回收被截断的旧档
损坏日志上的回档不静默:宿主的严格重放是权威,但一条畸形事件(例如第三方写入的
畸形替换行)就能毒化整次重放。这种情况会退到镜像重放,日志同时记录
「已降级」与原始错误,并在 wire 上把结果标为 degraded;连镜像都跑不了时返回结构化的
replay-failed错误,而不是笼统的internal。
为什么与众不同(交互层差异——上面的保证是存储层):
- 🎯 整轮撤回 —— 移除输入 和 它的输出(含工具行),而不只是单条气泡。
- 🖥️ Web + Desktop 双端 —— 同一插件覆盖 DeepSeek Harness 两种界面。
- 🧠 视图 ⇄ 上下文同步 —— 对话视图永远反映智能体真正看到的内容。
- ⚡ 30 秒上手 —— 动态插件形式无需重建即可在当前会话试用。
📦 安装
1. Profile bundle(推荐)
包声明了 dsh.bundle 清单,可通过官方插件路径安装到任意 profile:
dsh plugin --profile <name> add dsh-retrace
⚠️ 安装后需要重启。 安装会写入新文件并重新生成 profile 组合,但运行中的应用
不会热加载 bundle —— 请退出并重新打开 DSH Desktop(独立 Web 部署则重启
dsh 进程)来加载插件。卸载:`dsh plugin --profile <name> remove
dsh-retrace`(卸载后同样需要重启)。
2. 手动安装(不依赖 dsh CLI)
用纯文件编辑 + pnpm 装进同一个 profile —— 也就是 dsh plugin add 帮你做的那些步骤:
下载了 ZIP? 解压到固定位置(如 ~/plugins/dsh-retrace),
然后执行 dsh plugin --profile desktop add ~/plugins/dsh-retrace;或按下面步骤,
把依赖行指向该文件夹:"dsh-retrace": "file:~/plugins/dsh-retrace"。
1. 打开 profile 清单(默认位置:DSH Desktop 为 <插件数据家>/profiles/desktop,
独立 Web 为 <插件数据家>/profiles/web —— 插件数据家在设了 $DSH_HOME 时就是它,
否则跟随活动会话基座(基座来自 $DSH_HOME 与 $DSH_SESSION_BASES 配置的额外基座,
最后兜底 ~/.dsh);~/.dsh/profiles 只是迁移前的兜底),同时加入依赖和 bundle 层条目:
{
"dependencies": {
"dsh-retrace": "^0.4.139"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-retrace"
]
}
}
}
(保留 profile 原有条目,只需新增 dsh-retrace 这两处。)
2. 在 profile 目录里安装:
cd "$DSH_HOME/profiles/<name>" && pnpm install # 或你实际使用的基座
3. 重启 DSH Desktop / dsh 进程(见上文)。
本地开发时,可以把依赖指向本地检出目录而不是注册表:
"dsh-retrace": "file:/路径/to/dsh-retrace" —— 或者交给 dsh:
dsh plugin --profile <name> add /路径/to/dsh-retrace。
想要最新提交而不等发版时,用本包 repository 字段里的仓库地址加 git 依赖
(pnpm 写法 "dsh-retrace": "github:<owner>/dsh-retrace"),放在同一个
dependencies 块里,再 pnpm install。
3. npm 包 + 组合文件(经典方式)
npm i dsh-retrace
在所使用的应用/部署的 cordis.yml 组合文件中加入一行普通插件条目:
- name: 'dsh-retrace'
Client 半区会依据包内 dsh.client 元数据被自动打包进 Web 客户端(组合变化时会自动
重建客户端模块);Host 半区为浏览器 UI 注册同源 HTTP 路由 /api/plugins/retrace/*。
4. 动态插件(当前会话,免安装、免重建)
包内提供了两个自包含的动态入口:
1. 打开插件编辑界面,用 lib/dynamic-host.js(Host 半区)和
lib/dynamic-client.js(Client 半区)新建插件;
2. 批准并运行 Client 半区;
3. 完成 —— 悬停任意助手回复或用户消息,即可使用 ↩ / ✎ / ↻。
动态 Host 通过 harness.handle 注册同一组操作
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:28,最后更新 2026-11-06