前言¶
DSH 把会话日志写成 session.vN.jsonl[.zstd],事件之间靠 turn / step 的嵌套和顺序维持可读性。一旦某个事件的坐标写错了——比如在没有打开 turn 的情况下写 tool/ptc-dispatch-start——整个会话在当前 reader 眼里就变成了 corrupt session,只会报一句「会话损坏」,不会告诉你是哪一条事件、哪一步出了问题。想自己翻文件定位,就得手工解压、逐行 parse。
下面介绍的 dsh-session-doctor 就是为这一类问题做的:它只读、不写,替你把违反 reader 检查规则的事件逐个点出来。它对应 deepseek-harness Discussions #11971、#11981、#11121 这一类生命周期问题的排查场景。
这是什么¶
dsh-session-doctor 是 aturzone 维护的 DSH 插件,分类为 admin-security,目录页显示星标 0,README 自己标注为「插件早期、使用 pre-release tag」。
它做的事情可以一句话概括:逐条解码 session.vN.jsonl[.zstd] 里的事件,重放当前 reader 生效的 turn/step/scope 规则,然后报出具体是哪个序号、哪种事件类型、哪条规则不再成立。全程只读,不会写入会话文件。
它能查到什么¶
README 列出的检查项有四类:
- turn/step 坐标完整性:
turn/start/turn/end/step/start/step/end的嵌套与顺序。 - 在同一个未结束的 turn 内 step 编号重新开始。
- turn/step 作用域内的事件被写到了作用域之外:
request/header、request/context、tool/ptc-dispatch-start、tool/ptc-dispatch、assistant/message、tool/call、tool/result的替换记录等。 - 行级损坏:非法 JSON、缺失 header、非事件行。
需要留意它的定位:这是一个「与当前 V4 reader 对齐的签名检测器」,不是完整的格式校验器。它不重新实现 message payload 校验、格式迁移,也不处理 zstd 之外的压缩 framing。所以它给出的结论是「这里违反了哪些规则」,而不是「这个文件格式上还对不对」。
安装¶
从 npm 安装(插件处于早期,用 next 这个预发布 tag):
dsh plugin --profile web add dsh-session-doctor@next
从 Git 仓库安装,命令会触发 package 的 prepare 构建:
dsh plugin --profile web add git+https://github.com/aturzone/dsh-session-doctor.git
package.json 里的 engines 限定 dsh >=0.2.2-rc.1 <0.3.0、node >=24.9.0,前者依赖 @deepseek-ai/cordis ^4.1.0,后者 @deepseek-ai/dsh-tools >=0.2.2-rc.1 <0.3.0。项目使用 zstd 解压,所以 Node 版本要求不低。许可证是 MIT。
作为 bundle 启用¶
装好之后 bundle 只往配置里插入一行插件声明。插件会注册一个面向模型调用的 session_doctor 工具,扫描 $DSH_HOME/sessions(也可以传 sessionsRoot 参数),返回和 CLI 相同的报告,同样是只读。
如果想在本地 checkout 上用覆盖文件做开发调试,README 给的做法是先写 overlay:
# overlay.yml
- insert:
- id: session-doctor-dev
name: /absolute/path/to/dsh-session-doctor/src/index.ts
然后带着 patch 启动:
pnpm dsh web --patch ./overlay.yml
这一步的意义是把源码路径直接挂进正在运行的 dsh,不必先打包发布。
当 CLI 用¶
不想走模型工具、只想在脚本里巡检一遍时,可以直接调命令行:
session-doctor [--home <DSH_HOME>] [--sessions-root <dir>] [--json] [--all-generations]
参数行为按 README 整理:
- 默认先找
$DSH_HOME/sessions,找不到再退回~/.dsh/sessions。 - 默认只检查每个会话里版本号最高的那个 canonical generation;加
--all-generations会把保留下来的更早版本一起校验,比如session.v3.jsonl与session.v4.jsonl并存的情况。 --sessions-root既可以传会话根目录,也可以只传某一个 workspace bucket,例如--sessions-root .../sessions/--my-project--。- 退出码:
0干净、1发现可疑 generation、2用法或 I/O 出错。--json打印结构化报告,便于接进别的脚本。
这些退出码可以直接当 CI 里的判定条件用。
输出长什么样¶
README 给的示例输出大概长这样:
session root: /home/me/.dsh/sessions
sessions: 12 scanned, 1 with reader-incompatible signatures
✗ --home-me-project--/session-8bc9…
file: …/session.v4.jsonl.zstd
events: 41, version: 4
- seq 22 tool/ptc-dispatch-start: turn-scope: tool/ptc-dispatch-start outside an open turn
- seq 23 tool/ptc-dispatch: turn-scope: tool/ptc-dispatch outside an open turn
报告会落到具体文件、事件总数、版本号和出问题的序号,拿到之后可以直接去对应位置看上下文。
适用场景与注意¶
适合这几类人:会遇到 corrupt session 报错、想自己定位而不是等上游修的 DSH 使用者;想审计一批历史会话是否适用当前 V4 reader 规则的维护者;想在 CI 里蹲住会话落盘格式变化的项目。
使用前需要注意三点。
- 插件以当前 dsh 进程的权限运行,安装前应当自己过一遍源码,确认
cordis.patch.yml这类 patch 没有超出预期。许可证是 MIT,但「MIT」不等于「可以无脑装」。 - 它是检测器,不是修复工具。README 明确说目前没有 repair 或 quarantine 能力,报告给出缺陷之后,要不要把坏掉的 generation 挪走仍是人工决策。
- 规则对齐的是发布时的 V4 reader,future 格式版本(
session-format-vN-to-vN+1)需要跟着更新这个插件。另外默认只扫最高 generation,历史版本不传--all-generations就看不到,这是设计使然,不是漏检。
社区目录(skillhub.cn)是独立站点,与 DeepSeek、幻方没有官方从属关系,插件列表别当成官方应用商店来引用。
结尾¶
dsh-session-doctor 的价值在于把「会话损坏」这种没法再往下查的报错,拆成「第几行、哪种事件、哪条规则违规」。它只读、不改文件、不承诺修复,代价是要跟 dsh reader 的版本一起维护规则。排查 corrupt session 时,先把这个插件跑一遍,比手工解 zstd 再逐行 parse 省事。
- 目录页:https://www.skillhub.cn/plugins/aturzone/dsh-session-doctor
- GitHub:https://github.com/aturzone/dsh-session-doctor