dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DeepSeek Harness 插件:同窗口内就地回退对话到更早的用户消息,可一并还原被改过的文件(Claude Code /rewind 语义)
DeepSeek Harness (DSH) 插件:同窗口内就地回退对话到任意更早的用户消息,只往会话日志追加一条标记,不新建分支、不删改历史;被撤回的原提示词自动回填输入框,改完直接重发。附带文件还原:回退时把 AI 改过的文件恢复成改动前,目标之后新建的文件删掉。
In-window conversation rewind for DeepSeek Harness: jump back to any earlier user message without forking the session; the withdrawn prompt returns to the composer for editing. Optional file restore brings AI-edited files back to their pre-edit state.
session.append + surfaceOp.replace、commands、slots、commandUi.decorate、tools/* 事件),不改 DSH 客户端代码。/rewind,但只做一件事:就地回退(不建分支、不留副本)。| 能力 | 状态 |
|---|---|
/rewind、/undo 命令 | ✅ |
| 裸命令打开官方 popupSelect 选目标 | ✅ |
| 回退到任意更早的用户消息(撤回目标及其之后的所有内容) | ✅ |
原提示词回填输入框(setDraft,失败退 DOM) | ✅ |
| 聊天界面隐藏被撤回的行(持久化:刷新/换会话/重启后仍然隐藏) | ✅ |
| 只追加不删改:日志保留全部原文,可搜索、可导出 | ✅ |
| 守卫:生成中先取消再回退、并发回退加锁、被压缩遮蔽的目标拒绝、子会话拒绝 | ✅ |
| 消息旁「↶」按钮(二次确认:只回退对话 / 对话+文件) | ✅ |
| 文件还原:回退时把 AI 改过的文件还原、删掉目标之后新建的文件 | ✅ |
| 撤销回退 | ❌(设计如此,见下) |
要求:DSH >=0.2.1-rc.2 <0.3.0-0,Node 22+。
# 方式一:直接从 GitHub 装(推荐)
dsh plugin --profile desktop add "github:280832849/dsh-rewind-lite"
# 方式二:本地打包安装
npm install && npm run build && npm pack
dsh plugin --profile desktop add "file:$PWD/dsh-rewind-lite-0.4.0.tgz"
装完重启 DSH(宿主半侧在新的 boot 组装时加载),再刷新页面(客户端半侧)。
卸载:
dsh plugin --profile desktop remove dsh-rewind-lite
若
dsh plugin add报ERR_PNPM_UNEXPECTED_STORE(profile 的 node_modules 与 dsh 转发的 pnpm 版本不一致),用同版本 pnpm 包一层再执行:PATH=<pnpm11 shim>:$PATH dsh plugin --profile desktop add …。
/rewind(或 /undo)→ 弹出候选列表(最新的在前)。也可以手输 /rewind @123 直接指定目标(seq 见候选列表),效果相同。
write / edit 工具执行前把原文件按字节暂存,执行成功后按「最近一条用户消息 seq」锚点提交。<DSH_HOME>/rewind-lite-snapshots/<sessionId>/<anchorSeq>/(只留最新几组,不自动清理,体积很小)。回退 = 往会话日志追加一条 user/message 标记,带 surfaceOp: {op:'replace', startSeq, endSeq} 覆盖「目标消息及其之后的所有表面节点」。DSH 重放日志时,模型可见表面自动从目标处截断;日志本身一个事件都不动。
客户端另算一遍:扫描持久化的 command 节点(@seq + outcome.sourceEventSeq)得到撤回区间,把落在区间里的 DOM 行隐藏。
(已回退,等待重新发送)),用户重发后与新消息并存,属正常现象。客户端依赖 harness 内部属性定位聊天行与输入框:
| 选择器 | 用途 |
|---|---|
[data-chat-anchor-key] / [data-chat-node-key] | 聊天行 → 快照节点 → anchorSeq(判断是否隐藏) |
[data-composer-input] | 输入框 DOM 兜底回填 |
这些属性随 UI 升级可能改名。DSH 大版本升级后第一件事:在浏览器里确认这两类属性还在;不在就改 src/client/index.js 里的选择器与 applyHidden() 的解析逻辑。
session.snapshotEvents() 已被标记 deprecated —— 若某次升级删掉它,改用新的只读事件读取 API(src/host.js 的两处调用)。surfaceOp 的 replace 语义与 sourceEventSeqs 完整性校验 —— 若语义变化,src/marker.js + src/host.js 的 append 调用要跟着改。uiConversation 服务的 binding().target('chat') 视图名与 conversation.input.for(scope).setDraft —— 若改名,改 src/client/index.js 的 chatOf / setComposerText。commandUi.decorate 的 popupSelect 契约 —— 若变化,退化成「裸命令只列候选、手输 @seq 执行」。npm run build # esbuild:宿主 ESM + 客户端 __ModuleLoader__ 闭包
npm test # 34 个离线测试(真 SDK 建会话 + 纯逻辑 + 宿主命令面)
npm pack # 出 tgz,供 dsh plugin add
升版本前必须先跑测试:test/session.test.mjs 用真的 @deepseek-ai/dsh-session 验证「追加标记 = 表面截断」,这个测试挂了就说明 SDK 语义变了,插件必须改,不能硬装。
思路与兼容性经验来自 SiriLee/dsh-rewind(MIT):本项目的回退语义、客户端隐藏行与输入框回填的做法与其一致,代码为独立实现,只保留「就地回退 + 轻量文件快照」这一件事。
MIT