/** * Agent Runtime provider-authoring contracts (declaration-only). * * The complete, neutral Agent Runtime provider contract a runtime package * implements while importing only `@excitedjs/dreamux-types`. The seam is * deliberately minimal: a provider facade for selection, creation, and neutral * recent Activity reads; a live handle with `start`, `submit`, `interrupt`, and * `stop`; * and a Core-owned leased state sink runtime facts are pushed into. It never * exposes Dreamux host-private types (`DispatcherRow`, `DispatcherStore`, * `DispatcherConfig`, config/state stores, or host path-helper * implementations); Dreamux core adapts its private objects into these shapes. * * Recovery, session-bound structured output, and recent Activity Records are * mandatory provider behavior rather than negotiated capability bits. Live * activity emission stays optional because its absence changes only * presentation. * * The live and cold Activity record shapes themselves (`RuntimeActivity` and * `AgentActivityRecord`, with their supporting types) live in `activity.js`: * that module is the Activity domain read through both of a runtime's * lifecycles, while this module stays about launching and running the session * that produces them. */ import type { AgentActivityPage, AgentActivityQuery, AgentActivityReadContext, RuntimeActivity } from './activity.js'; import type { DreamuxLogger } from './logger.js'; import type { JsonSchema } from './json.js'; import type { DreamuxEnvironment, ProviderBinCheck, ProviderDiagnosticRunner, ProviderDiagnosticScope, ProviderDiagnosticResult, ProviderFactory, ProviderOnboard } from './provider.js'; /** Runtime-specific alias of the shared public logger contract. */ export type AgentRuntimeLogger = DreamuxLogger; /** * One MCP server Core injects into a runtime. Core owns the whole list: a * provider launches exactly these entries and never discovers, appends to, or * mutates them. */ export interface AgentRuntimeMcpServer { readonly name: string; readonly command: string; readonly args: readonly string[]; readonly env?: Readonly>; } /** * A skill root core hands to a runtime. Core composes required bundled roots * with any authorized custom roots; the runtime package owns the mechanics of * applying them to its engine. */ export interface AgentRuntimeSkillSource { name: string; /** * Absolute canonical directory whose direct children are skill directories. * Dreamux core validates and normalizes custom roots before persistence. */ path: string; source: 'dreamux-core' | string; } /** * The neutral, Core-supplied identity of one runtime instance. * * `sessionId` is the provider's own prior session id, or `null` for a fresh * start. It is an opaque string Core persists atomically and returns only to * the same provider; Core never parses it or derives anything from its shape. * A session id is all a resumable runtime needs, so the seam carries a string * rather than an extensible object: nothing downstream may attach a second * durable fact to a session. */ export interface AgentRuntimeIdentity { readonly runtimeId: string; readonly sessionId: string | null; } export interface AgentRuntimePathContext { /** * The global host cache root for provider-owned rebuildable scratch. * Neutral: the runtime derives its own subpaths from here. Recovery state and * volatile rendezvous sockets do NOT live here. */ cacheDir(): string; /** * The central logs root. The runtime composes its OWN log subpaths under this * directory (e.g. `//.log`), so core never has to name a * per-runtime log file. Neutral: a runtime that logs differently lays out its * own tree here. */ logsDir(): string; /** * Candidate directories for volatile rendezvous sockets, in host preference * order. A runtime that needs a Unix-domain socket allocates a fresh random * short name inside the first candidate whose full path fits the platform * socket-path budget (see `@excitedjs/dreamux-utils` `unixSocketPathFitsBudget`). * Neutral: a runtime that needs no socket (e.g. a stdio engine) ignores it. * Sockets are never persisted and never live under {@link cacheDir}. */ runtimeSocketDirs(): readonly string[]; } /** * Neutral runtime status. Mirrors the host's dispatcher lifecycle states without * importing the host enum, so a provider can report status without depending on * `@excitedjs/dreamux`. */ export type AgentRuntimeStatus = 'declared' | 'starting' | 'ready' | 'degraded' | 'stopping' | 'stopped'; /** One authoritative runtime fact pushed into the Core-owned state sink. */ export type AgentRuntimeStateUpdate = { readonly kind: 'status'; readonly status: AgentRuntimeStatus; readonly lastError?: string; } | { readonly kind: 'session'; readonly sessionId: string; } | { readonly kind: 'session_lost'; readonly reason: string; }; /** * Push-only state sink, leased to exactly one runtime generation. * * Core creates a distinct sink per generation; the generation is not a public * field and the provider supplies no sequence number. Identity updates are * serialized in call-receipt order; `publish` resolves after the write is durable. * There is no pull counterpart: awaiting the provider's own initial `publish` * calls is the start fence. * * After Core revokes the lease (runtime replaced or stopped), `publish` rejects * with an {@link AgentRuntimeStateLeaseRevokedError} so the provider terminates * the stale writer. A persistence failure is a separate, fatal error. */ export interface AgentRuntimeStateSink { publish(update: AgentRuntimeStateUpdate): Promise; } /** * Structural shape of the `Error` {@link AgentRuntimeStateSink.publish} rejects * with once Core has revoked that runtime generation's lease. Callers branch on * `error.name` rather than `instanceof`, keeping this package declaration-only. */ export interface AgentRuntimeStateLeaseRevokedError extends Error { name: 'AgentRuntimeStateLeaseRevokedError'; } /** One accepted provider submission. Its identity never implies folding. */ export interface RuntimeSubmission { readonly settled: Promise; } /** A provider-observed native result. */ export type RuntimeCompletion = { readonly status: 'completed'; readonly resultText: string | null; } | { readonly status: 'failed'; readonly error: Error; }; /** Native observations, independent of host submission attribution. */ export type AgentRuntimeEvent = RuntimeActivity | { readonly kind: 'session.title.changed'; readonly title: string; } | { readonly kind: 'turn.result'; readonly completion: RuntimeCompletion; }; /** * Required synchronous, nonthrowing observation sink. Core drops events from * revoked generations. Accepted observations are not durable acknowledgements: * their owners may enqueue persistence without delaying the native runtime. * * Publish each normal or failed native terminal once as `turn.result`, including * turns with no host submission, before settling its submissions. The original * completion object is shared by the event and every settlement for that result; * its identity folds observation and settlement into one owner report. * Interruptions and transport failures do not manufacture results. * * Live activity is transient input to Core's conversation projection. It never * replays, or is replayed by, {@link AgentRuntimeProvider.readRecentActivity}. */ export type AgentRuntimeEventSink = (event: AgentRuntimeEvent) => void; export type RuntimeSubmissionSettlement = { readonly kind: 'completion'; readonly completion: RuntimeCompletion; } | { readonly kind: 'failed'; readonly error: Error; } | { readonly kind: 'stopped'; }; /** * The single input shape a live runtime accepts. * * Deliberately nothing but text: it is already the complete model-facing * message, so the seam carries no discriminator, no source enum, no source * identity, and no rendering instruction. Every caller prepares its final text * before submitting, so a runtime never renders an envelope and never branches * on where a turn came from. Stable source identity, origin, intent, and * display correlation stay on Core's own turn/admission state, and Core — not a * Provider — deduplicates with them. */ export interface AgentRuntimeSubmissionInput { readonly text: string; } /** * Admission is separate from the eventual outcome of an accepted turn. * * `failed` is narrowly reserved for a provider-proven pre-admission failure: * the provider knows that no native command was accepted or may later become * accepted. `ambiguous` means submission may have crossed the provider/native * boundary. Callers MUST NOT retry an ambiguous admission automatically. * A rejected/thrown input promise is likewise admission-ambiguous unless the * provider documents and returns the explicit `failed` result instead. * * `skipped` remains a provider-seam state; the Command boundary — not this * seam — normalizes it to the public `stopped`. * * There is no `duplicate` admission: a Provider has no source identity to * deduplicate with. Core's own admission ledger returns the public `duplicate` * before it ever calls {@link AgentRuntime.submit}. */ export type RuntimeAdmission = { status: 'submitted'; submission: RuntimeSubmission; } | { status: 'stopped'; } | { status: 'skipped'; } | { status: 'failed'; error: Error; } | { status: 'ambiguous'; error: Error; }; /** * Neutral system-prompt input. When both forms are present they are alternate * representations of the same instructions, and a Provider applies at most one * of them — whichever its runtime supports. `append` fragment order is * significant. Dreamux re-supplies the reconstructed bundle on every * runtime-context creation; a Provider must never become the authority for * prompt state. */ export interface AgentRuntimeSystemPrompt { readonly replace?: string; readonly append?: readonly string[]; } /** * The neutral facts required to launch one Dreamux role. Immutable: prior * session identity reaches `start` only through this object. */ export interface AgentRuntimeCreateContext { readonly identity: AgentRuntimeIdentity; /** Provider-parsed config (the output of the provider's own config capability). */ readonly config: TConfig; /** * The directory the runtime runs in. Always supplied by the launcher; never * derived inside the runtime. */ readonly cwd: string; /** Core-supplied role instructions; see {@link AgentRuntimeSystemPrompt}. */ readonly systemPrompt?: AgentRuntimeSystemPrompt; /** * MCP servers Core injects for this runtime instance. Already fully resolved: * an empty array means "no MCP servers", and the provider must launch exactly * these — it must not infer, append, or mutate the list. */ readonly mcpServers: readonly AgentRuntimeMcpServer[]; /** * Effective skill sources core selected for this runtime, including required * bundled role roots and authorized custom roots. */ readonly skillSources: readonly AgentRuntimeSkillSource[]; /** * Neutral feature names the host asks this runtime to disable. Core emits * only neutral names; each runtime maps the names it understands to its own * mechanism and ignores the rest. */ readonly disabledFeatures: readonly string[]; /** * Optional JSON Schema constraining the model's final assistant message, bound * once to this runtime session. A provider that applies the schema natively * per turn stores this fixed value and reapplies it; a later submit can never * change it. When set, every settled turn's result text is expected to be * valid JSON conforming to the schema; the caller parses it. */ readonly outputSchema?: JsonSchema; readonly paths: AgentRuntimePathContext; /** Leased, push-only state sink for this runtime generation. */ readonly state: AgentRuntimeStateSink; /** Leased synchronous observations from this runtime generation. */ readonly events: AgentRuntimeEventSink; readonly logger: AgentRuntimeLogger; } /** What `start` restored. Core consumes it before admitting the first submission. */ export interface AgentRuntimeStartOutcome { readonly continuity: 'fresh' | 'resumed'; } /** What happened when a caller asked a live runtime to interrupt its turn. */ export interface AgentRuntimeInterruptOutcome { readonly status: 'interrupted' | 'idle'; } /** * The live runtime handle. Nothing is pulled from it: every runtime fact flows * out through the leased state and event sinks. */ export interface AgentRuntime { /** * Launch or restore the native session. A non-null create-context session MUST * restore continuous model context; failure rejects and never silently becomes * fresh. The provider durably publishes its session and ready state before * this resolves. */ start(): Promise; submit(input: AgentRuntimeSubmissionInput): Promise; /** Interrupt the running native turn without starting or stopping the runtime. */ interrupt(): Promise; /** * Fence new input synchronously, terminate the owned runtime, and converge * every `submit` call that started before the fence. This promise MUST NOT * resolve while an already-started admission can still resolve to a newly * accepted {@link RuntimeSubmission}. A stop racing a still-pending start * stops the runtime that appears later; a failed start rolls back all partial * ownership. */ stop(): Promise; } export interface AgentRuntimeProviderConfigReadContext { providerRef: string; /** * The `agents[].id` whose config block is being parsed — a config-internal * alias, not a dispatcher identity. */ agentId: string; file: string; prefix: string; } /** * Optional provider-owned config parsing. A parse/validation failure must throw * (the host fails loud), never return a partially-valid config. Throw the * `RuleViolation` from `@excitedjs/dreamux-utils` for a value this reader * checked and refused, so a host request that carried that value (an online * config replace) reports it as the caller's mistake; any other throw is * reported as an internal failure. */ export interface AgentRuntimeConfigCapability { read(rawConfig: Record, context: AgentRuntimeProviderConfigReadContext): TConfig | Promise; } /** * Optional provider-owned onboarding. Core asks only for host envelope fields * and delegates provider-specific raw config collection to this capability. */ export type AgentRuntimeOnboardCapability = ProviderOnboard>; /** Runtime-specific alias of the shared provider binary check. */ export type AgentRuntimeBinCheck = ProviderBinCheck; /** Runtime-specific alias of the shared provider diagnostic result. */ export type AgentRuntimeDiagnosticResult = ProviderDiagnosticResult; /** Runtime-specific alias of the shared provider diagnostic runner. */ export type AgentRuntimeDiagnosticRunner = ProviderDiagnosticRunner; /** * Per-runtime diagnostic context. Neutral: it carries the runtime instance id, * the provider-parsed config, the resolved env, and the diagnostic `scope`, * rather than a host `DispatcherConfig`. */ export interface AgentRuntimeDiagnosticContext { runtime_id: string; config: TConfig; env: DreamuxEnvironment; scope: ProviderDiagnosticScope; /** * The same neutral path context the create context carries, supplied by * doctor so a provider diagnostic can pre-check placement-sensitive paths * (e.g. validate that a runtime socket would fit the platform budget via * {@link AgentRuntimePathContext.runtimeSocketDirs}). Always supplied by the * host; a provider with no path-dependent checks simply never reads it. */ paths: AgentRuntimePathContext; } /** * Optional provider-owned diagnostics: the provider DECLARES the bin checks * Dreamux core should dedup + execute, and RUNS its own non-bin internal * checks. The host supplies the {@link AgentRuntimeDiagnosticRunner}; the * provider only implements the checks, never the runner. */ export interface AgentRuntimeDiagnosticCapability { binChecks(context: AgentRuntimeDiagnosticContext): AgentRuntimeBinCheck[]; runDiagnostic(context: AgentRuntimeDiagnosticContext, runner: AgentRuntimeDiagnosticRunner): Promise; } /** * The Agent Runtime provider facade: selection, neutral recent Activity reads, * and runtime creation, plus operational capabilities composed as optional * members. A capability with more than one operation is an optional object * (`config`, `onboard`, `diagnostic`) rather than a set of fake always-present * methods; a capability that is a single pure function (`operatorStateRoot`) * is declared directly as an optional method, with no object wrapper to add. * * Registration identity is absent by construction — Core owns the descriptor in * its {@link RegisteredProvider} wrapper, so this interface has no `ref` or * `descriptor` member and a live {@link AgentRuntime} echoes neither. * * A provider resumes from its own opaque session id and nothing else; see * {@link AgentRuntimeIdentity}. */ export interface AgentRuntimeProvider { /** * Read the recent tail of one session's activity. Mandatory: it must work * against an actively growing session — producing useful records before any * completion marker — and against the same session after the live runtime has * closed. The provider enforces its own native read bounds and sets * {@link AgentActivityPage.truncated}; Core checks page and record shape, * record count, and recognized public errors. Text, page, and cursor size * bounds belong to the provider. */ readRecentActivity(query: AgentActivityQuery, context: AgentActivityReadContext): Promise; createRuntime(context: AgentRuntimeCreateContext): Promise; readonly config?: AgentRuntimeConfigCapability; readonly onboard?: AgentRuntimeOnboardCapability; readonly diagnostic?: AgentRuntimeDiagnosticCapability; /** * The provider's own global state directory (e.g. `~/.codex`), with no * per-agent `extra_env` override applied. Host-wide operations that are not * scoped to any one agent (uninstall's directory-safety guard) call this * with the operator's ambient env to learn which directories this provider * owns, instead of the host hard-coding provider-specific path literals. */ operatorStateRoot?(env: DreamuxEnvironment): string; } /** * The default (or `npm:pkg#export`-selected) factory export an Agent Runtime * package ships. */ export type AgentRuntimeProviderFactory = ProviderFactory>; /** Re-export so provider packages can take a logger in their own contexts. */ export type { DreamuxLogger }; //# sourceMappingURL=agent-runtime.d.ts.map