基于官方 7 讲中文教程(deepseek-harness
docs/cordis-tutorial/)与本地快速入门项目整理,以实例驱动,方便边学边练。 概念速览见 cordis。
Cordis 是什么
Cordis 是一个「时空可组合性」插件元框架,DeepSeek Harness 的底座:
- 可逆 effect(时间维度):插件运行时插拔,卸载时全部副作用自动回滚,无需重启宿主进程
- 响应式 coeffect(空间维度):插件用
inject声明依赖,依赖就绪自动加载、消失自动卸载、恢复自动复活 - 核心不到 2,000 行 TS,同一设计已在 Koishi 生产环境跑 4 年(4000+ 插件)
前置要求
- Node.js >= 20(开发机验证于 v24)
- TypeScript 基础(插件用
.ts写,靠tsx直接运行,无需编译步骤) - 无需任何 API 密钥:前 7 课全部离线可跑
练习环境
两种方式,推荐方式一(已验证通过):
方式一:直接用快速入门项目
cd ~/tmp/proj/cordis
npm install
npm start # 聚合演示:一次跑完全部课程插件方式二:从官方教程环境起步
git clone https://github.com/deepseek-ai/deepseek-harness
cd deepseek-harness && pnpm install
# 在 tmp/cordis-tutorial/ 下写代码,用下面命令运行每章示例
node --import tsx ../../vendor/cordis/bin.js启动器 bin.js 做三件事:创建根 Context → 挂 Loader → Include 插件读取 cordis.yml。注意 Include 会把 baseUrl 重置为 yml 所在目录,所以 yml 里的 './xxx.ts' 相对 yml 自己解析,与运行目录无关。
学习路径(建议顺序)
| 章节 | 内容 | 关键概念 | 对应命令 |
|---|---|---|---|
| 01-first-plugin | 环境 + 第一个插件 + 启动器原理 | 插件即函数、cordis.yml | lesson:01 |
| 02-lifecycle-effect | 生命周期与可逆 effect | disposer、fiber.dispose() | lesson:02 |
| 03-services | 服务提供与依赖消费 | Service 子类、inject | lesson:03 |
| 04-events | 类型化事件五种模式 | emit、waterfall 短路 | lesson:04 |
| 05-config-diagnose | 配置校验 + PENDING 诊断 | Config schema、fiber 状态机 | lesson:05/06 |
| 06-composition-hmr | 条目元数据与热替换 | id/disabled/组/isolate、HMR | lesson:07 |
| 07-into-harness | 进入真实 harness:注册工具 | defineTool、tools/result 事件 | 官方环境 |
每章对应快速入门项目的一课(npm run lesson:0X),先读代码、再运行、最后做「动手练习」。
概念速查(读代码前 2 分钟)
- 插件是实现 Service 的对象:函数(
apply(ctx),最常见)/ 对象(带apply)/ 类(Service子类)三种形态。可选导出name(诊断标识)、inject(依赖)、Config(配置 schema)。 - Context 是服务容器:服务占据稳定的
ctx.<key>,消费方按 key 查找而非 import 实现 → 配置层可换提供方。 - inject 声明依赖:插件停在 PENDING 直到依赖就绪;加载顺序由依赖决定,与 yml 书写顺序无关。
- 事件五种分发模式:
emit(同步广播)/parallel(并发等待)/serial(按序取首个有效返回)/bail(serial 同步版)/waterfall(环绕中间件)。waterfall 纪律:只观察的监听器必须调next(),不调即有意短路。 - 注册是可逆副作用:
ctx.on()、ctx.plugin()、服务注册本身都是 effect,随插件卸载撤销;框架外的资源(定时器/连接)自己包ctx.effect()并返回 disposer。
Fiber 状态机:PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED(或 FAILED)。
常见问题速查
| 现象 | 排查 |
|---|---|
| 插件没输出也没报错 | 遍历 ctx.registry 看 fiber 是否卡在 PENDING(缺服务),见第 03 章 |
HMR 报 --expose-internals is required | 启动命令加 --expose-internals flag |
| yml 里相对路径找不到模块 | 路径相对 yml 所在目录,不是运行目录 |
| 编辑 yml 后插件全部重挂 | 条目没写 id,每次读取都视为删了重挂;加 id 即可按 diff 只动变化项 |
参考链接
- 官方 7 讲中文教程:https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/cordis-tutorial/index.zh.md
- 概念参考(primer):https://deepseek-harness.github.io/deepseek-harness/reference/cordis-primer
- 论文(88 页):https://github.com/cordiverse/paper
- 源码:核心不到 2,000 行,阅读顺序
context.ts → service.ts/registry.ts → events.ts → fiber.ts - 知识库页面:cordis、yakumo(cordis 生态的构建工具)