dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DSH session and file rewind plugin (shadow git repo)
DSH 会话回退插件:给会话事件日志打「版本点」,可把会话回退到任意版本点(归档原日志 → 重建日志文件 → 刷新投影缓存),并可选 git 锚点实现文件级回退。
<会话工作区>/.dsh-rewind/<session>/ 独立目录.git 放在 .dsh-rewind/shadow-repos/,绝不侵入用户项目目录(不 git init、不写 .gitignore);快照范围受 pathspec 白名单约束(默认排除 .git/node_modules/.dsh-rewind/.agent-teams/_rollback/日志等,可配置)DeepSeek Harness(DSH)≥ 0.1.2-rc.1(插件在 0.1.2-rc.1 开发与验证;兼容依赖新版 Session API,旧版 DSH < 0.1.2 不支持)
Node.js ≥ 20(zstd 写回需要 node:zlib 的 zstdCompressSync,Node 22.2+ 才有;较老版本自动降级为明文 JSONL,功能不受影响)
Git ≥ 2.x(文件快照依赖;影子仓库基于 git 实现)
Git 下载链接(任选其一):
git 在 PATH 中(git --version 能输出即成功)从 GitHub 克隆本仓库到你的机器(任选其一):
# HTTPS(推荐,需要先配置 git)
git clone https://github.com/JJXjustin/dsh-session-rewind.git
# 或 SSH(配置了 SSH key 后)
git clone git@github.com:JJXjustin/dsh-session-rewind.git
克隆后进入目录:cd dsh-session-rewind
插件通过 DSH 的 profile 装配(link 目录方式,免 build)。在你的 DSH profile 目录(~/.dsh/profiles/web):
# macOS / Linux
cd ~/.dsh/profiles/web
pnpm add -w link:/你克隆到的绝对路径/dsh-session-rewind
# Windows
cd C:\Users\<你>\.dsh\profiles\web
pnpm add -w link:C:/你克隆到的绝对路径/dsh-session-rewind
确认 package.json 的 dsh.profile.bundles 数组包含 dsh-session-rewind。
说明:
dsh-session-rewind是纯 JS 插件(lib/*.js手写、无 build 步骤),无需npm install/build,link 装配后刷新页面即可生效。若改了package.json的dsh.client声明、或 client bundle 生效异常,重启 DSH 让 client-modules 重新扫描。
删掉 package.json 里的 dependencies + bundles 两处引用 + node_modules\dsh-session-rewind junction 即可。
~/.dsh/dsh-session-rewind.json:
{
"autoCheckpoint": false,
"autoCheckpointPerTurn": true,
"checkpointOnTool": false,
"autoEveryNTurns": 0,
"gitAnchor": true,
"shadowDir": null,
"rewindPaths": null,
"rewindExclude": null
}
| 字段 | 默认 | 说明 |
|---|---|---|
autoCheckpoint | false | agent/pre-step(每步/模型请求前)打点,默认关——打点统一为「每轮一次」 |
autoCheckpointPerTurn | true | 每轮对话结束打 1 个版本点(唯一的默认打点来源;autoEveryNTurns>0 时改按 N 轮取模) |
checkpointOnTool | false | 每个顶层工具调用前打一版(标签「工具:」),显式开启才生效(旧名 checkpointOnTools: true 仍兼容) |
autoEveryNTurns | 0 | 每 N 轮打点(0 = 用 autoCheckpointPerTurn 的每轮语义) |
gitAnchor | true | 文件快照默认开:每个检查点同时在影子仓库建 git 提交(commit message = dsh-rewind:<ckptId>:<label>),还原时把工作区受管范围完整恢复到该快照 |
shadowDir | null | 影子仓库根目录(显式指定则不用 rewindDir/shadow-repos);默认 <工作区>/.dsh-rewind/shadow-repos/<sha1(cwd)16> |
rewindPaths | null | 快照白名单(数组),默认整个工作区;配置后只快照这些路径 |
rewindExclude | null | 额外排除路径(追加到内置排除 .git/node_modules/.dsh-rewind/.agent-teams/_rollback/日志等之后) |
输入卡片上方有一个常驻的 「🕐 还原检查点」 入口(注册在 conversation.input.dock 插槽,与待办/队列/goal 行并存):
clean -fd + checkout -f <commit> -- <paths>(影子仓库,reset 不支持 pathspec,故用组合拳)把受管范围恢复到检查点快照;快照后新增的已跟踪文件也一并移除(移到影子仓库 restore-backups/ 备份,不是硬删);成功显示摘要后页面自动重载;失败显示错误(归档保留可恢复)撤销:回退后未发新消息时,面板顶部显示 「↩ 撤销回退」(两次点击确认)——会话日志从归档恢复 + 文件恢复到回退前状态(git reset --hard gitBefore + 未跟踪文件从备份移回),均无需重启。
⚠ 无文件快照的检查点:列表里标红「⚠ 无文件快照」的检查点是 git 快照机制启用之前打的旧点(或打点时 git 快照失败)——还原它们只回退会话、不会回退文件(当时没有拍过快照,技术上限无法补)。git 快照启用后打的所有检查点默认带
git xxx绿色标记,还原即可同步回退文件。
数据经 host 侧 /api/rewind/{list,preview,confirm,undo,undoable,status}(loopback-only)流转,client 不直接读文件。UI 全部包在 React error boundary 内,崩溃只降级该入口,不影响对话面板。
关于「回退后继续对话」:回退 live 会话时会就地热重置内存副本(磁盘+内存+文件三者一致),无需重启即可继续;热重置失败才回落到冻结兜底。
位点说明:最初按 Cline 对齐选用
conversation.chat.turnTail(每轮末尾),但该 chain 已被dsh-client-ui-deliverables/dsh-better-sidebar的产出文件行占用(chain 只渲染一个 entry,有文件时必赢)——改为conversation.input.dock(list 型,多 ID 共存,输入卡上方独立行)。
注意:client bundle 改动只需刷新页面即生效(bundle 从
/plugins/实时服务);若改package.json的dsh.client声明则需要重启 DSH 让 client-modules 重新扫描(包声明缓存不热更新)。
| 工具 | 作用 |
|---|---|
rewind_checkpoint { label?, withFiles? } | 手动打版本点;文件快照(影子仓库 git)默认随打点创建,需工作区有 git(影子仓库自动 init,不侵入项目) |
rewind_list { sessionId? } | 列版本点与回退记录(时间/标签/seq/轮数/工具数/git 锚点) |
session_rewind { sessionId?, checkpointId?, seq? } | 预览回退:展示将丢弃的事件/轮数/工具数统计并挂起待确认请求(不执行任何修改) |
session_rewind_confirm | 确认并执行挂起的回退(磁盘截断 + live 会话热重置,可直接继续对话) |
rewind_undo { sessionId? } | 撤销最近一次回退(仅当回退后未发新消息);从归档恢复 + 热重置 |
rewind_restore { checkpointId?, commit? } | P1 文件级回退:clean -fd + checkout -f <commit> -- <paths> 到影子仓库锚点 |
rewind_status | 插件状态:配置 / 冻结会话 / 挂起请求 |
回退流程(模型侧标准操作):
rewind_list 查看版本点 → 选定目标session_rewind 获取预览(丢弃 N 条事件 / M 轮 / K 个工具调用)ask_user_question 向用户展示预览并请求确认;用户明确同意后才调用 session_rewind_confirm;拒绝则放弃(pending 10 分钟过期)seq 是独占边界:回退到 seq V = 保留 events[0..V),V 及之后的事件被截断~/.dsh/dsh-session-rewind/archive/<session>-<time>.jsonl,人读)→ 两步原子替换日志文件(zstd 保持 header 独立帧)→ 刷新投影缓存(coldSnapshot)→ 记录回退摘要checkpoints.json 里的 rewinds 记录构成可审计副本,原日志绝不静默删除回退正在运行的会话时,磁盘截断后同步热重置其内存副本(日志数组、surface 折叠、派生消息缓存、header/context 折叠、持久化写游标、投影单元)——与磁盘状态一致后直接继续对话,新事件 seq 从版本点连续追加,无需重启 DSH:
agent/pre-step 拦截防 seq 冲突,重启后从磁盘恢复)——日志安全始终优先回退后只要还没发出新消息,可以一键撤销、完整恢复到回退前状态:
rewind_undo默认写入「会话自己的工作区」 <会话工作区>/.dsh-rewind/(cwd = 会话 header.cwd;例如本机工作区为 D:\AI_WORK\DeepSeek Work):
<工作区>/.dsh-rewind/
├── archive/ # 回退归档(原始 JSONL 文本)+ untracked/restore-backups 备份
│ ├── <session>-<timestamp>.jsonl
│ └── untracked-<timestamp>/ # 还原时移除的未跟踪文件(撤销可移回)
├── shadow-repos/<sha1(cwd)16>/ # 影子 git 仓库(文件快照,.git 不侵入项目)
│ ├── .git/ # 快照对象库 + commit(message=dsh-rewind:<ckptId>:<label>)
│ ├── exclude # 影子仓库自己的排除规则(core.excludesFile)
│ └── restore-backups/<ts>/ # 还原时移除的快照后新增跟踪文件(撤销可移回)
├── <session-id>/ # 每会话版本点簿
│ └── <session-id>.json # { checkpoints: [...], rewinds: [...] }
~/.dsh(用户明确要求不落 C 盘);~/.dsh/dsh-session-rewind.json 的 rewindDir 可显式覆盖<DSH 进程启动目录>/.dsh-rewind(rewind_status 的 fallbackRootDir 展示).git/.gitignore,快照全部落在 .dsh-rewind/shadow-repos/ 下~/.dsh-rewind / ~/.dsh/dsh-session-rewind)可用
node tools/migrate-data.mjs 合并进工作区(按 id/seq 去重、保留最新 200 点,幂等可重跑)harness.defineTool/registerTool → ctx.tools.register → 降级不注册),任何失败不影响 DSH 启动inject: ['tools', 'webServer'];sessions / sessionPersistence / sessionProjectionCache 全部 ctx.get 可选获取,缺哪个功能降级到哪window.__ModuleLoader__.load 格式(DSH client-modules 标准),不依赖 __DSH_MODULES__;package.json 的 dsh.client.inject 使用 better-sidebar 0.14.0 验证过的注入组合@deepseek-ai/* 运行时包(chunk-rows 展开/打包为自实现最小版本,写回采用不打包布局,官方读取路径布局无关),无 peer 依赖安装坑cd C:\Users\asus\.dsh\plugin-src\dsh-session-rewind
node --test test/core.test.mjs
覆盖:chunk-rows 展开、seq 连续性校验、编码往返、轮边界校验、统计/标签、bookkeeping 去重、回退事务(截断+归档+记录)、边界失败零写入、投影失败全量回滚、zstd 分帧、恶意 session id 路径转义。
dsh-* npm 包)