import type { AgentAdapter, AgentInput, AgentMetadata, IsolationPaths, TranscriptEntry } from "../../types/agent.js"; import { type ResolvedCommand } from "../utils/resolve.js"; /** Default timeout for agent execution (10 minutes). */ export declare const DEFAULT_TIMEOUT_MS: number; /** Maximum bytes of stderr to buffer before truncating. */ export declare const MAX_STDERR_BYTES = 100000; /** Grace period between SIGTERM and SIGKILL for non-responsive processes. */ export declare const SIGTERM_TO_SIGKILL_MS = 5000; /** Context handed to `prepare` before the agent process is spawned. */ export interface SetupContext { readonly input: AgentInput; /** Agent's `cwd` — pristine, only scenario-provided files. */ readonly workingDirectory: string; /** Agent's HOME — adapter config dirs (`.codex`, `.claude`, …) live here. */ readonly homeDirectory: string; /** * Authoritative env the child will actually receive. The runner merges * `isolationEnv({ workspace, home })` into `input.env` before calling `run`, * so this already contains e.g. `CODEX_HOME` / `GEMINI_CLI_HOME` pointing * under `homeDirectory`. */ readonly env: Record | undefined; } /** Context available during stdout streaming (`onLine` / `onChunk` / `onEnd`). */ export interface StreamContext { readonly state: State; readonly transcript: TranscriptEntry[]; /** * Feed assistant text to the live token estimator. Call with any text the * agent produced (assistant messages, reasoning, etc.). */ feedAssistantText(text: string): void; } /** Context handed to `getResult` after the agent process exits. */ export interface ResultContext { readonly state: State; readonly transcript: TranscriptEntry[]; readonly exitCode: number; readonly stderr: string; readonly startTime: Date; readonly endTime: Date; } /** Return shape for `getResult`. Merged on top of base-computed metadata. */ export interface AdapterResult { /** * The final assistant-visible result. Use `null` for "no result" — do NOT * return `""`, as the base uses `null` as the sentinel for missing output. */ result: string | null; /** * Metadata overrides. Spread on top of base-computed fields (`startTime`, * `endTime`, `durationMs`, `exitCode`), so e.g. `{ durationMs: upstream }` * replaces the wall-clock duration with a CLI-reported value. */ metadata?: Partial; } /** * A declarative spec for an agent adapter. Pass to `createAgentAdapter` * to get back an `AgentAdapter`. * * `streamConfig` defines how the adapter processes the agent's stdout stream. * It's a discriminated union: `lines` mode hands you parsed NDJSON-style lines, * `aggregate` mode hands you raw stdout chunks. This is encoded at the type * level so `mode` and its handler can never be out of sync. */ export type AgentAdapterSpec = { /** Adapter name. Used in logs, error messages, and `AgentAdapter.name`. */ name: string; /** * CLI binary resolved via `resolveCommand` + npx fallback. Omit if the * adapter gets its command from `input.config.command` at runtime. */ cliCommand?: string; /** Execution timeout. Defaults to `DEFAULT_TIMEOUT_MS` (10 min). */ timeoutMs?: number; /** Stderr buffer cap. Defaults to `MAX_STDERR_BYTES` (100 KB). */ maxStderrBytes?: number; /** Env vars the adapter requires (validated by runner pre-flight). */ requiredEnv?: () => string[]; /** * Detect a usable local CLI login. Runner calls this only when * `requiredEnv` is missing — API keys always take precedence. */ hasLocalSession?: () => boolean | Promise; /** Workspace isolation env vars (merged into child env by runner). */ isolationEnv?: (paths: IsolationPaths) => Record; /** * Pre-spawn side effects: mkdir, MCP config writers, skills writers, etc. * Runs after env is finalized and before the process is spawned. */ prepare?: (ctx: SetupContext) => void | Promise; /** * Override how the CLI command is resolved. Default: prefer the CLI resolved * from `cliCommand` via npx fallback; otherwise fall back to * `input.config.command`; otherwise throw. */ resolveCommand?: (input: AgentInput, resolved: ResolvedCommand | null) => ResolvedCommand; /** Build the CLI arguments for the agent process. Prefix args from command resolution are prepended automatically. */ buildArgs: (input: AgentInput) => string[]; /** Per-run mutable state. Called once per run to create a fresh state bag for `streamConfig` handlers and `getResult`. */ initialState: () => State; /** * How to process the agent's stdout stream. Choose a mode: * * - **`lines`** — readline-based: each line is delivered to `onLine`. Use for agents that emit NDJSON. * - **`aggregate`** — raw chunks: each `data` event is delivered to `onChunk`. Use for agents * that write plain text or when you just need the full output. */ streamConfig: { mode: "lines"; /** Called once per stdout line. Parse JSON inside the callback. */ onLine: (line: string, ctx: StreamContext) => void; /** Called in `finally` after stream ends (success, error, or timeout). */ onEnd?: (ctx: StreamContext) => void; } | { mode: "aggregate"; /** * Called once per stdout chunk. The base automatically feeds each chunk * to the token estimator, so typically just accumulate into state. */ onChunk: (chunk: string, ctx: StreamContext) => void; /** Called after data has fully drained (success, error, or timeout). */ onEnd?: (ctx: StreamContext) => void; }; /** Build the final result + metadata from accumulated state after the process exits. */ getResult: (ctx: ResultContext) => AdapterResult; }; /** * Build an `AgentAdapter` from a declarative spec. The returned adapter owns: * spawn, stdin close, cleanup registration, stderr cap, timeout → * SIGTERM → SIGKILL (with proper timer cleanup), exit promise ordering, raw * output capture, token estimator wiring, and the three outcome branches * (timed-out / non-zero exit with no result / success). * * Error precedence on failure: * 1. `getResult(...).metadata.error` — wins if set * 2. `stderr` — if non-empty * 3. Generic `"Agent process exited with non-zero code"` */ export declare function createAgentAdapter(spec: AgentAdapterSpec): AgentAdapter; //# sourceMappingURL=agent-adapter.d.ts.map