DeepSeek Harness DSH plugin:Context、inject、事件与可逆注册

插件开发发布于 2026-10-02作者: DeepSeek Plugin 插件市场
DSH pluginDeepSeek HarnessCordisContextService
DeepSeek Harness 的 DSH plugin 跑在 Cordis 上:一切皆插件,插件即实现 Service 的对象;Context 是服务容器,inject 声明依赖与加载顺序,类型化事件负责通信与拦截,注册是可逆副作用。

Cordis 是 DeepSeek Harness 底层以 vendor 方式引入的插件框架,DSH plugin 的一切挂载、依赖与通信都由它定义——在 Cordis 里一切皆插件(来源)。 官方要求插件作者在阅读子系统页面上生成的服务 / 事件参考之前,先掌握五个核心概念:插件是实现 Service 的对象、Context 是服务容器、inject 声明依赖、类型化事件通信、注册是可逆副作用。

DSH plugin 的 Service 与 Context:一切皆插件与服务容器

在 DSH plugin 里一切皆插件:插件本身既可以是带可选 inject 与 apply(ctx) 的函数,也可以是 Service 子类;Context 则是承载这些服务的容器(来源)。 对 DSH插件 作者来说,这套写法对应两点:

  1. 插件是实现 Service 的对象 — 可以是带可选 inject 与 apply(ctx) 的函数,也可以是 Service 子类。预期:生命周期由 Cordis 挂载到当前上下文。
  2. Context 是服务的容器 — 一个服务占据稳定的 ctx.<key>,如 ctx.tools、ctx.llm、ctx.sessions。预期:插件按 key 查找服务,不导入具体实现,于是你会看到同一 key 背后的实现被整体替换。

为什么「服务按 key 查找」如此关键:它意味着别人可以换掉某个服务的实现而不动调用方,这正是 能力 Seams 与核心服务 讨论的扩展点分类基础。

DSH plugin 的 inject:用服务依赖声明加载顺序

Context 让实现按 key 查找,inject 则把加载顺序变成依赖关系——你需要按下面三步组织提供方与消费方(来源)。

  1. 写一个提供方 — 把能力挂到 ctx.<key> 上,或用 Service 子类。预期:其他插件可通过 key 访问。
  2. 写一个消费方 — 用 inject 声明依赖的服务 key。预期:提供方就绪后才启动;未就绪则停在 PENDING。
  3. 只依赖抽象 — 调用方不导入具体实现。预期:换实现不动调用方。

PENDING 是合法状态而非错误,这也是排查「插件没反应」的入口,具体诊断见 Cordis 组合与热重载。

DSH plugin 的事件与可逆副作用:五种分发模式与 effect

每种事件只有一种分发模式,且只能通过对应方法分发——模式是事件公开约定的一部分(来源)。 对照表:

模式是否 await分发顺序有返回值
emit否按注册顺序观察否
waterfall否按注册顺序观察是
parallel是所有监听器并行否
serial是按注册顺序观察是
bail否按注册顺序,直到首个 bail 值是

ctx.waterfall 是环绕中间件:监听器接收 (...args, next),调用 next() 执行下游并拿到下游返回值供本层包装;不调用 next() 直接返回即短路。只做标注或观察的监听器必须委托,只有拥有决策权的策略监听器才该短路;仅当监听器必须在普通注册之前运行时才用 prepend: true。

每个注册都应有对应的 disposer:要么从 ctx.effect() 返回一个,要么用 Cordis 提供的辅助方法自动处理。如果 teardown 顺序有要求,把相关工作放在同一个 effect 中,确保资源按预期顺序释放。

实践规则一句话:需要拦截 / 策略时优先用事件,需要直接能力调用时优先用服务方法——工具流水线事件属于 ctx.tools,模型流式输出属于 ctx.llm,实时 agent 协调属于 ctx.agents。写完自检三项:是否只依赖服务 key 而非实现;inject 是否覆盖全部依赖;每个注册是否有 disposer。想接着看事件实操,读 DSH plugin 事件系统;想找用这套概念写出的插件,可在 DSH Plugin Hub 检索。

常见问题

DSH plugin 的 Cordis 是什么?为什么开发前先读它?

Cordis 是 DSH plugin 底层以 vendor 方式引入的插件框架,决定了插件如何挂载、如何依赖、如何通信。官方要求插件作者在阅读子系统页面生成的服务与事件参考之前,先掌握它的核心概念,否则看不懂注册与生命周期语义。

DSH plugin 里 Context 和 Service 是什么关系?

在 DSH plugin 里,上下文是服务的容器,一个服务占据一个稳定的 ctx.<key>,例如 ctx.tools、ctx.llm、ctx.sessions。其他插件通过 key 查找服务,而不是导入具体实现,这正是插件可以互相替换的前提。

DSH plugin 的 inject 有什么作用?依赖没就绪时插件会怎样?

DSH plugin 用 inject 声明所需服务,声明后插件会等这些服务就绪才启动。加载顺序因此通过服务依赖表达,而不是手动编排启动序列;缺少提供方时插件会停在 PENDING 而不是报错。

DSH plugin 的注册为什么说「可逆」?热重载与卸载时会怎样?

DSH plugin 的注册是可逆副作用:提示词片段、工具 schema、适配器、提供方与监听器都通过 ctx.effect() 或 ctx.on() 安装,reload 与 teardown 时会按预期撤销。因此热重载能安全替换插件,也不会残留监听器。

DSH plugin 里拦截用事件、直接调用用服务,怎么理解?

DSH plugin 的实践规则是:需要拦截与策略时优先用事件,需要直接能力调用时优先用服务方法。工具流水线事件属于 ctx.tools、模型流式输出属于 ctx.llm、实时 agent 协调属于 ctx.agents。

相关术语

Cordis
Cordis 是 DSH plugin 底层以 vendor 方式引入的插件框架,提供上下文、服务、依赖注入、类型化事件与可逆副作用这套机制,DeepSeek Harness 建立在它之上。— https://deepseek-harness.github.io/deepseek-harness/reference/cordis-primer
Context
Context 是 DSH plugin 中承载服务的容器,每个服务占据一个稳定的 ctx.<key>,插件通过 key 查找服务而非导入具体实现,因此实现可被替换。— https://deepseek-harness.github.io/deepseek-harness/reference/cordis-primer
Service
Service 是 DSH plugin 暴露给其他插件的能力单元,插件本身既可以是带 inject 与 apply(ctx) 的函数,也可以是 Service 子类,其生命周期由框架挂载到当前上下文。— https://deepseek-harness.github.io/deepseek-harness/reference/cordis-primer
inject
inject 是 DSH plugin 声明服务依赖的字段,插件声明所需服务后会等待它们就绪才启动,从而用依赖关系表达加载顺序。— https://deepseek-harness.github.io/deepseek-harness/reference/cordis-primer

来源