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
bundlebundlean npm package carrying a config layer (cordis.patch.yml)
profileprofilea 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/apply and must not have a default export.


Prev: TL;DR · Contents · Next: The three plugin shapes