1. The plugin model
August 14, 2026 · View on GitHub
1.1 Everything is a plugin
DSH vendors Cordis (@deepseek-ai/cordis v4) and composes itself from @deepseek-ai/dsh-*
plugins. A service is a named capability mounted on a context key (ctx.tools, ctx.llm,
ctx.sessions, ctx.agents, …). A seam is a swappable capability with three roles:
- Service Definition — owns the
ctx.<key>and its vocabulary types (e.g.ShellExecutor). - Service Provider — one or more implementations of the definition (e.g.
bash-local,bash-sandbox). - Consumer — a plugin that
injects the service and calls it (e.g.tool-bash).
A plugin declares which services it needs with inject; the loader runs apply only after those
services exist. Load order is expressed through service dependencies, never file order.
1.2 Spatiotemporal composability
DSH's runtime guarantees come from the two dimensions formalized in the Cordis paper:
- Temporal composability (revertible effects): unloading a plugin completely and safely reverses every modification it made to the shared context. Every registration carries a disposer; the runtime accumulates them and replays them in LIFO order on unload.
- Spatial composability (reactive coeffects): plugins declare their dependencies, and the runtime reactively activates/deactivates them as providers appear, disappear, or change. A plugin whose dependency is missing simply stays inactive — it never crashes on a missing service.
In practice this means: you supply the inverse of each atomic effect; the composite teardown is derived for you, and you never write an uninstall path by hand.
1.3 Glossary
| English | 中文 | Meaning |
|---|---|---|
| plugin / component | 插件 / 组件 | a module exporting apply(ctx) (+ optional name/inject/Config) |
| context | 上下文 (ctx) | the first-class entity through which every registration flows |
| service | 服务 | a named capability on ctx.<key> |
| seam | 可替换能力 | Service Definition + Providers + Consumers |
| inject | 依赖声明 | the services a plugin requires before apply runs |
| effect | 副作用 | a modification to the shared environment |
| revertible effect | 可逆副作用 | an effect paired with an inverse the runtime tracks |
| coeffect | 协作用 | what a plugin requires from its environment (a dependency) |
| reactive coeffect | 响应式协作用 | dependency satisfaction re-evaluated on every context change |
| disposer | 清理器 | the inverse returned by a registration; runs on unload |
| fiber | 纤程 | one instantiation of a plugin, with its own lifecycle state |
| bundle | bundle | an npm package carrying a config layer (cordis.patch.yml) |
| profile | profile | a runnable composition under $DSH_HOME/profiles/<name> |
| dispatch mode | 派发模式 | emit / waterfall / parallel / serial |
1.4 Three plugin shapes
From docs/cordis-tutorial/01-first-plugin.md:
import { Service, type Context } from '@deepseek-ai/cordis'
// ① Function plugin (most common): named exports, no default export.
export const name = 'hello'
export function apply(ctx: Context) {}
// ② Object plugin: an object with an apply method.
export const objectPlugin = { name: 'object-plugin', apply(ctx: Context) {} }
// ③ Class plugin: a Service subclass (when you expose a service of your own).
export class MyService extends Service {
constructor(ctx: Context) { super(ctx, 'myService') }
}
Service packages default-export the service class; function plugins named-export
name/inject/Config/applyand must not have a default export.