/** * IModelRunner — Unified interface for CLI backends (STORY-011) * * Abstracts over Claude (PersistentCLI) and Codex (app-server) backends * so AgentLoop depends on a contract, not concrete implementations. */ import type { CompletedToolExchange, GatewayToolExecutionContext, PromptCallbacks, PromptResult } from './types.js'; export type { PromptResult } from './types.js'; export type HostToolJsonValue = null | boolean | number | string | HostToolJsonValue[] | { [key: string]: HostToolJsonValue; }; export interface HostToolInputSchema { readonly type: 'object'; readonly properties: Readonly>; readonly required?: readonly string[]; readonly additionalProperties: boolean; } /** Codex app-server dynamic function definition. */ export interface HostToolDefinition { type: 'function'; name: string; description: string; inputSchema: HostToolInputSchema; } /** A dynamic function call received from the model host. */ export interface HostToolCall { callId: string; name: string; input: Record; /** Aborted when the owning model turn fails, times out, or is disconnected. */ signal?: AbortSignal; } /** Serialized result returned to the model host. */ export interface HostToolCallResult { content: string; isError: boolean; stop?: boolean; /** Fail the active model turn after returning this error result to the host. */ abort?: boolean; /** Trusted terminal mutation code; never derived from model-visible text. */ terminalCode?: HostToolTerminalCode; } /** Tools and executor scoped to one prompt run. */ export interface HostToolBridge { readonly tools: readonly HostToolDefinition[]; execute(call: HostToolCall): Promise; } export type HostToolTerminalCode = 'CODE_ACT_MUTATION_COMMITTED_AFTER_ABORT' | 'CODE_ACT_MUTATION_OUTCOME_UNKNOWN'; export declare function isHostToolTerminalCode(value: unknown): value is HostToolTerminalCode; /** Typed transport for a trusted host-tool terminal result across Codex app-server. */ export declare class HostToolTerminalError extends Error { readonly terminalCode: HostToolTerminalCode; readonly completedToolExchanges?: readonly CompletedToolExchange[] | undefined; readonly retryable = false; constructor(terminalCode: HostToolTerminalCode, message: string, completedToolExchanges?: readonly CompletedToolExchange[] | undefined); } /** A host tool deliberately stopped a run without claiming a terminal mutation outcome. */ export declare class HostToolAbortError extends Error { readonly completedToolExchanges: readonly CompletedToolExchange[]; readonly retryable = false; constructor(message: string, completedToolExchanges: readonly CompletedToolExchange[]); } /** * Options passed to prompt() that are backend-agnostic. */ export interface PromptOptions { model?: string; resumeSession?: boolean; allowedTools?: string[]; disallowedTools?: string[]; /** Allow the backend's native single-agent delegation primitive for this route. */ allowSpawnAgent?: boolean; /** Allow the backend's native multi-agent team primitive for this route. */ allowAgentTeams?: boolean; hostToolBridge?: HostToolBridge; systemPrompt?: string; /** Stable source/channel route used by persistent backends across daemon restarts. */ sessionKey?: string; /** Stable identity/rules fingerprint, excluding dynamic conversation context. */ sessionPolicyFingerprint?: string; /** * Pool ROUTING key (SessionPool id) for THIS call, NOT the CLI --session-id. * The pool spawns processes with its own randomUUID() so the CLI never * reloads disk history. Routes this prompt to this session's process * without mutating shared adapter state. */ sessionId?: string; /** * Per-call CLI request timeout (ms) applied when this call spawns a fresh * pooled process. Undefined leaves the pool's construction-time default in * place, so only callers that opt in (operator worker runs) are affected. */ requestTimeout?: number; /** Host-issued authority for this exact prompt attempt; persistent Claude binds it to MCP. */ toolExecutionContext?: GatewayToolExecutionContext | null; /** * Rebuilds the FULL instructions for a backend that has to rehydrate a durable * session on this call. Codex re-anchors the resumed thread with them * (thread/resume accepts baseInstructions) instead of replaying a per-call prompt * as user text. Lazy: backends invoke it only when a resume actually happens, so * live sessions never pay the rebuild. */ resumeInstructions?: () => Promise; } export type SessionPolicyStatus = 'missing' | 'compatible' | 'mismatch'; /** * Runtime metrics collected by a model runner. */ export interface RunnerMetrics { requestCount: number; failureCount: number; avgLatencyMs: number; lastRequestAt: number | null; } /** * Standardized error categories for backend failures. */ export type ModelRunnerErrorCode = 'timeout' | 'crash' | 'context_overflow' | 'auth_failure' | 'rate_limit' | 'unknown'; /** * Typed error thrown by IModelRunner implementations. */ export declare class ModelRunnerError extends Error { readonly code: ModelRunnerErrorCode; readonly retryable: boolean; constructor(message: string, code: ModelRunnerErrorCode, retryable?: boolean); } /** * Backend type identifier. */ export type BackendType = 'claude' | 'codex' | 'cline'; /** * Unified model runner interface. * * Both PersistentCLIAdapter (Claude) and CodexRuntimeProcess (Codex) * implement this contract so AgentLoop is backend-agnostic. */ export interface IModelRunner { /** Backend identifier */ readonly backendType: BackendType; /** Send a prompt and receive a response */ prompt(content: string, callbacks?: PromptCallbacks, options?: PromptOptions): Promise; /** Read-only durable-session policy preflight. Codex uses this to rotate before a request. */ getSessionPolicyStatus?(options: PromptOptions): SessionPolicyStatus; /** Set the session/channel ID */ setSessionId(id: string): void; /** Set or update the system prompt (affects new processes only) */ setSystemPrompt(prompt: string): void; /** * Send a tool result back to the model (Claude-specific). * Optional: Codex backends may leave this unimplemented. */ sendToolResult?(toolUseId: string, result: string, isError?: boolean, callbacks?: PromptCallbacks): Promise; /** Check if the runner is alive and ready to accept prompts */ isHealthy(): boolean; /** Collect runtime metrics */ getMetrics(): RunnerMetrics; /** Gracefully stop all processes */ stop(): void | Promise; } //# sourceMappingURL=model-runner.d.ts.map