patch 层与层序
别名:补丁层、层栈、cordis.patch.yml、layer、patch 层
DSH 的一棵插件树不是写出来的,是叠出来的:bundle 层 → profile 层 → home 层 → --patch 覆盖,每一层都是一串补丁;同 id 的行被后面应用的补丁整段覆盖。
一句话
DSH 启动时挂上来的那棵树,没有任何一行是直接写的。profile 目录里的根配置文件永远是一个空数组,整棵树由若干层补丁按顺序叠出来。
层序(后者覆盖前者)
@deepseek-ai/dsh 的 profile 启动代码把补丁按固定顺序拼成一串,再一次性应用到空根上。顺序是:
- bundle 层:
dsh.profile.bundles列出的每个包各贡献一段补丁,按列表顺序(composed.bundlePatches); - profile 层:该 profile 目录下的
cordis.patch.yml; - home 层:
$DSH_HOME/cordis.patch.yml——机器级偏好,对所有 profile 生效,所以它高于 per-profile 层; --patch覆盖:命令行按 argv 顺序给的补丁文件;- 之后还有程序自己追加的遥测开关补丁(
DSH_TELEMETRY_DISABLED非空且组合里有遥测行时生成)。
补丁怎么作用在行上
补丁列表是一份顶层 YAML 数组,每项要么带 insert,要么靠 id 定位已有行:
id+insert:把行插进该 id 的分组(目标不是分组就告警跳过);没有 id 的insert直接追加到顶层。id+ 其它键:把这些顶层键逐个赋到目标行上。disabled: true就是靠这条路摘掉一行。- 匹配不到任何行的补丁只告警、不报错,被跳过。
关键细节:config 是整段替换,不是深合并。补丁写 config: {...} 时,目标行的整个 config 被换掉——所以只想改一个键也要把想保留的键一起写全。这也是「改默认模型」这类配方最容易踩的坑,实战写法见 tutorial/2。
热重载与空根
profile 的根配置每次启动都被重写成空数组:树是被 patch 出来的,如果某次运行把组合后的行写回了根文件,下次启动就会把每个 bundle 的行重复插一遍。运行时期间,profile 层与 home 层两个补丁文件都在监视之下,保存即重新组合,不必重启。
出处
- 层序与组合:
@deepseek-ai/dsh的lib/profile-boot-DG5t9aNs.js(composeProfile、allPatches),实测版本0.1.0-rc.6。 - 补丁语义(唯一权威实现):
@deepseek-ai/dsh-app-boot的lib/index.js里applyEntryPatches与composeEntries。 - 现场样本:市场整合包
hxh230802.smoother-deepseek-harness的 manifestpatch字段就是一层真实补丁(含disabled与整段config两种写法)。
相关教程
谁引用了这一条
信息表
- category
- concept.runtime
- layer
- runtime
- spec
- ~/.dsh/profiles/node_modules/@deepseek-ai/dsh/lib/profile-boot-DG5t9aNs.js(composeProfile / allPatches)
- updatedAt
- 2026-10-02
标签:层序、机制、启动