编写第一个 Cordis 插件

Cordis 是什么

Cordis 是 DeepSeek Harness 底层以 vendor 方式引入的插件框架。它的五个核心概念:

  • 插件是实现能力的对象:可以是带可选 inject 和 apply(ctx) 字段的函数,也可以是 Service 子类;
  • 上下文是服务的容器:服务占据稳定的 ctx.<key>(如 ctx.tools、ctx.llm),插件按 key 查找而非导入实现;
  • 用 inject 声明依赖:插件等待所需服务就绪后才启动,加载顺序由依赖决定而非手动编排;
  • 类型化事件用于通信:以 emit、waterfall、parallel、serial 等模式分发;
  • 注册是可逆的副作用:通过 ctx.effect() 或 ctx.on() 安装的东西,卸载时会自动撤销。

插件的最小结构

插件是一个导出 apply 函数的模块,框架加载时调用它并传入 ctx:

import type { Context } from '@deepseek-ai/cordis'

export const name = 'my-plugin'

export function apply(ctx: Context) {
  // 在这里注册你的能力。
}

name 是可选的显示元数据,用于诊断信息。函数形态最常见,但也支持对象形态({ name, inject, apply })和类形态(继承 Service)。大多数情况下函数形态就够了。

注册一个工具

下面这个完整示例向 harness 的 tools 服务注册一个可由模型调用的 greet 工具:

import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'greet-tool'
export const inject = ['tools']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'greet',
    description: 'Greet someone by name.',
    parameters: {
      name: { type: 'string', required: true, description: 'The name to greet' },
    },
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute(args) {
      return `Hello, ${args.name}!`
    },
  }))
}

拆解一下:

  • inject: ['tools'] 让 Cordis 等待工具注册表就绪,apply 内可放心使用 ctx.tools;
  • defineTool 把 parameters 规约转换为展示给模型的 JSON Schema,推导并校验 args 的类型;
  • execute 返回 output.schema 声明的规范值,output.render 再把结果转换成面向模型的内容;
  • ctx.tools.register(...) 的注册属于 effect,插件卸载时工具会自动注销。

在 DSH 里加载

开发期用 --patch 覆盖层把插件挂进 Web UI。先创建 scratch-plugin/cordis.yml:

- insert:
    - id: greet
      name: '/absolute/path/to/your-plugin/src/greet-tool.ts'

插件路径必须是绝对路径。然后带覆盖层启动(源码检出用 pnpm dsh web,已安装用 dsh web):

pnpm dsh web --patch ./scratch-plugin/cordis.yml

打开 http://127.0.0.1:3080,在会话里输入 Use the greet tool to greet Ada.,模型就能调用 greet 并收到 Hello, Ada!。终端日志会显示工具调用与结果事件。

想要发布给别人安装,就把插件打包成声明 dsh.bundle 的组合包,参考《安装 DSH 插件》中的 dsh plugin --profile web add 流程。