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

插件冲突诊断 ven314/dsh-conflict-doctor

DeepSeek Harness
ven31419 天前有提交已提供中文文档扫描:含敏感能力

定位插件静默失效原因并给出修复补丁

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ven314/dsh-conflict-doctor
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · dev
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 19 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 31 处,展示前 31 条)
  • 写入本地文件
    lib/cli.js:231
    writeFileSync(options.out, rendered, 'utf8');
  • 读取本地文件
    lib/static.js:102
    const parsed = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/static.js:114
    return readFileSync(file, 'utf8');
  • 读取本地文件
    lib/static.js:125
    if (existsSync(join(dir, 'package.json')))
  • 读取本地文件
    lib/apply.js:57
    if (!existsSync(target)) {
  • 读取本地文件
    lib/apply.js:60
    const stat = statSync(target);
  • 写入本地文件
    lib/apply.js:93
    copyFileSync(target, backupPath);
  • 写入本地文件
    lib/apply.js:105
    renameSync(tempPath, target);
  • 删除本地文件
    lib/apply.js:111
    rmSync(tempPath, { force: true });
  • 读取本地文件
    lib/apply.js:132
    if (!existsSync(backupPath)) {
  • 读取本地文件
    lib/apply.js:135
    const text = readFileSync(backupPath, 'utf8');
  • 写入本地文件
    lib/apply.js:155
    mkdirSync(outDir, { recursive: true });
  • 写入本地文件
    lib/apply.js:182
    writeFileSync(target, `${header}${fix.snippet}\n`, 'utf8');
  • 写入本地文件
    lib/apply.js:203
    writeFileSync(join(outDir, 'README.md'), manifest, 'utf8');
  • 读取本地文件
    lib/dryrun.js:67
    if (!existsSync(patchFile)) {
  • 读取本地文件
    lib/dryrun.js:70
    const original = readFileSync(patchFile, 'utf8');
  • 读取本地文件
    lib/source.js:30
    stat = statSync(dir);
  • 读取本地文件
    lib/source.js:39
    entries = readdirSync(dir, { withFileTypes: true });
  • 读取本地文件
    lib/source.js:61
    return readFileSync(file, 'utf8');
  • 读取本地文件
    lib/source.js:70
    if (statSync(file).size > MAX_FILE_BYTES)
  • 读取本地文件
    lib/source.js:206
    return existsSync(join(dir, 'package.json'));
  • 读取本地文件
    lib/hostroot.js:30
    return statSync(path).isDirectory();
  • 读取本地文件
    lib/hostroot.js:39
    return statSync(path).isFile();
  • 读取本地文件
    lib/hostroot.js:203
    return existsSync(join(dirname(process.execPath), 'resources')) || process.env.DSH_HOST_ROOT !== undefined;
  • 读取本地文件
    release.mjs:53
    const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'))
  • 执行外部命令来自配置/变量
    release.mjs:96
    return execFileSync(file, args, {
  • 读取本地文件
    release.mjs:116
    if (candidate && existsSync(candidate)) return candidate
  • 执行外部命令固定命令
    release.mjs:165
    const out = execFileSync('git', ['credential', 'fill'], {
  • 请求外部主机api.github.com
    release.mjs:179
    const res = await fetch(`https://api.github.com${path}`, {
  • 发起网络请求
    release.mjs:179
    const res = await fetch(`https://api.github.com${path}`, {
  • 写入本地文件
    release.mjs:326
    writeFileSync(ENTRY_PATH, ENTRY_BODY)
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:api.github.com

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 插件冲突治理:诊断 DeepSeek Harness 里悄无声息的插件冲突,并给出修复每个冲突的确切补丁。DSH 插件冲突诊断与修复建议。

README

由 DeepSeek 最新模型翻译生成
dsh-conflict-doctor 插件冲突治理:把「装上了但没生效」变成一条可执行的结论。 DSH 有大量手段告诉你插件装上了;没有任何手段告诉你插件没在工作。三类真实故障全部是静默的: | 现象 | 实际发生的事 | 现有工具为什么看不见 | | 装完插件,功能不出现 | fiber 停在 PENDING,等一个没人提供的服务,不报错、不打日志 | 没有报错就没有信号 | | 装第二个插件后整个功能没了 | tool id 重复 → 后注册者抛错 → 整行加载失败,错误信息不指出另一个 owner | 错误只说「already registered」 | | 「我明明关了它,怎么还生效」 | 后一层 patch 把前一层的 disabled/config 盖掉了 | 层语义是整段替换、最后一层胜出 | 本插件把运行期图谱与磁盘上的 patch 层对齐,给出谁和谁撞了 + 改哪一行。
展开完整文档(README 剩余 1 节)
dsh-conflict-doctor

插件冲突治理:把「装上了但没生效」变成一条可执行的结论。

DSH 有大量手段告诉你插件装上了;没有任何手段告诉你插件没在工作。三类真实故障全部是静默的:

| 现象 | 实际发生的事 | 现有工具为什么看不见 |
| 装完插件,功能不出现 | fiber 停在 PENDING,等一个没人提供的服务,不报错、不打日志 | 没有报错就没有信号 |
| 装第二个插件后整个功能没了 | tool id 重复 → 后注册者抛错 → 整行加载失败,错误信息不指出另一个 owner | 错误只说「already registered」 |
| 「我明明关了它,怎么还生效」 | 后一层 patch 把前一层的 disabled/config 盖掉了 | 层语义是整段替换、最后一层胜出 |

本插件把运行期图谱与磁盘上的 patch 层对齐,给出谁和谁撞了 + 改哪一行。

它检测什么

运行期(live)

| code | 严重度 | 含义 |
| live/tool-id-conflict | critical | 两个插件注册同一个 tool id;从失败 fiber 的错误里认出冲突名,并确认它已在注册表中 |
| live/failed-fiber | critical | 任何启动失败的 fiber,带原始错误首行 |
| live/pending-missing-service | critical | fiber 停在 PENDING 且 inject 的服务无人提供——静默失败的根源 |
| live/duplicate-entry-id | critical | 两个模块占用同一个 Loader entry id(整树启动失败) |
| live/unprovided-inject | warning | 声明依赖的服务在整个进程里都不存在(下次重载就会挂) |

磁盘组合(profile)

| code | 严重度 | 含义 |
| profile/duplicate-row-in-layer | critical | 同一 patch 层里 row id 重复 |
| profile/module-under-multiple-ids | critical / info | 同一模块挂两次。config 不同 → info(dsh-tool-subagent 用 toolName: subagent / subagent_fork 刻意挂两次);config 相同或为空 → critical(真的挂重了) |
| profile/disable-then-reinsert | critical | 某层停用、后面的层又插进来 |
| profile/missing-patch-file | critical | bundle 声明的 dsh.bundle.patch 在磁盘上不存在 |
| profile/tool-id-collision | critical | 两个包在编译产物里声明了同一个 tool id。这是静态版本比对永远覆盖不到的能力级冲突 |
| profile/peer-range-unsatisfied | warning / info | 按包分组。已装版本低于声明最小值 → warning(宿主比插件旧,真会坏);只是声明更旧 → info。仅在版本权威性已确认时运行(见下) |
| profile/host-import-unsatisfied | warning | 插件从宿主包里 import 了一个当前宿主并不导出的符号。这是「peer 版本字符串匹配 ≠ API 存在」的具体形态。仅在版本权威性已确认时运行 |
| profile/service-collision | warning | 两个包注册同名服务。按 realm 过滤:浏览器侧包(dsh.client)不与宿主共享服务表,不参与比对 |
| profile/row-config-replaced | info | 多层依次替换同一 row 的 config(DSH 的层语义,符合预期时无需处理,所以只作提示) |
| profile/dangling-override | warning | patch 里的 - id: X 不对应任何已插入的 row(空操作,不报错) |
| profile/node-engine-unsatisfied | warning | engines.node 不满足当前 Node。仅在版本权威性已确认时运行 |
| profile/bundle-unresolved | info | dsh.profile.bundles 里的名字在 node_modules 里解析不到 |

运行期还有两条需要跨两半才能看出的:

| code | 严重度 | 含义 |
| live/pending-self-dependent | critical | fiber 等的服务正是它自己要提供的——自锁,永远不会激活。修复不是「装 provider」 |
| live/outbound-tool-collision | warning | 两个已加载的插件都声明了同一 tool id,而该 id 还没进注册表:冲突是确定的,只是被时序掩盖 |

版本权威性:一次真实的误报与修正

这是本工具最重要的一条设计约束,来自一次被实测证伪的错误。

打包的桌面应用从自己的 archive 提供 profile bundle(@deepseek-ai/dsh-base@0.2.0-rc.2),而 profiles/node_modules 里可能是另一代(0.1.0-rc.6)。早期版本直接拿磁盘副本当基准,于是产出了 7 条并不存在的冲突:声称社区插件 import 了宿主没有的符号、peer 范围不满足。实测把那些符号在运行宿主的 archive 里数出来——IconBranchOutlineRegular 7 处、resolveImageAttachmentAccess 13 处,全都在。

所以现在:插件启动时先向 pluginManager 问运行中的真实版本,再决定要不要做版本敏感的判断。

- 两边一致 → authoritative,正常比对;
- 不一致 → stale-disk,跳过 peer / import / engines 三类检查,并在报告里说明原因;
- 读不到运行版本 → unknown,同样跳过。
宁可不报,也不拿错误的基准报。结构类检查(重复 row、双挂载、层覆盖、配置被替换)不依赖版本,任何时候都照常运行。

每条 finding 都带 refs(涉及对象)、evidence(证据,不是猜测)、impact(会怎么坏)和至少一条 fix;能用 patch 修的直接给出可粘贴的 YAML。

安装

从插件市场(Settings → Plugin Market)搜索安装,或直接:

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

然后把包名加进该 profile package.json 的 dsh.profile.bundles:

{
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-conflict-doctor"] } }
}

或者不安装,直接用 overlay 验证组合层:

dsh --profile web --patch <path-to>/conflict-doctor/cordis.patch.yml --dump-config

关于名字。 npm 上的 dsh-plugin-doctor 是另一个作者的工具,做的是「兼容性 / 安全性 / 隔离安装 / 回滚」。本插件做的是冲突诊断与修复——谁和谁撞了、为什么静默失效、改哪一行。定位不同但名字几乎相同,会在市场上造成安装歧义,因此本包定名为 dsh-conflict-doctor。

使用

模型侧工具:

conflict_doctor { scope: "all" | "live" | "profile", profilePath?: string, format?: "markdown" | "json" }

用户侧命令:

/conflict-doctor

- scope: "live" — 只看运行中的进程(Loader 树、fiber 状态、服务、tool 注册表)
- scope: "profile" — 只读磁盘(bundle 清单 → 每层 patch → row ledger)
- scope: "all"(默认)— 两者都有

设计取向

1. 只读。 不注册服务、不改配置、不碰注册表,只读 + 报告。一个「治理」插件自己成为故障源是荒谬的。
2. 只有一个硬依赖 tools。 loader/commands/systemPrompt/pluginManager 全部在用时 ctx.get——一个诊断插件如果自己停在 PENDING 就是个笑话。注册全部包在 ctx.effect() 里,卸载时干净撤销。
3. 宁缺毋滥。 每条检测器都在真实 profile 上跑过并调过阈值。真实数据把第一版的 23 条噪音收敛到可执行的少数几条;宁可不报,也不拿错误基准报。
4. 纯函数内核。 采集(live.ts / static.ts / source.ts)→ 检测(detect.ts)→ 渲染(render.ts)都是纯函数,可以用 fixture 单测,不需要启动 harness。38 项检查覆盖每个检测器的正例+反例、真实 profile 扫描、以及 Cordis 集成。

主动播报

有 critical 冲突时,插件会把它写进系统提示(systemPrompt.context,order 50),而不是等你来问。没有冲突时贡献空字符串——健康的组合为此付出 0 token。内容只报结论与第一条修复,并明确要求模型在用户提出相关问题前不要擅自改配置。

能力边界(老实说)

- tool id 归属无法 100% 归因。 dsh 的 tool 注册表不记录注册者,公开 API 也拿不到调用方 fiber。所以运行期只报告「冲突名 + 失败行」,跨插件的冲突归属由静态扫描(defineTool({ name: '...' }) 字面量)补上。动态拼出的 tool 名不在静态视野内。
- 静默覆盖只能报症状。 profile/row-config-replaced 里无法判断被丢掉的那层 config 是否必需——因为语义上就是整段替换。
- 版本敏感的检查会主动弃权。 当磁盘副本不是运行中的宿主时,peer / import / engines 三类检查直接跳过并说明原因(见上)。这是刻意的:一次被实测证伪的误报,比十次「可能有问题」更伤信任。
- 名称类静态提取只认字面量。 super(ctx, 'name')、provide('name')、defineTool({ name: '...' }) 能认;拼接出来的名字不能。所以报告措辞是「声明于编译产物」而不是「运行期已注册」。
- engines / peer 是证据不是因果。 范围不满足不等于一定坏,但它是「插件调了宿主里不存在的 API」的第一嫌疑人。
- !!js 不求值。 审计按原样记录 profile 提供的表达式——求值等于在审计里执行用户代码。因此 disabled: !!js ... 这类条件停用无法判定真假,相关行按「未停用」处理。
- fiber 错误文本读的是运行时记录的错误对象(fiber._error,非公开字段),取不到时降级为「无错误文本」而不是抛错。

开发

pnpm install
pnpm build # tsc -> lib/
pnpm test # 38 项检查:fixture 检测器 + 真实 profile 扫描 + Cordis 集成
node test/check-metadata.mjs # 发布元数据:name / engines.dsh / files / peer 声明

test/run.mjs 分三段:Part A 每个检测器的正例/反例 fixture(含版本权威性闸门);Part B 对 $DSH_PROFILE_DIR 真实 profile 做静态扫描;Part C 把 apply() 装进真实 Cordis 容器,验证工具/命令/告警注册、execute 输出契约、以及卸载后 ctx.effect 干净撤销。

test/emit-report.mjs 用真实数据写出仓库根目录的 conflict-doctor-report.md。

路线图

- 把 findings 主动播报进系统提示 ✅ 已实现(systemPrompt.context,无冲突时 0 token)
- 服务级冲突:两个插件提供同一个服务名 ✅ 已实现(realm 感知)
- 对「属性级 API 缺失」做真实比对 ✅ 已实现(import ↔ 导出面),并在实测中修正了基准错误
- slot / 客户端侧冲突(需要 Client Provider 配合)
- 把版本权威性做彻底:直接从运行宿主的 archive / 解析器拿导出面,而不是拿到版本号就弃权——这样 stale-disk 也能给出可信的 API 比对
- live/outbound-tool-collision 的时序预测:结合 fiber 的 inject 等待状态,预告「这一行一旦激活就会撞」

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

定位插件静默失效原因并给出修复补丁

回到顶部