🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

诊断医生 astra3294/dsh-doctor

DeepSeek Harnessv0.4.3
astra32940 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness 的确定性诊断与恢复工具。

33.6/100
综合分
5
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:engines.node 要求 >=24,不满足 Node 22.19.0。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add astra3294/dsh-doctor
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · other
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 0 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/27) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

engines.node 要求 >=24,不满足 Node 22.19.0

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-doctor @ 0.4.3
✗Node 引擎要求 >=24 · 基线 Node 22.19 不满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/25 02:11:25

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 64 处,展示前 60 条)
  • 执行外部命令固定命令
    src/boot-probe.ts:44
    spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    src/boot-probe.ts:155
    const child = spawn(spawnArgs[0] ?? 'dsh', spawnArgs.slice(1), {
  • 读取本地文件
    src/check-plugin.ts:29
    entries = await readdir(dir, { withFileTypes: true })
  • 读取本地文件
    src/checkpoints.ts:74
    ? (await readdir(root, { withFileTypes: true })).filter(entry => entry.isDirectory()).map(entry => entry.name)
  • 读取本地文件
    src/checkpoints.ts:80
    const ids = await readdir(directory, { withFileTypes: true })
  • 读取本地文件
    src/checkpoints.ts:84
    const raw = await readFile(join(directory, entry.name, 'checkpoint.json'), 'utf8')
  • 删除本地文件
    src/checkpoints.ts:108
    await rm(sourcePath, { force: true })
  • 读取本地文件
    src/checkpoints.ts:112
    const content = await readFile(backupPath)
  • 删除本地文件递归
    src/checkpoints.ts:132
    await rm(checkpointDirectory(dshHome, profile, checkpoint.id), { recursive: true, force: true })
  • 读取本地文件
    src/checks.ts:94
    const stat = await lstat(dotenvPath)
  • 执行外部命令固定命令
    src/checks.ts:109
    const result = spawnSync('netsh', ['int', 'ipv4', 'show', 'excludedportrange', 'protocol=tcp'], {
  • 读取本地文件
    src/checks.ts:272
    if (!(await lstat(target)).isDirectory()) continue
  • 读取本地文件
    src/checks.ts:360
    packages = (await readdir(searchRoot, { withFileTypes: true }))
  • 执行外部命令来自配置/变量
    src/cli.ts:55
    const child = spawn(command, ['--profile', profile], { stdio: 'inherit', windowsHide: false })
  • 发起网络请求
    src/cli.ts:224
    const response = await fetch(source, { signal: AbortSignal.timeout(30_000), redirect: 'follow' })
  • 请求外部主机registry.npmjs.org
    src/cli.ts:255
    const response = await fetch('https://registry.npmjs.org/dsh-doctor/latest', { signal: AbortSignal.timeout(10_000) })
  • 发起网络请求
    src/cli.ts:255
    const response = await fetch('https://registry.npmjs.org/dsh-doctor/latest', { signal: AbortSignal.timeout(10_000) })
  • 执行外部命令来自配置/变量
    src/cli.ts:269
    const result = spawnSync(command, ['add', `dsh-doctor@${latest}`], { cwd, encoding: 'utf8', timeout: 180_000, windowsHide: true })
  • 读取本地文件
    src/cli.ts:360
    const manifestRaw = readFileSync(join(directory, 'package.json'), 'utf8')
  • 请求外部主机raw.githubusercontent.com
    src/cli.ts:362
    const response = await fetch('https://raw.githubusercontent.com/AdamPlatin123/awesome-dsh-plugins/main/PLUGINS.md', { signal: AbortSignal.timeout(20_0
  • 发起网络请求
    src/cli.ts:362
    const response = await fetch('https://raw.githubusercontent.com/AdamPlatin123/awesome-dsh-plugins/main/PLUGINS.md', { signal: AbortSignal.timeout(20_0
  • 读取本地文件
    src/cli.ts:387
    const pkg = JSON.parse(readFileSync('package.json', 'utf8')) as {
  • 读取本地文件
    src/cli.ts:395
    const changelog = readFileSync('CHANGELOG.md', 'utf8')
  • 执行外部命令固定命令
    src/cli.ts:399
    const tag = spawnSync('git', ['rev-parse', '--verify', `refs/tags/v${pkg.version}`], { encoding: 'utf8' })
  • 执行外部命令来自配置/变量
    src/cli.ts:405
    const registry = spawnSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['config', 'get', 'registry'], { encoding: 'utf8', shell: process.platfor
  • 读取本地文件
    src/cli.ts:412
    checks.push(existsSync(pkg.main)
  • 执行外部命令来自配置/变量
    src/cli.ts:435
    const result = spawnSync(build, { cwd: directory, shell: true, stdio: 'inherit', windowsHide: true })
  • 写入本地文件
    src/cli.ts:488
    writeFileSync(bodyFile, markdown, 'utf8')
  • 执行外部命令固定命令
    src/cli.ts:489
    const gh = spawnSync('gh', ['issue', 'create', '--repo', reportRepo(), '--title', title, '--body-file', bodyFile], { encoding: 'utf8' })
  • 读取本地文件
    src/cli.ts:508
    const manifest = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as { repository?: { url?: string } }
  • 执行外部命令来自配置/变量
    src/daemon.ts:71
    const child = spawn(command, ['--profile', profile], {
  • 写入本地文件
    src/daemon.ts:80
    await writeFile(pidFile(dshHome), JSON.stringify({ pid: child.pid, startedAt: new Date().toISOString() }), 'utf8')
  • 执行外部命令固定命令
    src/daemon.ts:90
    spawn('taskkill', ['/pid', String(status.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' })
  • 删除本地文件
    src/daemon.ts:94
    await rm(pidFile(dshHome), { force: true }).catch(() => {})
  • 读取本地文件
    src/fs-utils.ts:9
    await access(path, constants.F_OK)
  • 读取本地文件
    src/fs-utils.ts:18
    return await readFile(path, 'utf8')
  • 写入本地文件
    src/fs-utils.ts:35
    await mkdir(path, { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/fs-utils.ts:36
    if (process.platform !== 'win32') await chmod(path, 0o700)
  • 写入本地文件
    src/fs-utils.ts:50
    await rename(temporary, path)
  • 写入本地文件
    src/fs-utils.ts:51
    if (process.platform !== 'win32') await chmod(path, 0o600)
  • 删除本地文件
    src/fs-utils.ts:53
    await rm(temporary, { force: true }).catch(() => {})
  • 读取本地文件
    src/fs-utils.ts:75
    record = JSON.parse(await readFile(lockPath, 'utf8')) as LockRecord
  • 读取本地文件
    src/fs-utils.ts:86
    const info = await stat(lockPath)
  • 删除本地文件
    src/fs-utils.ts:101
    await rm(lockPath, { force: true }).catch(() => {})
  • 删除本地文件
    src/fs-utils.ts:115
    await rm(lockPath, { force: true }).catch(() => {})
  • 读取本地文件
    src/fs-utils.ts:122
    await access(path, mode)
  • 读取本地文件
    src/fs-utils.ts:133
    return (await stat(path)).size
  • 读取本地文件
    src/knowledge.ts:91
    names = (await readdir(base, { withFileTypes: true })).filter(entry => entry.isDirectory()).map(entry => entry.name)
  • 写入本地文件
    src/repair.ts:146
    await rename(file, target)
  • 执行外部命令来自配置/变量
    src/repair.ts:446
    const child = spawn(command, args, { cwd, stdio: 'ignore', windowsHide: true })
  • 执行外部命令来自配置/变量
    src/restart.ts:29
    const helper = spawn(process.execPath, ['-e', relaunchScript(process.platform, profile)], {
  • 读取本地文件
    src/scanner.ts:60
    return (await readdir(directory, { withFileTypes: true }))
  • 读取本地文件
    src/scanner.ts:207
    const entry = await lstat(dependencyPath)
  • 读取本地文件
    src/scanner.ts:209
    const target = resolve(join(dependencyPath, '..'), await readlink(dependencyPath))
  • 执行外部命令来自配置/变量
    src/scanner.ts:270
    const result = spawnSync(command, ['--version'], { encoding: 'utf8', timeout: 5000, windowsHide: true })
  • 读取本地文件
    src/scanner.ts:336
    const entries = (await readdir(directory, { withFileTypes: true }))
  • 请求外部主机registry.npmjs.org
    src/scanner.ts:375
    const response = await fetch('https://registry.npmjs.org/@deepseek-ai%2Fdsh/latest', { signal: AbortSignal.timeout(5000) })
  • 发起网络请求
    src/scanner.ts:375
    const response = await fetch('https://registry.npmjs.org/@deepseek-ai%2Fdsh/latest', { signal: AbortSignal.timeout(5000) })
  • 读取本地文件
    src/scanner.ts:409
    const workspaces = (await readdir(sessions, { withFileTypes: true })).filter(entry => entry.isDirectory())
  • 读取本地文件
    src/scanner.ts:414
    files = (await readdir(workspacePath, { withFileTypes: true }))
扫描于 2026/11/3(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org、raw.githubusercontent.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-layout@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-client-ui-sidebar@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-llm
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 确定性诊断
  • 故障恢复

为 DeepSeek Harness 提供确定性诊断与恢复

README

由 DeepSeek 最新模型翻译生成
DSH Doctor DeepSeek Harness 的确定性诊断与恢复工具。 DSH Doctor 是 Harness「把自己改坏」两种典型情况的安全网:开得了但无法对话(WebUI 能打开但对话循环坏了),以及根本起不来(改了配置、依赖或插件后启动失败)。WebUI 还能打开时,Doctor 按钮调用仅限本机访问的 Host 救援服务;Harness 起不来时,同一套引擎以独立 CLI 运行——包括捕获启动失败的启动探针,和「一键恢复到最近健康检查点」的重置,让插件开发者可以放心折腾、随时回到能对话能用工具的状态。 DSH Doctor 0.2.0 面向 @deepseek-ai/dsh 0.1.0-rc.6。DeepSeek Harness 仍处于 Developer Preview;遇到未知版本时,Doctor 只做保守的只读诊断。
展开完整文档(README 剩余 1 节)
DSH Doctor

DeepSeek Harness 的确定性诊断与恢复工具。

DSH Doctor 是 Harness「把自己改坏」两种典型情况的安全网:开得了但无法对话(WebUI 能打开但对话循环坏了),以及根本起不来(改了配置、依赖或插件后启动失败)。WebUI 还能打开时,Doctor 按钮调用仅限本机访问的 Host 救援服务;Harness 起不来时,同一套引擎以独立 CLI 运行——包括捕获启动失败的启动探针,和「一键恢复到最近健康检查点」的重置,让插件开发者可以放心折腾、随时回到能对话能用工具的状态。

DSH Doctor 0.2.0 面向 @deepseek-ai/dsh 0.1.0-rc.6。DeepSeek Harness 仍处于 Developer Preview;遇到未知版本时,Doctor 只做保守的只读诊断。

安装

把 Doctor 安装进 Web profile:

dsh plugin --profile web add dsh-doctor
dsh --profile web

一个 npm 包同时包含 Host 与浏览器部分,并在 WebUI 中提供:

- 侧栏设置旁边常驻的 Doctor 入口;
- Prompt 或 Agent 失败后,在输入框上方主动出现的恢复提示;
- 设置中的完整 Doctor 页面,用于查看问题、检查点和回滚;
- 页面框架层的应急浮标入口:profile 出问题时自动出现,不依赖侧栏与对话插件是否存活。

如果 WebUI 无法启动:

npx dsh-doctor recover --profile web

CLI

扫描一个 profile(默认离线、隐藏绝对路径)
npx dsh-doctor scan

启动探针:判断 Harness 能否启动,并从启动输出诊断失败原因
npx dsh-doctor boot

一键恢复:配置重置到健康检查点、对齐依赖,并再次验证能否启动
npx dsh-doctor recover --profile web
npx dsh-doctor recover --profile web --yes # 同时执行需确认的动作

把当前 profile 快照为健康恢复基准
npx dsh-doctor checkpoint --profile web

启动 Harness;启动失败时自动诊断(--auto-recover 会修复并重启一次)
npx dsh-doctor launch --auto-recover

回滚检查点
npx dsh-doctor rollback <checkpoint-id>

recover 零确认执行安全动作,之后在 Harness 原本未运行时用启动探针验证结果。仍有 Error 或启动验证失败时退出码为 1;Warning 默认返回 0,--strict 时返回 1;参数或内部错误返回 2。--json 输出机器可读结果。

v0.2.0 检查内容

- Node、操作系统、Harness 版本和 profile;
- profile manifest、bundle 列表、cordis.yml、cordis.patch.yml、pnpm workspace 的语法与权限;
- 缺失依赖、重复 bundle 和损坏链接;
- 从 WebUI 调用时的 Cordis 插件运行阶段;
- 启动失败:真实启动探针(端口监听 + 捕获输出并映射为修复动作);
- 会话记录(session.jsonl.zstd)与 storage 缓存的完整性;
- 本地近期日志中的 fatal/plugin failure 标记;
- 非 registry 和外部插件来源(仅提示,永不阻塞恢复);
- 模型路由/凭据状态,以及验证模型真实应答的极小非会话请求。

恢复

每次修改都遵守同一事务:

1. 重新检查修复计划是否过期,并核对 profile 文件哈希。
2. 创建仅本机可访问的修复前检查点。
3. 只执行用户选定的动作。
4. 重新运行完整结构检查(Harness 原本未运行时追加启动验证)。
5. 验证失败时自动回滚。

一键安全动作包括准备 Doctor 状态,以及把 profile 配置整体重置到最近健康检查点。冷启动(还没有健康检查点)时,Doctor 可以在明确确认后合成最小合法配置文件,损坏的原文件保留在修复前检查点里。安装依赖、禁用导致启动崩溃的插件、隔离损坏的会话文件、重新启用被 Doctor 禁用的插件都需要确认。Doctor 拒绝禁用连接、布局、设置、对话、运行时、模块加载器以及 Doctor 自身入口。

检查点位于 $DSH_HOME/doctor/checkpoints/,每个 profile 保留最近 10 个,且最新的健康检查点永不被清理。为了精确回滚,检查点可能包含本地配置文件的原始副本,但绝不会进入诊断报告或上传。Doctor 不显示、不修改也不上传 API Key。

参见恢复矩阵和安全策略。

开发

需要 Node 24 和 pnpm:

pnpm install
pnpm check
npm pack --dry-run

许可证

MIT
预览分享卡片长什么样 ↓astra3294/dsh-doctor
分享 · DeepSeek Harness Hub
astra3294/dsh-doctor

DeepSeek Harness 的确定性诊断与恢复工具。

这是你的仓库?认领条目

回到顶部