Plugin、Bundle 和 Profile 是三种不同抽象
Plugin 是 Cordis 挂载的运行时单元。Bundle 是 npm 包形式的 patch layer,声明要向树中插入或覆盖哪些 Plugin rows。Profile 是本机 DSH Home 中的命名组合,保存有序 Bundle 列表、额外依赖和自己的 patch。
DSH 安装命令管理的是 Profile 目录里的依赖。依赖解析为声明 dsh.bundle 的包后,CLI 才把它加入有序 layer 列表;普通库可以安装,但不会自动成为运行时层。
Manifest 把包变成可组合层
Bundle 在 package.json 的 dsh.bundle.patch 中指向自己的 cordis.patch.yml。Profile 则在 dsh.profile.bundles 中保存 Bundle 包名,并把顺序作为组合的一部分。
这种设计让 npm、Git、path 或 tarball 负责代码分发与依赖解析,而 DSH 只读取明确的 manifest 和 patch,不重新发明包管理器。
{
"dsh": {
"bundle": { "patch": "./cordis.patch.yml" },
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app"
]
}
}
}组合从空树开始,后层拥有更高优先级
每次启动都从空 entry list 开始。DSH 依次应用 Profile 中列出的 Bundle layers、Profile 自己的 cordis.patch.yml、DSH Home 的全局 patch,再应用命令行 --patch overlays 和运行时开关。
Patch 通过稳定 row id 定位目标。后层可以插入新 row、禁用 row 或覆盖已有 row。针对 config 的覆盖替换整份 config,不做 deep merge,因此作者必须重述希望保留的字段。
- id: tools
config:
mode: both
maxParallelSubCalls: 8
- insert:
- id: team-policy
name: '@acme/dsh-team-policy'依赖关系决定激活,Patch 顺序决定最终配置
Bundle 顺序决定哪一层最后改写某个 row;它不负责手工安排 Plugin 的启动时刻。最终树形成后,Cordis 根据 inject 和 service availability 激活 Plugin。
这个区分让组合保持确定性:patch precedence 回答最终挂载什么和配置是什么,Cordis lifecycle 回答它何时可以安全运行。
配置既能检查,也能在长生命周期应用中重载
dsh --profile <name> --dump-config 会输出真正准备挂载的组合树,并标注 rows 来自哪些层。它是理解覆盖结果和排查缺失 row 的第一工具。
Profile patch 和 Home patch 在长生命周期 surface 上由 watcher 重新读取并重新组合。Cordis 用同一套 effect ownership 卸载旧 generation、挂载新 generation;命令行 overlay 始终保持在用户层之上。
dsh --profile web --dump-config
dsh plugin --profile web add @acme/dsh-team-tools