ARCHITECTURE · 02

Cordis 框架:DeepSeek Harness 的插件地基

直接答案

Cordis 是 DeepSeek Harness 底层的插件框架,但它不是 DeepSeek 自研——它是第三方开源项目(上游 cordiverse/cordis),dsh 以 vendor(固定源码副本)方式引入自己仓库。理解它只需抓住五个概念:插件、上下文、依赖注入、类型化事件、可逆注册。

Cordis 从哪来:第三方框架,vendor 引入

官方事实

Cordis 的上游是 github.com/cordiverse/cordis,其设计写在一篇论文《A Programming Paradigm for Spatiotemporal Composability》里。dsh 仓库的 vendor/ 目录是带上游 SHA 清单的固定源码副本,同步流程写在 vendor/README.md

vendor 进来的包被重新命名(rescope)为 @deepseek-ai/* 且标记为 private: true@deepseek-ai/cordis 是每个 harness 包的 peerDependency(同伴依赖,即由使用方提供而不是重复安装)。vendor 引入与分层的关系见架构总览

写作红线:Cordis 不是 DeepSeek 自研,任何"DeepSeek 开发的 Cordis"表述都是错的。

五个核心概念

官方事实

出自官方 docs/cordis-primer.zh.md

  1. 插件:一个实现 Service 的对象——可以是带 inject 声明和 apply(ctx) 方法的函数,也可以是 Service 子类。
  2. 上下文(Context):服务容器。每个服务占据一个稳定的键名,比如 ctx.toolsctx.sessions
  3. 依赖注入(inject):插件用 inject 声明自己依赖哪些服务,Cordis 等依赖就绪后才启动它。
  4. 类型化事件:插件之间靠类型化事件通信(下一节展开)。
  5. 可逆注册:注册是可逆副作用——用 ctx.effect() / ctx.on() 注册的东西,在插件 reload(重载)或 teardown(卸载)时会被撤销。这就是 dsh"插件卸载时撤销注册"的底层机制(插件系统如何用这个机制,见插件系统页)。
示意图
01中央一个"Context(服务容器)"容器块,挂着 ctx.tools、ctx.sessions 等键;插件块通过标注 inject 的箭头指向容器;插件之间一条标注"类型化事件"的连线;角落小循环箭头标注"注册可逆:reload / teardown 时撤销"。

四种事件分发模式

官方事实

Cordis 的事件有四种分发模式,分发模式是事件公开约定的一部分,官方源码里用 @mode 标签记录:

模式是否等待(await)有无返回值典型用途
emit广播通知
waterfall中间件式加工,可短路
parallel并行扇出,等全部完成
serial按顺序执行
示意图
02四条横向泳道画出发射方与监听器的时序关系:emit 单向箭头不等返回;waterfall 箭头逐个穿过监听器、可中途短路;parallel 箭头扇出后汇合;serial 箭头按序串联并带回返回值。

新手最常踩的坑有两个:

  • emitwaterfall 都不会等待监听器完成。需要等监听器跑完,得用 serialparallel;其中只有 serial 会带回返回值。
  • waterfall 监听器必须调 next() 才能把处理委托给下游。监听器收到 (...args, next);调用 next() 可以委托下游并包装返回值;不调 next() 直接 return,是"短路"(后面的人收不到),不是"透传"。官方 AGENTS.md 用 MUST 级别的措辞强调这一点。prepend: true 只在该监听器必须先于普通注册运行时才用。

Loader 与配置文件:!!js 与三种 yml

官方事实
  • Cordis 的 Loader 配置由 @deepseek-ai/cordis-plugin-include 处理:!!js 会被解析为表达式节点(注意是 !!js 两个感叹号,不是 !js)。config 基于插件上下文插值,disabled 在每次挂载决策时基于 loader 上下文插值;需要按环境选择插件时应使用 overlay(覆盖层)。
  • cordis.yml 里只允许 !!js 出现在插件的 config 和条目的 disabled 下,其余元数据保持字面值。
  • 配置文件有三种形态:cordis.yml(插件树)、cordis.patch.yml(按 id 覆盖或插入条目)、cordis.snapshot.yml(快照回放替换,只识别特定文件 basename)。前两种在本站《Profile / 组合包 / Patch》页有展开。

为什么普通用户也需要懂一点 Cordis

DSHOPC 分析

你不写插件的话,不需要掌握 Cordis API。但有两个场景绕不开它:一是改 cordis.patch.yml 调整配置时,你其实就是在写 Cordis 配置(见教程《Profile 与配置分层》);二是排查"插件装了没生效"时,理解"注册是可逆副作用、Bundle 层变更要重启"(教程实测口径,详见插件系统页第 4 节)能省很多时间。把 Cordis 想成 dsh 世界的"地基图纸":不用会画,但看得懂图例很有用。

EVIDENCE

证据与来源

本页包含:官方事实 / DSHOPC 分析

#事实声明状态来源
1Cordis 上游为 cordiverse/cordis,dsh vendor 引入,vendor 流程见 vendor/README.md官方事实
2五个核心概念(插件 / 上下文 / inject / 类型化事件 / 可逆注册)官方事实
3四种分发模式语义及 @mode 标签官方事实
4waterfall 短路语义、next() 委托、prepend: true 使用限制官方事实
5!!js 规则、config / disabled 插值、overlay 建议官方事实
6rescope 为 @deepseek-ai/*、peerDependency官方事实
7三种配置文件形态(cordis.yml / cordis.patch.yml / cordis.snapshot.yml)官方事实
8第 5 节的场景建议DSHOPC 分析
  • 基于本站教程 src/content/tutorials/profile.ts、plugins.ts 的已验证内容归纳
适用版本
DSH 0.1.1-rc.2(2026 年 8 月,开发者预览阶段)
发布
2026-08-26
更新
2026-08-26
最后核验
2026-08-26