@agent-compose/sdk 0.5.2 → 0.5.6

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.
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ export type { WorkflowDefinition } from "./types/workflow.js";
16
16
  export { defineSandboxEnvironment } from "./types/sandbox-environment.js";
17
17
  export type { SandboxEnvironmentDefinition } from "./types/sandbox-environment.js";
18
18
  export type { AgentRuntime, McpServerConfig, ModelExecutionContract, ToolCallGateResult, RuntimeOptions, } from "./types/runtime.js";
19
- export type { WorkflowFn, WorkflowCtx, WorkflowRun, AgentBudget, WorkflowHooks, SnapshotConfig, BootSnapshot, IOSchema, OutputSchema, WorkflowMemoryConfig, } from "./types/workflow.js";
19
+ export type { WorkflowFn, WorkflowCtx, WorkflowRun, AgentBudget, WorkflowHooks, SnapshotConfig, BootSnapshot, ReuseSnapshot, IOSchema, OutputSchema, WorkflowMemoryConfig, } from "./types/workflow.js";
20
20
  export type { RunSnapshotEntry } from "./client.js";
21
21
  export type { WorkflowPlan, WorkflowStepPlan } from "./types/workflow-plan.js";
22
22
  export type { BaseExecutionContext, InvokeChild } from "./types/execution-context.js";
@@ -27,7 +27,7 @@ export type { Processor, ProcessorContext, ProcessorVerdict, ToolCall, } from ".
27
27
  export type { AgentMessage, AgentMessageInit, AgentMessageText, AgentMessageThinking, AgentMessageToolUse, AgentMessageToolResult, AgentMessageDone, AgentMessageError, AgentMessageUsage, AgentStatus, } from "./types/protocol.js";
28
28
  export type { SandboxProvider, DesktopSandboxProvider, } from "./types/sandbox.js";
29
29
  export { AgentComposeClient } from "./client.js";
30
- export type { RegisterResult, RegisterWorkflowInput, RuntimeSourceInput, InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult, ListSnapshotsOptions, TemplateRow, ListTemplatesOptions, CreateFactoryInput, UpdateFactoryInput, SecretOptions, SetSecretResult, SecretListEntry, CreateApiKeyInput, StreamRunLogsOptions, EventSubjectType, EventRow, ReportEventInput, ListEventsOptions, ListEventsResult, RunLogLine, ListRunLogsOptions, RegisteredRuntime, RunState, RunStatus, FactoryRow, SnapshotListEntry, SnapshotListResponse, ApiKey, ApiKeyCreated, UsageRollupRow, UsageResponse, CancelRunResponse, RequestAgentPauseOptions, RequestAgentPauseResponse, SendAgentMessageOptions, SendAgentMessageResponse, AnswerSteerOptions, } from "./client.js";
30
+ export type { RegisterResult, RegisterWorkflowInput, RuntimeSourceInput, InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult, ListSnapshotsOptions, TemplateRow, ListTemplatesOptions, CreateFactoryInput, UpdateFactoryInput, SecretOptions, SetSecretResult, SecretListEntry, CreateApiKeyInput, StreamRunLogsOptions, EventSubjectType, EventRow, ReportEventInput, ListEventsOptions, ListEventsResult, RunLogLine, ListRunLogsOptions, RegisteredRuntime, RunState, RunStatus, FactoryRow, SnapshotListEntry, SnapshotListResponse, ApiKey, ApiKeyCreated, UsageRollupRow, UsageResponse, CancelRunResponse, RequestAgentPauseOptions, RequestAgentPauseResponse, SendAgentMessageOptions, SendAgentMessageResponse, AnswerSteerOptions, ResumePauseOptions, ResumePauseResponse, ResumePauseSuccess, ResumePausePending, ResumePauseActor, } from "./client.js";
31
31
  export { parseSseStream } from "./sse.js";
32
32
  export { AgentComposeError } from "./errors.js";
33
33
  export { formatError } from "./utils/errors.js";
@@ -37,8 +37,15 @@ export { AgentStatusSchema } from "./utils/schemas.js";
37
37
  export { createClaudeRuntime, ClaudeRunner } from "./runtimes/claude.js";
38
38
  export type { ClaudeRuntimeConfig } from "./runtimes/claude.js";
39
39
  export { default as claudeRuntime } from "./runtimes/claude.js";
40
- export { createVercelRuntime, VercelRunner } from "./runtimes/vercel.js";
41
- export type { VercelRuntimeConfig } from "./runtimes/vercel.js";
40
+ export { createVercelRuntime, VercelRunner, listVercelRuntimeModels } from "./runtimes/vercel.js";
41
+ export type { VercelRuntimeConfig, VercelRuntimeModel } from "./runtimes/vercel.js";
42
+ export type { GatewayModelId } from "ai";
43
+ export { createCodexRuntime } from "./runtimes/codex.js";
44
+ export type { CodexRuntimeConfig } from "./runtimes/codex.js";
45
+ export { default as codexRuntime } from "./runtimes/codex.js";
46
+ export { createAmpRuntime } from "./runtimes/amp.js";
47
+ export type { AmpRuntimeConfig } from "./runtimes/amp.js";
48
+ export { default as ampRuntime } from "./runtimes/amp.js";
42
49
  export { bashTool, codingTools, editTool, readTool, writeTool } from "./tools/index.js";
43
50
  export type { CodingTool } from "./tools/index.js";
44
51
  export type { RunEvent } from "./types/events.js";
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ var __toESM = (mod, isNodeMode, target) => {
18
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
20
  // src/runtimes/vercel.ts
21
- import { streamText, stepCountIs, tool } from "ai";
21
+ import { streamText, stepCountIs, tool, gateway } from "ai";
22
22
 
23
23
  // src/types/runtime.ts
24
24
  function defineRuntime(pkg) {
@@ -387,6 +387,8 @@ class VercelRunner {
387
387
  options;
388
388
  config;
389
389
  supportsToolCallProcessor = true;
390
+ kind;
391
+ model;
390
392
  tools;
391
393
  messages = [];
392
394
  constructor(sandbox, options, config) {
@@ -394,6 +396,8 @@ class VercelRunner {
394
396
  this.options = options;
395
397
  this.config = config;
396
398
  this.tools = config.tools ?? codingTools;
399
+ this.kind = config.kind;
400
+ this.model = config.modelId;
397
401
  }
398
402
  async gateToolCall(call, ctx) {
399
403
  const verdict = await runProcessorChain(this.options.processors ?? [], (p) => p.processToolCall, call, ctx);
@@ -511,6 +515,10 @@ function createVercelRuntime(config) {
511
515
  create: (sandbox, opts) => new VercelRunner(sandbox, opts, config)
512
516
  });
513
517
  }
518
+ async function listVercelRuntimeModels() {
519
+ const { models } = await gateway.getAvailableModels();
520
+ return models.filter((m) => m.modelType == null || m.modelType === "language").map((m) => ({ id: m.id, name: m.name })).sort((a, b) => a.id.localeCompare(b.id));
521
+ }
514
522
  // src/types/workflow.ts
515
523
  import { z as z3 } from "zod";
516
524
 
@@ -2368,6 +2376,259 @@ function createClaudeRuntime(config = {}) {
2368
2376
  });
2369
2377
  }
2370
2378
  var claude_default = createClaudeRuntime();
2379
+ // src/runtimes/_cli-agent.ts
2380
+ function now3() {
2381
+ return new Date().toISOString();
2382
+ }
2383
+ function shellQuote(value) {
2384
+ return `'${value.replace(/'/g, `'\\''`)}'`;
2385
+ }
2386
+
2387
+ class CliAgentRunner {
2388
+ sandbox;
2389
+ options;
2390
+ spec;
2391
+ configModel;
2392
+ kind;
2393
+ constructor(sandbox, options, spec, configModel) {
2394
+ this.sandbox = sandbox;
2395
+ this.options = options;
2396
+ this.spec = spec;
2397
+ this.configModel = configModel;
2398
+ this.kind = spec.kind;
2399
+ }
2400
+ get model() {
2401
+ return this.configModel ?? this.options.model ?? this.spec.defaultModel;
2402
+ }
2403
+ installed = false;
2404
+ async ensureInstalled() {
2405
+ if (this.installed)
2406
+ return;
2407
+ const probe = await this.sandbox.commands.run(`command -v ${this.spec.bin}`);
2408
+ if (probe.exitCode === 0) {
2409
+ this.installed = true;
2410
+ return;
2411
+ }
2412
+ const res = await this.sandbox.commands.run(this.spec.install, { timeoutMs: 300000 });
2413
+ if (res.exitCode !== 0) {
2414
+ throw new Error(`failed to install ${this.spec.bin}: ${(res.stderr || res.stdout || "").slice(-500)}`);
2415
+ }
2416
+ this.installed = true;
2417
+ }
2418
+ async* sendMessage(opts) {
2419
+ yield { type: "init", sessionId: opts.sessionId ?? "", timestamp: now3() };
2420
+ let sessionId = opts.sessionId;
2421
+ let sawError = false;
2422
+ try {
2423
+ await this.ensureInstalled();
2424
+ const promptPath = `/tmp/ac-${this.spec.kind}-${this.options.agentId ?? "agent"}-${opts.iteration ?? 0}.in`;
2425
+ await this.sandbox.files.write(promptPath, this.spec.promptPayload(opts.prompt));
2426
+ const cmd = this.spec.buildCommand({
2427
+ promptPath,
2428
+ sessionId: opts.sessionId,
2429
+ model: this.model,
2430
+ cwd: this.options.cwd
2431
+ });
2432
+ const lines = new AsyncQueue;
2433
+ let buf = "";
2434
+ const onStdout = (data) => {
2435
+ buf += data;
2436
+ let nl;
2437
+ while ((nl = buf.indexOf(`
2438
+ `)) >= 0) {
2439
+ const line = buf.slice(0, nl).trim();
2440
+ buf = buf.slice(nl + 1);
2441
+ if (line)
2442
+ lines.push(line);
2443
+ }
2444
+ };
2445
+ const runPromise = this.sandbox.commands.run(cmd, {
2446
+ ...this.options.cwd ? { cwd: this.options.cwd } : {},
2447
+ onStdout
2448
+ }).then((res2) => {
2449
+ const tail = buf.trim();
2450
+ if (tail)
2451
+ lines.push(tail);
2452
+ lines.close();
2453
+ return res2;
2454
+ }, (err) => {
2455
+ lines.close();
2456
+ throw err;
2457
+ });
2458
+ for await (const line of lines) {
2459
+ let parsed;
2460
+ try {
2461
+ parsed = JSON.parse(line);
2462
+ } catch {
2463
+ continue;
2464
+ }
2465
+ const sid = this.spec.extractSessionId(parsed);
2466
+ if (sid)
2467
+ sessionId = sid;
2468
+ for (const msg of this.spec.mapEvent(parsed)) {
2469
+ if (msg.type === "error")
2470
+ sawError = true;
2471
+ yield msg;
2472
+ }
2473
+ }
2474
+ const res = await runPromise;
2475
+ if (res.exitCode !== 0 && !sawError) {
2476
+ const tail = (res.stderr ?? "").slice(-2000);
2477
+ yield { type: "error", text: `${this.spec.kind} exited with code ${res.exitCode}${tail ? `: ${tail}` : ""}`, timestamp: now3() };
2478
+ return;
2479
+ }
2480
+ if (!sawError)
2481
+ yield { type: "done", sessionId: sessionId ?? "", timestamp: now3() };
2482
+ } catch (err) {
2483
+ yield { type: "error", text: formatError(err), timestamp: now3() };
2484
+ }
2485
+ }
2486
+ }
2487
+ function createCliAgentRuntime(spec, configModel) {
2488
+ return defineRuntime({
2489
+ create: (sandbox, opts) => new CliAgentRunner(sandbox, opts, spec, configModel)
2490
+ });
2491
+ }
2492
+
2493
+ // src/runtimes/codex.ts
2494
+ function now4() {
2495
+ return new Date().toISOString();
2496
+ }
2497
+ var codexSpec = {
2498
+ kind: "codex",
2499
+ authEnv: "CODEX_API_KEY",
2500
+ bin: "codex",
2501
+ install: 'sudo npm install -g @openai/codex && (command -v codex >/dev/null 2>&1 || sudo ln -sf "$(npm prefix -g)/bin/codex" /usr/local/bin/codex)',
2502
+ promptPayload: (prompt) => prompt,
2503
+ buildCommand: ({ promptPath, sessionId, model, cwd }) => {
2504
+ const flags = [
2505
+ "--json",
2506
+ "--skip-git-repo-check",
2507
+ "--dangerously-bypass-approvals-and-sandbox",
2508
+ ...model ? ["-m", shellQuote(model)] : [],
2509
+ ...cwd ? ["-C", shellQuote(cwd)] : []
2510
+ ].join(" ");
2511
+ const exec = sessionId ? `codex exec resume ${shellQuote(sessionId)} ${flags}` : `codex exec ${flags}`;
2512
+ return `${exec} - < ${shellQuote(promptPath)}`;
2513
+ },
2514
+ extractSessionId: (p) => p.type === "thread.started" && typeof p.thread_id === "string" ? p.thread_id : undefined,
2515
+ mapEvent: (p) => {
2516
+ const ts = now4();
2517
+ switch (p.type) {
2518
+ case "item.started":
2519
+ case "item.completed": {
2520
+ const item = p.item;
2521
+ if (!item)
2522
+ return [];
2523
+ const itype = String(item.type ?? "");
2524
+ if (itype === "agent_message") {
2525
+ return p.type === "item.completed" ? [{ type: "text", text: String(item.text ?? ""), timestamp: ts }] : [];
2526
+ }
2527
+ if (itype === "reasoning") {
2528
+ return p.type === "item.completed" ? [{ type: "thinking", text: String(item.text ?? ""), timestamp: ts }] : [];
2529
+ }
2530
+ if (itype === "command_execution") {
2531
+ const id = String(item.id ?? "");
2532
+ if (p.type === "item.started") {
2533
+ return [{ type: "tool_use", toolName: "shell", toolInput: { command: String(item.command ?? "") }, toolUseId: id, timestamp: ts }];
2534
+ }
2535
+ const failed = item.status === "failed" || typeof item.exit_code === "number" && item.exit_code !== 0;
2536
+ return [{ type: "tool_result", toolUseId: id, output: String(item.aggregated_output ?? item.output ?? ""), isError: failed, timestamp: ts }];
2537
+ }
2538
+ if (p.type === "item.completed") {
2539
+ return [{ type: "tool_use", toolName: itype || "item", toolInput: item, toolUseId: String(item.id ?? ""), timestamp: ts }];
2540
+ }
2541
+ return [];
2542
+ }
2543
+ case "turn.completed": {
2544
+ const u = p.usage;
2545
+ if (!u)
2546
+ return [];
2547
+ return [{
2548
+ type: "usage",
2549
+ inputTokens: u.input_tokens ?? 0,
2550
+ outputTokens: u.output_tokens ?? 0,
2551
+ cacheReadTokens: u.cached_input_tokens ?? 0,
2552
+ cacheCreationTokens: 0,
2553
+ durationMs: 0,
2554
+ numTurns: 1,
2555
+ timestamp: ts
2556
+ }];
2557
+ }
2558
+ case "turn.failed":
2559
+ case "error":
2560
+ return [{ type: "error", text: formatError(p.error ?? p.message ?? p), timestamp: ts }];
2561
+ default:
2562
+ return [];
2563
+ }
2564
+ }
2565
+ };
2566
+ function createCodexRuntime(config = {}) {
2567
+ return createCliAgentRuntime(codexSpec, config.model);
2568
+ }
2569
+ var codex_default = createCodexRuntime();
2570
+ // src/runtimes/amp.ts
2571
+ function now5() {
2572
+ return new Date().toISOString();
2573
+ }
2574
+ function blocks(msg) {
2575
+ const inner = msg.message?.content ?? msg.content ?? [];
2576
+ return inner;
2577
+ }
2578
+ var ampSpec = {
2579
+ kind: "amp",
2580
+ authEnv: "AMP_API_KEY",
2581
+ bin: "amp",
2582
+ install: 'sudo npm install -g @ampcode/cli && (command -v amp >/dev/null 2>&1 || sudo ln -sf "$(npm prefix -g)/bin/amp" /usr/local/bin/amp)',
2583
+ promptPayload: (prompt) => JSON.stringify({ type: "user", message: { role: "user", content: [{ type: "text", text: prompt }] } }) + `
2584
+ `,
2585
+ buildCommand: ({ promptPath, sessionId }) => {
2586
+ const cont = sessionId ? `threads continue ${shellQuote(sessionId)} ` : "";
2587
+ return `amp ${cont}-x --stream-json --stream-json-input < ${shellQuote(promptPath)}`;
2588
+ },
2589
+ extractSessionId: (p) => typeof p.session_id === "string" ? p.session_id : undefined,
2590
+ mapEvent: (p) => {
2591
+ const ts = now5();
2592
+ if (p.type === "assistant") {
2593
+ return blocks(p).flatMap((b) => {
2594
+ if (b.type === "text")
2595
+ return [{ type: "text", text: String(b.text ?? ""), timestamp: ts }];
2596
+ if (b.type === "thinking")
2597
+ return [{ type: "thinking", text: String(b.thinking ?? ""), timestamp: ts }];
2598
+ if (b.type === "tool_use")
2599
+ return [{ type: "tool_use", toolName: String(b.name ?? ""), toolInput: b.input ?? {}, toolUseId: String(b.id ?? ""), timestamp: ts }];
2600
+ return [];
2601
+ });
2602
+ }
2603
+ if (p.type === "user") {
2604
+ return blocks(p).flatMap((b) => b.type === "tool_result" ? [{ type: "tool_result", toolUseId: String(b.tool_use_id ?? ""), output: typeof b.content === "string" ? b.content : JSON.stringify(b.content ?? ""), isError: Boolean(b.is_error), timestamp: ts }] : []);
2605
+ }
2606
+ if (p.type === "result") {
2607
+ const out = [];
2608
+ const u = p.usage;
2609
+ if (u)
2610
+ out.push({
2611
+ type: "usage",
2612
+ inputTokens: u.input_tokens ?? 0,
2613
+ outputTokens: u.output_tokens ?? 0,
2614
+ cacheReadTokens: u.cache_read_input_tokens ?? 0,
2615
+ cacheCreationTokens: u.cache_creation_input_tokens ?? 0,
2616
+ durationMs: Number(p.duration_ms ?? 0),
2617
+ numTurns: Number(p.num_turns ?? 0),
2618
+ timestamp: ts
2619
+ });
2620
+ if (p.is_error || p.subtype === "error") {
2621
+ out.push({ type: "error", text: formatError(p.result ?? p.error), timestamp: ts });
2622
+ }
2623
+ return out;
2624
+ }
2625
+ return [];
2626
+ }
2627
+ };
2628
+ function createAmpRuntime(config = {}) {
2629
+ return createCliAgentRuntime(ampSpec, config.model);
2630
+ }
2631
+ var amp_default = createAmpRuntime();
2371
2632
  // src/sandbox.ts
2372
2633
  import { promises as fs2 } from "node:fs";
2373
2634
  import { dirname as dirname2 } from "node:path";
@@ -3666,6 +3927,7 @@ export {
3666
3927
  parseAgentResponse,
3667
3928
  makeSandboxProvider,
3668
3929
  makeDesktopSandboxProvider,
3930
+ listVercelRuntimeModels,
3669
3931
  listOwnedSandboxes,
3670
3932
  killSandboxById,
3671
3933
  killAllSandboxes,
@@ -3683,8 +3945,11 @@ export {
3683
3945
  defineRuntime,
3684
3946
  createVercelRuntime,
3685
3947
  createSandbox,
3948
+ createCodexRuntime,
3686
3949
  createClaudeRuntime,
3950
+ createAmpRuntime,
3687
3951
  codingTools,
3952
+ codex_default as codexRuntime,
3688
3953
  claude_default as claudeRuntime,
3689
3954
  classifyError,
3690
3955
  bundleWorkflow,
@@ -3692,6 +3957,7 @@ export {
3692
3957
  buildInvokeChild,
3693
3958
  bashTool,
3694
3959
  assertDefaultExportIsDefineWorkflow,
3960
+ amp_default as ampRuntime,
3695
3961
  agentLoop,
3696
3962
  agent,
3697
3963
  WorkflowSourceValidationError,
@@ -0,0 +1,89 @@
1
+ /**
2
+ * CLI-agent runtime base — drive an external agentic coding CLI inside the
3
+ * sandbox and map its JSON-Lines (JSONL) stream onto the `AgentMessage`
4
+ * contract.
5
+ *
6
+ * This is a different *mechanism* from the other runtimes: `claudeRuntime`
7
+ * drives the Anthropic Agent SDK and `vercelRuntime` drives the Vercel AI SDK,
8
+ * but a CLI-agent runtime spawns the provider's own CLI (`codex exec --json`,
9
+ * `amp -x --stream-json`) — the CLI brings its own agent loop + tools, and we
10
+ * only stream-parse the events it prints. Codex and Amp are the first two; this
11
+ * base is the shared machinery (spawn → line-buffer stdout → JSONL parse →
12
+ * AsyncQueue bridge → init/usage/done/error lifecycle), parameterised per-CLI
13
+ * by a `CliAgentSpec`.
14
+ *
15
+ * Provisioning (per spec): the runtime installs the provider CLI on demand —
16
+ * `command -v <bin>` before the first turn, falling back to the spec's
17
+ * `install` command when it's absent — so it works on a bare sandbox with no
18
+ * manual setup or hardcoded snapshot id. Pair it with
19
+ * `snapshots: { bootFrom: "reuse" }` on the workflow and the install happens
20
+ * exactly once: the first run installs the CLI and captures a snapshot, and
21
+ * every run after boots from that snapshot with the CLI already present (the
22
+ * probe short-circuits). The provider's API key must be in the sandbox env
23
+ * (see each spec's `authEnv`); `commands.run` inherits the sandbox env, so
24
+ * values set via `agentc secrets set` are visible to the CLI.
25
+ */
26
+ import type { AgentMessage, ModelExecutionContract, RuntimeOptions, SandboxProvider } from "../index.js";
27
+ /** Single-quote a value for safe interpolation into a `sh -c` command line. */
28
+ export declare function shellQuote(value: string): string;
29
+ /** Per-CLI behaviour. The base owns the lifecycle (init/done/error) and the
30
+ * transport (spawn + JSONL parse); a spec owns the CLI-specific bits. */
31
+ export interface CliAgentSpec {
32
+ /** Runtime self-id surfaced on `agent.spawned` (dashboard runtime icon). */
33
+ kind: string;
34
+ /** Env var the CLI reads for auth — documentation only (must be set in the
35
+ * sandbox env via a workflow secret). */
36
+ authEnv: string;
37
+ /** Default model id when none is configured; omit to let the CLI choose. */
38
+ defaultModel?: string;
39
+ /** Binary the runtime spawns (`codex`, `amp`). Probed with `command -v`
40
+ * before the first turn; if absent, `install` provisions it. */
41
+ bin: string;
42
+ /** Shell command that installs `bin` when it's missing from the sandbox.
43
+ * Runs at most once per runner, and only when the probe fails — so booting
44
+ * from a snapshot that already has the CLI (the steady state under
45
+ * `snapshots: { bootFrom: "reuse" }`) skips it. Must leave `bin` resolvable
46
+ * on a non-login shell's PATH (the runtime spawns via `sh -c`). */
47
+ install: string;
48
+ /** Serialise the user prompt into the bytes written to the prompt file —
49
+ * plain text for a CLI that reads the prompt from stdin (codex `-`), or a
50
+ * JSONL user message for a `--stream-json-input` CLI (amp). */
51
+ promptPayload(prompt: string): string;
52
+ /** Build the one-shot shell command for a turn. `promptPath` is a file in the
53
+ * sandbox holding `promptPayload(prompt)`; `sessionId` continues a thread. */
54
+ buildCommand(args: {
55
+ promptPath: string;
56
+ sessionId?: string;
57
+ model?: string;
58
+ cwd?: string;
59
+ }): string;
60
+ /** Map one parsed JSONL stdout event to `AgentMessage`s. The base emits
61
+ * `init`/`done`/`error` lifecycle itself, so a spec maps only content +
62
+ * usage (text / thinking / tool_use / tool_result / usage). */
63
+ mapEvent(parsed: Record<string, unknown>): AgentMessage[];
64
+ /** Pull a session/thread id out of a parsed event so the next turn can
65
+ * resume it (codex `thread.started.thread_id`, amp `session_id`). */
66
+ extractSessionId(parsed: Record<string, unknown>): string | undefined;
67
+ }
68
+ export declare class CliAgentRunner implements ModelExecutionContract {
69
+ private readonly sandbox;
70
+ private readonly options;
71
+ private readonly spec;
72
+ private readonly configModel?;
73
+ readonly kind: string;
74
+ constructor(sandbox: SandboxProvider, options: RuntimeOptions, spec: CliAgentSpec, configModel?: string | undefined);
75
+ get model(): string | undefined;
76
+ private installed;
77
+ /** Provision the CLI on demand. A no-op once `bin` is on PATH — the steady
78
+ * state under `snapshots: { bootFrom: "reuse" }`, where the first run's
79
+ * install is baked into the snapshot every later run boots from. So the
80
+ * install command runs exactly once: on the first run of a content hash. */
81
+ private ensureInstalled;
82
+ sendMessage(opts: {
83
+ prompt: string;
84
+ sessionId?: string;
85
+ iteration?: number;
86
+ signal?: AbortSignal;
87
+ }): AsyncGenerator<AgentMessage>;
88
+ }
89
+ export declare function createCliAgentRuntime(spec: CliAgentSpec, configModel?: string): import("../index.js").AgentRuntime<SandboxProvider>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Amp CLI runtime — drives Sourcegraph's `amp -x --stream-json` agentic CLI
3
+ * inside the sandbox and maps its (Claude-Code-compatible) JSONL stream onto
4
+ * the AgentMessage contract. Built on the shared CLI-agent base; Amp brings its
5
+ * own loop + tools, so we only stream-parse what it prints.
6
+ *
7
+ * Auth: set `AMP_API_KEY` (`sgamp_…`) in the sandbox env via a workflow secret.
8
+ * The runtime installs the `amp` CLI (`@ampcode/cli`) on demand — no image
9
+ * baking needed; pair with `snapshots: { bootFrom: "reuse" }` to install once
10
+ * and boot from the captured snapshot on every run after. The model is chosen
11
+ * by the AMP_API_KEY account (e.g. a GPT-only token runs GPT); the runtime
12
+ * doesn't pin a model.
13
+ *
14
+ * Verified against a live `amp -x --stream-json` run: the user-message stdin
15
+ * shape, assistant content blocks, and result usage below all round-trip.
16
+ */
17
+ export interface AmpRuntimeConfig {
18
+ /** Amp uses its configured model; reserved for forward-compatibility. */
19
+ model?: string;
20
+ }
21
+ export declare function createAmpRuntime(config?: AmpRuntimeConfig): import("../index.js").AgentRuntime<import("../sandbox.js").SandboxProvider>;
22
+ declare const _default: import("../index.js").AgentRuntime<import("../sandbox.js").SandboxProvider>;
23
+ export default _default;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * CliAgentRunner self-provisioning — the runtime installs its CLI on demand
3
+ * (`command -v <bin>` → install if missing), runs the install at most once per
4
+ * runner, and surfaces an install failure as an `error` message rather than
5
+ * blowing up. This is what lets `createCodexRuntime()` work on a bare sandbox
6
+ * with no image baking, and lets `snapshots: { bootFrom: "reuse" }` collapse
7
+ * the install to a one-time cost.
8
+ */
9
+ export {};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Codex CLI runtime — drives OpenAI's `codex exec --json` agentic CLI inside
3
+ * the sandbox and maps its JSONL event stream onto the AgentMessage contract.
4
+ * Built on the shared CLI-agent base; Codex brings its own loop + tools, so we
5
+ * only stream-parse what it prints.
6
+ *
7
+ * Auth: set `OPENAI_API_KEY` (or `CODEX_API_KEY`) in the sandbox env via a
8
+ * workflow secret. The runtime installs the `codex` CLI (`@openai/codex`) on
9
+ * demand — no image baking needed; pair with `snapshots: { bootFrom: "reuse" }`
10
+ * to install once and boot from the captured snapshot on every run after.
11
+ *
12
+ * Verified against codex-cli 0.124.0: `codex exec --json` + resume-by-thread,
13
+ * with the command_execution / reasoning / agent_message item shapes below.
14
+ */
15
+ export interface CodexRuntimeConfig {
16
+ /** Codex model id (`-m`). Omit to use the codex CLI's configured default. */
17
+ model?: string;
18
+ }
19
+ export declare function createCodexRuntime(config?: CodexRuntimeConfig): import("../index.js").AgentRuntime<import("../sandbox.js").SandboxProvider>;
20
+ declare const _default: import("../index.js").AgentRuntime<import("../sandbox.js").SandboxProvider>;
21
+ export default _default;