Files
deepseek-harness/docs/cordis-catalog/services.md

18 KiB

Cordis Services Catalog

Every ctx.<key> 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, and core-data-structures/ 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.agentLoopAgentLoop

Concrete ReactLoopAgent factory and driver service.

create(id: AgentId, options: AgentOptions = {}, meta: Pick<SessionHeader, 'cwd'> = {}): ReactLoopAgent
async createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>
async resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>

Source: packages/core/agent-loop/src/index.ts:335

ctx.agentsAgentRegistry

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.

setFactory(factory: AgentFactory): () => void
async create(options: CreateAgentOptions): Promise<AgentHandle>
async resume(options: ResumeAgentOptions): Promise<AgentHandle>
register(agent: Agent): () => void
enter(agent: Agent): () => void
announce(agent: Agent): void
get(id: AgentId): Agent | undefined
list(): Agent[]

Types: Agent

Source: packages/core/agent/src/index.ts:133

ctx.approvalApprovalService

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.

async request(req: ApprovalRequest): Promise<ApprovalOutcome>

Types: ApprovalOutcome · ApprovalRequest

Source: packages/ui/user-approval/src/index.ts:229

ctx.bashBashExecutor (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).

Semantics every implementation must honor:

  • run REJECTS only for infrastructure failures (unusable workdir, missing shell, pre-aborted signal). Nonzero exits, timeout kills, and abort kills RESOLVE with a descriptive BashRunResult — reporting a failed command is the tool layer's job, not an exception.
  • start returns immediately; no timeout applies to background processes (callers stop them via BashProcess.kill or the spec's AbortSignal). The handle's done settles at process close and never rejects (a spawn failure settles as killed with the error readable on stderr).
  • BashProcess.readOutput is incremental: consecutive reads never re-deliver output. Implementations bound their buffers; reads that lost data flag lossy and point at full-stream spill files when available.
  • Disposal kills every running background process and awaits their exit (no orphan processes survive fiber.dispose()).
abstract resolve(request: BashExecRequest): BashExecSpec
abstract run(spec: BashExecSpec): Promise<BashRunResult>
abstract start(spec: BashExecSpec): BashProcess

Types: BashExecRequest · BashExecSpec · BashRunResult

Source: packages/bash/bash/src/index.ts:68

ctx.codeRuntimeCodeRuntime (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.

abstract run(request: CodeRunRequest): Promise<CodeRunResult>

Types: CodeRunRequest · CodeRunResult

Source: packages/code-runtime/code-runtime/src/index.ts:30

ctx.compactCompactService (abstract seam)

Abstract compaction service. Implementations own token estimation, retention, and summarization, but a successful run must replace the selected surface span with one summary node and prevent concurrent compaction of the same session. Load one implementation per context as ctx.compact.

abstract compactIfNeeded( agent: CompactAgentContext, fullSystemPrompt: string, sessionPrefix: readonly Message[], signal: AbortSignal, ): Promise<CompactionResult | null>
abstract compactRegion( session: Session, start: number, end: number, agent: CompactAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>

Types: Message

Source: packages/compact/compact/src/index.ts:36

ctx.fsFileSystem (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.

abstract resolve(path: string, opts?: { cwd?: string }): Promise<FsTarget>
abstract stat(target: FsTarget, signal?: AbortSignal): Promise<FsInfo | undefined>
abstract readText(target: FsTarget, signal?: AbortSignal): Promise<string>
abstract streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>
abstract listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>
abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>
abstract editText(target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal): Promise<FsEditOutcome>

Types: FsEditOutcome · FsEditRequest · FsInfo · FsTarget · FsVersion · FsWriteIntent · FsWriteOutcome

Source: packages/fs/fs/src/index.ts:78

ctx.llmLlmService

The abstract llm service: an adapter registry plus a streaming model-call surface, interceptable via the llm/stream waterfall.

registerAdapter(models: string[], adapter: LlmAdapter): () => void
models(): string[]
stream(options: GenerateOptions): AsyncIterable<StreamChunk>

Types: GenerateOptions · StreamChunk

Source: packages/llm/llm/src/index.ts:75

ctx.permissionPermissionService

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.

current(events: readonly SessionEvent[]): string
resolve(name: string): PresetSpec
optionOf(name: string): PresetOption
set(session: Session, name: string): void

Types: SessionEvent

Source: packages/ui/permission/src/index.ts:94

ctx.sandboxSandboxProvider (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.

abstract confine(argv: readonly string[], policy: SandboxPolicy): ConfinedArgv

Types: ConfinedArgv · SandboxPolicy

Source: packages/sandbox/sandbox/src/index.ts:111

ctx.sessionPersistenceSessionPersistence (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.

abstract create(meta: SessionHeader): Promise<void>
abstract append(id: SessionId, events: readonly SessionEvent[]): Promise<void>
abstract load(id: SessionId): Promise<{ meta: SessionHeader; events: SessionEvent[] }>
abstract list(): Promise<SessionHeader[]>

Types: SessionEvent

Source: packages/session-persistence/session-persistence/src/index.ts:30

ctx.sessionQuerySessionQueryService

Live-preferred logical-corpus and exact-event read service.

listSessions(): Promise<SessionRecord[]>
async listEvents(sessionId: SessionId): Promise<SessionEventRecord[]>
async readEvent(request: SessionEventReadRequest): Promise<SessionEventWindow>

Source: packages/session-query/session-query/src/index.ts:35

ctx.sessionsSessionStore

In-memory session store (ctx.sessions).

Persistence is intentionally not implemented here — persistence plugins subscribe to session/event and flush on session/flush / dispose.

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<void>
get(id: SessionId): Session | undefined
list(): Session[]
fork(source: SessionForkSource, boundary?: number, childSessionId?: SessionId): Session

Source: packages/core/session/src/index.ts:564

ctx.skillsSkillService

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.

registerProvider(provider: SkillProvider): () => void
register(skill: SkillRegistration): () => void
async list(options: SkillLookupOptions = {}): Promise<SkillSummary[]>
async get(name: string, options: SkillLookupOptions = {}): Promise<SkillDefinition | undefined>

Source: packages/skill/skill/src/index.ts:141

ctx.subagentsSubagentService

Named provider registry and capability-checked start surface.

registerProvider(provider: SubagentProvider): () => void
getProvider(name: string): SubagentProvider | undefined
list(): string[]
async start(name: string, request: SubagentStartRequest): Promise<SubagentRun>

Source: packages/subagent/subagent/src/index.ts:141

ctx.systemPromptSystemPrompt

Registry service for the prompt inputs assembled before each model step.

section(section: PromptSection): () => void
tools(provider: (context: AssembleContext) => ToolProviderResult): () => void
variable(name: string, provider: (context: AssembleContext) => string | undefined): () => void
async assemble(context: AssembleContext = {}): Promise<PromptAssembly>

Source: packages/core/system-prompt/src/index.ts:209

ctx.tasksTaskService

The tasks service: the runtime-global background task registry. See the module doc for the ownership, isolation, and lifecycle contracts.

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-terminal'
async wait(id: TaskId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise<TaskSnapshot>
onTaskDone(listener: TaskDoneListener): () => void
attachSurface(name: string): () => void

Types: Agent

Source: packages/tasks/tasks/src/index.ts:98

ctx.toolsToolRegistry

Tool registry and execution pipeline. Scoped registrations shadow globals; one visibility resolver feeds presentation, lookup, and dispatch.

register(definition: ToolDefinition): () => void
restrict(filter: ToolRestriction): () => void
guard(guard: ToolGuard): () => void
get(name: string, scope?: ScopeKey): ToolDefinition | undefined
schemas(scope?: ScopeKey): ToolSchema[]
async execute(exec: ToolExecutionInput): Promise<ToolExecutionResult>

Types: ToolDefinition · ToolExecutionInput · ToolExecutionResult

Source: packages/core/tools/src/index.ts:363

ctx.userInteractionUserInteractionService

ctx.userInteraction: one active UI provider plus an ask() surface.

registerProvider(provider: UserInteractionProvider): () => void
async ask(request: AskUserQuestionRequest): Promise<AskUserQuestionAnswer>

Source: packages/ui/user-interaction/src/index.ts:82

ctx.webWebService

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.
registerSearchProvider(provider: WebSearchProvider): () => void
registerFetchProvider(provider: WebFetchProvider): () => void
async search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>
async fetch(request: WebFetchRequest, signal?: AbortSignal): Promise<WebFetchResult>

Source: packages/web/web/src/index.ts:74

ctx.workflowsWorkflowService (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.

abstract start(request: WorkflowStartRequest): WorkflowRun

Source: packages/workflow/workflow/src/index.ts:159

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); 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.