DSH 插件怎么开发?从最小插件到打包安装
DSH 插件是一个导出 apply 函数的 TypeScript 模块:框架加载时调用 apply 并传入 ctx 上下文,你通过 ctx 注册能力,用 inject 声明依赖,用 Config schema 接受配置。
插件是什么
在 DSH 里,插件就是导出 apply 的模块。 框架加载时调用 apply,传给你一个 ctx(上下文对象),一切能力都通过它注册(来源):
import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-plugin'
export function apply(ctx: Context) {
// 在这里注册能力。
}
这就已经是完整的最小插件了。name 是插件的唯一标识,apply 是入口,ctx 提供注册接口。
最小可运行插件
一个会打日志的插件就三行核心代码。 创建 src/my-plugin.ts:
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(ctx: Context) {
console.log('[hello-plugin] plugin loaded!')
}
用 --patch 覆盖层把它挂进 Web UI,启动时终端会打印 [hello-plugin] plugin loaded!(来源)。
自动清理
通过 ctx 注册的任何东西——事件监听、工具、定时器——在插件卸载时都会自动清理。 有需要手动清理的资源(比如网络连接),用 ctx.effect() 告诉框架怎么清理:
export function apply(ctx: Context) {
ctx.effect(() => {
const timer = setInterval(() => console.log('heartbeat'), 5000)
// 返回的函数在插件卸载时执行。
return () => clearInterval(timer)
})
}
声明依赖
插件要用别的服务(如 tools、llm),就导出 inject 声明依赖。 框架会确保依赖的服务就绪后才加载你的插件:
export const name = 'my-tool-plugin'
export const inject = ['tools']
export function apply(ctx: Context) {
// 到这里 ctx.tools 已经就绪。
ctx.tools.register(/* ... */)
}
让插件接受配置
导出 Config 类型和同名的 Schemastery schema,默认值直接写在 schema 里。 插件加载时框架用 schema 校验配置并补默认值(来源):
import Schema from '@deepseek-ai/schemastery'
export interface Config {
greeting: string
maxRetries: number
}
export const Config: Schema<Config> = Schema.object({
greeting: Schema.string().default('Hello'),
maxRetries: Schema.number().default(3),
})
export function apply(ctx: Context, config: Config) {
console.log(config.greeting) // 用户值或 schema 默认值。
}
约定:凡是不同部署可能要改的参数都定义成配置字段,别硬编码;无效配置要在加载时响亮报错。
打包成 bundle
分发的插件包叫「组合包」(bundle),由一份 package.json 声明 dsh.bundle。 目录结构:
hello-plugin/
├── package.json # 声明 dsh.bundle
├── cordis.patch.yml # 该组合包贡献的配置层
└── index.js # patch 行引用的插件模块
package.json 长这样(来源):
{
"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" } }
}
cordis.patch.yml 按包名引用这个包:
- insert:
- id: hello
name: dsh-hello-plugin
安装进 profile
打好包就用 dsh plugin add 装进 profile。 命令转发给 profile 目录里的 pnpm(来源):
dsh plugin --profile demo add ./hello-plugin
因为包声明了 dsh.bundle,DSH 会把它追加进 dsh.profile.bundles。启动前先用 dsh --profile demo --dump-config 验证层生效,再 dsh --profile demo 启动。
从 GitHub 安装的坑
git 安装拉的是源码,不会跑你的 build 脚本。 所以 TypeScript 包需要作者提供一个 prepare 脚本,在 pnpm 安装后构建出发布入口;用户侧第一次 add 会被 pnpm 的 allowBuilds 拦住,按报错把允许 key 写进 profile 的 pnpm-workspace.yaml 再重试(来源)。不想让用户做这项授权,就发布到 npm 或交付 pnpm pack 出来的 tarball。
用脚手架快速起步
不想手写就一键生成。 官方社区脚手架 create-dsh-plugin 支持 tool / events / webui 三种模板,并锁定了正确的 @deepseek-ai/dsh-tools 版本:
npx create-dsh-plugin my-plugin -t tool
生成的工程自带 package.json、tsconfig.json、dsh.bundle manifest 和 cordis.patch.yml,加 --verify 还会自动构建并装进临时 profile 验证加载。开发完回到《DSH plugin 怎么安装》把成品装起来试用。
常见问题
是一个导出 apply 函数的 TypeScript 模块,框架加载时调用 apply 并传入 ctx 上下文,你通过 ctx 注册能力。
最快用脚手架:npx create-dsh-plugin my-plugin -t tool,一键生成 tool / events / webui 模板。想手动写就从导出 apply 的最小插件开始。
导出 inject 数组,比如 export const inject = ['tools'],框架会等依赖的服务就绪后再加载插件。
在 package.json 里声明 dsh.bundle.patch 指向 cordis.patch.yml,然后用 dsh plugin --profile <name> add <包> 装进 profile。
pnpm 默认不放行 git 依赖的构建脚本,按报错提示把允许 key 写进 profile 的 pnpm-workspace.yaml,重新 add 即可。
来源
- DeepSeek Harness 官方文档 - 第一个插件· deepseek-harness
- DeepSeek Harness 官方文档 - 打包与安装插件· deepseek-harness
- dsh CLI README· deepseek-ai