跳到正文
dsh-market 浏览插件 GitHub EN

moonquake2004/dsh-doctor#plugin

离线诊断工具:环境/Profile/会话共 19 项检查,带设置「诊断」面板与只读 JSON API。

Star 数 ★ 1 分类 开发与运行时 收录于 2026-08-15 npm @moonquake2004/dsh-doctor

安装

在 DeepSeek Harness 里通过 dsh-market 安装

dsh plugin --profile web add dshmarket

或使用命令行

dsh plugin --profile web add @moonquake2004/dsh-doctor

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。

README

DeepSeek Harness 的离线诊断工具——在启动前安装插件前跑一次,它会告诉你社区反复报告的哪几类故障会在你机器上咬人。

零 npm 依赖。单文件。任何有 node 的环境都能跑(zstd 只在扫 .zstd 会话日志时需要,E1 会检查它)。

为什么

dsh 的插件树"装出来就是脆的":一个悬空引用、一个断掉的 file: 链接、一个重复的 entry id、一段损坏的会话日志,都能让 profile 在启动时直接挂掉或拖垮整个 web 服务器——而 --dump-config 从不挂载 loader,所以在坏配置上也"一切正常"。这类故障被汇总在 dsh discussion #1496(Advisory:插件安装路径需要护栏)。dsh-doctor 就是这个护栏——26 项内置检查(env 7 / profile 11 / session 8)映射到 18 个社区报告,每一项都用合成负样例验证过;外加一个自更新的远程检查目录(声明式规则,v0.2.0 起)。

用法

node dsh-doctor.mjs                      # 全部检查(env + profile + session)
node dsh-doctor.mjs --profile web        # 仅 profile 检查
node dsh-doctor.mjs --session <path>     # 仅会话检查(默认自动找最新会话)
node dsh-doctor.mjs --env                # 仅环境检查
node dsh-doctor.mjs --json               # 机器可读输出
node dsh-doctor.mjs --no-catalog         # 不拉远程目录(只用内置副本)

退出码:0 = 全部通过 · 1 = 发现问题(内置检查 + 目录中 severity: error 的项)· warn 级目录失败不改退出码。

检查项(28 内置 + 5 目录)

env

ID 检查 对应讨论
E1 node/pnpm/zstd 在 PATH #1270
E2 .env 是文件而非目录 #71
E3 node 版本 / --expose-internals 可及性 #113, #1313
E4 node-pty 原生二进制在位(prebuilds/<platform>-<arch>/pty.node #1219
E5 存储 JSON 文件合法(严格 UTF-8 + 可解析) #1357
E6 锚点 tripwire:S6/S7/S10 依赖的契约仍在安装的 dsh-session anti-rot idea
E10 启动前 Web 端口 3080 可用性(dsh web 自身占用=正常;其他进程=FAIL;DSH_DOCTOR_PORT 可覆盖) #1719

profile

ID 检查 对应讨论
P2 bundle 层与用户 patch 的 insert id 冲突(启动必崩) #1404
P3 用户 patch 的 insert name: 能从 profile 锚点解析 #1197, #880
P4 file: 依赖完整 #1197
P5 顶层无 @deepseek-ai/* 重复(双模块实例) #1486, #1697
P7 cordis.patch.yml 结构 lint(~ insert: null 字面量、tab 缩进、缺冒号、顶层映射+序列混排 → UI 打不开) #1724
P12 profile 内 bundle 版本 vs 运行 CLI(发词汇名 installed_bundle,#1719 v1.1:未声明=skip / manifest 撒谎或分歧=warn / 一致=pass;web「诊断」面板 / /dsh-doctor/run API 跑的是 bundle) #1719
P13 client 半 provide 服务名抢注核心客户端服务(chatFileMentions@deepseek-ai/dsh-client-*,warn)或跨 bundle 同名(浏览器端 service already registered → UI 白屏、服务端日志无感知) #2752
P14 声明 bin 可执行性(目标文件在位 + 文本 bin 必须带 shebang;仅可执行位不识别解释器 → 直接执行 ENOEXEC,#1846) #1846

session

ID 检查 对应讨论
S1 孤儿 tool_call(无对应 tool result) #1363, #1544
S2 未闭合 turn(会话卡"运行中") #466, #1265
S6 seq == index 连续性(官方语义,chunk 行按 expandRow 展开) #1333, #1452, #1469
S7 end-seed 后重放(重放已提交尾部) #1497
S8 未知事件类型且无 ignorable(整包拒绝) #1538
S9 zstd 容器帧数(单帧日志 → session.list 整体 500) #1043
S10 sourceEventSeqs 引用非更早事件 #1469
S11 全会话扫描:损坏 → 隔离建议;超大 / 工作区估算物化堆(max(事件×600B, 字节×6),默认 1GiB,DSH_DOCTOR_HEAP_MB)→ 冷启动卡顿风险 #1550

备注

  • S 类检查复刻了 harness 自身的校验(如 SessionLogScannerseq == events.length + expandRow chunk 展开),所以离线结论与 boot/resume 实际行为一致。
  • 尊重 $DSH_HOME(默认 ~/.dsh),可以用临时 home 干跑,不碰真实数据。
  • 当前活跃 turn 的尾部 in-flight 工具调用按警告而非错误处理,扫活会话不会误报。
  • 同生态位兄弟实现:boyin111-1/dsh-doctor —— 两工具用同一批坏 fixture 交叉验证过。

相关社区工具

dsh-doctor/v1 词汇表 r5 兼容,v1.1 installed_bundle 待认领 —— 起草 @ciceroyang(ciceroyang/dsh-doctor),审阅 @sjh9714(dsh-win32)与 @moonquake2004#1719)。我们的 node/pnpm 检查按 r5 语义输出词汇名(pass/warn/fail/skip;summary.skip 常驻);P12 直接发 v1.1 词汇名 installed_bundle(四态 skip/warn/pass/warn,r6 表待发)。

  • zoahdev/dsh-plugin-doctor —— 发布前插件 bundle 健康检查(manifest/patch/entry/files/build/pack+全新 profile 安装)+ 宿主遮蔽 profile-shadow 哨兵(作者/CI 侧)。与本工具的用户侧 profile/session/env 诊断互补;它的 profile-shadow 与我们的 P5 从两个方向标记同一个宿主遮蔽前置条件。
  • boyin111-1/dsh-doctor —— 同生态位离线诊断兄弟实现,用同一批坏 fixture 交叉验证。

Symptom → check quick-start (dsh-diagnose alignment)

If you're coming from a symptom (rather than from the machine), these are the checks to run first. Coverage is honest: ✅ = direct offline coverage, ⚠️ = partial (we see the log/profile effects, not the runtime internals), ❌ = gap (runtime-only, no offline probe today).

Symptom family dsh-doctor checks What they catch
session log corruption / can't resume S1, S2, S6, S7, S8, S9, S10 orphan tool calls, unclosed turns, seq gaps, end-seed replay, unknown event types, zstd single-frame, sourceEventSeqs drift
oversized / cold-start stall S11 estimated materialization heap, corrupt-session quarantine
boot failure (UI won't open) P1–P10, E10 dangling bundles, id collisions, patch syntax, host shadowing, adapter conflicts, client-service injects, port 3080
tool registry gaps (tools missing) P1, P2, P8, P10, P9 unresolved/conflicting/duplicated tool registrations, client-only service injects
compaction / history unavailable S10, S6, S8 sourceEventSeqs not remapped after compaction
agent-loop lifecycle (session stuck "running") S2, S1, S6 unclosed turns, orphan tool calls, broken seq
llm retry storms S6, S11, S2 retry traffic effects on log integrity/size
token metering off S11, S1, S2 metering derives from the event stream
workflow script failures P7, S6, S8, S1 patch syntax (boot), workflow event integrity
approval policy pending S2, S1 open turns / orphan calls from pending or rejected approvals
credentials resolution E2, E5, P4 .env shape, storage JSON, file: links
web internals E10, P10, E5 port, client half, workspace storage
subagent depth S11, S8 session size, subagent event types
sandbox denials E4 node-pty binary (infra only) — ❌ runtime policy not offline-checkable
approval internals S2 ⚠️ runtime policy; only the turn-level effect
credentials internals E2, E5 ⚠️ file-level only

The dsh-doctor/v1 envelope (--json --envelope) is the machine-readable form of any of these runs, so a symptom tool can consume the verdict directly.

自更新检查(v0.2.1,层 B)

工具也会盯着自己的 npm 版本:每次运行对比已装版本与 dist-tags.latest(与目录同样的 6h TTL 缓存 + 离线回退)。有新版时打印提示、JSON 里报 update: { current, latest, available }——未经你要求绝不改动你的安装

  • --update —— 立即执行更新:在宿主 profile 里跑 pnpm install(可用 DSH_DOCTOR_UPDATE_CMD 覆盖),然后提示重启 dsh web
  • DSH_DOCTOR_AUTO_UPDATE=1 —— 有新版时自动更新。
  • 诚实边界:cordis 启动时加载插件,新引擎要重启才生效——层 B 是"换文件 + 提醒重启",不做热替换。
  • --no-catalog 同时禁用更新检查(纯离线模式)。

远程检查目录(v0.2.0,层 A)

内置 26 项检查编译在工具里。目录是第二层、自更新的:本仓库的 plugin/checks.json 放声明式规则(规则是数据,不是代码),所有已装实例自动获取新规则——无需重装。

  • 工作机制:每次运行尝试从 GitHub 拉 plugin/checks.json(3s 超时)→ 成功后缓存到 $DSH_HOME/.cache/dsh-doctor/checks.json(TTL 6h)→ 失败回退 last-known-good 缓存 → 再回退内置副本。新检查因此在上游提交后 ≤6h 内自动到达。
  • 安全性:规则是只读探测原语,由内置引擎执行(command-existspath-*json-validtext-contains / text-not-containsfile-size-aboveglob-count)。远程内容永远无法执行代码——只能新增模式检查。
  • 严重级别error(默认,改退出码)或 warn(只报告,不影响退出码)。--no-catalog 关闭远程拉取。
  • 加一条检查(这就是重点——无需发版):往 plugin/checks.json 追加一条并提交即可。目前已随目录发布的检查:
ID 探测 检查 对应讨论
E7 command-exists dsh 在 PATH #1270 家族
E8 text-contains(warn) profile .npmrcignore-workspace-root-check=true dsh-market #20
E9 json-valid config/workspace.json 可解析 #1357 家族
P6 text-not-contains patch insert name: 含空格(Windows spawn lint) #1420

目录检查的结果在 JSON 输出中标 src: "catalog",CLI 输出标 [目录]

LLM 观察者(v0.3.0,层 C)

第三层把"现场信号 → 目录条目"的回路半自动化:从诊断运行产出候选检查提案,人做最后把关(认证门禁不变)。设计与细节见 docs/layer-c-observer.md

  • dsh-doctor --observe run.json —— 聚类诊断运行的 fail/warn 信号(--json / --envelope 输出,或含 JSON 的目录),按目录 schema 起草候选检查(确定性,默认 severity: warn)。
  • --observe-llm "<cmd>"(或 DSH_DOCTOR_LLM_CMD)—— 用 LLM 富化草稿:cmd 从 stdin 收 prompt,stdout 回 JSON。回复被封闭探测词表约束,任何解析/词表违规静默回退草稿。
  • --observe-apply proposals.json —— 把校验通过的提案并入本地覆盖层 plugin/checks.local.json(幂等)。覆盖层参与本地诊断直到你认证该检查,但永不随包分发——认证后的检查应进 plugin/checks.json

安全不变量:封闭探测词表(LLM 输出永远是数据、不是代码)、提案默认 warn、不自动上目录、不依赖任何外部服务(不带 --observe-llm 即确定性模式)。

也可作为 dsh 插件安装

工具以标准 dsh bundle 形态发布(plugin/),可以在 web UI 里跑同样的检查(28 内置 + 5 目录规则):

# 装进 profile(checkout 或已发布路径均可)
dsh plugin --profile web add file:/path/to/dsh-doctor/plugin

装完你会得到:

  • 设置 → 诊断面板:一键跑全部检查,按 env / profile / session 分组渲染结果,带逐项修复建议与隔离建议(只展示建议,绝不自动执行);
  • HTTP APIGET /dsh-doctor/run 返回同样的 JSON(可选 ?profile= / ?session= 收窄范围)。

架构:插件的服务端路由 shell 出 plugin/dsh-doctor.mjs --json——与 CLI 同一份真相源(检查按设计是离线/文件系统导向的,不需要 harness 内部接口)。仓库根目录的 dsh-doctor.mjs 是兼容 node dsh-doctor.mjs 的薄封装。

License

MIT

内容来自项目 README(GitHub)↗