@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 +11 -4
- package/dist/index.js +267 -1
- package/dist/runtimes/_cli-agent.d.ts +89 -0
- package/dist/runtimes/amp.d.ts +23 -0
- package/dist/runtimes/cli-agent.test.d.ts +9 -0
- package/dist/runtimes/codex.d.ts +21 -0
- package/dist/runtimes/openai-desktop.js +262 -1
- package/dist/runtimes/vercel.d.ts +41 -1
- package/dist/runtimes/vercel.js +10 -1
- package/dist/types/workflow-metadata.d.ts +19 -11
- package/dist/types/workflow.d.ts +2 -2
- package/package.json +1 -1
- package/src/index.ts +21 -2
- package/src/runtimes/_cli-agent.ts +194 -0
- package/src/runtimes/amp.ts +99 -0
- package/src/runtimes/codex.ts +114 -0
- package/src/runtimes/vercel.ts +52 -2
- package/src/types/workflow-metadata.ts +20 -11
- package/src/types/workflow.ts +2 -2
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;
|