通过前面两篇文章针对Profile的介绍(Profile究竟是什么?和创建一个新的Profile提供自定义插件),我们知道了所谓的Profile本质上就是构建了一组用来提供插件的配置,但是最终应用到Cordis上的插件不限于此,它还有其他的来源。这篇文章就来不起最后这张拼图。
1. Profile提供的两层插件配置
回顾一下前面的两篇文章,总计下它主要提供的如下的知识点:
- 最终的插件树是按照固有的顺序先后应用插件补丁文件构建而成;
- 每个补丁文件提供一组
PatchOptions列表,一个PatchOptions对象代表一个插件(组); - 插件补丁文件可以利用-insert在根节点或者在现有的插件组中添加一组插件(组),插入的插件(组)体现为一个
EntryOptions对象; PatchOptions和EntryOptions不仅可以指定作为标识的id和作为包名/模块的name,还可以分别利用confgi、inject和intercept指定插件配置、注入的依赖服务列表和针对服务的配置,基于利用isolate构建独立的隔离域(本质上就是根据指定的名称调用isolate方法来创建子Context);- Profile提供了两组
PatchOptions列表,分别以如下的两种方式构建:- 利用
package.json注册包提供的插件补丁文件构建而成; - 利用自身的
cordis.patch.yml补丁文件构建而成。
- 利用
2. 插件配置树的额外两层
DSH被启动并完成初始化流程后,除了通过指定Profile构建的两层插件配置,还包括如下两层:
- 在DSH运行时目录(通过环境变量
DSH_HOME定义,默认位置为~/.dsh或者%userprofile%.dsh)下定义的补丁文件; - 用户启动DSH以命令行参数–patch指定的补丁文件(这个采用可以服用,意味着可以指定一组补丁文件)。
上述两组补丁文件构建的PatchOptions会和Profile对象一起,组成一个ComposedProfile对象,该接口对应的定义如下:
interface ComposedProfile {
profile: Profile
bundlePatches: PatchOptions[]
homePatches: PatchOptions[]
overlays: PatchOptions[]
}
四个字段成员说明如下:
- profile: 构建的Profile对象;
- bundlePatches:由注册到Profile的包提供的补丁文件构建的一组
PatchOptions列表(PatchOptions列表的列表)被打平后的结构; - homePatches:由在DSH运行时目录提供的补丁文件构建的
PatchOptions列表; - overlays: 由命令行参数
--patch提供的补丁文件构建的PatchOptions列表。
上述作为四个来源的PatchOptions列表可以视为四个层次,在生成最终插件树时,会按照既定的顺序提取每个PatchOptions并应用到当前构建的这颗树上。具体的提取顺序如下:
- ComposedProfile.bundlePatches:
- ComposedProfile.profile.patchPath
- ComposedProfile.homePatches
- ComposedProfile.overlays
3. 注册homePatches
创建一个新的Profile提供自定义插件中,我们已经创建了一个用来提供自定义插件的Profile,我们现在来看看如何我们补齐其他两种类型的补丁,最后构建的插件树是否会改变。为此我们在%userprofile%.dsh目录下创建一个补丁文件cordis.patch.yml,提供如下的内容:
- insert:
- id: plugin7
name: '@jaydenai/foo'
config:
source: '$DSH_HOME/cordis.patch.yml'
- id: group1
insert:
- id: plugin8
name: '@jaydenai/bar'
config:
source: '$DSH_HOME/cordis.patch.yml'
我们在这个补丁中提供了两个插件,其中插件foo被至于根节点,另一个插件bar被添加到现有的组group1中。为了能够在运行时确定插件的来源,我们通过提供的配置将source指定为$DSH_HOME/cordis.patch.yml。接下来我们按照如下的方式执行命名npx tsx apps/cli/src/bin.ts --profile test以源码启动DSH,并将profile设置为test。从输出可以看出多出了两个来源匹配的插件被执行,输出的结构与与上面的定义相符。
PS E:\dsh\deepseek-harness> npx tsx apps/cli/src/bin.ts --profile test
npm notice run @deepseek-ai/dsh-root@0.1.5-alpha.2 npx
npm notice run tsx apps/cli/src/bin.ts --profile test
Loader>Include>foo[package.json]
Loader>Include>foo[cordis.patch.yml]
Loader>Include>foo[$DSH_HOME/cordis.patch.yml]
Loader>Include>bar[package.json]
Loader>Include>Group>bar[cordis.patch.yml]
Loader>Include>Group>bar[$DSH_HOME/cordis.patch.yml]
Loader>Include>Group>baz[package.json]
Loader>Include>Group>Group>qux[package.json]
Loader>Include>Group>Group>baz[cordis.patch.yml]
4. 注册overlays
我们进一步来验证利用命令行参数--patch提供的补丁文件能够按照我们的预期参与到插件树的构建流程,我们定义了如下两个补丁文件,分别命名为overlays1和overlays2。这两个补丁同样注册了foo和bar两个插件,前者至于顶层的根节点,后者分别添加到由ComposedProfile.bundlePatches创建的组group1和group2。我们将这两个文件保存到d:\下。
d:\overlays1:
- insert:
- id: plugin9
name: '@jaydenai/foo'
config:
source: overlays1
- id: group1
insert:
- id: plugin10
name: '@jaydenai/bar'
config:
source: overlays1
d:\overlays1:
- insert:
- id: plugin11
name: '@jaydenai/foo'
config:
source: overlays2
- id: group2
insert:
- id: plugin12
name: '@jaydenai/bar'
config:
source: overlays2
我们依然按照上面的方式启动DSH,不过这次我们通过两次使用命令行参数--patch分别指定了上述两个补丁文件。由它们提供的四个插件同样出现在最终的输出结果中。
PS E:\dsh\deepseek-harness> npx tsx apps/cli/src/bin.ts --profile test --patch d:\overlays1.yml --patch d:\overlays2.yml
npm notice run @deepseek-ai/dsh-root@0.1.5-alpha.2 npx
npm notice run tsx apps/cli/src/bin.ts --profile test --patch d:\overlays1.yml --patch d:\overlays2.yml
Loader>Include>foo[package.json]
Loader>Include>foo[cordis.patch.yml]
Loader>Include>foo[$DSH_HOME/cordis.patch.yml]
Loader>Include>foo[overlays1]
Loader>Include>foo[overlays2]
Loader>Include>bar[package.json]
Loader>Include>Group>bar[cordis.patch.yml]
Loader>Include>Group>bar[$DSH_HOME/cordis.patch.yml]
Loader>Include>Group>bar[overlays1]
Loader>Include>Group>baz[package.json]
Loader>Include>Group>Group>bar[overlays2]
Loader>Include>Group>Group>qux[package.json]
Loader>Include>Group>Group>baz[cordis.patch.yml]
5. 包含文件的使用
在定义补丁问文件的时候,插件的节点被我们设置成包名、插件组的名称被统一设置成预定义的cordis:group。其实我们还可以将节点名称设置为cordis:include将另一个补丁文件引进来。比如在d:\include.yml添加了针对foo和bar的两个插件。由于SDH针对包的解析会在该文件所在的目录进行,所以我们直接使用定义插件的源文件。除此之外,包含就隐含插入的意思,所以不能在外面在套一层insert。我们通过配置插件将source设置成include以示来源。
- id: plugin13
name: file:///E:/dsh/deepseek-harness/packages/demo/foo/lib/index.js
config:
source: include
- id: plugin14
name: file:///E:/dsh/deepseek-harness/packages/demo/bar/lib/index.js
config:
source: include
我们修改test Profile所在目录的补丁文件cordis.patch.yml,并添加了一个id和name分别为include-extra-tools和cordis:include的节点,在设置的配置中利用path字段只想上面这个include.yml文件(DSH要求文件路径严格采用为file:///为前缀的模式)。
- insert:
- id: plugin5
name: '@jaydenai/foo'
config:
source: cordis.patch.yml
- id: include-extra-tools
name: 'cordis:include'
config:
path: 'file:///d:/include.yml'
- id: group1
insert:
- id: plugin6
name: '@jaydenai/bar'
config:
source: cordis.patch.yml
- id: group2
insert:
- id: plugin7
name: '@jaydenai/baz'
config:
source: cordis.patch.yml
我们依然按照上面的方式启动DSH。会发现d:\include.yml包含的两个插件会出现在最终的输出结果中(最后两个)。
PS E:\dsh\deepseek-harness> npx tsx apps/cli/src/bin.ts --profile test --patch d:\overlays1.yml --patch d:\overlays2.yml
npm notice run @deepseek-ai/dsh-root@0.1.5-alpha.2 npx
npm notice run tsx apps/cli/src/bin.ts --profile test --patch d:\overlays1.yml --patch d:\overlays2.yml
Loader>Include>foo[package.json]
Loader>Include>foo[cordis.patch.yml]
Loader>Include>foo[$DSH_HOME/cordis.patch.yml]
Loader>Include>foo[overlays1]
Loader>Include>foo[overlays2]
Loader>Include>bar[package.json]
Loader>Include>Group>bar[cordis.patch.yml]
Loader>Include>Group>bar[$DSH_HOME/cordis.patch.yml]
Loader>Include>Group>bar[overlays1]
Loader>Include>Group>baz[package.json]
Loader>Include>Group>Group>bar[overlays2]
Loader>Include>Group>Group>qux[package.json]
Loader>Include>Group>Group>baz[cordis.patch.yml]
Loader>Include>Include>foo[include]
Loader>Include>Include>bar[include]

2780

被折叠的 条评论
为什么被折叠?



