动手:从 hello.ts 写出你的第一个 Cordis 插件
用一个函数插件和一份 cordis.yml,跑通 Loader、Context 与 Fiber 的最短路径。
目标:创建一个只做一件事的插件,让 Loader 读取 cordis.yml,调用 apply(ctx),并看到一行真实输出。
这一篇不先讲完整架构。先让一个插件跑起来,再回头看这三行代码为什么足以进入 Cordis 运行时。
01 / 创建插件文件
在教程使用的临时目录中创建 hello.ts:
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello'
export function apply(ctx: Context) {
console.log('hello from my first plugin')
}name 是诊断信息里的显示元数据。真正的入口是 apply(ctx):Loader 加载模块后,把当前 Context 传给它。
02 / 用 cordis.yml 组合它
创建同目录的 cordis.yml:
- name: './hello.ts'这份 YAML 是配置项列表。每项的 name 可以是相对路径或包名;Loader 会为每项挂载一个插件。
这里没有启动器代码。插件描述自己贡献什么,cordis.yml 决定这次运行组合哪些贡献。
03 / 运行并观察结果
在 DeepSeek Harness 仓库的教程目录中,运行:
node --import tsx ../../vendor/cordis/bin.js预期输出:
hello from my first plugin启动过程可以压缩成三步:
- 单文件启动器创建根 Context,并挂载 Loader。
- Loader 读取当前目录的
cordis.yml,解析./hello.ts。 - Cordis 调用插件的
apply(ctx),插件进入自己的 Fiber 生命周期。
各配置项可以并发启动;列表位置不保证加载顺序。如果插件依赖服务,应使用 inject 声明依赖,而不是把它排到某一行。
04 / 另外两种插件形态
函数是最轻的入口。需要公开命名服务时,可以使用 Service 子类:
import { Service, type Context } from '@deepseek-ai/cordis'
export class GreeterService extends Service {
constructor(ctx: Context) {
super(ctx, 'greeter')
}
}
export const objectPlugin = {
name: 'object-plugin',
apply(ctx: Context) {},
}三种形态最终都会被 Cordis 挂载。没有服务要公开时,优先使用函数插件,让入口保持小而直接。
05 / 加载失败如何表现
如果模块已经被解析,且 apply 抛出异常,插件加载会明确失败,启动器以失败状态结束,不会默默跳过:
export function apply(ctx: Context) {
throw new Error('apply exploded')
}另一个容易混淆的情况是模块解析失败,例如文件路径或包名拼写错误。Loader 会在创建 Fiber 前通过 logger 报告 import 错误,因此解析失败的模块不会进入 PENDING。在日志观察器尚未启动的早期阶段,这条消息可能不在控制台出现;先检查 name 拼写,确认模块能加载后,再检查缺少依赖造成的 PENDING。
06 / 这和 DSH 有什么关系
DeepSeek Harness 的 bundle 也是由许多 Cordis 配置项组合而成。写一个 DSH 插件,本质上是写一个能被 Loader 读取的插件,再把它插入 profile 的 patch 层;无需修改中央 agent loop。
下一篇会把“能运行的函数”升级成“可被其他插件消费的服务”: 服务与上下文:共享能力。
更多文章
事件:不知道谁在听,也能让插件协作
从类型化事件和五种分发模式出发,理解 Cordis 如何让服务广播事实、并发工作或交出决策。
服务与上下文:Cordis 如何共享能力而不绑定实现
从 Service、Context 与声明合并出发,理解提供者、消费者和作用域如何连接 DeepSeek Harness 的能力。
inject:让依赖决定加载顺序,而不是 YAML 行号
理解 Cordis 的 PENDING、依赖跟踪和可选服务探测,解释为什么 provider 更换会自动带动 consumer。
邮件列表
加入我们的社区
订阅邮件列表,及时获取最新消息和更新