DeepSeek Harness 组合包 bundle 与 profile:两个 manifest 菜鸟教程
之前的章节我们用 --patch overlay 加载本地插件,这篇开始把它们打包成可安装的组合包。
本章节我们将讲清楚两个最基础的概念:bundle(组合包) 与 profile,以及它们各自的 manifest。
两个概念,两种 manifest
安装机制建立在两个概念之上,二者都由一份 package.json 描述。
它们在 dsh 键下携带的 manifest 种类不同,回答的问题也不同。
组合包是附带一个配置层的 npm 包。
它的 manifest 声明 dsh.bundle,回答的是"这个包贡献什么":一个插入或覆盖插件行的 patch 文件。
profile 是位于 $DSH_HOME/profiles/ 下、描述一份可启动组合的目录。
它的 manifest 声明 dsh.profile,回答的是"这套配置由哪些组合包按什么顺序组成"。
bundle 是你编写并分发的东西;profile 是用户用
dsh --profile <name>启动的东西。没有东西同时是两者。
| 概念 | manifest 键 | 回答的问题 | 谁编写 / 谁使用 |
|---|---|---|---|
| bundle(组合包) | dsh.bundle |
这个包贡献什么(一个 patch 文件) | 插件作者编写,随包分发 |
| profile | dsh.profile |
这套配置由哪些 bundle 按什么顺序组成 | 由 dsh plugin 自动创建维护,用户启动 |
profile 位于安装目录之外,路径模板是 $DSH_HOME/profiles/。
动手:创建 hello-plugin 组合包
按官方教程,先创建包目录。
实例
组合包目录结构如下,一共三个文件。
实例
<span>hello</span><span>-</span><span>plugin</span><span>/</span><span>
</span><span>├──</span><span> </span><span>package</span><span>.</span><span>json </span><span># 声明 dsh.bundle</span><span>
</span><span>├──</span><span> cordis</span><span>.</span><span>patch</span><span>.</span><span>yml </span><span># profile 列出该 bundle 时应用的配置层</span><span>
</span><span>└──</span><span> index</span><span>.</span><span>js </span><span># patch 行引用的插件模块</span>
创建 hello-plugin/package.json,声明组合包 manifest。
实例
{
“name”: “dsh-hello-plugin”,
“version”: “0.1.0”,
“type”: “module”,
“main”: “index.js”,
“files”: [“index.js”, “cordis.patch.yml”],
“dsh”: { “bundle”: { “patch”: “./cordis.patch.yml” } }
}
package.json 各字段的含义如下。
| 字段 | 说明 |
|---|---|
name |
包名,Node 模块解析靠它找到已安装的代码 |
version |
版本号 |
type |
"module" 表示使用 ESM 模块格式 |
main |
入口文件 |
files |
发布时只包含的文件清单 |
dsh.bundle.patch |
组合包 manifest:声明贡献的 patch 文件路径 |
创建 hello-plugin/index.js,写入插件入口。
实例
// 文件路径:hello-plugin/index.js
export const name = ‘hello-plugin’ // 插件名,用于日志与诊断
export function apply() {
console.log(’[hello-plugin] plugin loaded!’) // 加载时打印一行日志
}
创建 hello-plugin/cordis.patch.yml。
实例
# 文件路径:hello-plugin/cordis.patch.yml
# 这个 patch 与一直用的 –patch overlay 一样,是 patch 条目的 YAML 数组
# 区别:插件行按包名而不是相对源码路径引用,Node 模块解析才能找到已安装的代码
- insert: - id: hello name: dsh-hello-plugin
这个 patch 与 --patch overlay 完全同构。
关键区别在 name 字段:这里写的是包名 dsh-hello-plugin,而不是相对源码路径。
安装后 pnpm 把包链接到 node_modules,Node 的模块解析就能按包名找到已安装的代码。
没有
dsh.bundle声明的包仍然可以安装,但只作为普通依赖。此时
dsh plugin会打印警告,且不激活任何层。如果一个库供插件包 import、而不是供用户启用,就使用这种包格式。
profile manifest:从不需要手写
profile 目录包含两个文件。
第一个是 package.json,包含 profile 的树外插件依赖(由 pnpm 管理),加上 dsh.profile manifest 及其有序的 bundles 列表。
第二个是 cordis.patch.yml,是用户自己的 patch 层,在每个组合包层之后应用。
profile manifest 从不需要手写。
dsh plugin 负责创建和维护它,下一篇安装插件时会展示它的真实结果。
进阶:让表层组合包持有自己的命令行
定义了可运行应用的组合包,可以挂载一个普通提供方插件来持有自己的命令行。
这个提供方插件导出 inject = [‘cmdlineArgs’],用自己的 commander program 调用 parseCmdline,再在 program 自己的 action 中把应用自有服务提供出去。
实例
# 挂载提供方插件:id 随意,name 指向 bundle 包内的 startup 模块
- id: hello-startup name: ‘dsh-hello-plugin/startup’
受这些参数配置的行会注入提供方服务,并在自己的 !!js 选项中读取它,同时把部署取值写在旁边作为回退。
实例
# 示例:端口号来自提供方服务,取不到时回退到 8080
- id: my-app name: ‘@example/my-app’ inject: [myAppStartup] config: port: !!js ctx.myAppStartup.port ?? 8080
启动器把自身 flag 之后的同一份不可变参数交给每个插件,因此添加应用专属 flag 无需修改启动器,多个插件也可以解析同一份快照。
遇到 --help 时,提供方不会发布该服务,所以这些行不会激活。
Loader 只挂载一次组合,等待每一行的普通注入,再基于其已注入的上下文求值该行的 !!js 配置。
小结与自测
组合包声明 dsh.bundle 回答"贡献什么",profile 声明 dsh.profile 回答"由哪些 bundle 组成",两者由一份 package.json 承载但 manifest 不同。
自测题:
- bundle 的 manifest 声明哪个键,回答什么问题?
- profile 位于哪个目录,它的 manifest 回答什么问题?
- 为什么 hello-plugin 的 cordis.patch.yml 里用包名而不是相对源码路径?
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/gpt/post/20260818/DeepSeek-Harness-%E7%BB%84%E5%90%88%E5%8C%85-bundle-%E4%B8%8E-profile%E4%B8%A4%E4%B8%AA-manifest-%E8%8F%9C%E9%B8%9F%E6%95%99%E7%A8%8B/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com