# Cordis Services Catalog Every `ctx.` service a plugin can call: the exact public interface plus the class JSDoc. This is one axis of the **wiring** reference a plugin author works against — the events a plugin listens to are the sibling [events catalog](events.md), and [core-data-structures/](../core-data-structures/core.md) catalogs the *data structures* these signatures move around. An abstract seam (e.g. `ctx.bash`) is implemented by a separate package; the interface is what consumers code against. 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 (skipped by doc-typecheck, since a bare signature is not standalone-compilable). Type names in a signature link to the page that documents them. The **harness tier** below (the `@deepseek-ai/dsh-*` packages) is the vocabulary this repo owns. The **inherited tier** at the end is the cordis-core + loader/hmr/timer `ctx` surface a plugin also sees — pinned vendor source, summarized tersely. ## `ctx.agentLoop` — `AgentLoop` Concrete agent factory and driver service. ```ts cordis-catalog create(id: SessionId, options: AgentOptions = {}, meta: Pick = {}): Agent async createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise async resume(ownerCtx: Context, options: ResumeAgentOptions): Promise ``` Types: [Agent](../core-data-structures/core.md) Source: [`packages/core/agent-loop/src/index.ts:407`](../../packages/core/agent-loop/src/index.ts) ## `ctx.agents` — `AgentRegistry` Agent registry (`ctx.agents`): tracks live agents so UI, hook, and orchestrator plugins can find them without depending on the concrete loop package. Agent *creation* is provided by whichever plugin implements the AgentFactory (`@deepseek-ai/dsh-agent-loop`), registered via setFactory. ```ts cordis-catalog setFactory(factory: AgentFactory): () => void async create(options: CreateAgentOptions): Promise async resume(options: ResumeAgentOptions): Promise register(agent: Agent): () => void enter(agent: Agent, owner: Agent | undefined): () => void announce(agent: Agent): void get(id: SessionId): Agent | undefined isOwnedBy(id: SessionId, owner: Agent): boolean list(): Agent[] roots(): Agent[] ``` Types: [Agent](../core-data-structures/core.md) Source: [`packages/core/agent/src/index.ts:201`](../../packages/core/agent/src/index.ts) ## `ctx.approval` — `ApprovalService` Approval service that applies session policy before answerers and logs every ask/outcome pair to the requesting session. It exposes deterministic policy changes to the model through prompt and pre-step notices. ```ts cordis-catalog async request(req: ApprovalRequest): Promise ``` Types: [ApprovalOutcome](../core-data-structures/approval.md) · [ApprovalRequest](../core-data-structures/approval.md) Source: [`packages/ui/user-approval/src/index.ts:229`](../../packages/ui/user-approval/src/index.ts) ## `ctx.bash` — `BashExecutor` (abstract seam) Abstract bash execution service. Subclass, implement the abstract methods, and load the subclass as a plugin — it registers as `ctx.bash` (one implementation per context; loading a second throws, which is cordis' standard duplicate-service behavior). Implementations must honor these semantics: - run rejects only for infrastructure failures. Nonzero exits, timeout kills, and abort kills resolve with a BashRunResult. - start returns immediately; no timeout applies to background processes. `done` settles at process close and never rejects; spawn failures settle as `killed` with the error on stderr. - BashProcess.readOutput is incremental: consecutive reads never repeat output. Lossy reads report truncation and available spill files. - Disposal kills all running background processes and awaits their exit. ```ts cordis-catalog abstract resolve(request: BashExecRequest): BashExecSpec abstract run(spec: BashExecSpec): Promise abstract start(spec: BashExecSpec): BashProcess ``` Types: [BashExecRequest](../core-data-structures/bash.md) · [BashExecSpec](../core-data-structures/bash.md) · [BashRunResult](../core-data-structures/bash.md) Source: [`packages/bash/bash/src/index.ts:49`](../../packages/bash/bash/src/index.ts) ## `ctx.bashEnv` — `BashEnvRegistry` Registry (`ctx.bashEnv`) for trusted, per-execution `DSH_*` variables. The namespace is rebuilt for every model bash call: ambient `DSH_*` values are discarded by the executor, then the registry's current snapshot is injected. Built-in shell facts remain owned by the registry itself while plugins can register additional, enumerable facts with effect-scoped disposal. ```ts cordis-catalog register(contributor: BashEnvContributor): () => void collect(execution: ToolExecution): DshEnvironment list(): BashEnvVariableInfo[] ``` Types: [ToolExecution](../core-data-structures/tools.md) Source: [`packages/bash/tool-bash/src/index.ts:102`](../../packages/bash/tool-bash/src/index.ts) ## `ctx.codeRuntime` — `CodeRuntime` (abstract seam) Registers one `ctx.codeRuntime` implementation. Program, budget, abort, and substrate failures resolve in CodeRunResult; only seam misuse rejects. Implementations bridge structured-cloneable bindings while treating programs as hostile peers, isolate runs from one another, and terminate and await in-flight runs during disposal. ```ts cordis-catalog abstract run(request: CodeRunRequest): Promise ``` Types: [CodeRunRequest](../core-data-structures/code-runtime.md) · [CodeRunResult](../core-data-structures/code-runtime.md) Source: [`packages/code-runtime/code-runtime/src/index.ts:30`](../../packages/code-runtime/code-runtime/src/index.ts) ## `ctx.compact` — `CompactService` (abstract seam) Abstract compaction service. Implementations own trigger policy, retention, and summarization, and may consume a separate measurement service. A successful run replaces the selected surface span with one summary node and prevents concurrent compaction of the same session. Load one implementation per context as `ctx.compact`. ```ts cordis-catalog abstract compactIfNeeded( agent: CompactAgentContext, fullSystemPrompt: string, sessionPrefix: readonly Message[], signal: AbortSignal, ): Promise abstract compactRegion( start: number, end: number, agent: CompactAgentContext, signal?: AbortSignal, ): Promise ``` Types: [Message](../core-data-structures/core.md) Source: [`packages/compact/compact/src/index.ts:38`](../../packages/compact/compact/src/index.ts) ## `ctx.fs` — `FileSystem` (abstract seam) Abstract filesystem provider. Targets must preserve identity across aliases; reads expose regular UTF-8 text or typed errors, listings are stable and content-free, and mutations are atomic. Optional guards add stale protection without changing the unguarded provider contract. ```ts cordis-catalog abstract resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): Promise abstract stat(target: FsTarget, signal?: AbortSignal): Promise abstract lstat(path: string, opts?: { cwd?: string }, signal?: AbortSignal): Promise abstract readText(target: FsTarget, signal?: AbortSignal): Promise abstract streamText(target: FsTarget, signal?: AbortSignal): Promise> abstract listDir(target: FsTarget, signal?: AbortSignal): Promise abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise abstract editText(target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal): Promise ``` Types: [FsEditOutcome](../core-data-structures/filesystem.md) · [FsEditRequest](../core-data-structures/filesystem.md) · [FsInfo](../core-data-structures/filesystem.md) · [FsTarget](../core-data-structures/filesystem.md) · [FsVersion](../core-data-structures/filesystem.md) · [FsWriteIntent](../core-data-structures/filesystem.md) · [FsWriteOutcome](../core-data-structures/filesystem.md) Source: [`packages/fs/fs/src/index.ts:80`](../../packages/fs/fs/src/index.ts) ## `ctx.llm` — `LlmService` The abstract `llm` service: an adapter registry plus a streaming model-call surface, interceptable via the `llm/stream` waterfall. ```ts cordis-catalog registerAdapter(providers: string[], adapter: LlmAdapter): () => void listProviders(): LlmProviderInfo[] async listModels(provider: string): Promise stream(options: GenerateOptions): AsyncIterable ``` Types: [GenerateOptions](../core-data-structures/core.md) · [StreamChunk](../core-data-structures/llm-streaming.md) Source: [`packages/llm/llm/src/index.ts:94`](../../packages/llm/llm/src/index.ts) ## `ctx.permission` — `PermissionService` Owns the deployment's permission presets and their write path. Requires a confining `ctx.bash` executor and `ctx.approval`; unmatched knob values are reported as CUSTOM_PRESET, not an error. ```ts cordis-catalog current(events: readonly SessionEvent[]): string resolve(name: string): PresetSpec optionOf(name: string): PresetOption set(session: Session, name: string): void ``` Types: [SessionEvent](../core-data-structures/core.md) Source: [`packages/ui/permission/src/index.ts:94`](../../packages/ui/permission/src/index.ts) ## `ctx.sandbox` — `SandboxProvider` (abstract seam) Abstract process-sandbox service. confine must return enforcing argv or fail closed at wrap or runner-execution time; silent unconfined passthrough is forbidden. Functional probes arbitrate multi-runner chains and may be skipped for a sole candidate, whose own refusal remains the fail-closed end. ```ts cordis-catalog abstract confine(argv: readonly string[], policy: SandboxPolicy): ConfinedArgv ``` Types: [ConfinedArgv](../core-data-structures/sandbox.md) · [SandboxPolicy](../core-data-structures/sandbox.md) Source: [`packages/sandbox/sandbox/src/index.ts:111`](../../packages/sandbox/sandbox/src/index.ts) ## `ctx.sessionPersistence` — `SessionPersistence` (abstract seam) Durable append-only session storage. Implementations preserve contiguous, losslessly JSON-serializable events; append resolves only after durability, and load balances a complete interrupted tail without rewriting committed events. ```ts cordis-catalog abstract locate(meta: SessionHeader): SessionLocation | undefined abstract create(meta: SessionHeader): Promise abstract append(id: SessionId, events: readonly SessionEvent[]): Promise abstract load(id: SessionId): Promise<{ meta: SessionHeader; events: SessionEvent[] }> abstract list(): Promise ``` Types: [SessionEvent](../core-data-structures/core.md) Source: [`packages/session-persistence/session-persistence/src/index.ts:42`](../../packages/session-persistence/session-persistence/src/index.ts) ## `ctx.sessionQuery` — `SessionQueryService` Live-preferred logical-corpus exact-read and relationship-tracing service. ```ts cordis-catalog listSessions(): Promise async listEvents(sessionId: SessionId): Promise async traceSession(sessionId: SessionId): Promise async traceEvent(request: SessionEventTraceRequest): Promise async readEvent(request: SessionEventReadRequest): Promise ``` Source: [`packages/session-query/session-query/src/index.ts:38`](../../packages/session-query/session-query/src/index.ts) ## `ctx.sessions` — `SessionStore` In-memory session store (`ctx.sessions`). Persistence is intentionally not implemented here — persistence plugins subscribe to `session/event` and flush on `session/flush` / dispose. ```ts cordis-catalog create(id?: SessionId, options?: CreateSessionOptions): Session prepare(id?: SessionId, options?: CreateSessionOptions): Session enter(session: Session): () => void announce(session: Session): void async flush(session: Session): Promise get(id: SessionId): Session | undefined list(): Session[] fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId): Session ``` Source: [`packages/core/session/src/index.ts:577`](../../packages/core/session/src/index.ts) ## `ctx.skills` — `SkillService` Registry of skill providers. It merges provider catalogs with stable first-wins duplicate handling, exposes sorted model-visible summaries, and loads full skill bodies on demand. ```ts cordis-catalog registerProvider(provider: SkillProvider): () => void register(skill: SkillRegistration): () => void async list(options: SkillLookupOptions = {}): Promise async get(name: string, options: SkillLookupOptions = {}): Promise ``` Source: [`packages/skill/skill/src/index.ts:141`](../../packages/skill/skill/src/index.ts) ## `ctx.spillStore` — `SpillStore` (abstract seam) Abstract spill storage service. Subclass, implement saveText, and load the subclass as a plugin — it registers as `ctx.spillStore` (one implementation per context; loading a second throws, cordis' standard duplicate-service behavior). Semantics every implementation must honor: - saveText persists the FULL `content` verbatim and returns an opaque locator, exact byte length, and model-facing retrieval guidance. - Storage is scoped by the request's SaveTextSpill.owner session; the backend chooses a private (not world-readable) location and a collision-free name derived from — never equal to — the caller's `suggestedName`. - `saveText` REJECTS on a real storage failure (permissions, ENOSPC, backend unavailable); the caller decides how to degrade (the spill policy treats a rejection as best-effort and keeps the inline result). ```ts cordis-catalog abstract saveText(input: SaveTextSpill): Promise ``` Source: [`packages/spill/spill/src/index.ts:45`](../../packages/spill/spill/src/index.ts) ## `ctx.subagents` — `SubagentService` Named provider registry and capability-checked start surface. ```ts cordis-catalog registerProvider(provider: SubagentProvider): () => void getProvider(name: string): SubagentProvider | undefined list(): string[] async start(name: string, request: SubagentStartRequest): Promise ``` Source: [`packages/subagent/subagent/src/index.ts:153`](../../packages/subagent/subagent/src/index.ts) ## `ctx.systemPrompt` — `SystemPrompt` Registry service for the prompt inputs assembled before each model step. ```ts cordis-catalog section(section: PromptSection): () => void tools(provider: (context: AssembleContext) => ToolProviderResult): () => void variable(name: string, provider: (context: AssembleContext) => string | undefined): () => void async assemble(context: AssembleContext = {}): Promise ``` Source: [`packages/core/system-prompt/src/index.ts:209`](../../packages/core/system-prompt/src/index.ts) ## `ctx.tasks` — `TaskService` The `tasks` service: the runtime-global background task registry. See the module doc for the ownership, isolation, and lifecycle contracts. ```ts cordis-catalog start(spec: TaskStart): TaskId list(caller?: Agent): TaskSnapshot[] get(id: TaskId, caller?: Agent): TaskSnapshot read(id: TaskId, caller?: Agent): TaskRead kill(id: TaskId, caller?: Agent, reason?: string): 'requested' | 'already-finished' async wait(id: TaskId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise onTaskDone(listener: TaskDoneListener): () => void attachSurface(name: string): () => void ``` Types: [Agent](../core-data-structures/core.md) Source: [`packages/tasks/tasks/src/index.ts:76`](../../packages/tasks/tasks/src/index.ts) ## `ctx.tokenMeter` — `TokenMeterService` Replay owner for one service-wide estimator and isolated per-session folds. ```ts cordis-catalog measure(session: Session, requestHeader?: EpochHeader): TokenMeasurement estimateMessage(message: Message): number ``` Types: [Message](../core-data-structures/core.md) Source: [`packages/llm/token-meter/src/index.ts:106`](../../packages/llm/token-meter/src/index.ts) ## `ctx.tools` — `ToolRegistry` Tool registry and execution pipeline. Scoped registrations shadow globals; one visibility resolver feeds presentation, lookup, and dispatch. ```ts cordis-catalog register(definition: ToolDefinition): () => void restrict(filter: ToolRestriction): () => void guard(guard: ToolGuard): () => void get(name: string, scope?: ScopeKey): ToolDefinition | undefined schemas(scope?: ScopeKey): ToolSchema[] executionMode(exec: ToolExecutionInput): ToolExecutionMode async execute(exec: ToolExecutionInput): Promise ``` Types: [ToolDefinition](../core-data-structures/tools.md) · [ToolExecutionInput](../core-data-structures/tools.md) · [ToolExecutionMode](../core-data-structures/tools.md) · [ToolExecutionResult](../core-data-structures/tools.md) Source: [`packages/core/tools/src/index.ts:438`](../../packages/core/tools/src/index.ts) ## `ctx.userInteraction` — `UserInteractionService` `ctx.userInteraction`: one active UI provider plus an `ask()` surface. ```ts cordis-catalog registerProvider(provider: UserInteractionProvider): () => void async ask(request: AskUserQuestionRequest): Promise ``` Source: [`packages/ui/user-interaction/src/index.ts:82`](../../packages/ui/user-interaction/src/index.ts) ## `ctx.web` — `WebService` The web access service. Registered as `ctx.web` (one instance per context). Selection semantics (resolved at execution time, never order-dependent): - A configured id that is registered and `available()` → that provider. - A configured id not registered → `WEB_PROVIDER_CONFIGURED_MISSING`. - A configured id registered but unavailable → `WEB_PROVIDER_CONFIGURED_UNAVAILABLE`. - No id configured, exactly one registered usable provider → that provider. - No id configured, multiple usable providers → `WEB_PROVIDER_AMBIGUOUS`. - No id configured, no usable provider → `WEB_PROVIDER_UNAVAILABLE`. ```ts cordis-catalog registerSearchProvider(provider: WebSearchProvider): () => void registerFetchProvider(provider: WebFetchProvider): () => void async search(request: WebSearchRequest, signal?: AbortSignal): Promise async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise ``` Source: [`packages/web/web/src/index.ts:74`](../../packages/web/web/src/index.ts) ## `ctx.workflows` — `WorkflowService` (abstract seam) Workflow execution seam. Invalid requests throw before publication; a live run is holder-owned, its result never rejects, cancellation and disposal are bounded, and disposal waits for child cleanup within that bound. Lifecycle listener failures are contained, and `workflow/end` fires exactly once as the result settles. ```ts cordis-catalog abstract start(request: WorkflowStartRequest): WorkflowRun ``` Source: [`packages/workflow/workflow/src/index.ts:159`](../../packages/workflow/workflow/src/index.ts) ## Inherited `ctx` members (cordis core + loader/hmr/timer) The framework `ctx` surface every plugin also sees, beyond the harness services above. This is pinned vendor source ([vendoring policy](../../vendor/README.md)); it is summarized here so the page is a complete picture of what `ctx` offers, without elevating framework internals to the harness tier's prominence. - `ctx.on / ctx.once` — Register an event listener (disposable). ([`vendor/cordis/src/events.ts:34`](../../vendor/cordis/src/events.ts)) - `ctx.emit / ctx.parallel / ctx.serial / ctx.bail / ctx.waterfall` — Dispatch an event (sync / awaited / first-bail / veto-chain). ([`vendor/cordis/src/events.ts:34`](../../vendor/cordis/src/events.ts)) - `ctx.plugin / ctx.inject` — Load a plugin / declare required services. ([`vendor/cordis/src/registry.ts:164`](../../vendor/cordis/src/registry.ts)) - `ctx.effect` — Register a disposable side effect tied to the fiber. ([`vendor/cordis/src/fiber.ts:9`](../../vendor/cordis/src/fiber.ts)) - `ctx.get / ctx.set / ctx.provide / ctx.accessor / ctx.mixin` — Low-level service-store access and binding. ([`vendor/cordis/src/reflect.ts:7`](../../vendor/cordis/src/reflect.ts)) - `ctx.extend / ctx.isolate / ctx.intercept` — Derive a child context (scoped services / isolation / interception). ([`vendor/cordis/src/context.ts:42`](../../vendor/cordis/src/context.ts)) - `ctx.root / ctx.scope / ctx.fiber / ctx.registry / ctx.reflect / ctx.events / ctx.logger` — Ambient handles onto the running context graph. ([`vendor/cordis/src/context.ts:16`](../../vendor/cordis/src/context.ts)) - `ctx.timer (+ interval / timeout / throttle / debounce / setTimeout / setInterval)` — Disposable timer helpers. The `timer` key is provided at runtime; the six helpers are mixed onto ctx directly (declared via Pick). ([`vendor/timer/src/index.ts:4`](../../vendor/timer/src/index.ts)) - `ctx.loader` — The config Loader that booted the app (present under the loader). ([`vendor/loader/src/index.ts:30`](../../vendor/loader/src/index.ts)) - `ctx.hmr` — The hot-module-reload watcher (present under the hmr plugin). ([`vendor/hmr/src/index.ts:15`](../../vendor/hmr/src/index.ts))