配置体系:patch 与覆盖层
本教程共 32 篇 · 第 9 篇 · 更新于 2026-08-15 · 约 5 分钟阅读
本节目标:掌握 cordis.patch.yml 的写法、按 id 定位条目的规则,以及四层配置叠加顺序,学会用 —dump-config 查看最终配置树。
dsh 没有传统的「配置文件大全」。它的配置由一层层 patch 叠出来,每一层都是 YAML 文件。这一章把 patch 语法和叠加规则讲透,你就能读懂任何一份 dsh 配置。
配置项:cordis.yml 的基本单元
cordis.yml 是一个配置项的列表。每个配置项可以带这些字段:
- id: greeter # 稳定标识,patch 靠它定位
name: './greeter.ts' # 插件模块:相对路径、绝对路径或 npm 包名
config: # 传给插件的配置(可选)
greeting: Hello
disabled: false # true 时保留条目但不挂载
name 是模块指定符。loader 会挂载每个配置项,各项并发启动。列表位置不保证加载先后,顺序由服务依赖(inject)决定。
patch:按 id 定位条目
patch 文件与 cordis.yml 同构,都是配置项列表。区别在语义:patch 按 id 定位已有条目并替换其整个 config,或插入新条目。看一个实际例子——用 --patch 覆盖层插入本地插件:
# scratch-plugin/cordis.yml
- insert:
- id: hello
name: '/absolute/path/to/my-plugin.ts' # 本地插件必须用绝对路径
insert 是加载本地插件时的显式写法。修改既有配置则直接给出 id 和新的 config,例如把某插件的超时从 5 秒改成 60 秒,只需在 patch 里写:
- id: dsh-bash-local
config:
timeoutMs: 60000
Warningpatch 按 id 替换的是条目的整个 config,不是合并键值。漏写一个键,它的默认值或出厂值就没了。改配置前先
--dump-config看原样,再动笔。
四层叠加顺序
第 7 章讲过组合顺序,这里落到文件层面:
- bundle 序:profile 列出的每个 bundle 的 patch(如
dsh-base的cordis.patch.yml) - profile patch:
$DSH_HOME/profiles/<name>/cordis.patch.yml - home 级 patch:
$DSH_HOME/cordis.patch.yml - —patch 覆盖层:命令行传入的任意 YAML
dsh web --patch ./scratch-plugin/cordis.yml
靠后的层覆盖靠前的层。出厂配置写在 bundle 层;个人偏好写 home 层;临时调试写 --patch。id 相同则后层替换前层,这是整个配置体系唯一的核心规则。
可以想成贴便利贴:越晚贴的越靠上,盖住下面同位置的内容。patch 不跟你商量,同 id 直接整条替换。
显式 id 有多重要
id 为配置项提供稳定标识,使 loader 能区分「修改现有条目」与「先删后加」。没有 id 的配置项,每次读取都会获得一个新生成的 id——只要配置文件有任何编辑,即使它自身文本没变,也会被当作先删除再添加,重新挂载一次。
热重载(HMR)按 id 比较配置项,只挂载、卸载或重新配置发生变化的部分。所以:自己写的插件条目,永远显式写 id。
人话版:id 是配置项的身份证。没有身份证,每次读文件都当新人,重新挂载一遍;有了 id,系统才知道你是回头客,只更新你的资料。
配置校验与计算值
每个插件导出一个同名 Config schema(用 Schemastery 定义),loader 在运行 apply 前校验 config。配置不合法,插件直接加载失败,绝不带病启动:
ValidationError: invalid config:
- $.targets expected array but got not-an-array (at targets)
loader 还支持 !!js 标签,在加载时计算配置值:
- id: demo
name: './config-demo.ts'
config:
greeting: !!js process.env.DEMO_GREETING ?? 'Hello'
!!js 只在 config 与条目 disabled 字段内有效。按平台或环境门控一行插件是常见用法:
- id: pwsh
name: '@deepseek-ai/dsh-pwsh-local'
disabled: !!js process.platform !== 'win32'
查看最终配置树
配置叠了几层,难免想确认最终结果。两个命令不启动即可查看:
# 完整组合树(含 profile/home/--patch 各层)
dsh --profile web --dump-config
# 仅部署默认(不含用户层)
dsh --profile web --dump-default-config
打印出的任何条目,都可以由你自己的 patch 替换。官方还有一个生成的参考文档 config-catalog:每个可加载包原样列出其 config: 声明(含 JSDoc),并标注 Requires: 注入的服务键。想查「这个插件能配什么」,先翻它。
改配置没生效,八成不是语法错,而是改在了被覆盖的层上。先 dump 看最终树,再动手。
Tip排查思路:插件没生效 → 先看它是否卡在 PENDING(依赖未满足);配置没生效 → 先
--dump-config看最终树里 id 是否被后层覆盖。两步能解决绝大多数配置问题。
Warning版本基线
@deepseek-ai/dsh0.1.0-rc.6 处于快速迭代期。!!js求值、patch 语义等细节以dsh --version实测和官方 config-catalog 为准。
小结
- 配置是一层层 patch 叠出来的,每层都是 YAML 文件。
- patch 按 id 定位条目,替换整个 config,不做深度合并。
- 四层顺序:Bundle 序 → Profile patch → home patch →
--patch。 - 自己写的插件条目永远显式写 id,热重载才能只动该动的部分。
- 配置不合法直接加载失败;
!!js可在 config 里注入计算值。