@agentproto/driver-agent-cli 0.4.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/model.ts","../src/continuation/strategies/none.ts","../src/continuation/types.ts","../src/continuation/strategies/pinned-session.ts","../src/continuation/strategies/transcript.ts","../src/continuation/strategies/native-resume.ts","../src/continuation/registry.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Agent CLI as a model port — turn ANY AIP-45 agent CLI runtime into a generic\n * `complete({system?, prompt}) → {result}` executor. This is the one bridge that\n * lets the SAME registry (hermes, claude-code, opencode, codex, openclaw, …)\n * back any prompt→completion seam: a report's chapter writer, a corpus\n * distiller, a Mastra tool's judgment step. The executor swaps, the prompts\n * (built by each seam's engine) don't.\n *\n * It drives the CLI over **ACP**: per `complete()` it spawns a fresh session,\n * sends one user turn, concatenates the `text-delta` stream until `turn-end`,\n * then closes. Lives here (not in a product) so seams BELOW the products —\n * `@agentproto/corpus` distill, the CLI — can consume it without importing\n * upward. The runner is injectable so assembly is unit-tested without a binary.\n */\n\nimport type { AgentCliRuntime } from \"./types.js\"\n\n/**\n * The minimal structural model port every seam consumes. Anything with this\n * `complete` shape satisfies the corpus `ReportModelPort` / `DistillPort`-backing\n * model / an AIP `ModelPort` — duck-typed, no nominal coupling.\n */\nexport interface ModelLike {\n complete(req: {\n system?: string\n prompt: string\n [k: string]: unknown\n }): Promise<{ result: string }>\n}\n\n/**\n * The \"file-reading sub-agent\" tier — opt-in across every file-IO-capable\n * executor. When `datasetDir` is set the executor is rooted there and granted\n * its own read tools, so instead of being limited to the excerpts a seam quotes\n * in the prompt it can open the primary sources directly and ground first-hand.\n */\nexport interface FileReadingOptions {\n /** Absolute path to the dataset/source root the executor may read from. */\n datasetDir?: string\n}\n\n/** The instruction prepended to a completion when {@link FileReadingOptions.datasetDir} is set. */\nexport function datasetPreamble(datasetDir: string): string {\n return (\n `You have direct read access to the source files under \\`${datasetDir}\\` ` +\n `(e.g. \\`sources/\\` raw captures, \\`entries/\\` refined notes). Use your ` +\n `file-reading tools to consult the primary sources directly when grounding ` +\n `claims — do not rely only on the excerpts quoted in this prompt.`\n )\n}\n\n/** Compose system + prompt with an optional source-access preamble (shared by every executor). */\nexport function composePrompt(\n system: string | undefined,\n prompt: string,\n datasetDir?: string\n): string {\n const head = datasetDir ? `${datasetPreamble(datasetDir)}\\n\\n` : \"\"\n return system ? `${head}${system}\\n\\n${prompt}` : `${head}${prompt}`\n}\n\n/** Provider keys an agent CLI may route through, forwarded from the parent env by default. */\nexport const PROVIDER_KEY_ENV = [\n \"OPENROUTER_API_KEY\",\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n] as const\n\nexport interface AgentCliModelOptions extends FileReadingOptions {\n /**\n * Env handed to the spawned CLI process — the provider key it routes through.\n * Defaults to forwarding {@link PROVIDER_KEY_ENV} from the parent process env.\n */\n env?: Record<string, string>\n /** Working directory for the CLI process. Defaults to `datasetDir` when set. */\n cwd?: string\n /** Timeout per completion (ms). Default 5 min. */\n timeoutMs?: number\n /**\n * Injectable runner (composed prompt → completion text). Defaults to driving\n * the runtime over ACP. Override in tests to avoid the CLI.\n */\n run?: (prompt: string) => Promise<string>\n}\n\n/** Build the env for the spawned CLI: explicit override, else forwarded provider keys. */\nexport function resolveCliEnv(\n opts: Pick<AgentCliModelOptions, \"env\">\n): Record<string, string> {\n if (opts.env) return opts.env\n const env: Record<string, string> = {}\n for (const k of PROVIDER_KEY_ENV) {\n const v = process.env[k]\n if (v) env[k] = v\n }\n return env\n}\n\n/** Drive one ACP turn on `runtime`, concatenating the text deltas. */\nasync function driveTurn(\n runtime: AgentCliRuntime,\n prompt: string,\n opts: AgentCliModelOptions\n): Promise<string> {\n const controller = new AbortController()\n const timer = setTimeout(\n () => controller.abort(),\n opts.timeoutMs ?? 5 * 60 * 1000\n )\n\n const cwd = opts.cwd ?? opts.datasetDir\n const session = await runtime.start({\n env: resolveCliEnv(opts),\n signal: controller.signal,\n ...(cwd ? { cwd } : {}),\n })\n\n try {\n let text = \"\"\n for await (const evt of session.send({ role: \"user\", content: prompt })) {\n if (evt.kind === \"text-delta\") {\n text += evt.text\n } else if (evt.kind === \"error\") {\n throw new Error(`${runtime.definition.id} model: ${evt.error.message}`)\n } else if (evt.kind === \"turn-end\") {\n if (evt.reason !== \"completed\")\n throw new Error(`${runtime.definition.id} model: turn ${evt.reason}`)\n break\n }\n }\n if (controller.signal.aborted)\n throw new Error(`${runtime.definition.id} model: timed out`)\n return text.trim()\n } finally {\n clearTimeout(timer)\n await session.close()\n }\n}\n\n/**\n * Build a {@link ModelLike} backed by an AIP-45 agent-CLI runtime. Hand it any\n * `*Runtime()` from the registry (Hermes, claude-code, opencode, …); per-CLI\n * presets are one-liners over this.\n */\nexport function makeAgentCliModel(\n runtime: AgentCliRuntime,\n opts: AgentCliModelOptions = {}\n): ModelLike {\n const run = opts.run ?? ((prompt: string) => driveTurn(runtime, prompt, opts))\n return {\n async complete({ system, prompt }) {\n return {\n result: await run(composePrompt(system, prompt, opts.datasetDir)),\n }\n },\n }\n}\n","/**\n * `none` strategy — pre-AIP-45-extension behaviour.\n *\n * Spawn a fresh session per acquire; close it on release. No state,\n * no reuse. The default when a manifest declares no `continuation`\n * block (back-compat for adapters that haven't been updated).\n */\n\nimport type { ContinuationStrategy } from \"../types.js\"\n\nexport const noneStrategy: ContinuationStrategy = {\n id: \"none\",\n async acquire(ctx) {\n return ctx.runtime.start(ctx.startOptions)\n },\n async release(ctx) {\n await ctx.session.close()\n },\n}\n","/**\n * AIP-45 ContinuationStrategy interface.\n *\n * A continuation strategy decides HOW prior conversation turns reach a\n * spawned CLI on subsequent invocations. Built-ins handle:\n *\n * - `none` — fresh session per call (current pre-AIP-45 behaviour)\n * - `pinned-session` — keep the spawned child alive, reuse across turns\n * - `transcript` — caller-supplied preamble prepended to each turn\n * - `native-resume` — pass a session id to the CLI's own `--resume` flag\n *\n * Adapter packages MAY register custom strategies via the registry —\n * for example, a Goose-specific strategy that uses MCP-side session\n * load semantics. Custom strategy ids require a follow-up AIP that\n * opens the `ContinuationStrategyId` enum (so the manifest schema can\n * validate them).\n *\n * The strategy owns the SESSION LIFECYCLE: `acquire` returns a session\n * the caller can `send()` against, and `release` decides whether the\n * session lives on (pinned-session) or closes immediately (none). The\n * runner / generation strategy MUST go through `acquire`/`release` —\n * it MUST NOT call `runtime.start()` / `session.close()` directly when\n * a strategy is active.\n */\n\nimport type {\n AgentCliRuntime,\n AgentCliRuntimeSession,\n AgentCliStartOptions,\n ContinuationKeyScope,\n ContinuationStrategyId,\n RuntimeConfig,\n TurnContext,\n} from \"../types.js\"\n\n/**\n * Per-acquire context the strategy gets. The runner builds this from\n * the manifest, the operator config, and the current turn's identity.\n */\nexport interface AcquireContext {\n runtime: AgentCliRuntime\n /** Already-composed start options (cwd / env / signal / config /\n * turnCtx). Strategies MAY override individual fields when they\n * call `runtime.start(...)` themselves. */\n startOptions: AgentCliStartOptions\n /** Per-call config (already validated against the manifest). */\n config: RuntimeConfig\n /** Identity context for key derivation. */\n turnCtx: TurnContext\n}\n\n/**\n * Strategies can hint to the runner about how the turn played out so\n * the strategy can decide whether to keep the session alive (normal\n * end), reset its TTL but keep it (transient error), or evict it\n * (dead-process error).\n */\nexport type ReleaseOutcome =\n | { kind: \"completed\" }\n | { kind: \"cancelled\" }\n | { kind: \"error\"; reason: \"transient\" | \"fatal\"; message: string }\n\nexport interface ReleaseContext {\n session: AgentCliRuntimeSession\n outcome: ReleaseOutcome\n turnCtx: TurnContext\n}\n\n/**\n * The strategy contract. `acquire` returns a session ready for the\n * caller to `send()` against — fresh OR reused. `release` decides\n * the session's fate. Strategies MAY hold internal state (e.g.\n * the pinned-session map) keyed by `turnCtx`.\n */\nexport interface ContinuationStrategy {\n readonly id: ContinuationStrategyId\n acquire(ctx: AcquireContext): Promise<AgentCliRuntimeSession>\n release(ctx: ReleaseContext): Promise<void>\n}\n\n/**\n * Derive a stable pin key from `turnCtx` according to the manifest's\n * `pinned_session.key_scope`. Missing scope fields downgrade to a\n * less-specific key with a warning — pinning still works, it just\n * collides more.\n *\n * Returns `null` when EVERY scope field the manifest asked for is\n * missing (no key derivable; strategy falls back to per-spawn).\n */\nexport function deriveKeyFromScope(\n scope: ContinuationKeyScope[],\n turnCtx: TurnContext\n): string | null {\n const parts: string[] = []\n for (const s of scope) {\n const v = turnCtx[s]\n if (v) parts.push(`${s}=${v}`)\n }\n return parts.length === 0 ? null : parts.join(\"|\")\n}\n","/**\n * `pinned-session` strategy — keep the spawned child alive across\n * turns so the CLI's in-memory model context carries over.\n *\n * Suitable for manifests that declare `session.mode: persistent` AND\n * `context_carryover: true` (Claude Code, OpenCode, ...). Acquires\n * either reuse a live pinned session or spawn fresh and pin; releases\n * keep the session alive and reset its idle TTL. The strategy\n * auto-evicts after the manifest's `pinned_session.idle_timeout_ms`.\n *\n * The pin key is derived from `turnCtx` according to the manifest's\n * `pinned_session.key_scope` (default: `[conversation, operator]` —\n * different conversations and different operators each get their own\n * child process).\n *\n * Lost on process restart. DB-backed pin persistence is a follow-up\n * (track sessionId in `cli_sessions` table, then optionally fall back\n * to native-resume / transcript on restart).\n */\n\nimport type {\n AgentCliRuntimeSession,\n AgentCliRuntime,\n AgentCliStartOptions,\n} from \"../../types.js\"\nimport type { ContinuationStrategy } from \"../types.js\"\nimport { deriveKeyFromScope } from \"../types.js\"\n\ninterface PinnedEntry {\n session: AgentCliRuntimeSession\n /** Cached so retry-after-eviction can recreate without re-resolving\n * the runtime entry from outside. */\n runtime: AgentCliRuntime\n /** Cached so eviction-and-retry uses the same start options. */\n startOptions: AgentCliStartOptions\n idleTimer: ReturnType<typeof setTimeout> | null\n}\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000\n\nconst pins = new Map<string, PinnedEntry>()\n\nfunction clearIdleTimer(entry: PinnedEntry): void {\n if (entry.idleTimer) {\n clearTimeout(entry.idleTimer)\n entry.idleTimer = null\n }\n}\n\nfunction scheduleIdleEviction(\n key: string,\n entry: PinnedEntry,\n idleTimeoutMs: number\n): void {\n clearIdleTimer(entry)\n entry.idleTimer = setTimeout(() => {\n pins.delete(key)\n entry.session.close().catch(err => {\n console.warn(\n `[pinned-session] idle close failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n })\n console.log(\n `[pinned-session] ${key} idle ${idleTimeoutMs / 60_000}m → closed`\n )\n }, idleTimeoutMs)\n // Don't keep the event loop alive just for the idle close — the\n // child will be reaped on process exit anyway. Without `unref`\n // a stale pin would block graceful shutdown.\n entry.idleTimer.unref?.()\n}\n\nfunction evictPin(key: string): void {\n const entry = pins.get(key)\n if (!entry) return\n clearIdleTimer(entry)\n pins.delete(key)\n entry.session.close().catch(err => {\n console.warn(\n `[pinned-session] evict close failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n })\n}\n\nexport const pinnedSessionStrategy: ContinuationStrategy = {\n id: \"pinned-session\",\n\n async acquire(ctx) {\n const tuning = ctx.runtime.definition.continuation?.pinned_session\n const scope = tuning?.key_scope ?? [\"conversation\", \"operator\"]\n const key = deriveKeyFromScope(scope, ctx.turnCtx)\n const idleTimeoutMs = tuning?.idle_timeout_ms ?? DEFAULT_IDLE_TIMEOUT_MS\n\n if (key === null) {\n // No identity to pin against — fall back to per-spawn behaviour.\n // Warn so the host learns to populate turnCtx.\n console.warn(\n `[pinned-session] turnCtx has no fields matching key_scope ${JSON.stringify(scope)}; falling back to per-spawn (no pin).`\n )\n return ctx.runtime.start(ctx.startOptions)\n }\n\n const existing = pins.get(key)\n if (existing) {\n // Cancel the idle timer — this turn is reusing the pin.\n clearIdleTimer(existing)\n return existing.session\n }\n\n const session = await ctx.runtime.start(ctx.startOptions)\n const entry: PinnedEntry = {\n session,\n runtime: ctx.runtime,\n startOptions: ctx.startOptions,\n idleTimer: null,\n }\n pins.set(key, entry)\n scheduleIdleEviction(key, entry, idleTimeoutMs)\n return session\n },\n\n async release(ctx) {\n // Find the entry by identity — ReleaseContext doesn't carry `runtime`,\n // so we match by session reference. Acceptable since the pin map is small.\n let foundKey: string | null = null\n for (const [k, e] of pins) {\n if (e.session === ctx.session) {\n foundKey = k\n break\n }\n }\n\n if (!foundKey) {\n // Session wasn't pinned (per-spawn fallback path) — close it\n // like the `none` strategy would.\n await ctx.session.close()\n return\n }\n\n const entry = pins.get(foundKey)!\n const tuning = entry.runtime.definition.continuation?.pinned_session\n const idleTimeoutMs = tuning?.idle_timeout_ms ?? DEFAULT_IDLE_TIMEOUT_MS\n\n // Fatal errors → evict so the next turn re-spawns. Transient\n // errors and normal completion → reset the idle TTL and keep.\n // Cancelled (user aborted) is treated like normal completion —\n // the user wanted to stop this turn, not the whole session.\n if (ctx.outcome.kind === \"error\" && ctx.outcome.reason === \"fatal\") {\n evictPin(foundKey)\n return\n }\n\n scheduleIdleEviction(foundKey, entry, idleTimeoutMs)\n },\n}\n\n/**\n * Test helper — drop all pinned entries and clear timers. Not part\n * of the public API; exposed under `__test__` so tests can reset the\n * module's singleton state between runs.\n */\nexport const __test__ = {\n resetPins(): void {\n for (const [k] of pins) evictPin(k)\n },\n pinCount(): number {\n return pins.size\n },\n}\n","/**\n * `transcript` strategy — works for any CLI, including those with\n * `resumable: false` and ephemeral sessions.\n *\n * The driver doesn't know about Mastra memory or the host's\n * conversation log — that's the host's domain. The host supplies the\n * preamble at acquire-time via `startOptions.config.options` (the\n * convention is option id `__transcript`, see below) and the strategy\n * is otherwise identical to `none` — fresh session per acquire,\n * close on release.\n *\n * In practice the host does the prepending itself before calling\n * `runtime.start` (it controls the `message` text). This strategy\n * exists mostly as a NAMED policy choice in the manifest — declaring\n * it tells the host \"use the transcript-replay path for this CLI\"\n * without the host needing to inspect capabilities.\n *\n * Token-costly but stateless and survives API restarts.\n */\n\nimport type { ContinuationStrategy } from \"../types.js\"\n\nexport const transcriptStrategy: ContinuationStrategy = {\n id: \"transcript\",\n async acquire(ctx) {\n return ctx.runtime.start(ctx.startOptions)\n },\n async release(ctx) {\n await ctx.session.close()\n },\n}\n","/**\n * `native-resume` strategy — reattach to the agent's own session by id\n * (ACP `loadSession`, MCP equivalent, or argv-style `--resume`).\n *\n * Two-step lifecycle:\n * 1. **acquire**: look up a persisted sessionId for `turnCtx` via\n * `loadHook`. If found, pass it to `runtime.start` as\n * `resumeSessionId` so the protocol arm reattaches. If not, spawn\n * fresh — and after the session is up, capture the new id from\n * `session.sessionId` and persist it via `saveHook`.\n * 2. **release**: close the spawned process. The session lives in\n * the agent's storage layer (e.g. Claude Code's JSONL files);\n * cold-start resume on the next acquire reads from that store.\n *\n * Hooks are registered once per host process via\n * `configureNativeResume({ load, save })`. Without hooks the strategy\n * degrades to per-spawn behaviour with a one-line warning — it's not\n * fatal because the spawn still works, just without continuity.\n *\n * Requires the manifest to declare `capabilities.resumable: true`\n * AND the agent to advertise the matching protocol capability (e.g.\n * ACP `loadSession: true`). The schema enforces the manifest side at\n * validation; runtime capability mismatch surfaces from the protocol\n * arm as the agent's own error.\n */\n\nimport type { ContinuationStrategy, AcquireContext } from \"../types.js\"\nimport { deriveKeyFromScope } from \"../types.js\"\nimport type { TurnContext } from \"../../types.js\"\n\nexport interface NativeResumeHooks {\n /** Look up a persisted sessionId for the given identity scope. Return\n * undefined when no prior session exists — strategy spawns fresh. */\n load: (turnCtx: TurnContext) => Promise<string | undefined>\n /** Persist a freshly-established sessionId so the next cold start\n * can resume. Called once per \"fresh spawn\" acquire (not per turn).\n * Idempotent / upsert semantics expected on the host side. */\n save: (turnCtx: TurnContext, sessionId: string) => Promise<void>\n /** Optional: drop the persisted entry when a session is detected as\n * unresumable (agent rejected loadSession with a hard error). */\n forget?: (turnCtx: TurnContext) => Promise<void>\n}\n\nlet _hooks: NativeResumeHooks | null = null\n\n/**\n * Register the host's session-id load/save callbacks. Call once at\n * boot. Subsequent calls overwrite — useful in tests; in prod treat\n * the registration as exclusive.\n */\nexport function configureNativeResume(hooks: NativeResumeHooks): void {\n _hooks = hooks\n}\n\n/** Reset to no-hooks. Test helper; not part of public API. */\nexport function __resetNativeResumeForTests(): void {\n _hooks = null\n}\n\nexport const nativeResumeStrategy: ContinuationStrategy = {\n id: \"native-resume\",\n async acquire(ctx: AcquireContext) {\n if (!_hooks) {\n console.warn(\n \"[native-resume] no hooks registered (call configureNativeResume at boot); falling back to per-spawn — no continuity.\"\n )\n return ctx.runtime.start(ctx.startOptions)\n }\n // Use the same key-derivation as pinned-session so a host can\n // declare its scope ONCE in the manifest (`continuation.pinned_session.key_scope`)\n // and have both strategies key off the same identity. Native-resume\n // doesn't have its own key_scope today; it inherits.\n const scope =\n ctx.runtime.definition.continuation?.pinned_session?.key_scope ?? [\n \"conversation\",\n \"operator\",\n ]\n const key = deriveKeyFromScope(scope, ctx.turnCtx)\n if (key === null) {\n console.warn(\n `[native-resume] turnCtx has no fields matching key_scope ${JSON.stringify(scope)}; falling back to per-spawn (no resume).`\n )\n return ctx.runtime.start(ctx.startOptions)\n }\n\n const existingId = await _hooks.load(ctx.turnCtx).catch(err => {\n console.warn(\n `[native-resume] load hook failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n return undefined\n })\n\n let session\n let resumed = false\n if (existingId) {\n try {\n session = await ctx.runtime.start({\n ...ctx.startOptions,\n resumeSessionId: existingId,\n })\n resumed = true\n } catch (err) {\n // Most likely the agent rejected the id (session expired,\n // wiped, mismatched cwd). Drop the stale pin and spawn fresh\n // so the user gets continuity going forward instead of being\n // stuck on a dead reference.\n console.warn(\n `[native-resume] resume failed for ${key} (id=${existingId.slice(0, 12)}…), starting fresh:`,\n err instanceof Error ? err.message : err\n )\n if (_hooks.forget) {\n await _hooks.forget(ctx.turnCtx).catch(() => undefined)\n }\n session = await ctx.runtime.start(ctx.startOptions)\n }\n } else {\n session = await ctx.runtime.start(ctx.startOptions)\n }\n\n // Persist the established id when this is a NEW session (resume\n // path keeps the same id we already have, no need to re-save).\n // The runtime guarantees session.sessionId reflects the protocol\n // session id when the arm exposes it.\n if (!resumed && session.sessionId) {\n await _hooks.save(ctx.turnCtx, session.sessionId).catch(err => {\n console.warn(\n `[native-resume] save hook failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n })\n }\n return session\n },\n\n async release(ctx) {\n // The protocol session lives in the agent's own storage; closing\n // the spawned subprocess is fine — `loadSession` on the next\n // acquire reattaches via the persisted id.\n await ctx.session.close()\n },\n}\n","/**\n * Continuation strategy registry.\n *\n * Module-scoped singleton — all built-ins are registered at import\n * time, custom strategies (from adapter packages) register via\n * `registerContinuationStrategy`. The runner looks up by id;\n * unregistered ids throw at acquire-time so the caller fails fast\n * with a clear \"this strategy id isn't registered\" message.\n */\n\nimport type { ContinuationStrategyId } from \"../types.js\"\nimport type { ContinuationStrategy } from \"./types.js\"\nimport { noneStrategy } from \"./strategies/none.js\"\nimport { pinnedSessionStrategy } from \"./strategies/pinned-session.js\"\nimport { transcriptStrategy } from \"./strategies/transcript.js\"\nimport { nativeResumeStrategy } from \"./strategies/native-resume.js\"\n\nconst registry = new Map<ContinuationStrategyId, ContinuationStrategy>()\n\n/**\n * Register (or replace) a continuation strategy. Adapter packages\n * MAY register custom strategies on import — but they MUST first\n * land an AIP that opens the `ContinuationStrategyId` enum so the\n * manifest schema accepts the new id.\n */\nexport function registerContinuationStrategy(\n strategy: ContinuationStrategy\n): void {\n registry.set(strategy.id, strategy)\n}\n\nexport function getContinuationStrategy(\n id: ContinuationStrategyId\n): ContinuationStrategy {\n const s = registry.get(id)\n if (!s) {\n throw new Error(\n `[agent-cli] No continuation strategy registered for id '${id}'. Built-ins: ${Array.from(registry.keys()).join(\", \")}.`\n )\n }\n return s\n}\n\nexport function listContinuationStrategies(): ContinuationStrategyId[] {\n return Array.from(registry.keys())\n}\n\n// Register built-ins eagerly at module load so any importer of the\n// registry sees them. Custom strategies layer on top.\nregisterContinuationStrategy(noneStrategy)\nregisterContinuationStrategy(pinnedSessionStrategy)\nregisterContinuationStrategy(transcriptStrategy)\nregisterContinuationStrategy(nativeResumeStrategy)\n","/**\n * @agentproto/driver-agent-cli — AIP-45 AGENT-CLI.md `defineAgentCli`\n * reference impl.\n *\n * Spec: https://agentproto.sh/docs/aip-45\n *\n * Authoring paths:\n * - TS: `defineAgentCli({...})` → `AgentCliHandle`\n * - MD: `parseAgentCliManifest(src) → agentCliFromManifest({...})` → `AgentCliHandle`\n *\n * Runtime: `createAgentCliRuntime(handle)` → spawn binary, dispatch\n * turns through the protocol arm (acp / mcp / proprietary), normalise\n * events to {@link StreamEvent}.\n */\n\nexport const SPEC_NAME = \"agentcli-interactive/v1\" as const\nexport const SPEC_VERSION = \"0.1.0-alpha\" as const\n\nexport {\n defineAgentCli,\n createAgentCliRuntime,\n} from \"./define-agent-cli.js\"\n// Agent CLI → generic model port: one executor backing every prompt→completion\n// seam (report writer, corpus distiller, Mastra judgment step) over any AIP-45 CLI.\nexport {\n makeAgentCliModel,\n resolveCliEnv,\n composePrompt,\n datasetPreamble,\n PROVIDER_KEY_ENV,\n} from \"./model.js\"\nexport type {\n ModelLike,\n FileReadingOptions,\n AgentCliModelOptions,\n} from \"./model.js\"\n// Exposed so callers can build a sandbox-resident `AgentCliRuntime`\n// against the same protocol layer the host-spawn factory uses, by\n// passing a `ChildProcess`-shaped duck whose stdio is bridged to a\n// remote subprocess (e2b sandbox, ssh, etc.). See guilde's\n// `cli-session-spawn/sandbox-runtime.ts` for a worked example.\nexport {\n createAcpProtocolArm,\n autoAllowPermissionHandler,\n planModePermissionHandler,\n type AcpPermissionHandler,\n type AcpPermissionOutcome,\n type AcpPermissionRequestParams,\n} from \"./protocol/acp-client.js\"\nexport {\n createPrintSession,\n mapMastraEvent,\n createMastraMapperState,\n type PrintArmOptions,\n type MastraMapperState,\n} from \"./protocol/print-arm.js\"\n// Generic proprietary-protocol arm loader — dynamically imports the\n// manifest's `adapter` package. Exported so proprietary adapter packages\n// (and their tests) can drive the same loader `createAgentCliRuntime`\n// uses, without duplicating the load-and-validate logic.\nexport {\n createProprietaryProtocolArm,\n type ProprietaryProtocolOptions,\n} from \"./protocol/proprietary.js\"\nexport {\n agentCliFrontmatterSchema,\n runtimeConfigSchema,\n type AgentCliFrontmatter,\n type RuntimeConfigInput,\n} from \"./schema.js\"\nexport {\n toFileBasedMcpServers,\n type MastracodeMcpServerConfig,\n} from \"./mcp-servers.js\"\nexport {\n composeSpawn,\n resolveContinuationStrategy,\n RuntimeConfigError,\n type ComposedSpawn,\n} from \"./manifest/compose.js\"\nexport {\n registerContinuationStrategy,\n getContinuationStrategy,\n listContinuationStrategies,\n} from \"./continuation/registry.js\"\nexport {\n configureNativeResume,\n type NativeResumeHooks,\n} from \"./continuation/strategies/native-resume.js\"\nexport {\n deriveKeyFromScope,\n type ContinuationStrategy,\n type AcquireContext,\n type ReleaseContext,\n type ReleaseOutcome,\n} from \"./continuation/types.js\"\nexport type {\n AgentCliDefinition,\n AgentCliHandle,\n AgentCliProtocol,\n AgentCliSessionMode,\n AgentCliClient,\n AgentCliConnectOptions,\n AgentCliRuntime,\n AgentCliRuntimeSession,\n AgentCliStartOptions,\n AgentCliCapabilities,\n AgentCliInstallMethod,\n AgentCliVersionCheck,\n AgentCliAuth,\n AgentCliSetupStep,\n AgentCliSetupSkipIf,\n AgentCliSetupPersist,\n AgentCliSession,\n AgentCliModels,\n AgentCliMcpBlock,\n AgentCliMode,\n AgentCliOption,\n AgentCliOptionType,\n AgentCliPresetDeclaration,\n AgentCliContinuation,\n AgentCliPinnedSessionTuning,\n AgentCliPrintConfig,\n ContinuationStrategyId,\n ContinuationKeyScope,\n RuntimeConfig,\n TurnContext,\n StreamEvent,\n} from \"./types.js\"\n"]}
1
+ {"version":3,"sources":["../src/model.ts","../src/continuation/strategies/none.ts","../src/continuation/types.ts","../src/continuation/strategies/pinned-session.ts","../src/continuation/strategies/transcript.ts","../src/continuation/strategies/native-resume.ts","../src/continuation/registry.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Agent CLI as a model port — turn ANY AIP-45 agent CLI runtime into a generic\n * `complete({system?, prompt}) → {result}` executor. This is the one bridge that\n * lets the SAME registry (hermes, claude-code, opencode, codex, openclaw, …)\n * back any prompt→completion seam: a report's chapter writer, a corpus\n * distiller, a Mastra tool's judgment step. The executor swaps, the prompts\n * (built by each seam's engine) don't.\n *\n * It drives the CLI over **ACP**: per `complete()` it spawns a fresh session,\n * sends one user turn, concatenates the `text-delta` stream until `turn-end`,\n * then closes. Lives here (not in a product) so seams BELOW the products —\n * `@agentproto/corpus` distill, the CLI — can consume it without importing\n * upward. The runner is injectable so assembly is unit-tested without a binary.\n */\n\nimport type { AgentCliRuntime } from \"./types.js\"\n\n/**\n * The minimal structural model port every seam consumes. Anything with this\n * `complete` shape satisfies the corpus `ReportModelPort` / `DistillPort`-backing\n * model / an AIP `ModelPort` — duck-typed, no nominal coupling.\n */\nexport interface ModelLike {\n complete(req: {\n system?: string\n prompt: string\n [k: string]: unknown\n }): Promise<{ result: string }>\n}\n\n/**\n * The \"file-reading sub-agent\" tier — opt-in across every file-IO-capable\n * executor. When `datasetDir` is set the executor is rooted there and granted\n * its own read tools, so instead of being limited to the excerpts a seam quotes\n * in the prompt it can open the primary sources directly and ground first-hand.\n */\nexport interface FileReadingOptions {\n /** Absolute path to the dataset/source root the executor may read from. */\n datasetDir?: string\n}\n\n/** The instruction prepended to a completion when {@link FileReadingOptions.datasetDir} is set. */\nexport function datasetPreamble(datasetDir: string): string {\n return (\n `You have direct read access to the source files under \\`${datasetDir}\\` ` +\n `(e.g. \\`sources/\\` raw captures, \\`entries/\\` refined notes). Use your ` +\n `file-reading tools to consult the primary sources directly when grounding ` +\n `claims — do not rely only on the excerpts quoted in this prompt.`\n )\n}\n\n/** Compose system + prompt with an optional source-access preamble (shared by every executor). */\nexport function composePrompt(\n system: string | undefined,\n prompt: string,\n datasetDir?: string\n): string {\n const head = datasetDir ? `${datasetPreamble(datasetDir)}\\n\\n` : \"\"\n return system ? `${head}${system}\\n\\n${prompt}` : `${head}${prompt}`\n}\n\n/** Provider keys an agent CLI may route through, forwarded from the parent env by default. */\nexport const PROVIDER_KEY_ENV = [\n \"OPENROUTER_API_KEY\",\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n] as const\n\nexport interface AgentCliModelOptions extends FileReadingOptions {\n /**\n * Env handed to the spawned CLI process — the provider key it routes through.\n * Defaults to forwarding {@link PROVIDER_KEY_ENV} from the parent process env.\n */\n env?: Record<string, string>\n /** Working directory for the CLI process. Defaults to `datasetDir` when set. */\n cwd?: string\n /** Timeout per completion (ms). Default 5 min. */\n timeoutMs?: number\n /**\n * Injectable runner (composed prompt → completion text). Defaults to driving\n * the runtime over ACP. Override in tests to avoid the CLI.\n */\n run?: (prompt: string) => Promise<string>\n}\n\n/** Build the env for the spawned CLI: explicit override, else forwarded provider keys. */\nexport function resolveCliEnv(\n opts: Pick<AgentCliModelOptions, \"env\">\n): Record<string, string> {\n if (opts.env) return opts.env\n const env: Record<string, string> = {}\n for (const k of PROVIDER_KEY_ENV) {\n const v = process.env[k]\n if (v) env[k] = v\n }\n return env\n}\n\n/** Drive one ACP turn on `runtime`, concatenating the text deltas. */\nasync function driveTurn(\n runtime: AgentCliRuntime,\n prompt: string,\n opts: AgentCliModelOptions\n): Promise<string> {\n const controller = new AbortController()\n const timer = setTimeout(\n () => controller.abort(),\n opts.timeoutMs ?? 5 * 60 * 1000\n )\n\n const cwd = opts.cwd ?? opts.datasetDir\n const session = await runtime.start({\n env: resolveCliEnv(opts),\n signal: controller.signal,\n ...(cwd ? { cwd } : {}),\n })\n\n try {\n let text = \"\"\n for await (const evt of session.send({ role: \"user\", content: prompt })) {\n if (evt.kind === \"text-delta\") {\n text += evt.text\n } else if (evt.kind === \"error\") {\n throw new Error(`${runtime.definition.id} model: ${evt.error.message}`)\n } else if (evt.kind === \"turn-end\") {\n if (evt.reason !== \"completed\")\n throw new Error(`${runtime.definition.id} model: turn ${evt.reason}`)\n break\n }\n }\n if (controller.signal.aborted)\n throw new Error(`${runtime.definition.id} model: timed out`)\n return text.trim()\n } finally {\n clearTimeout(timer)\n await session.close()\n }\n}\n\n/**\n * Build a {@link ModelLike} backed by an AIP-45 agent-CLI runtime. Hand it any\n * `*Runtime()` from the registry (Hermes, claude-code, opencode, …); per-CLI\n * presets are one-liners over this.\n */\nexport function makeAgentCliModel(\n runtime: AgentCliRuntime,\n opts: AgentCliModelOptions = {}\n): ModelLike {\n const run = opts.run ?? ((prompt: string) => driveTurn(runtime, prompt, opts))\n return {\n async complete({ system, prompt }) {\n return {\n result: await run(composePrompt(system, prompt, opts.datasetDir)),\n }\n },\n }\n}\n","/**\n * `none` strategy — pre-AIP-45-extension behaviour.\n *\n * Spawn a fresh session per acquire; close it on release. No state,\n * no reuse. The default when a manifest declares no `continuation`\n * block (back-compat for adapters that haven't been updated).\n */\n\nimport type { ContinuationStrategy } from \"../types.js\"\n\nexport const noneStrategy: ContinuationStrategy = {\n id: \"none\",\n async acquire(ctx) {\n return ctx.runtime.start(ctx.startOptions)\n },\n async release(ctx) {\n await ctx.session.close()\n },\n}\n","/**\n * AIP-45 ContinuationStrategy interface.\n *\n * A continuation strategy decides HOW prior conversation turns reach a\n * spawned CLI on subsequent invocations. Built-ins handle:\n *\n * - `none` — fresh session per call (current pre-AIP-45 behaviour)\n * - `pinned-session` — keep the spawned child alive, reuse across turns\n * - `transcript` — caller-supplied preamble prepended to each turn\n * - `native-resume` — pass a session id to the CLI's own `--resume` flag\n *\n * Adapter packages MAY register custom strategies via the registry —\n * for example, a Goose-specific strategy that uses MCP-side session\n * load semantics. Custom strategy ids require a follow-up AIP that\n * opens the `ContinuationStrategyId` enum (so the manifest schema can\n * validate them).\n *\n * The strategy owns the SESSION LIFECYCLE: `acquire` returns a session\n * the caller can `send()` against, and `release` decides whether the\n * session lives on (pinned-session) or closes immediately (none). The\n * runner / generation strategy MUST go through `acquire`/`release` —\n * it MUST NOT call `runtime.start()` / `session.close()` directly when\n * a strategy is active.\n */\n\nimport type {\n AgentCliRuntime,\n AgentCliRuntimeSession,\n AgentCliStartOptions,\n ContinuationKeyScope,\n ContinuationStrategyId,\n RuntimeConfig,\n TurnContext,\n} from \"../types.js\"\n\n/**\n * Per-acquire context the strategy gets. The runner builds this from\n * the manifest, the operator config, and the current turn's identity.\n */\nexport interface AcquireContext {\n runtime: AgentCliRuntime\n /** Already-composed start options (cwd / env / signal / config /\n * turnCtx). Strategies MAY override individual fields when they\n * call `runtime.start(...)` themselves. */\n startOptions: AgentCliStartOptions\n /** Per-call config (already validated against the manifest). */\n config: RuntimeConfig\n /** Identity context for key derivation. */\n turnCtx: TurnContext\n}\n\n/**\n * Strategies can hint to the runner about how the turn played out so\n * the strategy can decide whether to keep the session alive (normal\n * end), reset its TTL but keep it (transient error), or evict it\n * (dead-process error).\n */\nexport type ReleaseOutcome =\n | { kind: \"completed\" }\n | { kind: \"cancelled\" }\n | { kind: \"error\"; reason: \"transient\" | \"fatal\"; message: string }\n\nexport interface ReleaseContext {\n session: AgentCliRuntimeSession\n outcome: ReleaseOutcome\n turnCtx: TurnContext\n}\n\n/**\n * The strategy contract. `acquire` returns a session ready for the\n * caller to `send()` against — fresh OR reused. `release` decides\n * the session's fate. Strategies MAY hold internal state (e.g.\n * the pinned-session map) keyed by `turnCtx`.\n */\nexport interface ContinuationStrategy {\n readonly id: ContinuationStrategyId\n acquire(ctx: AcquireContext): Promise<AgentCliRuntimeSession>\n release(ctx: ReleaseContext): Promise<void>\n}\n\n/**\n * Derive a stable pin key from `turnCtx` according to the manifest's\n * `pinned_session.key_scope`. Missing scope fields downgrade to a\n * less-specific key with a warning — pinning still works, it just\n * collides more.\n *\n * Returns `null` when EVERY scope field the manifest asked for is\n * missing (no key derivable; strategy falls back to per-spawn).\n */\nexport function deriveKeyFromScope(\n scope: ContinuationKeyScope[],\n turnCtx: TurnContext\n): string | null {\n const parts: string[] = []\n for (const s of scope) {\n const v = turnCtx[s]\n if (v) parts.push(`${s}=${v}`)\n }\n return parts.length === 0 ? null : parts.join(\"|\")\n}\n","/**\n * `pinned-session` strategy — keep the spawned child alive across\n * turns so the CLI's in-memory model context carries over.\n *\n * Suitable for manifests that declare `session.mode: persistent` AND\n * `context_carryover: true` (Claude Code, OpenCode, ...). Acquires\n * either reuse a live pinned session or spawn fresh and pin; releases\n * keep the session alive and reset its idle TTL. The strategy\n * auto-evicts after the manifest's `pinned_session.idle_timeout_ms`.\n *\n * The pin key is derived from `turnCtx` according to the manifest's\n * `pinned_session.key_scope` (default: `[conversation, operator]` —\n * different conversations and different operators each get their own\n * child process).\n *\n * Lost on process restart. DB-backed pin persistence is a follow-up\n * (track sessionId in `cli_sessions` table, then optionally fall back\n * to native-resume / transcript on restart).\n */\n\nimport type {\n AgentCliRuntimeSession,\n AgentCliRuntime,\n AgentCliStartOptions,\n} from \"../../types.js\"\nimport type { ContinuationStrategy } from \"../types.js\"\nimport { deriveKeyFromScope } from \"../types.js\"\n\ninterface PinnedEntry {\n session: AgentCliRuntimeSession\n /** Cached so retry-after-eviction can recreate without re-resolving\n * the runtime entry from outside. */\n runtime: AgentCliRuntime\n /** Cached so eviction-and-retry uses the same start options. */\n startOptions: AgentCliStartOptions\n idleTimer: ReturnType<typeof setTimeout> | null\n}\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000\n\nconst pins = new Map<string, PinnedEntry>()\n\nfunction clearIdleTimer(entry: PinnedEntry): void {\n if (entry.idleTimer) {\n clearTimeout(entry.idleTimer)\n entry.idleTimer = null\n }\n}\n\nfunction scheduleIdleEviction(\n key: string,\n entry: PinnedEntry,\n idleTimeoutMs: number\n): void {\n clearIdleTimer(entry)\n entry.idleTimer = setTimeout(() => {\n pins.delete(key)\n entry.session.close().catch(err => {\n console.warn(\n `[pinned-session] idle close failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n })\n console.log(\n `[pinned-session] ${key} idle ${idleTimeoutMs / 60_000}m → closed`\n )\n }, idleTimeoutMs)\n // Don't keep the event loop alive just for the idle close — the\n // child will be reaped on process exit anyway. Without `unref`\n // a stale pin would block graceful shutdown.\n entry.idleTimer.unref?.()\n}\n\nfunction evictPin(key: string): void {\n const entry = pins.get(key)\n if (!entry) return\n clearIdleTimer(entry)\n pins.delete(key)\n entry.session.close().catch(err => {\n console.warn(\n `[pinned-session] evict close failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n })\n}\n\nexport const pinnedSessionStrategy: ContinuationStrategy = {\n id: \"pinned-session\",\n\n async acquire(ctx) {\n const tuning = ctx.runtime.definition.continuation?.pinned_session\n const scope = tuning?.key_scope ?? [\"conversation\", \"operator\"]\n const key = deriveKeyFromScope(scope, ctx.turnCtx)\n const idleTimeoutMs = tuning?.idle_timeout_ms ?? DEFAULT_IDLE_TIMEOUT_MS\n\n if (key === null) {\n // No identity to pin against — fall back to per-spawn behaviour.\n // Warn so the host learns to populate turnCtx.\n console.warn(\n `[pinned-session] turnCtx has no fields matching key_scope ${JSON.stringify(scope)}; falling back to per-spawn (no pin).`\n )\n return ctx.runtime.start(ctx.startOptions)\n }\n\n const existing = pins.get(key)\n if (existing) {\n // Cancel the idle timer — this turn is reusing the pin.\n clearIdleTimer(existing)\n return existing.session\n }\n\n const session = await ctx.runtime.start(ctx.startOptions)\n const entry: PinnedEntry = {\n session,\n runtime: ctx.runtime,\n startOptions: ctx.startOptions,\n idleTimer: null,\n }\n pins.set(key, entry)\n scheduleIdleEviction(key, entry, idleTimeoutMs)\n return session\n },\n\n async release(ctx) {\n // Find the entry by identity — ReleaseContext doesn't carry `runtime`,\n // so we match by session reference. Acceptable since the pin map is small.\n let foundKey: string | null = null\n for (const [k, e] of pins) {\n if (e.session === ctx.session) {\n foundKey = k\n break\n }\n }\n\n if (!foundKey) {\n // Session wasn't pinned (per-spawn fallback path) — close it\n // like the `none` strategy would.\n await ctx.session.close()\n return\n }\n\n const entry = pins.get(foundKey)!\n const tuning = entry.runtime.definition.continuation?.pinned_session\n const idleTimeoutMs = tuning?.idle_timeout_ms ?? DEFAULT_IDLE_TIMEOUT_MS\n\n // Fatal errors → evict so the next turn re-spawns. Transient\n // errors and normal completion → reset the idle TTL and keep.\n // Cancelled (user aborted) is treated like normal completion —\n // the user wanted to stop this turn, not the whole session.\n if (ctx.outcome.kind === \"error\" && ctx.outcome.reason === \"fatal\") {\n evictPin(foundKey)\n return\n }\n\n scheduleIdleEviction(foundKey, entry, idleTimeoutMs)\n },\n}\n\n/**\n * Test helper — drop all pinned entries and clear timers. Not part\n * of the public API; exposed under `__test__` so tests can reset the\n * module's singleton state between runs.\n */\nexport const __test__ = {\n resetPins(): void {\n for (const [k] of pins) evictPin(k)\n },\n pinCount(): number {\n return pins.size\n },\n}\n","/**\n * `transcript` strategy — works for any CLI, including those with\n * `resumable: false` and ephemeral sessions.\n *\n * The driver doesn't know about Mastra memory or the host's\n * conversation log — that's the host's domain. The host supplies the\n * preamble at acquire-time via `startOptions.config.options` (the\n * convention is option id `__transcript`, see below) and the strategy\n * is otherwise identical to `none` — fresh session per acquire,\n * close on release.\n *\n * In practice the host does the prepending itself before calling\n * `runtime.start` (it controls the `message` text). This strategy\n * exists mostly as a NAMED policy choice in the manifest — declaring\n * it tells the host \"use the transcript-replay path for this CLI\"\n * without the host needing to inspect capabilities.\n *\n * Token-costly but stateless and survives API restarts.\n */\n\nimport type { ContinuationStrategy } from \"../types.js\"\n\nexport const transcriptStrategy: ContinuationStrategy = {\n id: \"transcript\",\n async acquire(ctx) {\n return ctx.runtime.start(ctx.startOptions)\n },\n async release(ctx) {\n await ctx.session.close()\n },\n}\n","/**\n * `native-resume` strategy — reattach to the agent's own session by id\n * (ACP `loadSession`, MCP equivalent, or argv-style `--resume`).\n *\n * Two-step lifecycle:\n * 1. **acquire**: look up a persisted sessionId for `turnCtx` via\n * `loadHook`. If found, pass it to `runtime.start` as\n * `resumeSessionId` so the protocol arm reattaches. If not, spawn\n * fresh — and after the session is up, capture the new id from\n * `session.sessionId` and persist it via `saveHook`.\n * 2. **release**: close the spawned process. The session lives in\n * the agent's storage layer (e.g. Claude Code's JSONL files);\n * cold-start resume on the next acquire reads from that store.\n *\n * Hooks are registered once per host process via\n * `configureNativeResume({ load, save })`. Without hooks the strategy\n * degrades to per-spawn behaviour with a one-line warning — it's not\n * fatal because the spawn still works, just without continuity.\n *\n * Requires the manifest to declare `capabilities.resumable: true`\n * AND the agent to advertise the matching protocol capability (e.g.\n * ACP `loadSession: true`). The schema enforces the manifest side at\n * validation; runtime capability mismatch surfaces from the protocol\n * arm as the agent's own error.\n */\n\nimport type { ContinuationStrategy, AcquireContext } from \"../types.js\"\nimport { deriveKeyFromScope } from \"../types.js\"\nimport type { TurnContext } from \"../../types.js\"\n\nexport interface NativeResumeHooks {\n /** Look up a persisted sessionId for the given identity scope. Return\n * undefined when no prior session exists — strategy spawns fresh. */\n load: (turnCtx: TurnContext) => Promise<string | undefined>\n /** Persist a freshly-established sessionId so the next cold start\n * can resume. Called once per \"fresh spawn\" acquire (not per turn).\n * Idempotent / upsert semantics expected on the host side. */\n save: (turnCtx: TurnContext, sessionId: string) => Promise<void>\n /** Optional: drop the persisted entry when a session is detected as\n * unresumable (agent rejected loadSession with a hard error). */\n forget?: (turnCtx: TurnContext) => Promise<void>\n}\n\nlet _hooks: NativeResumeHooks | null = null\n\n/**\n * Register the host's session-id load/save callbacks. Call once at\n * boot. Subsequent calls overwrite — useful in tests; in prod treat\n * the registration as exclusive.\n */\nexport function configureNativeResume(hooks: NativeResumeHooks): void {\n _hooks = hooks\n}\n\n/** Reset to no-hooks. Test helper; not part of public API. */\nexport function __resetNativeResumeForTests(): void {\n _hooks = null\n}\n\nexport const nativeResumeStrategy: ContinuationStrategy = {\n id: \"native-resume\",\n async acquire(ctx: AcquireContext) {\n if (!_hooks) {\n console.warn(\n \"[native-resume] no hooks registered (call configureNativeResume at boot); falling back to per-spawn — no continuity.\"\n )\n return ctx.runtime.start(ctx.startOptions)\n }\n // Use the same key-derivation as pinned-session so a host can\n // declare its scope ONCE in the manifest (`continuation.pinned_session.key_scope`)\n // and have both strategies key off the same identity. Native-resume\n // doesn't have its own key_scope today; it inherits.\n const scope =\n ctx.runtime.definition.continuation?.pinned_session?.key_scope ?? [\n \"conversation\",\n \"operator\",\n ]\n const key = deriveKeyFromScope(scope, ctx.turnCtx)\n if (key === null) {\n console.warn(\n `[native-resume] turnCtx has no fields matching key_scope ${JSON.stringify(scope)}; falling back to per-spawn (no resume).`\n )\n return ctx.runtime.start(ctx.startOptions)\n }\n\n const existingId = await _hooks.load(ctx.turnCtx).catch(err => {\n console.warn(\n `[native-resume] load hook failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n return undefined\n })\n\n let session\n let resumed = false\n if (existingId) {\n try {\n session = await ctx.runtime.start({\n ...ctx.startOptions,\n resumeSessionId: existingId,\n })\n resumed = true\n } catch (err) {\n // Most likely the agent rejected the id (session expired,\n // wiped, mismatched cwd). Drop the stale pin and spawn fresh\n // so the user gets continuity going forward instead of being\n // stuck on a dead reference.\n console.warn(\n `[native-resume] resume failed for ${key} (id=${existingId.slice(0, 12)}…), starting fresh:`,\n err instanceof Error ? err.message : err\n )\n if (_hooks.forget) {\n await _hooks.forget(ctx.turnCtx).catch(() => undefined)\n }\n session = await ctx.runtime.start(ctx.startOptions)\n }\n } else {\n session = await ctx.runtime.start(ctx.startOptions)\n }\n\n // Persist the established id when this is a NEW session (resume\n // path keeps the same id we already have, no need to re-save).\n // The runtime guarantees session.sessionId reflects the protocol\n // session id when the arm exposes it.\n if (!resumed && session.sessionId) {\n await _hooks.save(ctx.turnCtx, session.sessionId).catch(err => {\n console.warn(\n `[native-resume] save hook failed for ${key}:`,\n err instanceof Error ? err.message : err\n )\n })\n }\n return session\n },\n\n async release(ctx) {\n // The protocol session lives in the agent's own storage; closing\n // the spawned subprocess is fine — `loadSession` on the next\n // acquire reattaches via the persisted id.\n await ctx.session.close()\n },\n}\n","/**\n * Continuation strategy registry.\n *\n * Module-scoped singleton — all built-ins are registered at import\n * time, custom strategies (from adapter packages) register via\n * `registerContinuationStrategy`. The runner looks up by id;\n * unregistered ids throw at acquire-time so the caller fails fast\n * with a clear \"this strategy id isn't registered\" message.\n */\n\nimport type { ContinuationStrategyId } from \"../types.js\"\nimport type { ContinuationStrategy } from \"./types.js\"\nimport { noneStrategy } from \"./strategies/none.js\"\nimport { pinnedSessionStrategy } from \"./strategies/pinned-session.js\"\nimport { transcriptStrategy } from \"./strategies/transcript.js\"\nimport { nativeResumeStrategy } from \"./strategies/native-resume.js\"\n\nconst registry = new Map<ContinuationStrategyId, ContinuationStrategy>()\n\n/**\n * Register (or replace) a continuation strategy. Adapter packages\n * MAY register custom strategies on import — but they MUST first\n * land an AIP that opens the `ContinuationStrategyId` enum so the\n * manifest schema accepts the new id.\n */\nexport function registerContinuationStrategy(\n strategy: ContinuationStrategy\n): void {\n registry.set(strategy.id, strategy)\n}\n\nexport function getContinuationStrategy(\n id: ContinuationStrategyId\n): ContinuationStrategy {\n const s = registry.get(id)\n if (!s) {\n throw new Error(\n `[agent-cli] No continuation strategy registered for id '${id}'. Built-ins: ${Array.from(registry.keys()).join(\", \")}.`\n )\n }\n return s\n}\n\nexport function listContinuationStrategies(): ContinuationStrategyId[] {\n return Array.from(registry.keys())\n}\n\n// Register built-ins eagerly at module load so any importer of the\n// registry sees them. Custom strategies layer on top.\nregisterContinuationStrategy(noneStrategy)\nregisterContinuationStrategy(pinnedSessionStrategy)\nregisterContinuationStrategy(transcriptStrategy)\nregisterContinuationStrategy(nativeResumeStrategy)\n","/**\n * @agentproto/driver-agent-cli — AIP-45 AGENT-CLI.md `defineAgentCli`\n * reference impl.\n *\n * Spec: https://agentproto.sh/docs/aip-45\n *\n * Authoring paths:\n * - TS: `defineAgentCli({...})` → `AgentCliHandle`\n * - MD: `parseAgentCliManifest(src) → agentCliFromManifest({...})` → `AgentCliHandle`\n *\n * Runtime: `createAgentCliRuntime(handle)` → spawn binary, dispatch\n * turns through the protocol arm (acp / mcp / proprietary), normalise\n * events to {@link StreamEvent}.\n */\n\nexport const SPEC_NAME = \"agentcli-interactive/v1\" as const\nexport const SPEC_VERSION = \"0.1.0-alpha\" as const\n\nexport {\n defineAgentCli,\n createAgentCliRuntime,\n} from \"./define-agent-cli.js\"\n// Agent CLI → generic model port: one executor backing every prompt→completion\n// seam (report writer, corpus distiller, Mastra judgment step) over any AIP-45 CLI.\nexport {\n makeAgentCliModel,\n resolveCliEnv,\n composePrompt,\n datasetPreamble,\n PROVIDER_KEY_ENV,\n} from \"./model.js\"\nexport type {\n ModelLike,\n FileReadingOptions,\n AgentCliModelOptions,\n} from \"./model.js\"\n// Exposed so callers can build a sandbox-resident `AgentCliRuntime`\n// against the same protocol layer the host-spawn factory uses, by\n// passing a `ChildProcess`-shaped duck whose stdio is bridged to a\n// remote subprocess (e2b sandbox, ssh, etc.). See guilde's\n// `cli-session-spawn/sandbox-runtime.ts` for a worked example.\nexport {\n createAcpProtocolArm,\n autoAllowPermissionHandler,\n planModePermissionHandler,\n type AcpPermissionHandler,\n type AcpPermissionOutcome,\n type AcpPermissionRequestParams,\n} from \"./protocol/acp-client.js\"\nexport {\n createPrintSession,\n mapMastraEvent,\n createMastraMapperState,\n type PrintArmOptions,\n type MastraMapperState,\n} from \"./protocol/print-arm.js\"\n// Generic proprietary-protocol arm loader — dynamically imports the\n// manifest's `adapter` package. Exported so proprietary adapter packages\n// (and their tests) can drive the same loader `createAgentCliRuntime`\n// uses, without duplicating the load-and-validate logic.\nexport {\n createProprietaryProtocolArm,\n type ProprietaryProtocolOptions,\n} from \"./protocol/proprietary.js\"\nexport {\n agentCliFrontmatterSchema,\n runtimeConfigSchema,\n type AgentCliFrontmatter,\n type RuntimeConfigInput,\n} from \"./schema.js\"\nexport {\n toFileBasedMcpServers,\n type MastracodeMcpServerConfig,\n} from \"./mcp-servers.js\"\nexport {\n composeSpawn,\n resolveContinuationStrategy,\n RuntimeConfigError,\n type ComposedSpawn,\n} from \"./manifest/compose.js\"\nexport {\n registerContinuationStrategy,\n getContinuationStrategy,\n listContinuationStrategies,\n} from \"./continuation/registry.js\"\nexport {\n configureNativeResume,\n type NativeResumeHooks,\n} from \"./continuation/strategies/native-resume.js\"\nexport {\n deriveKeyFromScope,\n type ContinuationStrategy,\n type AcquireContext,\n type ReleaseContext,\n type ReleaseOutcome,\n} from \"./continuation/types.js\"\nexport type {\n AgentCliDefinition,\n AgentCliHandle,\n AgentCliProtocol,\n AgentCliSessionMode,\n AgentCliClient,\n AgentCliConnectOptions,\n AgentCliRuntime,\n AgentCliRuntimeSession,\n AgentCliStartOptions,\n AgentCliCapabilities,\n AgentCliInstallMethod,\n AgentCliVersionCheck,\n AgentCliAuth,\n AgentCliSetupStep,\n AgentCliSetupSkipIf,\n AgentCliSetupPersist,\n AgentCliSession,\n AgentCliModels,\n AgentCliModelEntry,\n AgentCliMcpBlock,\n AgentCliMode,\n AgentCliOption,\n AgentCliOptionType,\n AgentCliPresetDeclaration,\n AgentCliContinuation,\n AgentCliPinnedSessionTuning,\n AgentCliPrintConfig,\n ContinuationStrategyId,\n ContinuationKeyScope,\n RuntimeConfig,\n TurnContext,\n StreamEvent,\n} from \"./types.js\"\n"]}
@@ -1,5 +1,5 @@
1
- import { l as AgentCliFrontmatter, A as AgentCliHandle } from '../schema-L-2rEB1H.js';
2
- export { E as agentCliFrontmatterSchema } from '../schema-L-2rEB1H.js';
1
+ import { l as AgentCliFrontmatter, A as AgentCliHandle } from '../schema-pfhEOoSm.js';
2
+ export { F as agentCliFrontmatterSchema } from '../schema-pfhEOoSm.js';
3
3
  import '@agentproto/acp';
4
4
  import 'zod';
5
5
 
@@ -1,5 +1,5 @@
1
- import { agentCliFrontmatterSchema, defineAgentCli } from '../chunk-L6BRNMVP.mjs';
2
- export { agentCliFrontmatterSchema } from '../chunk-L6BRNMVP.mjs';
1
+ import { agentCliFrontmatterSchema, defineAgentCli } from '../chunk-2E3ATB4P.mjs';
2
+ export { agentCliFrontmatterSchema } from '../chunk-2E3ATB4P.mjs';
3
3
  import matter from 'gray-matter';
4
4
 
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { AcpMcpServer, StreamEvent } from '@agentproto/acp';
1
+ import { AcpMcpServer, StreamEvent, AcpPermissionResolution } from '@agentproto/acp';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
@@ -49,6 +49,44 @@ interface AgentCliAuth {
49
49
  grace_s?: number;
50
50
  };
51
51
  }
52
+ /**
53
+ * The `subscription` (OAuth / bearer) billing mode declaration — the ONE
54
+ * axis of the billing-auth resolver that isn't a shared provider fact, so it
55
+ * lives on the adapter manifest rather than in the model catalog. Its env var
56
+ * is consumer-specific (claude CLI wrapper → `CLAUDE_CODE_OAUTH_TOKEN`;
57
+ * claude-sdk → `ANTHROPIC_AUTH_TOKEN`). Presence of this field is what tells
58
+ * the runtime "this adapter supports `subscription` mode"; an adapter without
59
+ * it that's asked for `subscription` fails with `unsupported_auth_mode`.
60
+ *
61
+ * The api-key axis needs NO such declaration — its env var derives from the
62
+ * catalog's `PROVIDER_KEY_ENV` via `providerEnvVar(provider)`; only the
63
+ * runtime resolver reads it, never this manifest.
64
+ */
65
+ interface AgentCliAuthSubscription {
66
+ /** Env var SET to the resolved subscription credential (the OAuth/bearer
67
+ * token). */
68
+ setEnv: string;
69
+ /**
70
+ * Sibling billing-credential env vars the SAME consumer also honors and
71
+ * that must therefore be scrubbed in EVERY resolved mode except when the
72
+ * var IS the one being set — a leftover of one of these would silently
73
+ * override the credential this spawn stated (the org-credit-leak class).
74
+ * For anthropic: the generic bearer `ANTHROPIC_AUTH_TOKEN`, which the
75
+ * claude binary honors above `ANTHROPIC_API_KEY`. Distinct from
76
+ * {@link unsetEnvAdd} (which is native-mode-only gateway hygiene, not a
77
+ * credential).
78
+ */
79
+ conflictEnv?: string[];
80
+ /**
81
+ * Extra env vars scrubbed ONLY in `subscription` (native) mode — gateway
82
+ * hygiene, not credentials: cloud-provider redirect toggles
83
+ * (`CLAUDE_CODE_USE_BEDROCK`/`_VERTEX`/…) + `ANTHROPIC_BASE_URL`, any of
84
+ * which would reroute or 401 a natively-billed spawn. Left present in
85
+ * api-key mode (a deliberate api-key + Bedrock combination is valid there),
86
+ * which is why this is separate from {@link conflictEnv}.
87
+ */
88
+ unsetEnvAdd?: string[];
89
+ }
52
90
  /**
53
91
  * Re-runnable health check that, when matching, skips the enclosing
54
92
  * setup step. Lets `agentproto setup <slug>` re-runs be idempotent
@@ -148,9 +186,36 @@ interface AgentCliSession {
148
186
  max_turns?: number;
149
187
  context_carryover?: boolean;
150
188
  }
189
+ /**
190
+ * A `models.allowed` entry that states who serves/bills a model and how
191
+ * this adapter reaches it — the structured alternative to a bare id
192
+ * string. `provider` is *who* (a `ProviderPreset` id, or a direct
193
+ * provider like "anthropic"); `mode` is *how this adapter* gets there
194
+ * (its own `modes[].id`), which is NOT redundant with `provider`: an
195
+ * adapter that routes by id prefix (opencode) needs no mode at all,
196
+ * while one that needs `ANTHROPIC_BASE_URL` pre-wired (claude-sdk,
197
+ * claude-code) does. Omit `mode` when the adapter routes on its own.
198
+ */
199
+ interface AgentCliModelEntry {
200
+ /** Model id, unchanged on the wire — this annotates, never renames. */
201
+ id: string;
202
+ /** Who serves/bills this model. Omit when unstated — an unstated
203
+ * provider must never be guessed downstream (a wrong-but-confident
204
+ * guess would bill the wrong account). */
205
+ provider?: string;
206
+ /** This adapter's mode id that routes to `provider`. Omit when the
207
+ * adapter routes on its own or the model needs no mode switch. */
208
+ mode?: string;
209
+ }
151
210
  interface AgentCliModels {
152
211
  default?: string;
153
- allowed?: string[];
212
+ /**
213
+ * Model ids the host MAY route to. A bare string keeps meaning exactly
214
+ * what it means today (provider unstated, adapter default) — additive,
215
+ * so no existing manifest breaks. A structured entry additionally
216
+ * states `provider`/`mode` (see {@link AgentCliModelEntry}).
217
+ */
218
+ allowed?: Array<string | AgentCliModelEntry>;
154
219
  /**
155
220
  * Model-id patterns this adapter must NEVER route to, even when a caller
156
221
  * passes the id explicitly (the `model` option is free-form, so `allowed`
@@ -467,11 +532,50 @@ interface AgentCliDefinition {
467
532
  version: string;
468
533
  bin: string;
469
534
  bin_args?: string[];
535
+ /**
536
+ * Static environment variables always merged into the spawn env,
537
+ * before any mode/option env patch (so those can still override).
538
+ * The always-on counterpart to `modes[].env` / `options[].env`, which
539
+ * only apply when the corresponding mode/option is selected. Primary
540
+ * user is a generic ACP agent (`acpHandleFromSpec`) whose whole config
541
+ * surface is bin + args + env; a native adapter can use it too for env
542
+ * that should apply on every spawn regardless of mode.
543
+ */
544
+ env?: Record<string, string>;
470
545
  install: AgentCliInstallMethod[];
471
546
  version_check: AgentCliVersionCheck;
472
547
  /** AIP-29 § Setup — post-install configuration pipeline. Optional. */
473
548
  setup?: AgentCliSetupStep[];
474
549
  auth?: AgentCliAuth;
550
+ /**
551
+ * FIXED billing provider for a single-provider adapter (`claude-code` /
552
+ * `claude-sdk` → `"anthropic"`, `codex` → `"openai"`, `hermes` →
553
+ * `"openrouter"`). A `CatalogProvider` id (typed as `string` here to keep
554
+ * this generic AIP-45 doctype decoupled from `@agentproto/model-catalog` —
555
+ * the runtime resolver validates it against the catalog and derives the
556
+ * api-key env via `providerEnvVar`). Omitted for by-model routers, whose
557
+ * provider the resolver derives from the requested model
558
+ * (`getModelProvider`). Consumed by the runtime billing-auth resolver, NOT
559
+ * by this driver (which stays mechanical).
560
+ */
561
+ provider?: string;
562
+ /**
563
+ * Declares that this adapter supports `subscription` billing mode and how
564
+ * (which env var to set + what to scrub). Presence = supported; absence
565
+ * means a `subscription` request is rejected with `unsupported_auth_mode`.
566
+ * Only the Claude adapters set it. See {@link AgentCliAuthSubscription}.
567
+ */
568
+ authSubscription?: AgentCliAuthSubscription;
569
+ /**
570
+ * When the runtime billing-auth resolver ENGAGES credential injection:
571
+ * - `"when-configured"` (default) — only when an operator explicitly set
572
+ * `auth` (per-spawn or in `defaults.adapters.<slug>.auth`). Non-breaking:
573
+ * an adapter with no auth config runs ambient, unchanged.
574
+ * - `"always"` — every spawn, even with nothing configured (then it
575
+ * fails fast with `missing_auth_credential`). Only `claude-code` sets
576
+ * this, preserving its #312 fail-fast contract.
577
+ */
578
+ authEnforce?: "always" | "when-configured";
475
579
  sandbox: string | Record<string, unknown>;
476
580
  runner?: string | Record<string, unknown>;
477
581
  protocol: AgentCliProtocol;
@@ -577,6 +681,14 @@ interface AgentCliConnectOptions {
577
681
  * one-shots) MAY ignore this field.
578
682
  */
579
683
  onActivity?: () => void;
684
+ /**
685
+ * When true, the ACP arm surfaces each `session/request_permission` as an
686
+ * `agent-prompt` StreamEvent and HOLDS the RPC until the host calls
687
+ * `respondPermission` — forwarded to the arm's
688
+ * `createAcpProtocolArm({ permissionHold })`. Arms with no permission
689
+ * surface (non-ACP) ignore it. Default false (auto-answer, unchanged).
690
+ */
691
+ permissionHold?: boolean;
580
692
  /**
581
693
  * Turn-idle watchdog, forwarded verbatim to the ACP arm's
582
694
  * `createAcpClient({ turnIdleTimeoutMs })` (see
@@ -599,6 +711,13 @@ interface AgentCliClient {
599
711
  send(turnId: string, message: unknown): Promise<void>;
600
712
  events(): AsyncIterable<StreamEvent>;
601
713
  cancel(turnId: string): Promise<void>;
714
+ /**
715
+ * Resolve a permission request parked by permission-hold mode — `requestId`
716
+ * is the `toolCallId` carried on the `agent-prompt` StreamEvent that
717
+ * surfaced it. Returns true when a matching parked request was found and
718
+ * resolved. Only the ACP arm implements this; other arms omit it.
719
+ */
720
+ respondPermission?(requestId: string, resolution: AcpPermissionResolution): boolean;
602
721
  close(): Promise<void>;
603
722
  /**
604
723
  * The session id the protocol arm holds. Populated after `connect()`
@@ -679,6 +798,58 @@ interface AgentCliStartOptions {
679
798
  * wants this protection.
680
799
  */
681
800
  turnIdleTimeoutMs?: number;
801
+ /**
802
+ * When true, the spawned session runs in permission-hold mode: the ACP arm
803
+ * surfaces each permission request as an `agent-prompt` StreamEvent and
804
+ * HOLDS the RPC until the host calls `respondPermission`. Forwarded to
805
+ * `protocolArm.connect({ permissionHold })`. Default false (unchanged
806
+ * auto-answer behaviour for every existing caller).
807
+ */
808
+ permissionHold?: boolean;
809
+ /**
810
+ * FULLY-RESOLVED billing-auth spec, computed by the runtime resolver
811
+ * (`@agentproto/runtime`'s `spawn-defaults`/`session-spawn`) and applied
812
+ * MECHANICALLY here — this driver does no provider lookup, mode selection,
813
+ * or catalog import of its own. EXPLICIT credential selection, not
814
+ * scrub-by-absence: the resolver already decided the mode (ordered
815
+ * preference — subscription over api-key when a subscription credential is
816
+ * present), the env var to SET (`setEnv`), the conflicting vars to SCRUB
817
+ * (`unsetEnv`), and resolved the `credential` from a NAMED config/store
818
+ * ref (never the ambient shell env).
819
+ *
820
+ * `createAgentCliRuntime(...).start()` ENGAGES this spec when
821
+ * `enforce === "always"` OR `explicit === true`; on engage it deletes every
822
+ * `unsetEnv` key (unless this spawn's own mode/option patch explicitly set
823
+ * it) then SETS `setEnv = credential`. When engaged with no `credential`, it
824
+ * FAILS FAST with `RuntimeConfigError` (`missing_auth_credential`) — never a
825
+ * fallback to another or ambient credential. When absent (the resolver
826
+ * produced no spec — e.g. a by-model adapter whose provider didn't resolve),
827
+ * this driver injects nothing and runs ambient.
828
+ */
829
+ auth?: ResolvedAuthSpec;
830
+ }
831
+ /**
832
+ * The resolved billing-auth spec the runtime hands the driver — see
833
+ * {@link AgentCliStartOptions.auth}. Every field is pre-decided; the driver
834
+ * only applies it.
835
+ */
836
+ interface ResolvedAuthSpec {
837
+ /** The resolved billing mode (already ordered/validated by the runtime). */
838
+ mode: "subscription" | "api-key";
839
+ /** The resolved secret value for `mode`, or absent when nothing resolved
840
+ * (⇒ fail-fast on engage). Never read ambiently. */
841
+ credential?: string;
842
+ /** Env var SET to `credential` on engage. */
843
+ setEnv: string;
844
+ /** Conflicting billing-credential (and, in native mode, gateway-hygiene)
845
+ * env vars DELETED on engage — unless this spawn's own mode/option patch
846
+ * explicitly set the key. */
847
+ unsetEnv: string[];
848
+ /** True when an operator explicitly configured `auth` (per-spawn or in
849
+ * `defaults.adapters.<slug>.auth`) — half the engage condition. */
850
+ explicit: boolean;
851
+ /** The adapter's enforcement policy — the other half of engage. */
852
+ enforce: "always" | "when-configured";
682
853
  }
683
854
  /**
684
855
  * Operator-side runtime configuration. Mirrors the `runtime.config`
@@ -720,6 +891,13 @@ interface AgentCliRuntimeSession {
720
891
  readonly pid?: number;
721
892
  send(message: unknown): AsyncIterable<StreamEvent>;
722
893
  cancel(): Promise<void>;
894
+ /**
895
+ * Resolve a permission request parked by permission-hold mode (see
896
+ * `AgentCliStartOptions.permissionHold`). Delegates to the protocol arm's
897
+ * `respondPermission`; returns true when a matching parked request was
898
+ * resolved. Absent for arms that don't model held permissions.
899
+ */
900
+ respondPermission?(requestId: string, resolution: AcpPermissionResolution): boolean;
723
901
  close(): Promise<void>;
724
902
  }
725
903
 
@@ -745,6 +923,7 @@ declare const agentCliFrontmatterSchema: z.ZodObject<{
745
923
  version: z.ZodString;
746
924
  bin: z.ZodString;
747
925
  bin_args: z.ZodOptional<z.ZodArray<z.ZodString>>;
926
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
748
927
  install: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
749
928
  method: z.ZodLiteral<"brew">;
750
929
  package: z.ZodString;
@@ -908,6 +1087,16 @@ declare const agentCliFrontmatterSchema: z.ZodObject<{
908
1087
  grace_s: z.ZodOptional<z.ZodNumber>;
909
1088
  }, z.core.$strict>>;
910
1089
  }, z.core.$strict>>;
1090
+ provider: z.ZodOptional<z.ZodString>;
1091
+ authSubscription: z.ZodOptional<z.ZodObject<{
1092
+ setEnv: z.ZodString;
1093
+ conflictEnv: z.ZodOptional<z.ZodArray<z.ZodString>>;
1094
+ unsetEnvAdd: z.ZodOptional<z.ZodArray<z.ZodString>>;
1095
+ }, z.core.$strict>>;
1096
+ authEnforce: z.ZodOptional<z.ZodEnum<{
1097
+ always: "always";
1098
+ "when-configured": "when-configured";
1099
+ }>>;
911
1100
  sandbox: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
912
1101
  runner: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
913
1102
  protocol: z.ZodEnum<{
@@ -957,7 +1146,11 @@ declare const agentCliFrontmatterSchema: z.ZodObject<{
957
1146
  }, z.core.$strict>>;
958
1147
  models: z.ZodOptional<z.ZodObject<{
959
1148
  default: z.ZodOptional<z.ZodString>;
960
- allowed: z.ZodOptional<z.ZodArray<z.ZodString>>;
1149
+ allowed: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
1150
+ id: z.ZodString;
1151
+ provider: z.ZodOptional<z.ZodString>;
1152
+ mode: z.ZodOptional<z.ZodString>;
1153
+ }, z.core.$strict>]>>>;
961
1154
  deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
962
1155
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
963
1156
  apply: z.ZodOptional<z.ZodEnum<{
@@ -1086,4 +1279,4 @@ declare const runtimeConfigSchema: z.ZodObject<{
1086
1279
  }, z.core.$strict>;
1087
1280
  type RuntimeConfigInput = z.infer<typeof runtimeConfigSchema>;
1088
1281
 
1089
- export { type AgentCliHandle as A, type AgentCliVersionCheck as B, type ContinuationStrategyId as C, type RuntimeConfigInput as D, agentCliFrontmatterSchema as E, runtimeConfigSchema as F, type RuntimeConfig as R, type TurnContext as T, type AgentCliRuntime as a, type AgentCliDefinition as b, type AgentCliClient as c, type AgentCliPrintConfig as d, type AgentCliRuntimeSession as e, type AgentCliStartOptions as f, type ContinuationKeyScope as g, type AgentCliAuth as h, type AgentCliCapabilities as i, type AgentCliConnectOptions as j, type AgentCliContinuation as k, type AgentCliFrontmatter as l, type AgentCliInstallMethod as m, type AgentCliMcpBlock as n, type AgentCliMode as o, type AgentCliModels as p, type AgentCliOption as q, type AgentCliOptionType as r, type AgentCliPinnedSessionTuning as s, type AgentCliPresetDeclaration as t, type AgentCliProtocol as u, type AgentCliSession as v, type AgentCliSessionMode as w, type AgentCliSetupPersist as x, type AgentCliSetupSkipIf as y, type AgentCliSetupStep as z };
1282
+ export { type AgentCliHandle as A, type AgentCliSetupStep as B, type ContinuationStrategyId as C, type AgentCliVersionCheck as D, type RuntimeConfigInput as E, agentCliFrontmatterSchema as F, runtimeConfigSchema as G, type RuntimeConfig as R, type TurnContext as T, type AgentCliRuntime as a, type AgentCliDefinition as b, type AgentCliClient as c, type AgentCliPrintConfig as d, type AgentCliRuntimeSession as e, type AgentCliStartOptions as f, type ContinuationKeyScope as g, type AgentCliAuth as h, type AgentCliCapabilities as i, type AgentCliConnectOptions as j, type AgentCliContinuation as k, type AgentCliFrontmatter as l, type AgentCliInstallMethod as m, type AgentCliMcpBlock as n, type AgentCliMode as o, type AgentCliModelEntry as p, type AgentCliModels as q, type AgentCliOption as r, type AgentCliOptionType as s, type AgentCliPinnedSessionTuning as t, type AgentCliPresetDeclaration as u, type AgentCliProtocol as v, type AgentCliSession as w, type AgentCliSessionMode as x, type AgentCliSetupPersist as y, type AgentCliSetupSkipIf as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/driver-agent-cli",
3
- "version": "0.4.0",
3
+ "version": "1.1.0",
4
4
  "description": "@agentproto/driver-agent-cli — AIP-45 AGENT-CLI.md reference implementation. Multi-protocol runner that loads an AGENT-CLI.md manifest, spawns the binary, and dispatches turns through an ACP / MCP / proprietary arm. ACP arm delegates to @agentproto/acp; emits the canonical StreamEvent taxonomy regardless of underlying protocol.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -24,7 +24,7 @@
24
24
  "bugs": {
25
25
  "url": "https://github.com/agentproto/ts/issues"
26
26
  },
27
- "license": "MIT",
27
+ "license": "Apache-2.0",
28
28
  "type": "module",
29
29
  "main": "dist/index.mjs",
30
30
  "module": "dist/index.mjs",
@@ -53,8 +53,8 @@
53
53
  "dependencies": {
54
54
  "gray-matter": "^4.0.3",
55
55
  "zod": "^4.4.3",
56
- "@agentproto/acp": "0.4.0",
57
- "@agentproto/define-doctype": "0.1.0"
56
+ "@agentproto/acp": "0.5.0",
57
+ "@agentproto/define-doctype": "0.1.1"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^25.6.2",