插件配置与发布
本教程共 32 篇 · 第 24 篇 · 更新于 2026-08-15 · 约 5 分钟阅读
本节目标:让插件接受配置并校验,再把插件打包成组合包发布,最后能被
dsh plugin安装进 profile。
配置从哪来
cordis.yml 里每个 Cordis 配置项都可以携带 config 块。插件声明一个 schema,在运行 apply 前验证这个块。错误配置会导致加载失败,并给出准确的错误——插件绝不会在配置不完整时启动。
Config 类型与同名 schema
import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'
export const name = 'my-plugin'
export interface Config {
greeting: string
maxRetries: number
verbose?: boolean
}
export const Config: Schema<Config> = Schema.object({
greeting: Schema.string().default('Hello'),
maxRetries: Schema.number().default(3),
verbose: Schema.boolean().default(false),
})
export function apply(ctx: Context, config: Config) {
console.log(config.greeting) // 用户传入的值或 schema 默认值
}
导出的 Config 既是 TypeScript 接口,又是同名的运行时 schema:消费方获得类型,Cordis 获得验证器。默认值直接写在 schema 里,apply 收到的永远是完整且经过验证的配置。
Warning不要导出普通对象作为
Config。Cordis 接受任意 Standard Schema 验证器(仓库用 Schemastery 定义),普通对象不满足接口,加载会失败。
配置校验
传入不合法配置,比如 targets: 'not-an-array',框架输出类似:
ValidationError: invalid config:
- $.targets expected array but got not-an-array (at targets)
插件的 fiber 进入 FAILED 状态,加载失败明确报错。schema 校验发生在插件加载时,不是运行时。需要严格约束时用 Schemastery 表达:Schema.string().required() 必填、Schema.union(['fast', 'accurate']) 枚举取值。
loader 还支持 !!js 标签计算配置值,适合注入密钥:
- name: './config-demo.ts'
config:
greeting: !!js process.env.DEMO_GREETING ?? 'Hello'
设计原则
- 无硬编码可调参数:不同部署可能取不同值的参数,都必须定义为配置字段。检验标准一句话:能不能在
cordis.yml里改这个值而不动代码? - 配置错误要响亮:在 schema 里表达自身完备的约束,让无效配置在加载时失败,而不是运行时静默行为异常。
- HMR 自动生效:修改
cordis.yml中某个插件的 config 后,框架卸载旧实例、加载新实例。注册都是 effect,替换后不留旧注册,不用重启进程。
打包为组合包(bundle)
本地插件用 --patch 加载;交付给别人的插件打包成组合包——附带一个配置层的 npm 包。目录结构:
hello-plugin/
├── package.json # 声明 dsh.bundle
├── cordis.patch.yml # 配置层
└── index.js # 插件模块
{
"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" } }
}
- insert:
- id: hello
name: dsh-hello-plugin # 用包名,不用文件路径
dsh.bundle 回答「这个包贡献什么」;profile 的 dsh.profile manifest 回答「由哪些组合包按什么顺序组成」。两者都由 package.json 描述,但没有任何东西同时是两者。没有 dsh.bundle 声明的包仍可安装,只作普通依赖,不激活任何层。
安装进 profile
dsh plugin --profile demo add ./hello-plugin
首次使用会初始化 profile(@deepseek-ai/dsh-base 自动成为第一个组合包),pnpm 链接该包,并把它追加进 dsh.profile.bundles。先验证再启动:
dsh --profile demo --dump-config # 输出里应有 "# == dsh-hello-plugin" 层
dsh --profile demo
移除同样简单:dsh plugin --profile demo remove dsh-hello-plugin,依赖和层一起删。
三种分发方式
| 方式 | 用户安装命令 | 装到什么 | 需要构建授权 |
|---|---|---|---|
| npm 发布 | dsh plugin add your-package | 预构建的 lib/ | 否 |
| tarball | dsh plugin add ./pkg-0.1.0.tgz | pnpm pack 产物 | 否 |
| Git 安装 | dsh plugin add github:you/repo | 源码 | 是 |
Git 安装拉的是源码,没有任何环节运行 build 脚本,TypeScript 包到手没有 lib/ 输出,加载会失败。作者要提供自包含的 prepare 脚本(直接转译 src/,不依赖 monorepo checkout);用户要在该 profile 的 pnpm-workspace.yaml 里加 allowBuilds 授权,然后重新 add。
Warning构建授权允许该包的代码在安装时于你的机器上执行,且不在任何沙箱之内。只对源码可信的包授权,并锁定 commit:
github:you/hello-plugin#<sha>。
发布、版本与发现
面向普通用户优先发布 npm:pnpm build && pnpm publish,用户装到的就是预构建代码,零授权。版本管理遵循语义化版本;项目处于 rc 阶段(基线 @deepseek-ai/dsh 0.1.0-rc.6),依赖的 harness API 可能破坏性变更,升级插件前对照 changelog。
发布后把 GitHub 仓库打上 dsh-plugin topic,插件就能被社区列表检索到——这是官方约定的插件发现方式。
小结
- 配置由 schema 校验,默认值写在 schema 里,
apply收到完整配置。 - 校验失败 fiber 进 FAILED,配置错误在加载时响亮报错。
- 打包成 bundle:声明
dsh.bundle+cordis.patch.yml+ 插件模块。 - 安装:
dsh plugin --profile <name> add <包>;npm / tarball / Git 三种分发。 - Git 安装要构建授权,只对源码可信的包授权并锁定 commit。