回滚对话、编辑后重发,并快速跳转历史轮次
24.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add sharedcare/dsh-conversation-rollback该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · ui
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 54 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 9 处,展示前 9 条)
- 读取本地文件lib/index.js:101
const raw = await readFile(filePath) - 写入本地文件lib/index.js:138
await writeFile(tmp, payload) - 读取本地文件lib/index.js:142
const probe = await readFile(tmp) - 写入本地文件lib/index.js:153
await rename(tmp, filePath) - 发起网络请求lib/client.js:385
fetch("/api/conversation-rollback", { - 发起网络请求lib/client.js:411
fetch("/api/conversation-rollback", { - 发起网络请求lib/client.js:556
fetch("/api/conversation-rollback", { - 发起网络请求lib/client.js:672
fetch("/api/conversation-rollback", { - 发起网络请求lib/client.js:1184
.fetch(SETTINGS_ROUTE, {
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
为 DeepSeek Harness(DSH)Web UI 提供 Codex 风格的会话回滚和编辑重发插件
README
由 DeepSeek 最新模型翻译生成conversation-rollback
Codex 风格的会话回滚、「编辑输入后重新生成」,以及 DeepSeek Harness(DSH)Web UI 右边缘的会话大纲栏。
- v1.3.0 —— 回滚 + 编辑后重发(本包最初的范围)。
- v1.4.0 —— 把独立的 dsh-session-toc 大纲栏并入本包:一个插件、一个客户端 bundle、一次安装。
- v1.4.1 —— 客户端兼容 DSH 0.1.2-rc.1:Chat 目标改为通过会话作用域的 chat 钩子(useChat)读取,user 节点的接管改为从条目变更监听安装,不再在 apply 时一次性查找。
- v1.4.2 —— 宿主兼容 DSH 0.1.5-rc.1:物理行编解码器内置到 lib/chunk-rows.js,已存储会话通过持久化句柄接缝(open(id, 'read'))读取,实时持久游标在 persistence.tracker.writers 上回退(含其 observedLength 守卫),事件日志从 session.log 读取。
- v1.5.0 —— DSH 设置通用页上的开关可打开或关闭大纲栏(及其 ☰ 头部按钮);该偏好是 conversation-rollback 命名空间下的用户设置,持久化在 settings.yaml。
展开完整文档(README 剩余 1 节)
conversation-rollback
Codex 风格的会话回滚、「编辑输入后重新生成」,以及 DeepSeek Harness(DSH)Web UI 右边缘的会话大纲栏。
- v1.3.0 —— 回滚 + 编辑后重发(本包最初的范围)。
- v1.4.0 —— 把独立的 dsh-session-toc 大纲栏并入本包:一个插件、一个客户端 bundle、一次安装。
- v1.4.1 —— 客户端兼容 DSH 0.1.2-rc.1:Chat 目标改为通过会话作用域的 chat 钩子(useChat)读取,user 节点的接管改为从条目变更监听安装,不再在 apply 时一次性查找。
- v1.4.2 —— 宿主兼容 DSH 0.1.5-rc.1:物理行编解码器内置到 lib/chunk-rows.js,已存储会话通过持久化句柄接缝(open(id, 'read'))读取,实时持久游标在 persistence.tracker.writers 上回退(含其 observedLength 守卫),事件日志从 session.log 读取。
- v1.5.0 —— DSH 设置通用页上的开关可打开或关闭大纲栏(及其 ☰ 头部按钮);该偏好是 conversation-rollback 命名空间下的用户设置,持久化在 settings.yaml。
- v1.5.1 —— 设置行与大纲栏文案在运行时跟随 harness 语言切换。
English · 中文
Features
- 编辑输入:入口在用户消息气泡的操作行里,紧挨复制按钮(✎)。点击打开内联编辑器。保存后,宿主把会话日志截断到该轮之前,再把编辑后的文本作为新消息推入 Agent 收件箱,让模型重新生成回答。原回答及其后所有轮次都会被删除。
- 回滚到此处:入口在助手回答底部,紧挨「在新会话中分支」按钮(↩,二次点击确认)。它会删除该轮之后的所有消息,并在原地继续对话。
- 会话大纲栏(1.4.0 新增):会话的右边缘目录。
- 收起时:一条 26px 的窄条固定在消息列右边缘——你发送的每条提示词对应一个刻度;高亮(蓝色)刻度是当前位于视口顶部下方的那一轮。
- 展开时(悬停、点击窄条上的 ☰,或按 Ctrl/Cmd+Shift+O 固定):把你发送的每条提示词列成一行——带轮次编号、时间戳,运行中插入的引导消息还带 steer 标记。点击某行(或某个刻度)即可把该轮滚动到视野内并闪烁高亮。
- 搜索:过滤已加载的窗口;没有命中时自动向历史翻页(session.loadOlder(),最多 40 页),直到加载到匹配项或历史到头。
- 只有 user / steering 聊天节点会进入大纲:空输入、纯图片输入、工具行和注入的上下文都排除在外。
- 侧边栏锚定的是会话栏的几何位置([data-conversation-scroll]),不是窗口,并用 ResizeObserver 跟随它。所以挤压会话栏的侧面板(dsh-better-sidebar、DSH 自带的详情栏、侧卡底部面板)永远不会盖住它,也不会有 z-index 冲突。
- 固定状态保存在 localStorage['dsh-session-toc:pinned'] 里(与独立插件用的是同一个键,所以已有的固定状态会保留)。
- 整条侧边栏可以在设置 → 通用 → 会话大纲里关掉。关掉后侧边栏和它的 ☰ 按钮都会消失,只有这个开关能恢复。这个选择是用户设置,存在 harness home 的 settings.yaml 里 conversation-rollback 下,由 web 和 desktop 两个配置档共享,不是每个浏览器各自的开关。如果连不上设置服务,侧边栏保持默认(开),那一行也会说明情况,所以设置服务缺失绝不会意外藏掉这个功能。那一行和侧边栏都会跟随 harness 语言切换,无需刷新。
- 最近一个已完成的轮次只显示编辑输入,那里不提供回滚。
- 暂不支持编辑含图片的输入。
- 会话运行中、子代理会话、以及存在未完成轮次时,操作不可用。
两个回滚操作都是破坏性的,无法撤销:原回复及其后所有消息会被永久删除。
主机端点
POST /api/conversation-rollback
- 回滚:{ "sessionId": "...", "atSeq": <any seq inside a completed turn> }
- 编辑:{ "operation": "edit", "sessionId": "...", "turn": <turn number>, "text": "..." }
- 读取大纲开关:{ "operation": "settings.get" } → { "ok": true, "outline": true, "revision": 0 }
- 写入:{ "operation": "settings.update", "patch": { "outline": false }, "expectedRevision": 0 } → 同样的结构,或者命名空间已变动时返回 { "ok": false, "code": "settings-conflict", ... }。
不属于以上任何一项的操作仍会派发到回滚,所以现有调用方不受影响。在没有设置服务的构建上,settings. 会返回 settings-unavailable,此时侧边栏保持默认(开)。
环境要求
- 装了 web 配置档的 DSH(dsh web)或 DSH Desktop 应用(用的是 desktop 配置档)。
- PATH 里有 pnpm,用于管理 dsh plugin。
- GitHub 安装和本地克隆需要 git;只有 npm pack 方式需要 npm。
安装
1. 先选好配置档
desktop 和 web 是两套独立的组合,各有自己的 package.json + node_modules。如果插件一直不出现,最可能的原因是装到了另一套里。
要判断运行中的 web 进程用的是哪个配置档,抓取它的根页面,找 Desktop 标记:
bash / macOS / Linux —— 把 <port> 换成环境变量 DSH_WEB_URL 里的 URL
curl -s "http://127.0.0.1:<port>/" | grep -o dsh-plugin-desktop
PowerShell / Windows
(Invoke-WebRequest "http://127.0.0.1:<port>/" -UseBasicParsing).Content | Select-String "dsh-plugin-desktop"
有命中,说明 Desktop 外壳托管着这个进程 —— 用 --profile desktop。
没有命中,说明是普通的 dsh web 进程 —— 用 --profile web。
2. 从 GitHub 安装(推荐)
dsh plugin --profile <web|desktop> add github:sharedcare/dsh-conversation-rollback#<sha-or-tag>
dsh plugin 会把包加到选定的配置档,并自动注册 bundle 补丁层。建议固定到某个 commit 或 tag,这样后续的 push 不会悄悄改掉实际运行的代码;v1.4.0 tag 指向 commit 5de8731。
如果是 fork,把 sharedcare 换成你的 GitHub 用户名,或者直接用完整仓库 URL,把固定版本追加到 git URL 后面:
dsh plugin --profile <web|desktop> add "git+https://github.com/<owner>/dsh-conversation-rollback.git#<sha-or-tag>"
合并后的 bundle 已经提交,包也声明了没有 prepare 脚本,所以 github: 安装只拉源码、不跑构建 —— 不需要 pnpm 的 allowBuilds 授权。
3. 从本地 clone 或 tarball 安装
开发时用,或者你想自己构建这个包:
git clone https://github.com/sharedcare/dsh-conversation-rollback.git
cd dsh-conversation-rollback
方案 A —— 把这个 checkout 直接 link 进配置档(开发时好用;改完跑 pnpm run build 再刷新页面就生效):
dsh plugin --profile <web|desktop> add link:$PWD
方案 B —— 安装打包好的 tarball:
npm pack
dsh plugin --profile <web|desktop> add ./conversation-rollback-1.5.1.tgz
(文件名以 npm pack 打印的为准 —— 当前版本是 1.5.1。)
4. 从 1.3.0(或独立的 session-toc 插件)迁移
- 如果你之前装过独立的 dsh-session-toc 插件,先把它删掉,否则合并后的包会挂出两条轨道:
dsh plugin --profile <web|desktop> remove dsh-session-toc
- 如果 web 配置档是在 bundle 补丁机制之前装的,配置档里的 cordis.patch.yml($DSH_HOME/profiles/web/cordis.patch.yml,默认 ~/.dsh/profiles/web/cordis.patch.yml)可能还留着手写的 - insert: conversation-rollback 行。删掉它 —— 装好的 bundle 补丁会自动加这条,手写的那行是重复的。
- 升级 git/link 方式的安装:先 remove,再按第 2 步用想要的 commit/tag 重新 add。
5. 启用并验证
1. 重启 DSH Web 进程 / Desktop,让宿主路由和浏览器客户端加载进来。(只有增删插件才需要重启;重新提供的 lib/client.js 每次请求都会读取。)
2. Web 配置档:
dsh plugin --profile web listsh
dsh web --dump-config | grep conversation-rollback
输出里应该能看到 bundle 段,以及一条 id: conversation-rollback 的条目。
3. 桌面端(shell 没有 --dump-config,直接从运行中的页面探测加载的 bundle;dsh-toc-root 是大纲栏的样式根类)。模块加载器按依赖图每行提供一个组合 URL(/plugins/??<id>/client.js&rev=<rev>,rev 取自 window.__DSH_BOOT__),所以直接问页面,别猜路径: js // DevTools console on the DSH page (the page already holds the auth cookie)
await fetch(__DSH_BOOT__.entries.find(e => e.id === 'conversation-rollback').url)
.then(r => r.text())
.then(t => ({ status: 200, hasRailCss: t.includes('dsh-toc-root'), bytes: t.length }))
预期 hasRailCss: true。如果大纲栏不见了、但回滚按钮还能用,说明客户端 bundle 是旧的——强制刷新浏览器页面再试。
卸载 sh
dsh plugin --profile <web|desktop> remove conversation-rollback
之后重启 DSH Web 进程 / 桌面端。
仓库结构与构建
模块加载器每个插件条目只提供一个客户端 bundle(/plugins/<id>/client.js),而且在工厂函数里,require 只能解析共享模块表(react、react-dom/client、注入的 @deepseek-ai/)。所以两个功能没法拆成两个 bundle——src/ 放手写源码,lib/ 放提交的产物。
| 文件 | 作用 |
| src/client.rollback.js | 回滚客户端 bundle(上游代码 + 下面唯一一处 FORK DEVIATION 标记) |
| src/session-toc.js | 大纲栏工厂函数体(已剥掉 bundle 外壳) |
| lib/client.js | pnpm run build 的产物——不要手改 |
| lib/index.js | 宿主侧(路由、改写、实时手术、设置命名空间) |
| lib/chunk-rows.js | 移植自 dsh-session 内部物理行编解码器的 vendored 版本 |
| tools/merge-client.mjs | 拼接 / 拆接工具 |
| test/chunk-rows.mjs | 宿主编解码器往返测试(pnpm test) |
| test/host-route.mjs | 宿主侧路由 + 设置命名空间测试(pnpm test) |
| test/host-stubs.mjs | 内存导入桩,宿主测试通过模块钩子加载 |
| test/smoke.mjs | 无浏览器客户端冒烟测试(pnpm test) |
sh
pnpm run build # src/client.rollback.js + src/session-toc.js -> lib/client.js
pnpm test # node --check lib/.js + browserless smoke test
pnpm run build:strip # inverse: lib/client.js -> src/client.rollback.js
为什么大纲栏要包在自己的 IIFE 里:两半都在工厂作用域里声明了 function apply。直接拼接是合法 JavaScript,但后声明的会静默胜出——回滚那一半就不再注册它的三个插槽条目,而且不报错。build 不是 npm 生命周期脚本,所以安装包时永远不会触发它(只有 prepare 会,而这个包故意不设)。
为什么产品坚持这样做:github: 安装会拉取源码,但不构建,因此要么包自带 prepare(用户得在配置档 pnpm-workspace.yaml 里通过 allowBuilds 批准它——等于授权执行代码),要么直接发布构建产物。本包发布构建产物:零构建、零审批,.gitignore 明确拒绝忽略 lib/。
与上游唯一的偏离标记在 src/client.rollback.js(FORK DEVIATION):注入的 带有 data-plugin / data-plugin-css——这是 dsh-client-hmr 在热替换时回收插件样式表唯一匹配的属性。没有它们,每次重载都会多留一份过期的 rollback CSS 副本。
跟进别处对 lib/client.js 的修改:merge 和 strip 是精确互逆的(往返后字节完全一致),生成的区域由 / == session-toc: BEGIN/END ... == / 标记框住,所以可以先把冲突挪开: sh
git merge <upstream> # conflict lands in lib/client.js
node tools/merge-client.mjs --strip # peel the generated regions off
resolve the conflict in src/client.rollback.js (or take upstream's version)
pnpm run build && pnpm test
整行锚点(exports.apply = apply; / exports.name = "conversation-rollback";)缺失或重复时,生成器会直接报错,而不是产出一个功能残缺的 bundle;行锚点保证上游文件的缩进原样保留。smoke.mjs 把合并本身钉死:两半都注册,rollback 对 user 节点的接管保持 priority: -1,rail 的投影和向后翻页正常,prepend 后读者的视口偏移不变,抛异常的 rail 拖不垮 rollback,两份样式表都带 HMR 可回收的归属标记。
桌面端:安装恢复账本说明
Desktop 宿主在 <DSH Desktop data>/plugin-install-recovery/state.json 维护一份安装恢复账本(macOS:~/Library/Application Support/DSH Desktop/...,Windows:%APPDATA%\DSH Desktop\...)。一次安装停在 phase: "awaiting-restart",下一次安装就会被 another plugin install recovery transaction is pending 挡住,唯一的清除办法是重启 Desktop(启动时健康检查)或在恢复页回滚该事务——没有命令行提交命令。
如果不想重启就要绕过,把那次调用指向另一个 WAL 位置:校验只要求文件名为 state.json、位于名为 plugin-install-recovery 的目录内(父目录的父目录任意,见 install-recovery-BD5jkQTK.js:121-129)。代价是:这次安装不会进入应用的常规账本,也不会被自动回滚。
故障排查
- 如果「Save and regenerate」失败并报 Cannot read properties of undefined (reading 'adapterDefaults'),说明运行中的 Agent 仍缓存着来自截断的日志。重启 Web 进程,让当前的 lib/index.js 被加载;这个版本会在拼接后重置会话请求/上下文折叠、派生消息缓存、agent.requestHeaderLogged 和运行时上下文投影。
- 如果安装后按钮没有出现,重启 DSH Web,运行上面的验证命令,然后硬刷新浏览器页面。
- 如果 rail 缺失,而 /plugins/conversation-rollback/client.js 返回 200 但不含 dsh-toc-root,说明提供的 bundle 早于 1.4.0——重新安装新版本并重启。
- 如果 rail 挂载失败,页面左下角会出现红色诊断条(dsh-toc-bar),带错误信息;回退那一半仍可用(rail 在自己的 try/catch 里挂载)。
- 如果关掉 rail 后它消失了,而设置行又够不着(旧构建,或设置界面坏了),偏好仍可直接编辑:在 harness home 的 settings.yaml 里设 conversation-rollback: { outline: true },或从 GUI 自己的源向 /api/conversation-rollback POST {"operation":"settings.update","patch":{"outline":true}}。
- 如果 dsh plugin add 对某个 git 托管的 fork 失败,而该 fork 加了 prepare/postinstall 脚本,按 pnpm 打印的 allowBuilds 提示,把确切的 key 加到配置档的 pnpm-workspace.yaml,再重新运行安装。上游包没有构建脚本,所以标准 GitHub 安装不需要额外批准。
功能
- 修改输入:入口在用户输入气泡的操作行里,紧挨着复制按钮(✎)。
点击后弹出内联编辑框;保存时宿主会把日志截断到该轮之前,再通过 Agent inbox 以新消息驱动模型重新生成。原回复和后续轮次都会被删除。
- 回退到此:入口在助手回答尾部的操作行里,紧挨着「在新对话中分支」按钮(↩,需二次点击确认)。删除该轮之后的所有消息并原地继续。
- 会话目录(outline rail,1.4.0 新增):消息流右缘的会话目录。
- 收起态:26px 窄条贴消息列右缘,每根刻度 = 你发过的一条提问;蓝色刻度表示当前视口顶部所在的轮次。
- 展开态(悬停 / 点窄条上的 ☰ / Ctrl/Cmd+Shift+O 固定展开):按轮次列出你发过的每条提问——含轮次号、时间戳,中途引导(steer)消息带 steer 标记。点击行(或刻度)即滚动到那一轮并闪一下高亮。
- 搜索:在已加载窗口内过滤;没有命中就自动向更早翻页
(session.loadOlder(),上限 40 页)直到匹配出现或历史到底。
- 只收 user / steering 两类 Chat Node:空白输入、纯图片输入、工具行、注入上下文都不进目录。
- 定位基准是会话列([data-conversation-scroll])的几何而不是窗口,并用 ResizeObserver 跟随——被侧栏/详情列/侧卡底部面板压缩列宽时 rail 跟着移动而不被压住,也不需要抢 z-index。
- 固定状态存在 localStorage['dsh-session-toc:pinned'](沿用旧独立插件的 key,合并前固定过的状态继续生效)。
- 整个 rail 可以在设置 → 通用 → 会话大纲里关掉。关掉后 rail 与 ☰ 按钮一起消失,开关是唯一的回去路径;它是一项用户设置——存在 harness home 的 settings.yaml 的 conversation-rollback 段,web 与 desktop profile 共用——不是单浏览器开关。设置服务不可达时 rail 保持默认(开)并在行内说明,绝不会因为读不到设置就把功能藏掉。开关行与 rail 本身都跟随 harness 的语言切换,无需刷新。
- 最新的已完成轮次只显示「修改输入」,不显示回退。
- 包含图片的输入暂不支持修改。
- 会话运行中、子代理会话、存在未结束回合时不可操作。
两种回退操作都是不可撤销的破坏性操作:原回复及其后的所有消息会被永久删除。
端点
POST /api/conversation-rollback
- 回退:{ "sessionId": "...", "atSeq": <完成轮次内任一 seq> }
- 修改:{ "operation": "edit", "sessionId": "...", "turn": <turn number>, "text": "..." }
- 读大纲开关:{ "operation": "settings.get" } → { "ok": true, "outline": true, "revision": 0 }
- 写大纲开关:{ "operation": "settings.update", "patch": { "outline": false }, "expectedRevision": 0 } → 同一形状;命名空间已被别处改动时返回 { "ok": false, "code": "settings-conflict", ... }。
以上都不是的 operation 仍按回退分发,既有调用方不受影响。宿主没有设置服务时 settings. 返回 settings-unavailable,rail 保持默认(开)。
环境要求
- 可正常启动 web profile 的 DSH 环境(dsh web),或 DSH Desktop 应用(使用 desktop profile)。
- PATH 中有 pnpm,供 dsh plugin 管理插件使用。
- GitHub 安装和本地 clone 需要 git;只有使用 npm pack 方式时才需要 npm。
安装
1. 先确认你在用哪个 profile
desktop 与 web 是两份独立组合,各有自己的 package.json + node_modules。装完不生效,最常见的原因就是把插件装进了另一份。
探测当前运行进程使用的 profile——抓首页找 Desktop 标记: sh
bash / macOS / Linux — <port> 替换成 DSH_WEB_URL 里的端口
curl -s "http://127.0.0.1:<port>/" | grep -o dsh-plugin-desktop
powershell
PowerShell / Windows
(Invoke-WebRequest "http://127.0.0.1:<port>/" -UseBasicParsing).Content | Select-String "dsh-plugin-desktop"
命中说明该进程由 Desktop 外壳承载——用 --profile desktop;没有命中说明是普通的 dsh web 进程——用 --profile web。
2. 从 GitHub 安装(推荐) sh
dsh plugin --profile <web|desktop> add github:sharedcare/dsh-conversation-rollback#<sha-or-tag>
dsh plugin 会把包加入所选 profile,并自动注册 bundle patch 层。建议锁
commit 或 tag,避免后续推送悄悄改变实际运行的代码;v1.4.0 tag 指向 commit 5de8731。
维护自己的 fork 时,把 sharedcare 换成你的 GitHub 用户名,或使用完整仓库地址(锁点追加在 git URL 末尾): sh
dsh plugin --profile <web|desktop> add "git+https://github.com/<owner>/dsh-conversation-rollback.git#<sha-or-tag>"
合并产物已提交,且本包不声明 prepare 脚本,所以 github: 安装拉取源码但不会运行构建——不需要 pnpm allowBuilds 授权。
3. 从本地克隆或 tarball 安装
适合二次开发,或希望自行打包的场景: sh
git clone https://github.com/sharedcare/dsh-conversation-rollback.git
cd dsh-conversation-rollback
方式 A:直接把当前 checkout 链接进 profile(适合边改边调试;改动后执行
pnpm run build 再刷新页面即可):
sh
dsh plugin --profile <web|desktop> add link:$PWD
方式 B:先打包,再安装生成的 tarball: sh
npm pack
dsh plugin --profile <web|desktop> add ./conversation-rollback-1.5.1.tgz
(文件名以 npm pack 输出为准——当前版本是 1.5.1。)
4. 从 1.3.0 升级(或从独立 session-toc 插件迁移)
- 之前单独装过独立版 dsh-session-toc 的话务必先卸掉,否则合并包会挂出两条目录 rail:
sh
dsh plugin --profile <web|desktop> remove dsh-session-toc
- web profile 若在 bundle patch 时代之前装过:profile 的 cordis.patch.yml($DSH_HOME/profiles/web/cordis.patch.yml,默认 ~/.dsh/profiles/web/cordis.patch.yml)里可能还留有旧方案的手工
- insert: conversation-rollback 行——删掉;安装后的 bundle patch 会自动插入该条目,手工行会和它重复。
- 基于 git/link 安装的升级:先 remove,再按第 2 步用目标 commit/tag 重新 add。
5. 启用并验证
1. 重启 DSH Web 进程 / Desktop,以加载 host 路由和浏览器端 client。(只有新增/删除插件需要重启;lib/client.js 是宿主按请求读盘的,改产物不需要重启。)
2. web profile:
sh
dsh plugin --profile web list
dsh web --dump-config | grep conversation-rollback
配置 dump 中应出现 bundle 分节,以及 id: conversation-rollback 条目。
3. Desktop(外壳没有 --dump-config——在运行中的页面里直接探测被服务的 bundle;dsh-toc-root 是 rail 样式表的根类名)。模块加载器每个 entry 只服务一个 combo URL(/plugins/??<id>/client.js&rev=<rev>,rev 取自 window.__DSH_BOOT__),所以不要猜路径,直接问页面:
js
// DSH 页面上的 DevTools 控制台(页面本身已带 auth cookie)
await fetch(__DSH_BOOT__.entries.find(e => e.id === 'conversation-rollback').url)
.then(r => r.text())
.then(t => ({ status: 200, hasRailCss: t.includes('dsh-toc-root'), bytes: t.length }))
期望 hasRailCss: true。若回退按钮正常但 rail 缺失,说明客户端 bundle 是旧版——强制刷新浏览器页面后再试。
卸载 sh
dsh plugin --profile <web|desktop> remove conversation-rollback
卸载后重启 DSH Web 进程 / Desktop。
代码布局与构建
模块加载器每个插件 entry 只服务一个客户端 bundle (/plugins/<id>/client.js),factory 里的 require 只能解析共享模块表(react、react-dom/client、被 inject 的 @deepseek-ai/),所以两个功能不可能留成两个 bundle——src/ 是手写源码,lib/ 是已提交的产物。
| 文件 | 角色 |
| src/client.rollback.js | rollback 的 client bundle(上游原文 + 下方唯一一处 FORK DEVIATION) |
| src/session-toc.js | rail 的 factory body(外壳已剥掉) |
| lib/client.js | pnpm run build 的产物,不要手改 |
| lib/index.js | 宿主半(路由、重写、live 手术、设置命名空间) |
| lib/chunk-rows.js | 内置移植的 dsh-session 内部物理行编解码器 |
| tools/merge-client.mjs | 拼接 / 反拼接工具 |
| test/chunk-rows.mjs | 宿主 codec 往返测试(pnpm test) |
| test/host-route.mjs | 宿主半身路由 + 设置命名空间测试(pnpm test) |
| test/host-stubs.mjs | 宿主测试通过 module hook 加载的内存 import 桩 |
| test/smoke.mjs | 无浏览器冒烟测试(pnpm test) |
sh
pnpm run build # src/client.rollback.js + src/session-toc.js -> lib/client.js
pnpm test # node --check lib/.js + 无浏览器冒烟
pnpm run build:strip # 反操作:lib/client.js -> src/client.rollback.js
rail 为什么要包进自己的 IIFE:两半都在 factory 作用域里声明 function apply,裸拼接是合法 JavaScript 且后声明者静默胜出—— rollback 的三处 slot 注册会直接消失,不抛任何错。build 不是 npm 生命周期脚本,安装本包不会触发(会被触发的只有 prepare,本包故意没有)。
产物为什么要入库:github: 安装拉的是源码且不会运行 build,作者要么提供自包含的 prepare(用户还得在 profile 的 pnpm-workspace.yaml 里写 allowBuilds: { conversation-rollback: true } 才允许跑——等于授权该包在用户机器上执行代码),要么直接分发产物。这里选后者:零构建、零授权,.gitignore 明确写了不许忽略 lib/。
与上游的唯一偏差在 src/client.rollback.js(标了 FORK DEVIATION):给它注入的 补上 data-plugin / data-plugin-css——dsh-client-hmr 热替换只回收这两个属性匹配的样式表,不打标记每次重建都会多留一份旧 CSS。
lib/client.js 被别处改过时:merge 与 strip 是精确互逆(往返字节一致),生成段用 /* == session-toc: BEGIN/END ... == */ 成对标记框住,冲突可以整体挪出这个特性: sh
git merge <上游> # 冲突落在 lib/client.js
node tools/merge-client.mjs --strip # 先摘掉生成段,冲突面缩回纯 rollback
在 src/client.rollback.js 上解决冲突(或直接取上游版本),然后:
pnpm run build && pnpm test
生成器在锚点(exports.apply = apply; 与
exports.name = "conversation-rollback"; 的整行)缺失或不唯一时报错
退出,不会产出一个少一半功能的 bundle;整行锚点也保证不会吞掉上游那行的缩进。smoke.mjs 钉住合并本身:两半各自的注册都在、rollback 的 user 节点接管仍是 priority: -1、rail 的目录投影与向前翻页正常、prepend 时保持读者视口位置、rail 抛错不拖垮 rollback、两份样式都带 HMR 可回收的归属标记。
桌面端:安装恢复账本注意事项
Desktop 宿主维护一个安装恢复账本,位置在 <DSH Desktop 数据目录>/plugin-install-recovery/state.json(macOS: ~/Library/Application Support/DSH Desktop/...;Windows: %APPDATA%\DSH Desktop\...)。一次安装会停在 phase: "awaiting-restart",下一次安装会被 another plugin install recovery transaction is pending 挡下,而结清只能靠重启 Desktop(启动健康确认)或在恢复页回滚——没有 CLI 提交命令。
需要绕开而不重启时,可以给那一次调用换 WAL 位置:校验只要求文件名为 state.json、父目录名为 plugin-install-recovery,再往上的父级随意(见 install-recovery-BD5jkQTK.js:121-129)。代价是这次安装不进应用的固定账本,不会被自动回滚。
故障排查
- 若「保存并重新生成」后出现 Cannot read properties of undefined (reading 'adapterDefaults'),说明 live Agent 仍缓存了被截断掉的 request/header 状态。重启 Web 进程加载当前 lib/index.js;该版本会在拼接日志后重置 session 的 request/context fold、派生消息缓存、 agent.requestHeaderLogged 和 runtime-context 投影。
- 安装后看不到按钮:重启 DSH Web,执行上面的验证命令,然后强制刷新浏览器页面。
- rail 缺失但 /plugins/conversation-rollback/client.js 返回 200 且内容里搜不到 dsh-toc-root:服务的是 1.4.0 之前的旧 bundle——重新安装新版本并重启。
- rail 挂载失败时页面左下角会出现红色诊断条(dsh-toc-bar)显示错误信息;rollback 半身仍可用(rail 在自己的 try/catch 中挂载)。
- 关掉 rail 之后找不到设置里的那一行(旧版本,或设置界面本身坏了)时,偏好仍可直接改:在 harness home 的 settings.yaml 里写
conversation-rollback: { outline: true },或从 GUI 自己的源向后端
/api/conversation-rollback POST
{"operation":"settings.update","patch":{"outline":true}}。
- 如果你的 fork 新增了 prepare/postinstall 脚本,dsh plugin add 安装
git 依赖时被 pnpm 拦截,请按 pnpm 打印的提示把对应 key 加入 profile 的
pnpm-workspace.yaml 的 allowBuilds,再重新执行安装。上游包没有构建脚本,因此标准 GitHub 安装不需要额外放行。
仓库
- <https://github.com/sharedcare/dsh-conversation-rollback>
- 许可证:MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
sharedcare/dsh-conversation-rollback
回滚对话、编辑后重发,并快速跳转历史轮次
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,350已汉化DSH
71.5
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,506已汉化DSH
71.1
AI 矢量设计工具ZSeven-W/openpencil
全球首个 AI 原生开源矢量设计工具。
★ 7,027已汉化DSH
71.1
这是你的仓库?认领条目