跳至正文
教程 / Step 16

实作:第一个 Cordis 工具插件

从 apply(ctx) 到工具注册、配置校验、事件观察和卸载验证,走完一条最小插件链路。

简要结论

从 apply(ctx) 到工具注册、配置校验、事件观察和卸载验证,走完一条最小插件链路。

本练习跟随官方 Cordis 教程的接口,但用一个“项目状态”工具串起插件、配置、工具和事件。命令与包接口可能随 Developer Preview 变化,执行前对照官方仓库当前文档。

1. 认识 apply(ctx)

Cordis 插件通过命名导出提供 apply,Loader 加载后用 Context 调用它:

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

export const name = 'project-status'

export function apply(ctx: Context) {
  console.log('project-status mounted')
}

name 是诊断元数据。插件描述自己的贡献,cordis.yml 负责组合应用。配置行可能并发启动,依赖顺序应由 inject 表达。

2. 添加可校验配置

import Schema from '@deepseek-ai/schemastery'

export interface Config {
  label: string
  maxLength: number
}

export const Config: Schema<Config> = Schema.object({
  label: Schema.string().default('workspace'),
  maxLength: Schema.number().default(200),
})

不同部署会改变的值放进 Config,不要硬编码。Schema 会在加载时验证并填充默认值;配置错误应该尽早、明确地失败。

3. 注册只读 Tool

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

export const name = 'project-status'
export const inject = ['tools']

export function apply(ctx: Context, config: Config) {
  ctx.tools.register(defineTool({
    name: 'project_status',
    description: 'Return a configured label for the current tutorial workspace.',
    parameters: {},
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute() {
      return config.label.slice(0, config.maxLength)
    },
  }))
}

注册返回的 disposer 会附着到插件生命周期,因此卸载时工具应一并注销。

4. 组合应用

- name: '@deepseek-ai/dsh-system-prompt'
- name: '@deepseek-ai/dsh-tools'
- name: './project-status.ts'
  config:
    label: 'tutorial-workspace'
    maxLength: 80

工具服务需要向系统提示贡献 Schema,因此组合中包含相应系统提示服务。缺少依赖提供方时,插件可能保持 PENDING。

5. 观察结果事件

另建一个观察插件监听 tools/result,只记录工具名、成功状态和有界摘要。观察者不需要知道生产者实现,两者通过服务注册表与事件解耦。

验证清单:

  1. 启动时插件挂载一次;
  2. Tool 出现在可用目录;
  3. 合法调用返回符合 Schema 的值;
  4. 非法配置在加载阶段失败;
  5. 修改配置触发热替换后没有重复注册;
  6. 卸载 Plugin 后 Tool 消失;
  7. 日志中没有凭据和完整敏感结果。

6. 接入完整 Harness

官方教程提供两条路径:

  • 直接通过真实工具执行流水线调用,无需模型 Key;
  • 在 Web UI 开发模式中用 --patch 挂载本地 cordis.yml,再让模型调用。

先完成无模型的确定性测试,再接入 Agent Loop。这样失败时可以区分“插件/工具实现错误”和“模型没有选择工具”。

扩展作业

  • 增加一个枚举参数,但保持 Tool 只读;
  • 为超长返回实现有界 render;
  • 为 Config 添加非法值测试;
  • 写一个独立观察插件统计调用次数;
  • 记录卸载和 HMR 后注册表是否恢复。

至此,你已经从使用者走到最小扩展开发者。回到教程中心选择架构或安全专题继续深入。

一手来源