DSH plugin 本地调试:--patch 覆盖层怎么用、--dump-config 看配置、改了不生效怎么排查

插件开发发布于 2026-09-12作者: DeepSeek Plugin 插件市场
DSH pluginDeepSeek Harness本地调试--patch排查
DeepSeek Harness(DSH)插件本地调试:用 --patch 覆盖层挂载源码、用 --dump-config 核对配置分层,按 Fiber 状态变化定位加载失败,并排查改了不生效、服务重复注册等常见问题。

DSH plugin 本地调试有两条通道:改源码阶段用 --patch 覆盖层挂载绝对路径的插件文件(改完重启即生效),要验证分发产物才用 dsh plugin --profile <name> add 装进 profile;两者验证的目标不同,混用会把「没挂载」误判成「代码有问题」。 无论你叫它 DSH插件 还是 DeepSeek插件,这两条通道的边界都一样。

DSH plugin 两条调试通道怎么选

判断标准只有一条:你要验证的是「加载」还是「安装」。来源

通道命令验证目标生效方式
覆盖层pnpm dsh web --patch ./scratch-plugin/cordis.yml插件能否被加载、代码是否正确改源码 + 重启
profile 安装dsh plugin --profile demo add ./hello-plugin打包产物能否被安装重新 add

调试源码时永远先用覆盖层,因为它的反馈链路最短:不需要 package.json 齐备、不需要打包、不需要走 pnpm 安装。

用 --patch 覆盖层挂载 DSH plugin 源码

覆盖层的两条硬规则:插件路径必须绝对,patch 只贡献配置。 官方教程的写法分三步(来源):

  1. 取绝对路径:先 pwd 拿到检出根,写进配置的必须是完整绝对路径。
  2. 写覆盖层配置:在 ./scratch-plugin/cordis.yml 里插入插件行:
yaml
- insert:
    - id: hello
      name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'
  1. 带覆盖层启动pnpm dsh web --patch ./scratch-plugin/cordis.yml预期插件随之加载、改完源码重启即生效。

为什么「写在 patch 里却没加载」多半不是语法问题:patch 不改变 loader 解析模块路径所用的 profile 目录,所以相对路径、软链、拼错的绝对路径都会静默失效。

用 --dump-config 看 DSH plugin 的配置树

不看配置树就调试,等于闭眼改代码。 dsh 提供两个不启动就能看合成结果的开关(来源):

  1. 看合成后的配置树dsh --profile demo --dump-config预期输出含各层 patch 叠加结果。
  2. 看默认配置树dsh --profile demo --dump-default-config,用于与合成结果对照。

合成顺序决定了「谁压过谁」

  1. 各 bundle 的 patch(按 dsh.profile.bundles 顺序)
  2. profile 自己的 cordis.patch.yml
  3. 家目录的 $DSH_HOME/cordis.patch.yml
  4. --patch 覆盖层(优先级最高

越靠后越优先,所以覆盖层能压过 profile 配置。理解了这层顺序,就能解释「明明改了配置却不生效」。

按 Fiber 状态定位 DSH plugin 加载到哪一步

插件的生命周期是一个状态机,卡在哪一步就说明问题在哪一类。来源

PENDING ──▶ LOADING ──▶ ACTIVE
                │
                └──▶ FAILED        ACTIVE ──▶ UNLOADING ──▶ DISPOSED
  • 根本没进入状态机:加载器没解析到这个模块——回去查路径与 patch。
  • 停在 LOADINGFAILED:依赖没就绪(inject 里声明的服务不存在)或 apply 抛了异常。
  • ACTIVE 但行为不对:插件加载成功,问题在注册逻辑或事件模式选择。
  • 卸载后还在跑:手动资源没交给 ctx.effect

处置器的一个坑:逆序开始调用,但异步处置器并发执行、不保证逐个完成;有顺序依赖的清理必须合并进同一个 ctx.effect

DSH plugin 改了不生效的五步排查

按成本从低到高查,通常第一步就命中。

  1. 确认 patch 被带上:启动命令里有没有 --patch,文件路径是否正确。
  2. 确认你的行进了配置树dsh --profile demo --dump-config 搜索插件 id。
  3. 确认路径是绝对路径:相对路径不会报错,只会静默不加载。
  4. 确认源码已重新编译:跑的是入口产物还是源码,改的文件是否是真正入口引用的那个。
  5. 确认不是被上层覆盖:同一 id 是否在 profile 或家目录配置里被改写(合成顺序见上一节)。

DSH plugin 清理与卸载验证

调试阶段就要验证清理,否则问题会推迟到用户机器上爆发。 两条规则:通过 ctx 注册的东西(事件监听、工具、定时器)会在插件卸载时自动清理;手动资源(网络连接、文件句柄)必须包进 ctx.effect() 交出处置器(来源)。

验证手段:卸载插件后观察日志是否停止、服务是否仍可访问。服务类问题(如重复注册)见 服务重复注册的排查;插件压根没激活见 插件没激活的排查

最后补几条容易忘的命令与前提

  • 源码运行需要先 pnpm run build(生产运行需要构建产物),再用 pnpm dsh <args...> 转发参数;
  • launcher 只解析自己的参数,第一个它不认识的 token 开始算应用参数——两者顺序不能颠倒;
  • webheadless profile 首次使用时从模板自动初始化,其他 profile 必须通过 dsh plugin 创建
  • 无效命令、错误配置与启动失败都会以非零码退出——退出码非零就是真的失败,不要忽略

环境本身没搭好的先看 开发环境搭建;调试通过后按 开发规范 过自检,再进 打包成 bundle

常见问题

DSH plugin 本地调试用 --patch 还是装进 profile?

**DSH plugin 本地调试按目的选通道:验证「插件能否被加载」用 --patch 覆盖层**,改完源码重启即生效,不用打包;**验证「打包产物能否安装」用 dsh plugin --profile <name> add <包>**。覆盖层只贡献配置、不改变 loader 解析模块路径的 profile 目录,所以本地插件的路径必须写绝对路径(来源:dsh CLI README)。

DSH plugin 改了代码却不生效,一般是什么原因?

先查三处:**① DSH plugin 的插件路径不是绝对路径**;**② 启动时没带上 --patch**(或 patch 文件路径写错);**③ 改的是源码但跑的是另一份构建产物**。用 --dump-config 打印合成后的配置树,就能确认你的 patch 行到底有没有进树(来源:dsh CLI README)。

怎么快速判断 DSH plugin 加载失败在哪一步?

**看 DSH plugin 的 Fiber 状态就能定位加载失败在哪一步**:PENDING → LOADING → ACTIVE,其中任一步出问题会转入 FAILED;卸载时走 ACTIVE → UNLOADING → DISPOSED。**卡在 LOADING/FAILED 通常是依赖(inject)没就绪或 apply 抛异常**,而不是模块没找到——模块问题的表现是插件根本没进入状态机(来源:官方「插件框架」)。

DSH plugin 的配置分层顺序是什么,调试时为什么要看它?

**DSH plugin 的配置合成顺序是:各 bundle 的 patch(按 dsh.profile.bundles 顺序)→ profile 自己的 cordis.patch.yml → 家目录的 $DSH_HOME/cordis.patch.yml--patch 覆盖层**。越靠后越优先,所以覆盖层能压过 profile 配置;看清这一层关系才能解释「明明改了配置却不生效」(来源:dsh CLI README)。

调试 DSH plugin 时怎么确认资源被正确清理了?

**确认 DSH plugin 资源清理的方法是卸载一次插件,观察两类信号**:通过 ctx 注册的东西(事件监听、工具、定时器)应当自动清理;**手动资源必须包在 ctx.effect 的处置器里**才会释放。注意处置器是逆序开始调用,但异步处置器并发执行、不保证逐个完成——有顺序依赖的清理要合并进同一个 ctx.effect(来源:官方「插件框架」)。

相关术语

--patch 覆盖层
--patch 是 DSH plugin 的启动参数,把一份额外的 cordis.yml 叠加到现有配置树之上,用于挂载尚未发布的本地插件;层级最高、优先于 profile 与家目录配置,但不改变 loader 解析模块路径的 profile 目录。https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md
--dump-config
--dump-config 是 DSH plugin 的调试开关,打印合成后的配置树(含各层 patch 叠加结果)而不真正启动,是确认插件是否被挂载的最快手段;--dump-default-config 则打印默认配置树。https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md
Fiber 状态
Fiber 是 DSH plugin 在框架中的生命周期状态机:PENDING → LOADING → ACTIVE,任一步失败转 FAILED;卸载时 ACTIVE → UNLOADING → DISPOSED。定位加载问题先看插件停在哪个状态。https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/framework/index.zh.md
profile
profile 是 DSH plugin 的启动单元,是一叠有序的插件 bundle patch 层加上用户自己的覆盖;目录内含 package.json(含 dsh.profile.bundles)与 cordis.patch.yml。https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md

来源