📄 一句话概括
profile 就是四层按顺序叠加的补丁栈(bundle → profile → home → CLI);补丁的 config 是整体替换不是深合并,找不到目标只警告并跳过。
📝 本节和前面几节的关系
4.1.2 用的那个 --patch,其实是四层里最上面的一层。这一节把整套叠加顺序讲清楚——注册不是一个瞬间,是一段生命周期。
一、官方对 profile 的定义
dsh --help 里那句原文值得抄下来:
boot a DeepSeek Harness profile — an ordered stack of plugin-bundle patch layers under your own overrides.
拆开就是三个词:有序(ordered)、补丁层(patch layers)、你自己的覆盖(your own overrides)。
所以一个 profile 不是【一张配置表】,是一叠按顺序盖上去的层。
二、四层的顺序
- bundle:插件包自带的那一层,搭出基本结构。
- profile:发行方的预设,补丁式改写(配置树里那句 patched by …)。
- home:用户目录里的长期覆盖。
- CLI:
--patch传进来的临时覆盖,只影响这一次启动。
顺序就是优先级:后盖的压前面的。考试式理解:越靠近【你这次敲的命令】,话语权越大。
三、补丁的语义(schema 原文)
config整体替换,不是深合并——4.7 的实验会把这条撞出来。insert是往分组里追加条目。- 找不到的目标、以及没有 id 的非插入补丁,只警告并跳过。
最后一条是安全设计:补丁写错了不会把系统搞崩,最多是不生效。对【一切皆插件】的系统来说,这条保证了外层乱改不会毁掉内层。
四、配置树自带出处注释
实测这份 web 配置树,带出处注释的段落一共 26 处:
# == @deepseek-ai/dsh-base——13 处,来自包自带那一层。# == @deepseek-ai/dsh-base, patched by dsh-web-app——12 处,被产品层改过。# == @deepseek-ai/dsh-web-app——1 处,产品层自己加的。
每一行都知道自己是谁加的、被谁改过——这是排查问题时最省事的设计。
五、动手 Demo:注册也有生命周期——四层叠加
四层顺序、出处统计、补丁语义,一张表看懂:
layers = ["bundle", "profile", "home", "CLI"]
print("叠加顺序(后盖的压前面的):")
for i, n in enumerate(layers, 1):
print(" %d. %s" % (i, n))
print()
print(" 补丁语义:config 整体替换,不是深合并")
print(" 找不到目标 -> 只警告并跳过")
print()
print(" 配置树出处注释:26 处", end="")
print("(base 13 / base+web-app 12 / web-app 1)")
实跑输出:
--------------------------------------------------------------------
注册也有生命周期——四层叠加
--------------------------------------------------------------------
官方的 --help 里,profile 的定义是一句话:
boot a DeepSeek Harness profile — an ordered stack of
plugin-bundle patch layers under your own overrides.
拆开看,一共四层,按顺序叠加:
层 是谁的 管什么
----------------------------------------------------------
bundle 插件包自带 搭出这个 profile 的基本结构
profile 发行方的预设 补丁式改写(patched by ...)
home 用户目录 你的长期覆盖
CLI --patch 文件 这一次启动的临时覆盖
----------------------------------------------------------
配置树里每一段都带着【出处注释】,真实统计是这样的:
出处注释 段数
-------------------------------------------------------
@deepseek-ai/dsh-base 13
@deepseek-ai/dsh-base, patched by dsh-web-app 12
@deepseek-ai/dsh-web-app 1
合计 26
-------------------------------------------------------
补丁的语义,schema 里写得很清楚:
config 整体替换,不是深合并;insert 是往分组里追加;
找不到的目标和没有 id 的非插入补丁,只警告并跳过。
【警告并跳过】这一条尤其重要:改错了不会把系统搞崩,只会不生效。
有序这两个字是重点:不是【谁覆盖谁】的权限问题,是一层层盖上去的顺序问题。
出处注释让我能一眼分辨:这一件是包自带的,还是产品层改过的,还是我这次补丁改的。
config 整体替换这条在 4.7 会实测撞出来——不写全字段就等于删字段。
30 秒实验
- 用
dsh --profile web --dump-config打一份配置树,数一数出处注释有几种。 - 写一份补丁,只改
sandbox-policy的mode,看workspaceRoot还在不在。 - 解释一下:为什么补丁找不到目标时【警告并跳过】,而不是直接报错退出?
常见误区
- 错误:profile 就是一份配置文件。——纠正:是一叠按顺序叠加的补丁层(bundle → profile → home → CLI)。
- 错误:补丁会和我改的字段深合并。——纠正:config 是整体替换——没写的字段等于被删掉。
- 错误:补丁写错会启动失败。——纠正:找不到目标只会警告并跳过,最多是不生效。
自测三问(点开对答案)
1. 四层叠加的顺序是什么? —— bundle → profile → home → CLI;**后盖的压前面的**。 2. 补丁的 config 是深合并还是整体替换? —— **整体替换**——没写的字段等于被删掉(4.7 有实测)。 3. 出处注释有什么用? —— **一眼分清**每一件是包自带的、产品层改过的,还是本次补丁改的——排查时最省事。- ☐ 下一节(4.2.2 不要把 Tool 看成一个函数)
相关笔记
- 动手实验:删除 Skill,观察能力是否还在 —— 用的就是四层里最上面那层
- 【一切皆插件】不等于没有内核 —— 补丁层能生效,靠的是内核的加载机制
- 配置模型 —— 配置从哪里来,这一节讲清了层
- 🐳 DeepSeek Harness · 索引