首页 › LLM大语言模型 › Deepseek › DeepSeek Harnrss 实战手册 › 第 8 章 打包与发布:把插件变成别人能装的东西

第 8 章 打包与发布:把插件变成别人能装的东西

本地 --patch 只能自己玩。想分享,就得把插件打包成 bundle,装进别人的 profile。​

8.1 两个概念,两种 manifest​

再强调一次(这是最容易绕晕的地方):​

•

组合包(bundle):附带一个配置层的 npm 包,package.json 声明 dsh.bundle,回答"这个包贡献什么";​

•

Profile:$DSH_HOME/profiles/ 下描述可启动组合的目录,package.json 声明 dsh.profile,回答"这套配置由哪些 bundle 按什么顺序组成"。​

bundle 是你编写并分发的东西;profile 是用户启动的东西。没有东西同时是两者。​

8.2 做一个 bundle​

目录结构:​

​

代码块​

Plain Text

hello-plugin/​

├── package.json # 声明 dsh.bundle​

├── cordis.patch.yml # profile 列出本 bundle 时应用的层​

└── index.js # 插件模块​

​

package.json:​

​

代码块​

Plain Text

{​

"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" } }​

}​

​

index.js(插件入口,和第 6 章一样的逻辑):​

​

代码块​

Plain Text

export const name = 'hello-plugin'​

​

export function apply() {​

console.log('[hello-plugin] plugin loaded!')​

}​

​

cordis.patch.yml(和 --patch 一样的 patch 数组,区别是插件行按包名引用,Node 才能解析到已安装的代码):​

​

代码块​

Plain Text

- insert:​

- id: hello​

name: dsh-hello-plugin​

​

​

小知识:没有 dsh.bundle 声明的包也能装,但只是普通依赖,不会激活任何层。库类包(供其他插件 import)就用这种格式。​

​

8.3 安装进 profile​

在包含 hello-plugin 的目录里:​

​

代码块​

Plain Text

dsh plugin --profile demo add ./hello-plugin​

​

首次使用会初始化 profile(自动把 @deepseek-ai/dsh-base 作为第一个 bundle),pnpm 链接你的 checkout,dsh 检测到 dsh.bundle 后把它追加进 dsh.profile.bundles。​

先验证再启动:​

​

代码块​

Plain Text

dsh --profile demo --dump-config # 可以看到 "# == dsh-hello-plugin" 层​

​

移除同样简单:​

​

代码块​

Plain Text

dsh plugin --profile demo remove dsh-hello-plugin​

​

8.4 加载顺序(重要)​

生效配置在空根之上按顺序叠加:​

dsh.profile.bundles 所列各 bundle 的 patch(按列表顺序);​

profile 自己的 cordis.patch.yml;​

home 级 $DSH_HOME/cordis.patch.yml;​

每个 --patch overlay。​

推论(给 bundle 作者的两条铁律):​

•

你的 patch 覆盖前面各层时,必须重述目标行需要的每一个键,因为 patch 替换整个 config,不是深合并;​

•

用户能在自己 profile 的 cordis.patch.yml 里覆盖你的行,所以给用户大概率会保留的默认值,把其余交给 schema。​

8.5 三种分发方式​

方式一:发布到 npm(推荐)​

​

代码块​

Plain Text

pnpm publish​

​

用户 dsh plugin add dsh-hello-plugin 安装的就是预构建代码,不需要任何构建权限。在 pnpm publish 前把 lib/ 构建好即可。​

方式二:交付 tarball​

​

代码块​

Plain Text

pnpm pack​

​

用户执行:​

​

代码块​

Plain Text

dsh plugin add ./hello-plugin-0.1.0.tgz​

​

方式三:从 GitHub 安装(有坑,务必看)​

​

代码块​

Plain Text

dsh plugin --profile demo add github:you/hello-plugin​

​

坑在于:git 安装拉的是源码,不是构建产物,没有任何环节运行你的 build 脚本,TypeScript 包到手时没有 lib/ 输出,加载会失败。两边各要做一件事:​

•

作者:提供 prepare 脚本(pnpm 在 git 安装后运行),且必须自包含——不能假设旁边有 monorepo checkout;​

•

用户:pnpm ≥10 默认拒绝运行 git 依赖的 prepare 脚本,首次 add 会失败。dsh 会提示把 pnpm 打印的包键写进该 profile 的 pnpm-workspace.yaml:​

​

代码块​

Plain Text

allowBuilds:​

dsh-hello-plugin: true​

​

然后重新 add。​

8.6 安全警告:不要随便授权​

请如实看待 allowBuilds 这项授权:它允许该包的代码在安装时于你的机器上执行,且不在 agent 运行的任何沙箱之内。​

•

只对源码可信的包授权;​

•

建议锁定 commit:github:you/hello-plugin#,让后续推送无法悄悄改变实际运行的内容;​

•

不想让用户做这项授权?用 npm 发布或 tarball 分发构建产物。​

8.7 本章小结​

•

bundle = 带 dsh.bundle 的 npm 包;profile = 带 dsh.profile 的可启动目录;​

•

dsh plugin --profile add/remove 管理安装;​

•

四层加载顺序:bundles → profile patch → home patch → --patch;​

•

patch 整行替换 config,覆盖时必须重述所有键;​

•

分发三选一:npm / tarball / git(git 需要 prepare + allowBuilds,注意安全)。​

下一章,往深处走:看看"一切皆插件"的架构到底长什么样。​