DeepSeek Harness 的插件安装、配置加载是两套独立但联动的流程:插件安装是包管理动作,负责把插件代码下载、写入 Profile 清单;配置加载是内核启动时的组合解析动作,按固定分层顺序合并配置,后加载层覆盖前面层。绝大多数配置不生效、插件加载失败、参数覆盖异常问题,根源就是混淆了「安装流程」和「启动加载流程」。
一、插件安装:两种安装方式与清单变更
插件安装本质是修改对应 Profile 的 package.json 与 dsh.profile,分为Bundle组合包安装和独立外置插件安装。
1. CLI 命令安装(推荐)
# 向 web profile 安装插件/组合包
dsh plugin --profile web add dsh-auto-clean
# 卸载
dsh plugin --profile web remove dsh-auto-clean
执行安装时内部发生的动作:
- 包管理器下载插件包(npm包、本地路径、github仓库);
- 将包写入当前 Profile 的
package.jsondependencies; - 如果该包包含
dsh.bundle声明,则自动追加到dsh.profile的bundles数组末尾; - 普通无 bundle 声明的独立插件,仅安装依赖,不会自动加入 bundles 列表,需要手动在patch中注册。
重点:Bundle 会追加到 bundles 数组尾部,数组越靠后,配置优先级越高,天然实现后置覆盖前置。
2. 本地手动安装(开发调试)
直接在 profile 的 package.json 添加依赖,或者用 link: 挂载本地插件源码。
- 有
dsh.bundle:手动在dsh.profile的 bundles 数组加入包名; - 无 bundle 的独立插件:仅添加依赖,需要在
cordis.patch.yml手动声明插件实例。
区分:安装只是把代码放到环境,不等于自动加载插件;只有被 Profile 引用的 Bundle,或者在patch里显式注册的插件,内核才会在启动阶段加载。
二、内核启动:配置分层加载顺序(核心)
Harness 启动时,从空配置开始逐层叠加,后应用的层,相同配置项直接覆盖前面层,优先级由低到高如下:
- Bundle 层(最低优先级)
按dsh.profile文件内bundles数组顺序依次加载每个 Bundle。
读取每个 Bundle 内部dsh.bundle清单,加载Bundle自带插件与默认配置。
数组靠前先加载;数组靠后后加载,同配置会覆盖前面Bundle。
- Profile 本地补丁层
读取当前Profile目录内cordis.patch.yml,对上面所有Bundle的配置做局部覆盖。仅作用于当前Profile。 - 全局Home补丁层
读取$DSH_HOME/cordis.patch.yml,全局补丁,对本机所有Profile生效,优先级高于Profile本地补丁。 - 命令行 –patch 层
启动命令传入的--patch参数,临时叠加配置,只在本次启动生效。 - 启动器内置补丁(最高优先级)
框架启动器自动注入的内置配置(遥测开关、agent预设参数等),优先级最高,无法通过patch覆盖。
一句话优先级:Bundle 默认配置 < Profile补丁 < 全局Home补丁 < CLI –patch < 框架内置补丁
三、插件实例加载与激活顺序(Cordis内核)
配置合并完成后,进入插件实例化阶段,遵循依赖拓扑排序,不是简单按Bundle数组顺序执行。
- 内核扫描全部插件声明,构建插件依赖图(Definition / Provider / Consumer三角色依赖关系);
- 按依赖拓扑排序:被依赖的插件优先启动;
- 执行插件生命周期钩子:
setup→ 注册服务、事件、工具 → 激活; - 依赖缺失的插件会延迟等待,超时则抛出加载失败;
- 热重载场景:修改Bundle/Profile/patch文件,内核重新执行整套配置合并+拓扑加载,无需完全重启进程。
注意:Bundle数组顺序决定配置合并顺序;插件之间的依赖关系决定实例激活顺序,二者不要混淆。
四、实战示例:安装插件后配置覆盖演示
假设 dsh.profile:
{
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web",
"dsh-auto-clean"
]
}
加载流程:
- 加载
@deepseek-ai/dsh-base基础Bundle,写入基础默认配置; - 加载
@deepseek-ai/dsh-web,覆盖base中冲突配置; - 加载
dsh-auto-clean(后安装的插件Bundle),覆盖web层冲突配置; - 读取当前profile的
cordis.patch.yml,覆盖上面三层; - 读取全局home补丁,继续覆盖;
- 解析命令行
--patch参数; - 内核做依赖拓扑排序,依次实例化插件。
五、调试加载顺序的工具
dsh --dump-config:导出合并完成后的完整最终配置,查看每一项配置来自哪一层,是排查配置不生效最常用命令;- 日志:启动日志会打印每层配置加载、插件注册、依赖等待信息;
- HMR热重载:开启后修改patch、profile、bundle清单,自动重新执行整套加载流程。
六、常见踩坑清单
- 安装插件后,插件不加载
原因:插件包没有声明dsh.bundle,安装仅写入package.json,没有加入bundles数组。
解决:要么手动声明bundle,要么在patch中手动注册插件。 - 修改Bundle源码配置,重启不生效
原因:Bundle包是版本固化,不要直接修改bundle源码;用户自定义修改统一写在patch层。 - 后面Bundle的配置无法覆盖前面Bundle
原因:bundle数组顺序写反,需要把需要覆盖的Bundle放到数组后面。 - 全局patch覆盖了本地profile配置
原因:全局home补丁优先级高于profile补丁,本机所有环境都会被影响,项目定制优先使用profile目录内patch。 - 插件安装成功,但启动报依赖缺失
原因:包安装完成,但插件内部依赖的服务没有被加载,内核拓扑排序等待依赖超时。检查依赖对应的Bundle是否加入profile bundles列表。
七、最佳实践
- 通用能力封装为Bundle,安装时自动追加到bundles末尾,利用后置覆盖特性;
- 项目级配置修改,优先写当前Profile的
cordis.patch.yml,不改动Bundle包; - 机器全局偏好,使用
$DSH_HOME/cordis.patch.yml; - 临时调试参数,使用命令行
--patch,不写入文件; - 新增Bundle一律放在bundles数组末尾,避免覆盖顺序混乱;
- 遇到配置异常,优先使用
dsh --dump-config查看最终合并后的配置,定位配置来源层。
小结
插件安装是包管理动作,只负责下载代码、修改Profile清单;配置加载是内核启动时分层合并动作,遵循固定优先级,后层覆盖前层;插件实例激活顺序由依赖拓扑关系决定,而非Bundle数组顺序。理解这套顺序,就能快速定位插件加载失败、配置不生效、参数覆盖异常等绝大多数问题。
0 条笔记