Passer au contenu principal
S

dsh-session-repair-ui

semidia/dsh-session-repair-ui

Session repair button in the conversation header: detects & fixes session-log corruption — tool-call id swaps, empty call ids (`message must have tool source`), unknown event types from disabled plugins (marks `ignorable`), torn zstd tails, missing final-frame newlines; ghost-style UI, auto-backup before writes.

Installer

dsh plugin --profile web add github:semidia/dsh-session-repair-ui

README

dsh-session-repair-ui

在 DeepSeek Harness 的会话头部(「导出会话」按钮旁)增加一个「修复会话」按钮,用于检测并修复会导致会话「加载失败 / 发不了新消息」的日志损坏:

  1. 助手消息声明了某个工具调用 id(tool_calls),但落盘的工具结果却记成了另一个 id —— 接口在续写历史时报 An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'
  2. 模型输出了 id 为空的工具调用tool-call id=""tool/call callId=""tool/result source.callId="")—— 会话加载时报 session event at seq N message must have tool source,整个历史被拒载。
  3. 停用/移除插件留下的未知事件类型(如 polyglot/served)——加载时报 SessionFormatUnsupportedError: … unknown to this harness and not marked ignorable
  4. 崩溃写入留下的 zstd 尾部残缺帧(torn tail)。

功能(v2)

  • 点按钮弹出面板,自动只检测当前会话(只读,不改任何东西)。
  • 诊断分类显示:无损坏 / 发现 N 处空工具调用 id / N 处调用-结果串号 / N 个未知事件类型(可安全修复)/ N 处需手动处理(seq 缺口 / 版本不匹配)
  • 可安全修复项(自动):
    • 调用-结果 id 串号 → 重映射(同 turn 内数量相等时);
    • 空工具调用 id → 补确定性合成 id(repaired-call-<seq>-<i>,message / tool/call / tool/result 三处一致);
    • 未知事件类型 → 事件信封标记 ignorable: true(官方信封契约的"可安全跳过"机制);
    • zstd 尾部残缺 → 截断到最后一个完整帧(与 DSH 自身 crash-repair 行为一致)。
  • 只报告不自动修:seq 缺口/重复、header 版本不匹配(日志由更新版本 harness 写入)、torn 之外的不平衡。
  • 修复前自动备份(.bak-repair),绝不删已提交事件、绝不改 seq,其余字节原样保留。
  • 修复成功后面板提示「已修复 N 处,请刷新页面重新打开本会话」。
  • 样式遵循全局规则:幽灵式(透明底 + 细边框 + 主题文字色,激活态表面色填充),按钮与弹窗内部全部使用 --dsw-alias-* 主题变量,浅色/深色/任意强调色主题下都清晰,与 DSH 官方按钮一致。

原理

修复逻辑在包内自带的 tools/repair-toolcalls.cjs(zstd 帧级读写,v2)里:

  1. 加载门分析analyzeLog):模拟 DSH 加载校验——header 版本、事件类型白名单(内置 KNOWN_EVENT_TYPES 镜像 + chunk 存储行标签)、chunk 行展开后 seq 连续性、JSONL 可解析性、zstd 帧完整性。
  2. 工具调用配对:按 turn 折叠「声明/发起的工具调用 id」与「结果 id」;dangling(有调用没结果)与 orphan(有结果但 id 对不上)数量相等时重映射;empty 三队列(空 block/toolcall/result id)平衡时补合成 id;不平衡只报告、不猜。
  3. 未知事件 → ignorable:白名单外且非 chunk 存储行、未标 ignorable 的事件,标记 ignorable: true(纯诊断/插件事件可安全跳过,不参与 surface 折叠)。
  4. torn 尾截断scanZstdFrames 找到最后一个完整帧之后的残缺字节,截断(备份后),与 DSH dsh-session-persistence-jsonl 的 crash-repair 语义一致。
  5. 修复后自验:重跑加载门 + 配对分析,无残留才报告成功。

安装

  1. 把本目录放到 web profile 的 node_modules/dsh-session-repair-ui(或建 junction)。
  2. 在 profile 的 cordis.patch.yml 里加一行:
- insert:
    - id: dsh-session-repair-ui
      name: 'dsh-session-repair-ui'
  1. 重启 dsh web

架构

  • Host(lib/index.js):通过 ctx.connection.rpc.handle('/dsh-session-repair-ui', …) 暴露 repair/scan(dry-run)与 repair/apply,内部用 node:child_process.execFile 调用包内修复工具;摘要解析会区分「空 id 修复数」与「串号重映射数」返回给前端。
  • Client(lib/client.js):window.__ModuleLoader__.load 客户端,注册到 conversation.session.header.utilities,通过 rpc.call 调 Host;按钮与弹窗均使用幽灵式样式(--dsw-alias-* 主题变量:透明底、细边框、主题文字色,hover/激活态用 --dsw-alias-interactive-bg-hover/active 表面色填充)。

独立 CLI

修复工具也可脱离 UI 单独用:

node tools/repair-toolcalls.cjs --root <sessions目录> --dry-run
node tools/repair-toolcalls.cjs --root <sessions目录> <session-id>

License

MIT

Plugins associés