import { A as AgentCliHandle, a as AgentCliRuntime, b as AgentCliDefinition, c as AgentCliRuntimeSession, d as AgentCliClient, S as SetModelResult, e as AgentCliPrintConfig, R as RuntimeConfig, C as ContinuationStrategyId, f as AgentCliStartOptions, T as TurnContext, g as ContinuationKeyScope } from './schema-CKrBhnuF.js';
export { h as AgentCliAuth, i as AgentCliCapabilities, j as AgentCliConnectOptions, k as AgentCliContinuation, l as AgentCliFrontmatter, m as AgentCliFsZones, n as AgentCliInstallMethod, o as AgentCliMcpBlock, p as AgentCliMode, q as AgentCliModelEntry, r as AgentCliModels, s as AgentCliOption, t as AgentCliOptionType, u as AgentCliPinnedSessionTuning, v as AgentCliPresetDeclaration, w as AgentCliProtocol, x as AgentCliRouteSelection, y as AgentCliSession, z as AgentCliSessionMode, B as AgentCliSetupPersist, D as AgentCliSetupSkipIf, E as AgentCliSetupStep, F as AgentCliVersionCheck, G as RuntimeConfigInput, H as SetEffortResult, I as SetSessionModeResult, J as SteerOutcome, K as agentCliFrontmatterSchema, L as runtimeConfigSchema } from './schema-CKrBhnuF.js';
import { StreamEvent, AcpMcpServer } from '@agentproto/acp';
export { StreamEvent } from '@agentproto/acp';
import { ChildProcess } from 'node:child_process';
import { SandboxMode } from '@agentproto/command-sandbox';
export { SessionConfigOption, SessionMode } from '@agentproto/acp/client';
import 'zod';

declare const defineAgentCli: (def: AgentCliDefinition) => Readonly<AgentCliDefinition>;
declare function createAgentCliRuntime(definition: AgentCliHandle): AgentCliRuntime;

/**
 * Live-session control surface, built once from a connected protocol arm.
 *
 * `AgentCliRuntimeSession` requires six members beyond
 * `send`/`cancel`/`close`: the three mid-session switches (`setModel`,
 * `setSessionMode`, `setEffort`, SPEC §3.9/§3.4a) and the three
 * read-surface snapshots (`availableConfigOptions`, `availableModes`,
 * `currentModeId`). All six are pure delegation to the arm — none of
 * them touch the child process, the spawn, or the transport.
 *
 * They used to live inline inside `createAgentCliRuntime`, which made
 * them unreachable for any host that builds its OWN session over a
 * different transport. Those hosts exist and are the whole point of
 * `createAcpProtocolArm` being exported: guilde runs one runtime whose
 * child lives in an e2b sandbox and another whose child lives on a
 * remote daemon behind a WS tunnel, both driving the same ACP arm. Every
 * such host had to hand-copy this block, and silently broke the day the
 * interface grew a seventh member.
 *
 * So it lives here, exported, and `createAgentCliRuntime` consumes it
 * like everyone else — one implementation, one place to extend.
 */

/**
 * The slice of `AgentCliRuntimeSession` {@link createArmSessionControls}
 * supplies. Spread it into the session literal alongside the
 * transport-specific `sessionId`/`send`/`cancel`/`close`.
 */
type ArmSessionControls = Pick<AgentCliRuntimeSession, "setModel" | "setSessionMode" | "setEffort" | "availableConfigOptions" | "availableModes" | "currentModeId">;
/**
 * Build the control surface from a CONNECTED arm.
 *
 * Call this after `arm.connect()` has resolved: the read-surface fields
 * are snapshots, so an ACP arm's captured `newSession`/`loadSession`
 * response has to already be populated. Arms that don't model this
 * (print, proprietary) leave the getters undefined and are defaulted
 * here to the same empty/absent shape their `setModel`-style
 * counterparts use for "not supported".
 *
 * Every switch resolves — none throws, none tears down the session, even
 * when the underlying agent rejects the request. See
 * {@link SetModelResult} and friends for the reason vocabulary.
 */
declare function createArmSessionControls(arm: AgentCliClient, definition: AgentCliHandle): ArmSessionControls;
/** See {@link MODEL_SWITCH_ACK_RE}. */
declare function isModelSwitchAcknowledgement(evt: unknown): boolean;
/**
 * Extract the target model id from a plain-text turn that opens with a
 * `/model <id>` control command — whether it arrives through
 * `applyModelCommand`'s dedicated control turn or as an ORDINARY
 * conversational prompt (see {@link MODEL_SWITCH_ACK_RE}'s doc for why the
 * latter matters: it's the case the hermes spawn recipe actually produces).
 */
declare function parseModelSwitchCommand(text: string): string | undefined;
/**
 * Switch the active model via a `/model <id>` control turn, for adapters
 * whose ACP session config doesn't select the model (`models.apply:
 * "command"`, e.g. hermes). The turn is fully drained so the switch
 * completes before the caller's next real turn. Best-effort: a transport
 * failure or a missing acknowledgement is warned and reported as
 * `{applied:false, reason}`, never thrown — the session simply continues
 * on whatever model it already had. Shared by the spawn-time apply
 * (return value ignored there) and the mid-session `setModel("command")`
 * path (return value surfaced to the caller).
 */
declare function applyModelCommand(arm: AgentCliClient, modelId: string): Promise<SetModelResult>;
/**
 * Send a turn and yield the arm's events for it.
 *
 * Re-attaches the recent stderr tail to error events. The ACP layer
 * surfaces a terse `{message: "Invalid params"}`; the child's stderr
 * almost always has a more useful line ("npx claude-agent-acp: not
 * authenticated, run `claude login`"). Hosts read `error.data` when
 * present, falling back to `message` for older payloads.
 */
declare function promptTurn(arm: AgentCliClient, turnId: string, message: unknown): AsyncIterable<StreamEvent>;

/**
 * Agent CLI as a model port — turn ANY AIP-45 agent CLI runtime into a generic
 * `complete({system?, prompt}) → {result}` executor. This is the one bridge that
 * lets the SAME registry (hermes, claude-code, opencode, codex, openclaw, …)
 * back any prompt→completion seam: a report's chapter writer, a corpus
 * distiller, a Mastra tool's judgment step. The executor swaps, the prompts
 * (built by each seam's engine) don't.
 *
 * It drives the CLI over **ACP**: per `complete()` it spawns a fresh session,
 * sends one user turn, concatenates the `text-delta` stream until `turn-end`,
 * then closes. Lives here (not in a product) so seams BELOW the products —
 * `@agentproto/corpus` distill, the CLI — can consume it without importing
 * upward. The runner is injectable so assembly is unit-tested without a binary.
 */

/**
 * The minimal structural model port every seam consumes. Anything with this
 * `complete` shape satisfies the corpus `ReportModelPort` / `DistillPort`-backing
 * model / an AIP `ModelPort` — duck-typed, no nominal coupling.
 */
interface ModelLike {
    complete(req: {
        system?: string;
        prompt: string;
        [k: string]: unknown;
    }): Promise<{
        result: string;
    }>;
}
/**
 * The "file-reading sub-agent" tier — opt-in across every file-IO-capable
 * executor. When `datasetDir` is set the executor is rooted there and granted
 * its own read tools, so instead of being limited to the excerpts a seam quotes
 * in the prompt it can open the primary sources directly and ground first-hand.
 */
interface FileReadingOptions {
    /** Absolute path to the dataset/source root the executor may read from. */
    datasetDir?: string;
}
/** The instruction prepended to a completion when {@link FileReadingOptions.datasetDir} is set. */
declare function datasetPreamble(datasetDir: string): string;
/** Compose system + prompt with an optional source-access preamble (shared by every executor). */
declare function composePrompt(system: string | undefined, prompt: string, datasetDir?: string): string;
/** Provider keys an agent CLI may route through, forwarded from the parent env by default. */
declare const PROVIDER_KEY_ENV: readonly ["OPENROUTER_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY"];
interface AgentCliModelOptions extends FileReadingOptions {
    /**
     * Env handed to the spawned CLI process — the provider key it routes through.
     * Defaults to forwarding {@link PROVIDER_KEY_ENV} from the parent process env.
     */
    env?: Record<string, string>;
    /** Working directory for the CLI process. Defaults to `datasetDir` when set. */
    cwd?: string;
    /** Timeout per completion (ms). Default 5 min. */
    timeoutMs?: number;
    /**
     * Injectable runner (composed prompt → completion text). Defaults to driving
     * the runtime over ACP. Override in tests to avoid the CLI.
     */
    run?: (prompt: string) => Promise<string>;
}
/** Build the env for the spawned CLI: explicit override, else forwarded provider keys. */
declare function resolveCliEnv(opts: Pick<AgentCliModelOptions, "env">): Record<string, string>;
/**
 * Build a {@link ModelLike} backed by an AIP-45 agent-CLI runtime. Hand it any
 * `*Runtime()` from the registry (Hermes, claude-code, opencode, …); per-CLI
 * presets are one-liners over this.
 */
declare function makeAgentCliModel(runtime: AgentCliRuntime, opts?: AgentCliModelOptions): ModelLike;

/**
 * AIP-45 protocol arm: `protocol: "acp"`.
 *
 * Wraps a subprocess's stdio in an `@agentproto/acp` client and
 * exposes the `AgentCliClient` shape the runner consumes. Each
 * `send()` call delegates to a single AcpClientSession.prompt() and
 * forwards the resulting StreamEvent stream.
 */

/**
 * Outcome the host returns to the agent on a permission request.
 *
 * Mirrors the upstream ACP `RequestPermissionResponse` shape EXACTLY —
 * note the doubly-nested `outcome` field: the outer is the response
 * envelope, the inner is the discriminator (string literal, not a
 * `{ type: ... }` object). Get this wrong and the agent silently
 * interprets the response as a refusal ("User refused permission to
 * run tool"), so we type it strictly here.
 *
 *   { outcome: { outcome: "selected", optionId: "..." } }
 *   { outcome: { outcome: "cancelled" } }
 */
type AcpPermissionOutcome = {
    outcome: {
        outcome: "selected";
        optionId: string;
    };
} | {
    outcome: {
        outcome: "cancelled";
    };
};
interface AcpPermissionRequestParams {
    sessionId?: string;
    toolCall?: {
        toolCallId?: string;
        title?: string | null;
        kind?: string | null;
        rawInput?: unknown;
    };
    options?: Array<{
        optionId: string;
        name?: string;
        kind?: string;
    }>;
}
type AcpPermissionHandler = (params: AcpPermissionRequestParams) => Promise<AcpPermissionOutcome> | AcpPermissionOutcome;
/**
 * Default handler: pick the first option whose `kind` starts with
 * `allow_` (Claude Code offers `allow_once` and `allow_always`).
 * Falls back to the first option if none match — keeps the agent
 * unblocked rather than throwing on an unfamiliar option set.
 *
 * Mirrors the trust model of in-process Mastra agents: the user
 * approved the operator binding once; subsequent tool calls don't
 * re-prompt by default. Hosts that want explicit per-call gating
 * pass their own `onPermissionRequest`.
 *
 * NOT safe to use as-is for a `mode: "plan"` session — see
 * `planModePermissionHandler` below.
 */
declare const autoAllowPermissionHandler: AcpPermissionHandler;
/**
 * Permission handler for a session spawned with `mode: "plan"`.
 *
 * `autoAllowPermissionHandler` picks the first `allow_*` option, but for
 * the plan-mode-exit request that option is always an escalation away
 * from plan (`auto`, `acceptEdits`, or `bypassPermissions` depending on
 * what the wrapper offers) — auto-approving it silently defeats the
 * mode the caller asked for (see the regression this fixes: a `plan`
 * session that wrote a file when prompted to). Noted as a known gap in
 * a naive auto-allow handler when #143 shipped the `CLAUDE_CONFIG_DIR`
 * override that makes `mode: "plan"` take effect in the first place;
 * this closes it.
 *
 * Behaves exactly like `autoAllowPermissionHandler` for every other
 * request. For the plan-mode-exit request specifically, it selects the
 * offered `reject_once` option ("No, keep planning") so the wrapper
 * denies the exit with a clean, structured outcome — the tool call
 * fails, the agent stays in plan mode and can keep reasoning or tell
 * the user it's blocked, instead of the turn throwing on a `cancelled`
 * outcome. Falls back to `cancelled` if no `reject_once` option is
 * offered (shouldn't happen with the current wrapper, but a safe
 * default beats guessing an allow).
 *
 * This is a deliberate one-way gate: a plan-mode session driven by this
 * handler can never escalate itself out of plan mode. A caller that
 * wants a human (or a policy engine) to approve that escalation must
 * supply its own `onPermissionRequest` — this handler is only the
 * default for callers that don't.
 */
declare const planModePermissionHandler: AcpPermissionHandler;
interface AcpProtocolOptions {
    child: ChildProcess;
    cwd: string;
    clientInfo?: {
        name: string;
        title?: string;
        version?: string;
    };
    /** Called when the agent asks for permission to run a tool (Write,
     *  Bash, ...). Defaults to `autoAllowPermissionHandler`, or
     *  `planModePermissionHandler` when `requestedMode === "plan"`. Pass a
     *  custom handler to plumb requests through a UI / governance
     *  policy. Throwing or returning a rejected promise bubbles to the
     *  agent as an internal error. */
    onPermissionRequest?: AcpPermissionHandler;
    /**
     * AIP-45 mode requested at spawn (`opts.config.mode` in
     * `define-agent-cli.ts`'s `start()`), if any. Used to pick the default
     * permission handler when `onPermissionRequest` is omitted — see
     * `defaultPermissionHandlerForMode`.
     */
    requestedMode?: string;
    /**
     * When true, permission requests are surfaced as `agent-prompt` StreamEvents
     * and HELD in the daemon's permission inbox rather than auto-answered —
     * forwarded verbatim to `createAcpClient({ permissionHold })`. The
     * `onPermissionRequest` / `requestedMode` handler is bypassed while this is
     * set. Default false (unchanged: requests are auto-answered in-arm).
     */
    permissionHold?: boolean;
}
declare function createAcpProtocolArm(options: AcpProtocolOptions): AgentCliClient;

/**
 * AIP-45 protocol arm: `protocol: "print"`.
 *
 * Drives a headless CLI as one fresh subprocess per turn — no
 * long-lived ACP connection. Simpler than the ACP arm and immune to
 * the stale-proxy race condition: the session object itself never dies
 * between turns; only the per-turn child does.
 *
 * ## Configuration
 *
 * The adapter's `print` manifest block declares the CLI's one-shot
 * surface (flags, output format, event taxonomy). When the block is
 * absent, Claude Code defaults are applied for backward compatibility.
 *
 * ## Session tracking
 *
 * The `sessionId` property starts empty (or pre-seeded from
 * `resumeSessionId`) and is updated after the first successful turn
 * from the wire event that carries the session / thread identifier
 * (Claude: `result.session_id`; Mastra: `result.threadId`).
 * Subsequent turns pass the appropriate resume flag so the CLI
 * rehydrates the conversation.
 */

interface PrintArmOptions {
    bin: string;
    /** Base argv passed to the binary BEFORE print flags and prompt.
     *  Typically permission-mode and model overrides from `composeSpawn`. */
    baseArgs: string[];
    cwd: string;
    env: Record<string, string>;
    /** Pre-seed from `resumeSessionId` so the first turn reattaches. */
    resumeSessionId?: string;
    /** Adapter-declared print surface config. Omit for Claude defaults. */
    printConfig?: AgentCliPrintConfig;
    /**
     * MCP servers to mount into the agent's session. For the `mastracode`
     * print arm (`event_schema: "mastra-jsonl"`) these are written to
     * `<cwd>/.mastracode/mcp.json` before the first turn's spawn (the
     * mastracode CLI has no CLI flag / env var / config-dir override for
     * MCP config — this was exhaustively verified against its source) and
     * restored/removed on `close()`. Ignored for other print schemas
     * (e.g. Claude Code), which don't load MCP config from this path.
     */
    mcpServers?: AcpMcpServer[];
    /** OS-level confinement for the per-turn spawn — see
     *  `AgentCliStartOptions.commandSandbox` in `../types.ts` and
     *  `wrapAgentCliSpawn`'s doc for the fail-closed contract. */
    commandSandbox?: SandboxMode;
    /** Extra write-capable paths beyond the default toolchain set, e.g. the
     *  per-session `CLAUDE_CONFIG_DIR` temp dir set up by the caller. */
    extraWritePaths?: string[];
    /** Extra READ-only paths beyond the confinement boundary — the exact-file
     *  AGENTS.md grant (`AgentCliStartOptions.additionalReadPaths`). READ
     *  exceptions only; never widens writes. */
    extraReadPaths?: string[];
    /** See `AgentCliStartOptions.fsZones`. */
    fsZones?: {
        readOnly: string[];
        writable: string[];
        hidden?: string[];
    };
    /**
     * The explicitly requested model id — when set, a wire event that
     * truthfully reports which model the agent ACTUALLY started on (today:
     * the jcode-ndjson `start` line's `model` field) is checked against it,
     * and a mismatch aborts the turn loudly (child killed, error event)
     * instead of letting the agent run on a model the operator didn't name.
     * Set by `define-agent-cli.ts` only for `routeSelection:
     * "derived-from-model"` adapters with an explicit `model` option — the
     * print-protocol counterpart of its ACP-arm guard. The bug this closes:
     * jcode's CLI silently falls back to its own default on an unknown
     * `--model` id (observed live: `--model totally-bogus-xyz` →
     * `{"type":"start","model":"gpt-5.6-sol","provider":"OpenAI"}`), which
     * for a derived-from-model adapter is a different provider on a
     * different bill. Schemas that never report the started model are
     * unaffected. Compared via {@link printModelMismatch} (basename,
     * `@suffix`/`provider/`-prefix tolerant).
     */
    expectedModel?: string;
}
declare function createPrintSession(opts: PrintArmOptions): AgentCliRuntimeSession;
/**
 * Mutable per-stream state for the jcode NDJSON mapper. Tool arguments
 * arrive as JSON-string `tool_input` deltas between `tool_start` and
 * `tool_exec`, so the pending call accumulates here until complete.
 */
interface JcodeMapperState {
    pending?: {
        id: string;
        name: string;
        input: string;
    };
}
declare function createJcodeMapperState(): JcodeMapperState;
/**
 * Maps a single `jcode run --ndjson` line to this repo's
 * {@link StreamEvent} taxonomy. Wire shape verified against a live
 * `jcode run --ndjson` (2026-08-14):
 *
 *   {type:"start", session_id, model, provider}          → session capture
 *   {type:"status_detail"|"connection_phase"|
 *    "connection_type"|"message_end", …}                 → dropped (noise)
 *   {type:"text_delta", text}                            → text-delta
 *   {type:"tool_start", id, name}                        → open pending call
 *   {type:"tool_input", delta}                           → accumulate args
 *   {type:"tool_exec", id, name}                         → tool-call
 *   {type:"tool_done", id, name, output, error}          → tool-result
 *   {type:"tokens", input, output, cache_read_input, …}  → usage_update
 *   {type:"done", text, session_id, usage}               → turn-end
 *
 * `tokens` fires once per upstream API call (a tool round-trip produces
 * several), so usage arrives as successive updates, not one total.
 */
declare function mapJcodeEvent(evt: Record<string, unknown>, sessionId: string, state: JcodeMapperState): StreamEvent | StreamEvent[] | null;
/**
 * Mutable per-stream state for the Mastra Code event mapper.
 * Mastra Code sends the FULL accumulated text on each `message_update`,
 * so we track the previous length to emit only the new portion.
 *
 * Exported so other Mastra Code protocol arms (e.g. the in-process
 * `proprietary` arm in `@agentproto/adapter-mastracode-inprocess`) can
 * reuse the same event mapper instead of reimplementing it — the wire
 * shape here is `AgentControllerEvent` regardless of whether it arrived
 * over a JSONL subprocess pipe or as a live in-process object.
 */
interface MastraMapperState {
    lastTextLength: number;
}
declare function createMastraMapperState(): MastraMapperState;
/**
 * Maps a single Mastra Code `AgentControllerEvent` (already a plain
 * object — JSON-parsed from a subprocess line, or handed over directly
 * by an in-process arm) to this repo's {@link StreamEvent} taxonomy.
 * `stderrLines` enriches `error` events for arms that have a real
 * subprocess to report on; pass `[]` when there is none (e.g. the
 * in-process arm).
 */
declare function mapMastraEvent(evt: Record<string, unknown>, sessionId: string, stderrLines: string[], state: MastraMapperState): StreamEvent | null;

/**
 * AIP-45 protocol arm: `protocol: "proprietary"`.
 *
 * Loads an NPM adapter package (named in the manifest's `adapter`
 * field) implementing `AgentCliClient`. The package translates the
 * vendor's REPL/proprietary stream into the canonical StreamEvent
 * taxonomy.
 *
 * Unlike the `acp` / `print` arms (built into this package, driving a
 * spawned subprocess), a proprietary arm may not involve a subprocess
 * at all — e.g. an in-process SDK integration. `createAgentCliRuntime`
 * skips the subprocess spawn entirely for `protocol: "proprietary"`
 * (see `define-agent-cli.ts`); this loader has no opinion on whether
 * the loaded package owns a child process, a socket, or nothing.
 *
 * ## Adapter package contract
 *
 * The named package's default export path (its `main`/`exports["."]`)
 * must export a factory:
 *
 *   export function createAgentCliClient(
 *     definition: AgentCliHandle,
 *   ): AgentCliClient | Promise<AgentCliClient>
 *
 * A default export function is accepted as a fallback for adapters
 * that only have one thing to export. The factory receives the full
 * manifest handle so adapter-specific config (models, capabilities,
 * metadata) is available without a second lookup — mirrors the ACP
 * arm receiving `clientInfo` derived from the manifest.
 */

interface ProprietaryProtocolOptions {
    /** NPM package name to load — from manifest.adapter. */
    adapter: string;
    /** Full manifest handle, forwarded verbatim to the loaded factory. */
    definition: AgentCliHandle;
}
declare function createProprietaryProtocolArm(options: ProprietaryProtocolOptions): Promise<AgentCliClient>;

/** Adapters with a verified switch for excluding host instruction files. */
declare function agentCliSupportsHostContextIsolation(adapterId: string): boolean;
/**
 * `claudeMdExcludes` entries covering every instruction file Claude Code
 * would load from a STRICT ancestor of `cwd` (the host monorepo around an
 * installed app). `cwd`'s own CLAUDE.md is deliberately left loadable — it
 * is the app's. Both the lexical and the symlink-resolved ancestor chains
 * are covered, since the SDK may walk either.
 */
declare function hostContextExcludes(cwd: string): string[];

/**
 * Shared converter from this repo's generic `AcpMcpServer[]`
 * (`{ name, transport: "stdio"|"http"|"sse", ref? }`) to the
 * `Record<string, McpServerConfig>` shape mastracode expects — both
 * for the in-process SDK config (`MastraCodeConfig.mcpServers`) and
 * for the file-based `.mastracode/mcp.json` the print arm writes.
 *
 * The target type is structurally identical in both contexts:
 *   - stdio → `{ command, args?, env? }`
 *   - http  → `{ url, headers? }`
 *   - sse   → `{ url }` (mastracode's `McpHttpServerConfig` doc says
 *             it handles SSE through the same `url` field, no separate
 *             discriminator)
 *
 * Neither `McpServerConfig`/`McpStdioServerConfig`/`McpHttpServerConfig`
 * is exported from `mastracode`'s public surface (only `.`, `./tui`,
 * `./acp`, `./headless`, `./plugin` subpaths are exported — no `./mcp`),
 * so we define a local, structurally-matching type here. TS structural
 * typing means a plain object literal shaped correctly type-checks fine
 * against `MastraCodeConfig.mcpServers` without a named import.
 *
 * Mirrors EXACTLY the same transport→field semantics the ACP arm uses
 * in `toAcpMcpServer` (`@agentproto/acp/client`), just flattened to
 * mastracode's keyed-record shape instead of the ACP wire array.
 */

/**
 * mastracode's per-server config entry (structural — not imported from
 * `mastracode`, which doesn't export these types from its public
 * surface). Detected structurally by mastracode: `command` present →
 * stdio, `url` present → http. Both keys present → entry is skipped
 * (mastracode's own validation).
 */
type MastracodeMcpServerConfig = {
    command: string;
    args?: string[];
    env?: Record<string, string>;
} | {
    url: string;
    headers?: Record<string, string>;
};
/**
 * Convert the repo's compact `AcpMcpServer[]` into mastracode's
 * `Record<string, McpServerConfig>` keyed by server name. Returns
 * `undefined` for an empty/missing input so callers can spread the
 * result conditionally (`...(cond ? { mcpServers } : {})`).
 *
 * On key collision the caller's entry simply overwrites — this matches
 * mastracode's own "higher precedence overrides lower, by server name"
 * merge semantics for both the SDK config field and the file-based
 * load-order.
 */
declare function toFileBasedMcpServers(servers: readonly AcpMcpServer[] | undefined): Record<string, MastracodeMcpServerConfig> | undefined;

/**
 * Thrown when `RuntimeConfig` references manifest entries that don't
 * exist or violates a declared constraint (type / enum / bounds). The
 * `code` field lets callers map to friendly UI messages without
 * inspecting the message string.
 */
declare class RuntimeConfigError extends Error {
    readonly code: "unknown_mode" | "unknown_option" | "option_type_mismatch" | "option_enum_violation" | "option_bounds_violation" | "unsupported_continuation" | "model_denied" | "missing_auth_credential";
    readonly path: string;
    constructor(code: RuntimeConfigError["code"], path: string, message: string);
}
/**
 * Resolved spawn args + env. The runtime's `start()` impl merges
 * `env` into the host process env / sandbox env before exec.
 */
interface ComposedSpawn {
    binArgs: string[];
    env: Record<string, string>;
    /**
     * Env keys the active mode AND active options declared for deletion
     * (AgentCliMode.env_unset / AgentCliOption.env_unset). Surfaced
     * pure-side so the runtime's `start()` — which owns the process.env
     * merge — can apply the deletions at the one point where the ambient
     * env is actually present (compose starts from `{}` and can't delete
     * what isn't there yet). Empty when nothing declares any.
     */
    envUnset: string[];
}
/**
 * Optional spawn-time hints that are outside the pure runtime config.
 * Today the only consumer is auth-aware codex model handling: the
 * composer can be told to skip `models.apply:"arg"` when the caller has
 * already determined that the current auth mode must preserve the CLI's
 * default model.
 */
interface ComposeSpawnOptions {
    skipModelArg?: boolean;
}
/**
 * Compose the final spawn args from a manifest + per-call config.
 * Pure — no I/O, no sandbox access, no global state. Safe to call
 * repeatedly with the same input.
 *
 * `config` may be undefined or an empty object — both fall back to
 * the manifest's defaults verbatim (manifest `bin_args`, no mode
 * patch, no option patches). Continuation is not applied here — the
 * `ContinuationStrategy` registry handles that — but we DO validate
 * `config.continuation` against `manifest.continuation.supported` so
 * a misconfigured operator fails fast at compose time, not at the
 * point the strategy tries to acquire a session.
 */
declare function composeSpawn(handle: AgentCliHandle, config?: RuntimeConfig, opts?: ComposeSpawnOptions): ComposedSpawn;
/**
 * Resolve the continuation strategy id to use for this call. Operator
 * config wins; manifest default is the fallback; "none" if neither
 * declares anything (preserves pre-AIP-45-extension behaviour).
 */
declare function resolveContinuationStrategy(handle: AgentCliHandle, config?: RuntimeConfig): ContinuationStrategyId;

/**
 * Legacy AIP-45 mode-id classification — the SINGLE SOURCE for recognizing the
 * gateway (route) and permission (posture) ids that used to be declared as
 * `modes[]` entries before the SPEC §3.4a route/posture extraction.
 *
 * Those entries are now deleted from the adapter manifests: route is derived
 * from the model catalog's `@route` route-identity and posture comes from the
 * harness's own ACP mode registry (`SessionModeState.availableModes`) plus the
 * canonical-posture layer (step 2c). But a caller may STILL pass one of the old
 * ids as `config.mode` — a persisted OPERATOR.md `runtime.config.mode`, a
 * `defaults.adapters.<slug>` binding, or an in-flight request written against
 * the pre-migration manifest. Both the compose path (`composeSpawn`) and the
 * daemon-boundary shim (`@agentproto/runtime`'s `decomposeMode`) therefore need
 * to recognize the legacy vocabulary. `@agentproto/runtime` imports this module
 * rather than re-hardcoding the list, so the id→axis classification stays
 * single-sourced across the driver/runtime boundary (runtime → driver only; the
 * driver stays lean, never depending back on the runtime).
 *
 * This module classifies onto the AXIS only (`route`/`posture`/`context`); the
 * canonical-posture value mapping (`bypass-permissions` → `bypass`, …) is a
 * daemon concept and lives in `@agentproto/runtime`, keyed by
 * {@link LEGACY_POSTURE_MODE_IDS}.
 */
/** Gateway-preset ids that were declared as `kind:"route"` modes. */
declare const LEGACY_GATEWAY_MODE_IDS: ReadonlySet<string>;
/**
 * Permission-profile ids that were declared as `kind:"posture"` modes across
 * the claude-code / codex / opencode adapters (the superset over adapters —
 * some ids are another adapter's vocabulary: codex's `full-access`, opencode's
 * `build`).
 */
declare const LEGACY_POSTURE_MODE_IDS: ReadonlySet<string>;
/**
 * Classify a legacy mode id onto its orthogonal axis. Gateway ids ⇒ `"route"`,
 * known permission ids ⇒ `"posture"`, everything else ⇒ `"context"` — the
 * least-privilege default, so a truly-unknown id never silently grants a
 * posture or reroutes billing (SPEC R4).
 */
declare function inferLegacyModeKind(modeId: string): "posture" | "route" | "context";
/**
 * True when `modeId` is a KNOWN legacy route-or-posture id that used to be a
 * `modes[]` entry but was extracted (SPEC §3.4a) — i.e. it classifies as
 * `route` or `posture`, not `context` and not a genuinely-unknown id.
 * `composeSpawn` degrades such an id to a soft no-op (no env/argv patch: route
 * now resolves from the catalog, posture from the ACP registry / canonical
 * layer) instead of throwing `unknown_mode`; a truly-unknown id — for which
 * this returns `false` — still throws.
 */
declare function isLegacyExtractedModeId(modeId: string): boolean;

/**
 * AIP-45 ContinuationStrategy interface.
 *
 * A continuation strategy decides HOW prior conversation turns reach a
 * spawned CLI on subsequent invocations. Built-ins handle:
 *
 *   - `none`           — fresh session per call (current pre-AIP-45 behaviour)
 *   - `pinned-session` — keep the spawned child alive, reuse across turns
 *   - `transcript`     — caller-supplied preamble prepended to each turn
 *   - `native-resume`  — pass a session id to the CLI's own `--resume` flag
 *
 * Adapter packages MAY register custom strategies via the registry —
 * for example, a Goose-specific strategy that uses MCP-side session
 * load semantics. Custom strategy ids require a follow-up AIP that
 * opens the `ContinuationStrategyId` enum (so the manifest schema can
 * validate them).
 *
 * The strategy owns the SESSION LIFECYCLE: `acquire` returns a session
 * the caller can `send()` against, and `release` decides whether the
 * session lives on (pinned-session) or closes immediately (none). The
 * runner / generation strategy MUST go through `acquire`/`release` —
 * it MUST NOT call `runtime.start()` / `session.close()` directly when
 * a strategy is active.
 */

/**
 * Per-acquire context the strategy gets. The runner builds this from
 * the manifest, the operator config, and the current turn's identity.
 */
interface AcquireContext {
    runtime: AgentCliRuntime;
    /** Already-composed start options (cwd / env / signal / config /
     *  turnCtx). Strategies MAY override individual fields when they
     *  call `runtime.start(...)` themselves. */
    startOptions: AgentCliStartOptions;
    /** Per-call config (already validated against the manifest). */
    config: RuntimeConfig;
    /** Identity context for key derivation. */
    turnCtx: TurnContext;
}
/**
 * Strategies can hint to the runner about how the turn played out so
 * the strategy can decide whether to keep the session alive (normal
 * end), reset its TTL but keep it (transient error), or evict it
 * (dead-process error).
 */
type ReleaseOutcome = {
    kind: "completed";
} | {
    kind: "cancelled";
} | {
    kind: "error";
    reason: "transient" | "fatal";
    message: string;
};
interface ReleaseContext {
    session: AgentCliRuntimeSession;
    outcome: ReleaseOutcome;
    turnCtx: TurnContext;
}
/**
 * The strategy contract. `acquire` returns a session ready for the
 * caller to `send()` against — fresh OR reused. `release` decides
 * the session's fate. Strategies MAY hold internal state (e.g.
 * the pinned-session map) keyed by `turnCtx`.
 */
interface ContinuationStrategy {
    readonly id: ContinuationStrategyId;
    acquire(ctx: AcquireContext): Promise<AgentCliRuntimeSession>;
    release(ctx: ReleaseContext): Promise<void>;
}
/**
 * Derive a stable pin key from `turnCtx` according to the manifest's
 * `pinned_session.key_scope`. Missing scope fields downgrade to a
 * less-specific key with a warning — pinning still works, it just
 * collides more.
 *
 * Returns `null` when EVERY scope field the manifest asked for is
 * missing (no key derivable; strategy falls back to per-spawn).
 */
declare function deriveKeyFromScope(scope: ContinuationKeyScope[], turnCtx: TurnContext): string | null;

/**
 * Continuation strategy registry.
 *
 * Module-scoped singleton — all built-ins are registered at import
 * time, custom strategies (from adapter packages) register via
 * `registerContinuationStrategy`. The runner looks up by id;
 * unregistered ids throw at acquire-time so the caller fails fast
 * with a clear "this strategy id isn't registered" message.
 */

/**
 * Register (or replace) a continuation strategy. Adapter packages
 * MAY register custom strategies on import — but they MUST first
 * land an AIP that opens the `ContinuationStrategyId` enum so the
 * manifest schema accepts the new id.
 */
declare function registerContinuationStrategy(strategy: ContinuationStrategy): void;
declare function getContinuationStrategy(id: ContinuationStrategyId): ContinuationStrategy;
declare function listContinuationStrategies(): ContinuationStrategyId[];

/**
 * `native-resume` strategy — reattach to the agent's own session by id
 * (ACP `loadSession`, MCP equivalent, or argv-style `--resume`).
 *
 * Two-step lifecycle:
 *   1. **acquire**: look up a persisted sessionId for `turnCtx` via
 *      `loadHook`. If found, pass it to `runtime.start` as
 *      `resumeSessionId` so the protocol arm reattaches. If not, spawn
 *      fresh — and after the session is up, capture the new id from
 *      `session.sessionId` and persist it via `saveHook`.
 *   2. **release**: close the spawned process. The session lives in
 *      the agent's storage layer (e.g. Claude Code's JSONL files);
 *      cold-start resume on the next acquire reads from that store.
 *
 * Hooks are registered once per host process via
 * `configureNativeResume({ load, save })`. Without hooks the strategy
 * degrades to per-spawn behaviour with a one-line warning — it's not
 * fatal because the spawn still works, just without continuity.
 *
 * Requires the manifest to declare `capabilities.resumable: true`
 * AND the agent to advertise the matching protocol capability (e.g.
 * ACP `loadSession: true`). The schema enforces the manifest side at
 * validation; runtime capability mismatch surfaces from the protocol
 * arm as the agent's own error.
 */

interface NativeResumeHooks {
    /** Look up a persisted sessionId for the given identity scope. Return
     *  undefined when no prior session exists — strategy spawns fresh. */
    load: (turnCtx: TurnContext) => Promise<string | undefined>;
    /** Persist a freshly-established sessionId so the next cold start
     *  can resume. Called once per "fresh spawn" acquire (not per turn).
     *  Idempotent / upsert semantics expected on the host side. */
    save: (turnCtx: TurnContext, sessionId: string) => Promise<void>;
    /** Optional: drop the persisted entry when a session is detected as
     *  unresumable (agent rejected loadSession with a hard error). */
    forget?: (turnCtx: TurnContext) => Promise<void>;
}
/**
 * Register the host's session-id load/save callbacks. Call once at
 * boot. Subsequent calls overwrite — useful in tests; in prod treat
 * the registration as exclusive.
 */
declare function configureNativeResume(hooks: NativeResumeHooks): void;

/**
 * @agentproto/driver-agent-cli — AIP-45 AGENT-CLI.md `defineAgentCli`
 * reference impl.
 *
 * Spec: https://agentproto.sh/docs/aip-45
 *
 * Authoring paths:
 *   - TS:  `defineAgentCli({...})` → `AgentCliHandle`
 *   - MD:  `parseAgentCliManifest(src) → agentCliFromManifest({...})` → `AgentCliHandle`
 *
 * Runtime: `createAgentCliRuntime(handle)` → spawn binary, dispatch
 * turns through the protocol arm (acp / mcp / proprietary), normalise
 * events to {@link StreamEvent}.
 */
declare const SPEC_NAME: "agentcli-interactive/v1";
declare const SPEC_VERSION: "0.1.0-alpha";

export { type AcpPermissionHandler, type AcpPermissionOutcome, type AcpPermissionRequestParams, type AcquireContext, AgentCliClient, AgentCliDefinition, AgentCliHandle, type AgentCliModelOptions, AgentCliPrintConfig, AgentCliRuntime, AgentCliRuntimeSession, AgentCliStartOptions, type ArmSessionControls, type ComposedSpawn, ContinuationKeyScope, type ContinuationStrategy, ContinuationStrategyId, type FileReadingOptions, type JcodeMapperState, LEGACY_GATEWAY_MODE_IDS, LEGACY_POSTURE_MODE_IDS, type MastraMapperState, type MastracodeMcpServerConfig, type ModelLike, type NativeResumeHooks, PROVIDER_KEY_ENV, type PrintArmOptions, type ProprietaryProtocolOptions, type ReleaseContext, type ReleaseOutcome, RuntimeConfig, RuntimeConfigError, SPEC_NAME, SPEC_VERSION, SetModelResult, TurnContext, agentCliSupportsHostContextIsolation, applyModelCommand, autoAllowPermissionHandler, composePrompt, composeSpawn, configureNativeResume, createAcpProtocolArm, createAgentCliRuntime, createArmSessionControls, createJcodeMapperState, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, datasetPreamble, defineAgentCli, deriveKeyFromScope, getContinuationStrategy, hostContextExcludes, inferLegacyModeKind, isLegacyExtractedModeId, isModelSwitchAcknowledgement, listContinuationStrategies, makeAgentCliModel, mapJcodeEvent, mapMastraEvent, parseModelSwitchCommand, planModePermissionHandler, promptTurn, registerContinuationStrategy, resolveCliEnv, resolveContinuationStrategy, toFileBasedMcpServers };
