$dshubuser@dshub:~/plugins$
  • 插件
  • 提交插件
  • 博客
动手:从 hello.ts 写出你的第一个 Cordis 插件
2026/08/20

动手:从 hello.ts 写出你的第一个 Cordis 插件

用一个函数插件和一份 cordis.yml,跑通 Loader、Context 与 Fiber 的最短路径。

目标:创建一个只做一件事的插件,让 Loader 读取 cordis.yml,调用 apply(ctx),并看到一行真实输出。

这一篇不先讲完整架构。先让一个插件跑起来,再回头看这三行代码为什么足以进入 Cordis 运行时。

01 / 创建插件文件

Terminal trace showing hello.ts becoming an active Cordis plugin through Loader

在教程使用的临时目录中创建 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 plugin shapes showing function, object apply, and Service class forms

这里没有启动器代码。插件描述自己贡献什么,cordis.yml 决定这次运行组合哪些贡献。

03 / 运行并观察结果

在 DeepSeek Harness 仓库的教程目录中,运行:

node --import tsx ../../vendor/cordis/bin.js

预期输出:

hello from my first plugin

启动过程可以压缩成三步:

  1. 单文件启动器创建根 Context,并挂载 Loader。
  2. Loader 读取当前目录的 cordis.yml,解析 ./hello.ts。
  3. 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。

下一篇会把“能运行的函数”升级成“可被其他插件消费的服务”: 服务与上下文:共享能力。

来源:第一个插件教程、教程启动器、Loader 配置。

全部文章

作者

avatar for DSH Research
DSH Research

分类

  • Agent 基础设施
01 / 创建插件文件02 / 用 cordis.yml 组合它03 / 运行并观察结果04 / 另外两种插件形态05 / 加载失败如何表现06 / 这和 DSH 有什么关系

更多文章

事件:不知道谁在听,也能让插件协作
Agent 基础设施

事件:不知道谁在听,也能让插件协作

从类型化事件和五种分发模式出发,理解 Cordis 如何让服务广播事实、并发工作或交出决策。

avatar for DSH Research
DSH Research
2026/08/25
服务与上下文:Cordis 如何共享能力而不绑定实现
Agent 基础设施

服务与上下文:Cordis 如何共享能力而不绑定实现

从 Service、Context 与声明合并出发,理解提供者、消费者和作用域如何连接 DeepSeek Harness 的能力。

avatar for DSH Research
DSH Research
2026/08/22
inject:让依赖决定加载顺序,而不是 YAML 行号
Agent 基础设施

inject:让依赖决定加载顺序,而不是 YAML 行号

理解 Cordis 的 PENDING、依赖跟踪和可选服务探测,解释为什么 provider 更换会自动带动 consumer。

avatar for DSH Research
DSH Research
2026/08/23

邮件列表

加入我们的社区

订阅邮件列表,及时获取最新消息和更新

[dshub] [zsh]$ dshub ls$ dshub submit$ dshub blog
-- NORMAL -- ✓ 2026 dshub