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

安装诊断修复 dushaobindoudou/dsh-recovery

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

诊断并修复 dsh 安装故障,支持备份撤销

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-recovery
npm 源 · dsh-recovery 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/10/27·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 47 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

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

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

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 07:35:44

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

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

可执行外部命令读写/删除本地文件
查看扫描证据(共 69 处,展示前 61 条)
  • 读取本地文件
    lib/paths.js:19
    return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
  • 读取本地文件
    lib/paths.js:103
    return existsSync(join(dir, 'package.json')) ? dir : null;
  • 读取本地文件
    lib/paths.js:127
    if (!existsSync(root)) return null;
  • 读取本地文件
    lib/paths.js:130
    entries = readdirSync(root).sort();
  • 读取本地文件
    lib/knowngood.js:58
    if (!existsSync(root)) return [];
  • 读取本地文件
    lib/knowngood.js:60
    return readdirSync(root).sort().map((entry) => join(root, entry));
  • 读取本地文件
    lib/knowngood.js:75
    return JSON.parse(readFileSync(join(dir, 'manifest.json'), 'utf8'));
  • 读取本地文件
    lib/knowngood.js:86
    const live = files.filter((f) => existsSync(f.path)).map((f) => f.name);
  • 读取本地文件
    lib/knowngood.js:91
    return readFileSync(join(dir, name), 'utf8') === readFileSync(file.path, 'utf8');
  • 读取本地文件
    lib/knowngood.js:101
    return JSON.parse(readFileSync(join(globalRoot, 'package.json'), 'utf8')).version ?? null;
  • 删除本地文件递归
    lib/knowngood.js:112
    rmSync(dir, { recursive: true, force: true });
  • 写入本地文件
    lib/knowngood.js:142
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    lib/knowngood.js:143
    for (const file of files) copyFileSync(file.path, join(dir, file.name));
  • 写入本地文件
    lib/knowngood.js:144
    writeFileSync(
  • 写入本地文件
    lib/knowngood.js:187
    mkdirSync(backup, { recursive: true });
  • 写入本地文件
    lib/knowngood.js:188
    copyFileSync(target.path, join(backup, name));
  • 写入本地文件
    lib/knowngood.js:190
    copyFileSync(source, target.path);
  • 读取本地文件
    lib/remote.js:119
    if (!existsSync(path)) return null;
  • 读取本地文件
    lib/remote.js:121
    const text = readFileSync(path, 'utf8');
  • 读取本地文件
    bin/recovery.js:89
    if (!existsSync(root)) return [];
  • 读取本地文件
    bin/recovery.js:90
    return readdirSync(root).filter((n) => existsSync(join(root, n, 'package.json')));
  • 读取本地文件
    bin/recovery.js:90
    return readdirSync(root).filter((n) => existsSync(join(root, n, 'package.json')));
  • 读取本地文件
    lib/checks/llm-config.js:106
    if (!existsSync(path)) return { ok: true, summary: 'settings.yaml not present', findings: [] };
  • 读取本地文件
    lib/checks/llm-config.js:107
    const problems = findConfigProblems(readFileSync(path, 'utf8'));
  • 写入本地文件
    lib/checks/llm-config.js:121
    copyFileSync(path, backup);
  • 读取本地文件
    lib/checks/llm-config.js:122
    const text = readFileSync(path, 'utf8');
  • 写入本地文件
    lib/checks/llm-config.js:123
    writeFileSync(path, stripProblems(text, findings));
  • 读取本地文件
    lib/checks/llm-config.js:134
    if (!existsSync(backup)) return { restored: [], failed: [] };
  • 写入本地文件
    lib/checks/llm-config.js:135
    copyFileSync(backup, path);
  • 读取本地文件
    lib/checks/settings-yaml.js:68
    if (!existsSync(path)) return { ok: true, summary: 'settings.yaml not present — defaults apply', findings: [] };
  • 读取本地文件
    lib/checks/settings-yaml.js:70
    const { value, error, unavailable } = parseSettingsYaml(readFileSync(path, 'utf8'));
  • 读取本地文件
    lib/checks/agent-default-model.js:66
    if (!existsSync(path)) return { ok: true, summary: 'settings.yaml not present', findings: [] };
  • 读取本地文件
    lib/checks/agent-default-model.js:67
    const { value, error, unavailable } = parseSettingsYaml(readFileSync(path, 'utf8'));
  • 读取本地文件
    lib/checks/api-key.js:36
    if (!existsSync(path)) return new Set();
  • 读取本地文件
    lib/checks/api-key.js:37
    const { value } = parseSettingsYaml(readFileSync(path, 'utf8'));
  • 读取本地文件
    lib/checks/api-key.js:61
    if (!existsSync(path)) return { ok: true, summary: 'settings.yaml not present', findings: [] };
  • 读取本地文件
    lib/checks/api-key.js:62
    const { value, error, unavailable } = parseSettingsYaml(readFileSync(path, 'utf8'));
  • 读取本地文件
    lib/checks/broken-links.js:37
    if (!existsSync(patchPath)) return [];
  • 读取本地文件
    lib/checks/broken-links.js:40
    doc = YAML.parse(readFileSync(patchPath, 'utf8'));
  • 读取本地文件
    lib/checks/broken-links.js:73
    if (existsSync(pkgPath)) {
  • 读取本地文件
    lib/checks/broken-links.js:76
    deps = JSON.parse(readFileSync(pkgPath, 'utf8'))?.dependencies;
  • 读取本地文件
    lib/checks/broken-links.js:83
    if (target !== undefined && !existsSync(target)) {
  • 读取本地文件
    lib/checks/broken-links.js:94
    if (existsSync(nmDir)) {
  • 读取本地文件
    lib/scan.js:70
    return JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')).version ?? null;
  • 读取本地文件
    lib/scan.js:78
    if (!existsSync(nodeModules)) return [];
  • 读取本地文件
    lib/scan.js:80
    for (const entry of readdirSync(nodeModules)) {
  • 读取本地文件
    lib/scan.js:86
    inner = readdirSync(scopeDir);
  • 读取本地文件
    lib/scan.js:124
    if (!existsSync(globalDir)) continue;
  • 读取本地文件
    lib/scan.js:128
    isLink = lstatSync(dir).isSymbolicLink();
  • 写入本地文件
    lib/repair.js:41
    mkdirSync(dirname(dest), { recursive: true });
  • 写入本地文件
    lib/repair.js:43
    renameSync(entry.localPath, dest);
  • 写入本地文件
    lib/repair.js:48
    renameSync(dest, entry.localPath);
  • 读取本地文件
    lib/repair.js:69
    if (!existsSync(backupDir)) return { restored, failed };
  • 读取本地文件
    lib/repair.js:72
    for (const entry of readdirSync(backupDir)) {
  • 读取本地文件
    lib/repair.js:74
    for (const sub of readdirSync(join(backupDir, entry))) names.push(`${entry}/${sub}`);
  • 读取本地文件
    lib/repair.js:83
    if (existsSync(to) || lstatSync(to, { throwIfNoEntry: false })) {
  • 读取本地文件
    lib/repair.js:83
    if (existsSync(to) || lstatSync(to, { throwIfNoEntry: false })) {
  • 删除本地文件递归
    lib/repair.js:84
    rmSync(to, { recursive: true, force: true });
  • 写入本地文件
    lib/repair.js:86
    mkdirSync(dirname(to), { recursive: true });
  • 写入本地文件
    lib/repair.js:87
    renameSync(from, to);
  • 执行外部命令固定命令
    lib/processes.js:74
    const text = execFileSync('ps', ['ax', '-o', 'pid=,command='], {
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-typert-protocol@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 诊断安装故障
  • 修复安装故障
  • 备份与撤销

诊断并修复 DeepSeek Harness(dsh)安装:设置页界面、/doctor 命令,以及一个独立命令行,即使 dsh 无法启动也能用。诊断与自修复。

v0.4.02026-09-09
已对照 dsh 0.1.2-rc.1 验证。 · 这个版本要解决的 bug duplicate-modules 对 dsh 升级后产生的状态视而不见。检查只在 profile 本地副本的版本与全局安装一致时才报错,所以全局树一旦升到新版本,所有过期的 @deepseek-ai/* 副本就都落进了「按设计如此」那一类。在真机上,web 配置档里有 15 个这样的副本——包括 @deepseek-ai/cordis——而扫描却打印出 No problems found.,偏偏漏掉的正是这个工具存在的意义所在:模块身份分裂。 scanProfile 现在会把分叉的 harness 副本和版本不同的普通库区分开,并把前者重新链接到全局版本(每次版本迁移都会点名;restore 可撤销)。来自另一条发布线的副本只报告,不提供修复——那种情况需要重装配置档。 · doctor 修复 doctor 动作现在是 fix 的别名,不再是 status。dsh 坏掉时你才会去敲 dsh doctor,所以它必须把 dsh 修好,而不是打印一份诊断。status 仍是只读的默认动作。这是破坏性的命令行变更——健康检查要显式写 status。 · 回滚到上一次能用的配置 五项检查里有三项只报告,因为工具无从知道损坏的配置原本想说什么。但它能知道它*曾经是什么*:一次以健康状态结束的修复运行会记录 settings.yaml 和配置档的 cordis.patch.yml,dsh doctor rollback 会把最近的快照放回去。这样能救回无法解析的 settings.yaml、指向不存在模型的默认模型,或手改过的 cordis.patch.yml。 ~/.dsh/.credentials.yaml 从不做快照。这个工具只读凭据的键名,从不读值,为了支持回滚而到处复制明文密钥库,等于拿这条纪律换一点小方便——所以缺少 API key 的服务商仍然只报告。 · 设置页 两个主题 bug,不特意找都看不见: · --dsw-alias-state-warning-primary 不是宿主 token(应为 state-warn-primary)。这个无效变量解析为空,于是警告圆点和卡片的强调边框在两种主题下都渲染成隐形——而 agent-default-model 和 api-key 都按 warning 级别报告。 · 品牌填充色上的文字写死成 #fff。--dsw-alias-brand-primary 在浅色模式下接近黑色,深色模式下接近白色,于是选中的检测模式 chip 标签白底白字,消失了。 页面现在通过宿主 locale 服务实现完整双语,并且能撤销:restore 和 rollback 是 Remote 端点,也是操作栏按钮。 · 另外 · peerDependencies 接受整个 @deepseek-ai/dsh-typert-protocol 0.1.x 系列,不再钉死某个 dsh 根本不发的版本;devDependency 和 lockfile 升到 0.1.2-rc.1。 · 运行进程检测改为匹配 dsh 可执行文件,而不是任何包含 dsh 的命令行,所以重启提示不再把跑修复的那个 shell 也算进去。 149 项测试通过,tsc --strict 无报错,对启动的 dsh web 做了端到端验证。 完整说明:CHANGELOG.md
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-recovery 0.6.0 起双名并轨:dsh-recovery 与 dsh-selfrepair 是同一代码库的双名发布——dsh-recovery 为今后主名,dsh-selfrepair 面向既有安装长期同步维护,两包版本号永远一致(用 node scripts/publish-both.mjs 发布)。 npm CI License: MIT 为 DeepSeek Harness(dsh)提供安装诊断与自修复。 五项检查,专抓那些症状与病因毫无关联的故障——插件挂载失败、模型找不到、启动时静默回退——可修复项全部支持备份与撤销。 它做什么 三个修复入口,一个引擎: | 入口 | 位置 | dsh 起不来时可用 | | 诊断设置页 | dsh web -> 设置 -> 诊断 | 否 | | /doctor 斜杠命令 | 任意 dsh 会话内 | 否 | | dsh-recovery CLI | 任意终端 | 是 | CLI 是主入口,这是刻意设计:本工具修复的最严重故障会让 dsh 连提示符都到不了,斜杠命令恰恰在最需要的时候够不着。
展开完整文档(README 剩余 1 节)
dsh-recovery

0.6.0 起双名并轨:dsh-recovery 与 dsh-selfrepair 是同一代码库的双名发布——dsh-recovery 为今后主名,dsh-selfrepair 面向既有安装长期同步维护,两包版本号永远一致(用 node scripts/publish-both.mjs 发布)。

npm
CI
License: MIT

为 DeepSeek Harness(dsh)提供安装诊断与自修复。

五项检查,专抓那些症状与病因毫无关联的故障——插件挂载失败、模型找不到、启动时静默回退——可修复项全部支持备份与撤销。

它做什么

三个修复入口,一个引擎:

| 入口 | 位置 | dsh 起不来时可用 |
| 诊断设置页 | dsh web -> 设置 -> 诊断 | 否 |
| /doctor 斜杠命令 | 任意 dsh 会话内 | 否 |
| dsh-recovery CLI | 任意终端 | 是 |

CLI 是主入口,这是刻意设计:本工具修复的最严重故障会让 dsh 连提示符都到不了,斜杠命令恰恰在最需要的时候够不着。

| 检查项 | 发现什么 | 自动修复 |
| duplicate-modules | 遮蔽全局 dsh 安装的 profile 包——两套依赖注入系统、所有 agent preset 挂载失败 | ✅ 换软链 + 备份 |
| llm-config | 静默顶掉可用默认值的杂散 llm- 键(如 baseURL: "11111") | ✅ 删坏键 + 备份 |
| settings-yaml | settings.yaml 无法解析,并指出坏掉的具体块 | 仅报告 |
| agent-default-model | 默认模型不在所选 provider 的 models: 列表里 | 仅报告 |
| api-key | provider 的 apiKeyEnv 在凭据库和环境变量里都不存在 | 仅报告 |

「仅报告」是刻意为之:这三项工具无法猜出损坏的配置原本想写什么。只读键名,永远不读值。

安装

需要 Node.js ≥ 20 与 dsh CLI(npm i -g @deepseek-ai/dsh)。

一条命令装进 profile——安装包、同步 dsh.profile.bundles、并组合包自带的 bundle patch(挂载本插件的那一行):

dsh plugin --profile web add dsh-recovery

重启一次 dsh web,设置 -> 诊断 就会出现。

独立 CLI 不需要任何 profile——全局装一次,留作救援通道:

npm install -g dsh-recovery
dsh-recovery status # 诊断找到的所有 profile

手动安装(不用 dsh plugin)

cd ~/.dsh/profiles/
npm install dsh-recovery

再往 ~/.dsh/profiles//cordis.patch.yml 加一行:

- insert:
- id: plugin-selfrepair
name: 'dsh-recovery'

insert 是新增;单独的 - id: 是修改已有条目,会报 patch: entry "..." not found。

诊断设置页

页面默认只读——打开即检查,但绝不写入。只有发现问题的检查项才会列出;健康的安装只显示一个 一切正常,别无其他。

顶部可切换两种检测模式:

- AI 检测(配置了可用默认模型时默认):先跑规则检查,再把证据——环境路径、每条规则结果、settings.yaml 原文(只有键名,永不含凭据值)——交给默认模型做第二意见,以「AI 分析」卡片展示。模型调用失败自动降级为纯规则视图。
- 规则检测:仅五项检查。

重新检查 与 一键修复 位于右下角固定操作栏,页面滚动时不动。单项修复原地二次确认(点两下);一键修复是一次郑重的点击,应用全部可修复项。

CLI 参考

dsh-recovery doctor # 诊断并修复所有 profile —— 出问题时就用这一条 dsh-doctor doctor # 同上,短一点的二进制名 dsh-recovery # status,所有 profile(默认动作,绝不写入) dsh-recovery status # 子命令下的只读报告 dsh-recovery fix --profile web # 只修一个 profile(doctor 就是 fix 的别名) dsh-recovery --fix --profile web # --fix 即动作,无需位置参数 dsh-recovery fix --only llm-config # 限定一个检查项 dsh-recovery restore --profile web # 从备份撤销最近一次修复 dsh-recovery rollback --profile web # 回滚到上一个已知可用的配置 dsh-recovery status --json # 机器可读输出

doctor 修复,status 只报告。dsh 坏掉时要用的那条命令必须把它修回可用,而不是打印一份诊断——所以 doctor 会诊断、应用全部可修复项、再报告剩下的问题。每次修复都先写备份,restore 可以回退。重链后的模块只在新进程里生效,因此修复报告会点名仍持有旧副本的运行中 dsh 进程。

不健康时退出码为 1,可直接接健康检查——见 examples/healthcheck.sh;健康检查请用 status,它是那个绝不写入的动作。

dsh doctor 在 dsh 0.1.5-rc.2 上不可用。 0.1.5 的原版启动器只路由
web 与 plugin 两个子命令;本 README 过去宣传的 doctor 路由是对已安装启动器(@deepseek-ai/dsh/lib/bin.js)的本地补丁,升级 dsh 即被冲掉、每次升级后都要手工重打。全局安装的 dsh-recovery / dsh-doctor 两个二进制不受升级影响——请直接使用它们。

会话内斜杠命令(挂载本插件的 profile):

/doctor # 报告(默认)—— 绝不写入 /doctor fix # 应用可修复项 /doctor restore # 撤销最近一次修复 /doctor rollback # 回滚到上一个已知可用的配置

每次修复都可撤销

无法撤销的修复比不修复更糟:这些操作动的是用户已安装的包和配置文件。每次修复先写备份——换链的包移入 .dsh-doctor-backup//,settings.yaml 复制为 settings.yaml.doctor-backup——restore 从其留下的备份精确撤销最近一次修复。

上一个能用的配置

五项检查里有三项只报告,因为工具无法知道损坏的配置原本想写什么。但它可以知道这份配置原来是什么:一次以健康收尾的修复运行会把 settings.yaml 与该 profile 的 cordis.patch.yml 记为 known-good 快照,dsh-recovery rollback 把最近一份放回去。

dsh-recovery doctor # 配好后跑这一次,可用状态就被记下了……某次改动把配置弄坏了……
dsh-recovery rollback # 把记录下来的状态放回去

它能救回定点修复救不了的情况:settings.yaml 语法坏掉、默认模型指向不存在的型号、手改坏的 cordis.patch.yml。快照存在 .dsh-doctor-known-good/snapshots//(保留最近 5 份);配置没变则沿用原快照,所以时间戳表示状态上一次发生变化的时刻;回滚会把被覆盖的内容备份到 .dsh-doctor-known-good/pre-rollback//。

restore 与 rollback 回答的是两个问题:restore 撤销本工具上一次的修复; rollback 撤销的是自配置上次可用以来、由任何人造成的破坏。

~/.dsh/.credentials.yaml 永远不进快照。 本工具只读凭据的键名、从不读值;为了支持回滚而到处复制明文密钥库,是拿这条纪律换一点小便利。因此「provider 缺 API key」始终只报告,任何回滚都修不好它。

记录只发生在写入路径上:detect 永远不能写(设置页每次打开都会跑),所以快照是在一次以健康收尾的修复运行末尾拍下的。

最严重的故障是怎么发生的

把 @deepseek-ai/ 声明为普通依赖(而非 peerDependencies)的 profile 插件,会让 pnpm 在 profile 的 node_modules 里装出第二份真实的 dsh 树——包括 @deepseek-ai/cordis 本身。Node 以解析后的真实路径作为 ESM 模块身份,于是 profile 里跑起了两套依赖注入系统,一边注册的服务另一边不可见:

@deepseek-ai/dsh-base (全局) -> 全局 cordis,全局 dsh-system-prompt
dsh-acp-server (本地) -> 本地 cordis,本地 dsh-system-prompt

所有 agent preset 挂载失败:prompt section "deployment:persona" is already registered,任何会话都起不来。修复方式是把每个副本换成指向全局包的软链——真实路径坍缩回同一实例。副本被移动进备份,绝不删除。

升级 dsh 会把每个 profile 推入这个状态

升级全局 dsh 会把整棵 @deepseek-ai/ 树换到新版本,而每个 profile 仍持有 lockfile 锁定的旧副本——没人动过 profile,身份分裂就已经发生。版本不同并不能让副本变得无害:harness 自己的模块图无论版本号如何,一个进程内只能有一个实例。因此这些陈旧副本按故障报告,并重链到全局版本——这与照着升级后的全局树重装一次得到的结果相同(报告会写明每个包的版本变化,restore 可以回退)。

普通三方库则相反:两份 zod 完全可以共存,重链反而会静默替换插件构建时依赖的版本,所以非 @deepseek-ai/ 的包版本不同就按设计保留本地副本。若 harness 副本与全局处于不同发布线(本地 3.x vs 全局 4.x),同样只报告不重链——那种情况需要照着升级后的 dsh 重装该 profile。

为什么 peer 是 optional

dsh 每次启动都会把自己的依赖树软链进共享的 ~/.dsh/profiles/node_modules/
回退层,因此把 @deepseek-ai/ 声明为 optional peer 的插件会解析到 dsh 自身运行的同一实例——一套依赖注入系统。npm 一旦在插件旁边装出真实副本,真实路径身份分裂,duplicate-modules 故障立刻复发。Optional peer 让治愈手段不会变成病因。

新增一个检查项

lib/checks/.js,注册进 lib/checks/index.js——完整契约见 lib/types.d.ts:

export const myCheck = {
id: 'my-check',
title: 'Human readable title',
severity: 'critical', // 或 'warning' fixable: true,
detect(env) { // env = { profileRoot, globalRoot, dshHome }
return { ok: false, summary: '...', detail: ['...'], findings: [...] };
},
fix(env, findings) { // 先备份,再写入
return { fixed: ['...'], failed: [], note: 'backup: ...' };
},
undo(env) { // 可选:启用 restore
return { restored: ['...'], failed: [] };
},
};

detect 绝不写入:报告可以随时安全运行。抛错的检查会被当作一条失败结果报告,而不是中断整个运行——一个坏探针不能掩盖其余诊断。

开发

git clone https://github.com/dushaobindoudou/dsh-recovery.git
cd dsh-recovery
npm install
npm test # 149 个测试,无需网络、无需 dsh 安装
npm run typecheck

测试在沙盒里复现两种原始故障,并断言完整的 修复 -> 撤销 往返。

软链开发安装挂进 profile 时,把协议 peer 指向运行中 dsh 自己的那份(与兄弟插件同一做法),保证两端共享同一实例:

G=$(dirname $(realpath $(which dsh)))/../lib/node_modules/@deepseek-ai/dsh/node_modules
ln -sfn "$G/@deepseek-ai/dsh-typert-protocol" node_modules/@deepseek-ai/dsh-typert-protocol

参与贡献

欢迎 PR——见 CONTRIBUTING.md。安全问题请走 SECURITY.md。

许可

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

诊断并修复 dsh 安装故障,支持备份撤销

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部