Skip to content

API & types

Every config: block a cordis.yml entry can set: for each loadable harness package, the verbatim config declaration (JSDoc included) its apply function or service constructor receives, with every referenced type pasted alongside (package-local types) or linked (everything else). The paste is the plugin’s full declared config type — a field the runtime schema deliberately excludes is a runtime-only seam (its own JSDoc says so) and is not settable from cordis.yml. This is the deployment-axis reference — the wiring a plugin author works against is the generated Cordis API region on each subsystem page, the model-facing tool schemas are the tool catalog, and subsystems/ documents the types these declarations reference.

This file is GENERATED from source (scripts/gen-config-catalog.ts) and verified fresh by pnpm run verify-config-catalog (part of doc-sync) — do not edit it by hand. Declaration blocks use a ts config-catalog fence (skipped by doc-typecheck, since a lone declaration referencing imports is not standalone-compilable). The generator also cross-checks the runtime schemastery schema against the pasted declaration — every schema-validated key, nested keys included, must be locatable on the declared config type — so the paste cannot hide a loader-accepted field.

A Requires: line lists the service keys the plugin injects: its cordis.yml tree must also load providers for those services. Scope is the harness tier (packages/); the vendored cordis plugins a config tree may also load (hmr, the console logger, …) are pinned upstream source (vendoring policy) and not catalogued here.

Every model-facing tool a shipped plugin contributes to ctx.tools: the name, description, and JSON-Schema parameters the model receives via the system-prompt assembly. It complements the subsystem pages (the types plus each page’s generated Cordis API region) — this page is the tools the agent is offered.

This file is GENERATED and verified fresh by pnpm run verify-tool-catalog (part of doc-sync) — do not edit it by hand. Unlike the cordis catalog (a pure source-AST pass), this generator BOOTS each tool plugin on a real context and reads ctx.tools.schemas(), because a tool schema is not statically knowable (runtime-spread enums, concatenated descriptions, config-driven names, raw-JSON-Schema MCP tools). A completeness guard globs packages/*/tool-* and fails if any package is missing from the generator’s boot manifest, so a new tool cannot be silently undocumented. See the tool-schema-catalog Agent Note.

Scope: shipped product tools under packages/*/tool-*, each booted with its DEFAULT config, except where a Config field is REQUIRED with no default — there the generator must choose, and the per-package note records which branch this page shows. The registered tool NAME can be a load-time config (e.g. tool-subagent’s toolName), so a deployment may expose a package under a different or additional name — a per-package note records those shipped aliases where they exist. The examples/ demo tools (e.g. echo) are excluded, matching the cordis catalog’s packages-only scope.

Every event type that can appear in a session’s durable event log: the complete persisted SessionEvent envelope and each member of the merge-extensible SessionEventMap — the owning vocabulary in @deepseek-ai/dsh-session plus every plugin declaration merge into @deepseek-ai/dsh-session/types in this repo — with source JSDoc, full payload declaration, surface badge, and declaration site. It complements session.md (surface ordering and the deriveMessages() projection), persistence.md (how the log is made durable), and the generated region of session.md (the live bus wiring — a log event is NOT a cordis event; it reaches listeners via the single session/event emit).

This file is GENERATED from source (scripts/gen-persistence-catalog.ts) and verified fresh by pnpm run verify-persistence-catalog (part of doc-sync) — do not edit it by hand. Declaration blocks retain the source declaration and nested property JSDoc, removing only the indentation imposed by a containing interface/module, and use a ts persistence-catalog fence (skipped by doc-typecheck because declarations reference types from their owning modules). Type names in a payload link to the page that documents them. See the persistence-log-catalog Agent Note.

The envelope declarations below compose each event’s type, monotonic seq, epoch-ms time, data, the optional ignorable unknown-type skip marker, and the conditional surfaceOp/sourceEventSeqs fields. surface marks a SurfaceEventType member: it produces an LLM message and declares how it joins the surface list. log-only marks everything else: a durable, replayable record with no derived-history contribution. Every payload is JSON-serializable (enforced at Session.append), and the whole format is pinned at SESSION_FORMAT_VERSION = 0 — pre-release, no compatibility implied (the version stance). Scope: the packages in this repo; a downstream plugin can merge further event types, which are outside this catalog by construction.

The context is the core Cordis object: every service, event, and lifecycle API is reached through ctx. Event methods are documented on Events, effects and the current fiber on Fiber, and plugin loading on Registry.

Root and child dependency containers for Cordis plugins.

A context is a proxy: normal property reads go through the service resolver, while extend(), isolate(), and intercept() create scoped child contexts without mutating their parent.

Source

/**
* Create a child context with extra metadata on top of the current scope.
*
* The child prototypally inherits every property of this context; own
* properties of `meta` shadow the inherited ones. The parent is not mutated.
*
* @param meta — own properties (including symbol keys) to define on the child.
* @returns a child context inheriting from this one.
*/
extend(meta = {}): this

Create a child context with extra metadata on top of the current scope.

The child prototypally inherits every property of this context; own properties of meta shadow the inherited ones. The parent is not mutated.

  • meta — own properties (including symbol keys) to define on the child.

Returns a child context inheriting from this one.

Source

/**
* Create a child context with an independent service scope for `name`.
*
* Below the returned context, reads and writes of the service `name`
* resolve against the new label instead of the parent's, so a different
* implementation can be provided without affecting the parent scope.
* Passing the same `label` to two `isolate()` calls joins their scopes.
*
* @param name — the service name to isolate.
* @param label — scope label to join; defaults to a fresh unique symbol.
* @returns a child context whose `name` service resolves in the new scope.
*/
isolate(name: string, label?: symbol)

Create a child context with an independent service scope for name.

Below the returned context, reads and writes of the service name resolve against the new label instead of the parent’s, so a different implementation can be provided without affecting the parent scope. Passing the same label to two isolate() calls joins their scopes.

  • name — the service name to isolate.
  • label — scope label to join; defaults to a fresh unique symbol.

Returns a child context whose name service resolves in the new scope.

Source

/**
* Add service-specific intercept config for plugins started below this
* context.
*
* Plugins loaded under the returned context see `config` merged into the
* service's resolved config (ancestor entries first; see
* `Service[symbols.resolveConfig]`). The parent context is not affected.
*
* @param name — the service name whose config to intercept.
* @param config — the intercept config to merge for that service.
* @returns a child context carrying the additional intercept entry.
*/
intercept<K extends InjectKey>(name: K, config: Context[K] extends { [symbols.config]: infer T } ? T : never): this
intercept(name: string, config: any): this

Add service-specific intercept config for plugins started below this context.

Plugins loaded under the returned context see config merged into the service’s resolved config (ancestor entries first; see Service[symbols.resolveConfig]). The parent context is not affected.

  • name — the service name whose config to intercept.
  • config — the intercept config to merge for that service.

Returns a child context carrying the additional intercept entry.

Source

/** The root context of the application (every child context shares it). @experimental */
root: this

The root context of the application (every child context shares it). @experimental

Source

/** Base URL used to resolve relative plugin/module specifiers, if the runtime sets one. */
baseUrl?: string

Base URL used to resolve relative plugin/module specifiers, if the runtime sets one.

Source

/** The event bus. Its methods are also mixed onto `ctx` (`ctx.on`, `ctx.emit`, ...). */
events: EventsService

The event bus. Its methods are also mixed onto ctx (ctx.on, ctx.emit, …).

Source

/** The logging service. Call `ctx.logger(name)` for a named logger. */
logger: LoggerService

The logging service. Call ctx.logger(name) for a named logger.

Source

/** The reflection layer backing the context proxy (`ctx.get`, `ctx.provide`, ...). */
reflect: ReflectService

The reflection layer backing the context proxy (ctx.get, ctx.provide, …).

Source

/** The plugin registry. Its methods are mixed onto `ctx` (`ctx.plugin`, `ctx.inject`). */
registry: RegistryService

The plugin registry. Its methods are mixed onto ctx (ctx.plugin, ctx.inject).

Source

The event-dispatch API mixed into every context. Harness event declarations and their dispatch modes are generated into each owning subsystem page.

/**
* Dispatch an event, running all listeners concurrently.
*
* @param name — the event name.
* @param args — arguments passed to every listener.
* @returns a promise resolving once every listener has settled.
*/
parallel<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promise<void>
parallel<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promise<void>

Dispatch an event, running all listeners concurrently.

  • name — the event name.
  • args — arguments passed to every listener.

Returns a promise resolving once every listener has settled.

Source

/**
* Dispatch an event synchronously, ignoring listener return values.
*
* @param name — the event name.
* @param args — arguments passed to every listener.
*/
emit<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): void
emit<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): void

Dispatch an event synchronously, ignoring listener return values.

  • name — the event name.
  • args — arguments passed to every listener.

Source

/**
* Dispatch an event, awaiting listeners in order until one bails.
*
* @param name — the event name.
* @param args — arguments passed to each listener.
* @returns the first bail value (non-null, non-false, non-undefined), if any.
*/
serial<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>
serial<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): Promisify<ReturnType<Events[K]>>

Dispatch an event, awaiting listeners in order until one bails.

  • name — the event name.
  • args — arguments passed to each listener.

Returns the first bail value (non-null, non-false, non-undefined), if any.

Source

/**
* Dispatch an event, calling listeners in order until one bails.
*
* @param name — the event name.
* @param args — arguments passed to each listener.
* @returns the first bail value (non-null, non-false, non-undefined), if any.
*/
bail<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
bail<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>

Dispatch an event, calling listeners in order until one bails.

  • name — the event name.
  • args — arguments passed to each listener.

Returns the first bail value (non-null, non-false, non-undefined), if any.

Source

/**
* Dispatch an event whose last argument is a `next` continuation.
*
* Each listener wraps the rest of the chain: calling `next()` invokes the
* next listener (finally the built-in behavior); not calling it vetoes.
*
* @param name — the event name.
* @param args — listener arguments; the final one is the innermost `next`.
* @returns the outermost listener's return value.
*/
waterfall<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>
waterfall<K extends keyof Events>(thisArg: NoInfer<ThisType<Events[K]>>, name: K, ...args: Parameters<Events[K]>): ReturnType<Events[K]>

Dispatch an event whose last argument is a next continuation.

Each listener wraps the rest of the chain: calling next() invokes the next listener (finally the built-in behavior); not calling it vetoes.

  • name — the event name.
  • args — listener arguments; the final one is the innermost next.

Returns the outermost listener’s return value.

Source

/**
* Register an event listener owned by the current fiber.
*
* @param name — the event name to listen for.
* @param listener — called with the dispatch arguments.
* @param options — listener options; a boolean is shorthand for `prepend`.
* @returns a disposer removing the listener; `true` if it was still registered.
*/
on<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean

Register an event listener owned by the current fiber.

  • name — the event name to listen for.
  • listener — called with the dispatch arguments.
  • options — listener options; a boolean is shorthand for prepend.

Returns a disposer removing the listener; true if it was still registered.

Source

/**
* Same as `on()`, but the listener disposes itself after its first call.
*
* @param name — the event name to listen for.
* @param listener — called at most once with the dispatch arguments.
* @param options — listener options; a boolean is shorthand for `prepend`.
* @returns a disposer removing the listener; `true` if it was still registered.
*/
once<K extends keyof Events>(name: K, listener: Events[K], options?: boolean | EventOptions): () => boolean

Same as on(), but the listener disposes itself after its first call.

  • name — the event name to listen for.
  • listener — called at most once with the dispatch arguments.
  • options — listener options; a boolean is shorthand for prepend.

Returns a disposer removing the listener; true if it was still registered.

Source

A fiber is one loaded plugin instance: its lifecycle state, validated config, and registered effects. ctx.fiber is the current fiber, and ctx.effect() delegates to it.

/**
* Register a cleanup-aware effect on this fiber.
*
* `execute` runs immediately; the disposers it produces are collected and
* run (in reverse order) either when the returned disposer is called or
* when the fiber unloads, whichever comes first. Calling the disposer twice
* is a no-op. Throws `CordisError('INACTIVE_EFFECT')` if the fiber is
* already disposed, and `TypeError` if `execute` returns an invalid shape.
*
* @param execute — the effect body; see {@link Effect} for accepted shapes.
* @param label — effect label shown in `getEffects()` diagnostics.
* @returns a disposer that tears the effect down and settles once done.
*/
effect(execute: () => SyncEffect, label?: string): Disposable<Promise<void>>
effect(execute: () => Effect, label?: string): AsyncDisposable<Promise<void>>

Register a cleanup-aware effect on this fiber.

execute runs immediately; the disposers it produces are collected and run (in reverse order) either when the returned disposer is called or when the fiber unloads, whichever comes first. Calling the disposer twice is a no-op. Throws CordisError('INACTIVE_EFFECT') if the fiber is already disposed, and TypeError if execute returns an invalid shape.

  • execute — the effect body; see Effect for accepted shapes.
  • label — effect label shown in getEffects() diagnostics.

Returns a disposer that tears the effect down and settles once done.

Source

/** The fiber (plugin runtime instance) that owns this context. */
fiber: Fiber

The fiber (plugin runtime instance) that owns this context.

Source

Plugin loading and dependency injection.

/**
* Run a callback once the requested services are available.
*
* Shorthand for `ctx.plugin({ inject, apply: callback })`: the callback
* is unloaded and re-run whenever a required service changes.
*
* @param deps — required services, as an array or a name → config map.
* @param callback — plugin body called with `(ctx, config)`.
* @returns the fiber; awaiting it settles once loading finished.
*/
inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>

Run a callback once the requested services are available.

Shorthand for ctx.plugin({ inject, apply: callback }): the callback is unloaded and re-run whenever a required service changes.

  • deps — required services, as an array or a name → config map.
  • callback — plugin body called with (ctx, config).

Returns the fiber; awaiting it settles once loading finished.

Source

/**
* Load a plugin in the current context.
*
* @param plugin — a function, class, or `{ apply }` object plugin.
* @param args — the plugin config, validated against its `Config` schema.
* @returns the fiber; awaiting it settles once loading finished
* (rejecting on config or startup errors).
*/
plugin<P extends Plugin>(plugin: P, ...args: Spread<GetPluginConfig<P>>): Fiber & PromiseLike<Fiber>

Load a plugin in the current context.

  • plugin — a function, class, or { apply } object plugin.
  • args — the plugin config, validated against its Config schema.

Returns the fiber; awaiting it settles once loading finished (rejecting on config or startup errors).

Source

The base class for context services. A subclass loaded as a plugin registers itself as ctx.<name>.

Base class for services that expose a named API on ctx.

Subclasses call super(ctx, name) from their constructor. The service is registered immediately and is automatically removed with the owning fiber.

Source

/** The service name this instance is registered under. */
public name!: string

The service name this instance is registered under.

Source

The framework ctx members and events every plugin sees beyond the harness tier — pinned vendor source (vendoring policy), summarized tersely so the harness pages stay focused on repository-owned vocabulary. Detailed Context, Fiber, Registry, and Service APIs are generated in context.md, fiber.md, registry.md, and service.md; the event-dispatch methods in events.md.

This file is GENERATED from source (scripts/gen-cordis-catalog.ts) and verified fresh by pnpm run verify-cordis-catalog (part of doc-sync) — do not edit it by hand. Signature blocks use a ts cordis-catalog fence and include the original source JSDoc immediately before each event or service method. doc-typecheck skips these bare declaration fragments; type names in a signature link to the page that documents them.