LiuJunheng/DeepSeekHarnessGreen--plugins-dsh-session-rewind16

dsh-session-rewind

在 WebUI 设置页可视化分析会话(逐回合/错误统计),并支持按回合「回退」——从选定回合之后派生干净的续接会话(官方 session.fork),等效于移除失败消息后继续对话

包名
dsh-session-rewind
版本
0.1.0
许可证
Apache-2.0
最近更新
2026年9月12日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:LiuJunheng/DeepSeekHarnessGreen#123f0e98ee3267b9da82e9af6e74c1ab93901deb&path:plugins/dsh-session-rewind

dsh-session-rewind — 会话回退插件 (WebUI 可视化)

English: WebUI session-rewind plugin for DeepSeek Harness. It visualizes per-turn session analysis and recovers conversations that were poisoned by the "tool runtime unavailable" bug family (GitHub Discussions #1959 / #1974) — fork at any completed turn, keep the good history, drop the poisoned tail.

解决的问题

DSH 的回合会因工具运行时失效(如 Cannot read properties of undefined (reading 'prepare'))而崩溃,并在会话日志里留下孤儿 tool_calls(有调用、永远没有结果),之后每一轮对话都会被 DeepSeek API 以 400 拒绝,会话永久毒化。DSH 0.1.0-rc.6 没有"删除失败消息"的界面功能。

本插件在 WebUI 设置页新增「会话回退」页面:

  • 列出全部会话(标题/工作区/是否运行中/创建时间);
  • 「分析」任意会话: 展示逐回合信息(用户问题、步骤数、工具调用数、错误码统计、是否完成);
  • 在任意一个已完成回合上点「回退到此」: 调用官方 session.fork 从该回合之后派生一个干净的续接会话并自动打开 —— 等效于"移除失败消息之后的内容, 重新发新消息不再被干扰";
  • 原会话保留不动(可再用「清理归档」等工具处理)。

因为孤儿 tool_calls 只存在于崩溃回合内, 从该回合之前的已完成回合边界派生, 即可干净地切掉毒化历史, 同时保住之前所有正常对话。

为什么是"派生新会话"而不是"原地删消息"

DSH 服务运行时, 会话由持久化层在内存中缓存, 原地改写磁盘日志会被内存状态覆盖或产生 seq 断裂, 不安全。官方 session.fork 正是为此设计: 从任意已完成回合边界截断并创建续接会话(与官方 UI 自带的"分支"同源, 官方只暴露末位回合, 本插件放开到任意回合)。

安装

本仓库已包含此插件(目录 plugins/dsh-session-rewind)。两种方式:

方式 A — 本地插件安装(推荐):

git clone https://github.com/LiuJunheng/DeepSeekHarnessGreen.git

然后在 DSH 启动器/插件管理器里选择本地插件文件夹安装 plugins/dsh-session-rewind(绿色版启动器: python launcher.py --install-plugin plugins\dsh-session-rewind), 重启服务后, 设置页出现「会话回退」。

方式 B — 手动加入 profile:

在 profile 的 package.json dependencies 中加入 "dsh-session-rewind": "file:/plugins/dsh-session-rewind", 然后 pnpm install 并重启服务。

注意: 会话解码改为自包含、跨版本容错的逻辑, 不再依赖 @deepseek-ai/dsh-session 的内部导出 (decodeStorageRecord 在 0.1.5-alpha(v3) 已被移除)。package.json 里保留依赖声明仅为兼容旧版安装流程。

配套工具 (tools/)

  • tools/rewind-session.mjs离线原地回退脚本: 服务停止时, 直接把会话日志截断到最后一个完整回合(自动备份)。适合服务停机维护场景。
  • tools/apply-agentloop-guard.mjs诊断守卫补丁: 给 dsh-agent-loop 的工具派发入口加存在性检查, 把晦涩的 Cannot read properties of undefined (reading 'prepare') 变成明确的可操作错误提示(幂等, 可反复执行; DSH 升级后重跑一次即可)。

接口

  • GET /__dsh/session-rewind/list — 会话列表(快速, 只读 header)。
  • GET /__dsh/session-rewind/inspect?id= — 逐回合分析(解码整个日志)。
  • 回退由客户端调用官方 session.fork({sessionId, atSeq})完成。
  • 所有接口要求自定义头 X-DSH-Plugin-Rewind: 1 防 CSRF。

实现说明

  • 宿主端直接按磁盘扫描 DSH_HOME/sessions/**/session.jsonl.zstd(zstd 多帧)。解码用自包含的 adoptPhysicalRow 跨版本容错处理: 忽略 ignorable 空事件, 对 v3 的表面替换折叠(surfaceOp.op === "replace")丢弃被取代的旧事件 seq 区间, 以 seq 为键收纳(对 chunk-run 打包行布局无关)。
  • 回退动作走官方 session.fork + 客户端 sessions.open, 与服务端持久化层完全一致。

相关讨论

License

MIT