@sandagent/runner-cli 0.1.2 → 0.2.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.
package/README.md CHANGED
@@ -1,8 +1,33 @@
1
1
  # @sandagent/runner-cli
2
2
 
3
- SandAgent Runner CLI - A command-line interface for running AI agents locally in your terminal.
3
+ SandAgent Runner CLI - A **lightweight, local** command-line interface for running AI agents in your terminal.
4
4
 
5
- Like gemini-cli or claude-code, this tool runs locally and streams AI SDK UI messages directly to stdout.
5
+ Like gemini-cli, claude-code, or codex-cli, this tool runs **directly on your local filesystem** and streams AI SDK UI messages to stdout.
6
+
7
+ ## 🎯 Key Features
8
+
9
+ - 🔌 **Choose Different Runners**: Switch between Claude, Codex, Copilot with `--runner` flag
10
+ - 🚀 **Local Execution**: Runs directly on your filesystem, no sandbox required
11
+ - 💨 **Lightweight**: No manager dependency, minimal overhead
12
+ - 📡 **Streaming**: Real-time AI SDK UI streaming
13
+
14
+ ## 📐 Architecture
15
+
16
+ ```
17
+ runner-cli → runner-* (direct, NO dependencies on manager or sandbox)
18
+ ├─ runner-claude ✅
19
+ ├─ runner-codex 🚧
20
+ └─ runner-copilot 🚧
21
+
22
+ Dependencies:
23
+ ✅ @sandagent/runner-claude (runtime)
24
+ ❌ NO @sandagent/manager
25
+ ❌ NO @sandagent/sandbox-*
26
+ ```
27
+
28
+ **Difference from manager-cli:**
29
+ - `runner-cli`: Local filesystem, no isolation, lightweight, direct runner usage
30
+ - `manager-cli`: Sandboxed execution, uses manager + sandbox adapters + runner
6
31
 
7
32
  ## Installation
8
33
 
@@ -19,17 +44,27 @@ sandagent run [options] -- "<user input>"
19
44
  ### Basic Examples
20
45
 
21
46
  ```bash
22
- # Simple task
47
+ # Using Claude (default)
23
48
  sandagent run -- "Create a hello world script"
24
49
 
50
+ # Explicitly choose Claude
51
+ sandagent run --runner claude -- "Create a hello world script"
52
+
53
+ # Using Codex (when implemented)
54
+ sandagent run --runner codex -- "Build a REST API with Express"
55
+
56
+ # Using GitHub Copilot (when implemented)
57
+ sandagent run --runner copilot -- "Refactor this code"
58
+
25
59
  # With custom system prompt
26
- sandagent run --system-prompt "You are a coding assistant" -- "Build a REST API with Express"
60
+ sandagent run --runner claude --system-prompt "You are a coding assistant" -- "Build a REST API with Express"
27
61
  ```
28
62
 
29
63
  ## Options
30
64
 
31
65
  | Option | Short | Description | Default |
32
66
  |--------|-------|-------------|---------|
67
+ | `--runner <runner>` | `-r` | Runner to use: `claude`, `codex`, `copilot` | `claude` |
33
68
  | `--model <model>` | `-m` | Model to use | `claude-sonnet-4-20250514` |
34
69
  | `--cwd <path>` | `-c` | Working directory | Current directory |
35
70
  | `--system-prompt <prompt>` | `-s` | Custom system prompt | - |
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Integration tests for runner-cli
3
+ * Tests actual process execution
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=runner-cli.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-cli.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/runner-cli.integration.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Integration tests for runner-cli
3
+ * Tests actual process execution
4
+ */
5
+ import { spawn } from "node:child_process";
6
+ import { join } from "node:path";
7
+ import { describe, expect, it } from "vitest";
8
+ // Get CLI path - works in both compiled and source context
9
+ const CLI_PATH = join(process.cwd(), "dist/bundle.mjs");
10
+ describe("runner-cli Integration Tests", () => {
11
+ const TIMEOUT = 10000;
12
+ it("should display help message", async () => {
13
+ const output = await runCLI(["--help"]);
14
+ expect(output.stdout).toContain("SandAgent Runner CLI");
15
+ expect(output.stdout).toContain("--runner");
16
+ expect(output.stdout).toContain("--model");
17
+ expect(output.exitCode).toBe(0);
18
+ }, TIMEOUT);
19
+ it("should show error when no user input provided", async () => {
20
+ const output = await runCLI(["run"]);
21
+ expect(output.stderr).toContain("User input is required");
22
+ expect(output.exitCode).toBe(1);
23
+ }, TIMEOUT);
24
+ it("should show error for invalid runner", async () => {
25
+ const output = await runCLI([
26
+ "run",
27
+ "--runner",
28
+ "invalid",
29
+ "--",
30
+ "test task",
31
+ ]);
32
+ expect(output.stderr).toContain("must be one of");
33
+ expect(output.exitCode).toBe(1);
34
+ }, TIMEOUT);
35
+ it("should accept claude runner option", async () => {
36
+ // This will fail without API key, but should parse arguments correctly
37
+ const output = await runCLI(["run", "--runner", "claude", "--", "echo hello"], {
38
+ env: { ...process.env, ANTHROPIC_API_KEY: "" },
39
+ });
40
+ // Should fail due to missing API key, not argument parsing
41
+ expect(output.stderr).toContain("ANTHROPIC_API_KEY");
42
+ }, TIMEOUT);
43
+ });
44
+ /**
45
+ * Helper to run CLI and capture output
46
+ */
47
+ function runCLI(args, options = {}) {
48
+ return new Promise((resolve, reject) => {
49
+ const proc = spawn("node", [CLI_PATH, ...args], {
50
+ env: options.env || process.env,
51
+ stdio: "pipe",
52
+ });
53
+ let stdout = "";
54
+ let stderr = "";
55
+ proc.stdout?.on("data", (data) => {
56
+ stdout += data.toString();
57
+ });
58
+ proc.stderr?.on("data", (data) => {
59
+ stderr += data.toString();
60
+ });
61
+ proc.on("close", (code) => {
62
+ resolve({
63
+ stdout,
64
+ stderr,
65
+ exitCode: code || 0,
66
+ });
67
+ });
68
+ proc.on("error", reject);
69
+ // Timeout
70
+ setTimeout(() => {
71
+ proc.kill();
72
+ reject(new Error("Process timed out"));
73
+ }, 15000);
74
+ });
75
+ }
76
+ //# sourceMappingURL=runner-cli.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-cli.integration.test.js","sourceRoot":"","sources":["../../src/__tests__/runner-cli.integration.test.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ describe("runAgent", () => {
27
27
  });
28
28
  it("should create a Claude runner with correct options (with default template)", async () => {
29
29
  await runAgent({
30
+ runner: "claude",
30
31
  model: "claude-sonnet-4-20250514",
31
32
  userInput: "Hello, world!",
32
33
  });
@@ -40,6 +41,7 @@ describe("runAgent", () => {
40
41
  });
41
42
  it("should pass optional parameters to runner (overriding template)", async () => {
42
43
  await runAgent({
44
+ runner: "claude",
43
45
  model: "claude-sonnet-4-20250514",
44
46
  userInput: "Hello, world!",
45
47
  systemPrompt: "You are a helpful assistant",
@@ -47,15 +49,16 @@ describe("runAgent", () => {
47
49
  allowedTools: ["bash", "write_file"],
48
50
  });
49
51
  // Explicit parameters override template values
50
- expect(createClaudeRunner).toHaveBeenCalledWith({
52
+ expect(createClaudeRunner).toHaveBeenCalledWith(expect.objectContaining({
51
53
  model: "claude-sonnet-4-20250514",
52
54
  systemPrompt: "You are a helpful assistant",
53
55
  maxTurns: 5,
54
56
  allowedTools: ["bash", "write_file"],
55
- });
57
+ }));
56
58
  });
57
59
  it("should stream output to stdout without modification", async () => {
58
60
  await runAgent({
61
+ runner: "claude",
59
62
  model: "claude-sonnet-4-20250514",
60
63
  userInput: "Hello, world!",
61
64
  });
@@ -70,10 +73,11 @@ describe("runAgent", () => {
70
73
  };
71
74
  vi.mocked(createClaudeRunner).mockReturnValue(mockRunner);
72
75
  await runAgent({
76
+ runner: "claude",
73
77
  model: "claude-sonnet-4-20250514",
74
78
  userInput: "Create a file",
75
79
  });
76
- expect(mockRunner.run).toHaveBeenCalledWith("Create a file", expect.any(AbortSignal));
80
+ expect(mockRunner.run).toHaveBeenCalledWith("Create a file");
77
81
  });
78
82
  });
79
83
  //# sourceMappingURL=runner.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.test.js","sourceRoot":"","sources":["../../src/__tests__/runner.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.test.js","sourceRoot":"","sources":["../../src/__tests__/runner.test.ts"],"names":[],"mappings":"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"}
package/dist/bundle.mjs CHANGED
@@ -3,6 +3,243 @@
3
3
  // src/cli.ts
4
4
  import { parseArgs } from "node:util";
5
5
 
6
+ // ../../packages/runner-claude/dist/ai-sdk-stream.js
7
+ import { writeFile } from "node:fs/promises";
8
+ import { join } from "node:path";
9
+ var UNKNOWN_TOOL_NAME = "unknown-tool";
10
+ function formatDataStream(data) {
11
+ return `data: ${JSON.stringify(data)}
12
+
13
+ `;
14
+ }
15
+ function generateId() {
16
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
17
+ }
18
+ function convertUsageToAISDK(usage) {
19
+ const inputTokens = usage.input_tokens ?? 0;
20
+ const outputTokens = usage.output_tokens ?? 0;
21
+ const cacheWrite = usage.cache_creation_input_tokens ?? 0;
22
+ const cacheRead = usage.cache_read_input_tokens ?? 0;
23
+ return {
24
+ inputTokens: {
25
+ total: inputTokens + cacheWrite + cacheRead,
26
+ noCache: inputTokens,
27
+ cacheRead,
28
+ cacheWrite
29
+ },
30
+ outputTokens: { total: outputTokens },
31
+ raw: usage
32
+ };
33
+ }
34
+ function mapFinishReason(subtype, isError) {
35
+ if (isError)
36
+ return "error";
37
+ switch (subtype) {
38
+ case "success":
39
+ return "stop";
40
+ case "error_max_turns":
41
+ return "length";
42
+ case "error_during_execution":
43
+ case "error_max_structured_output_retries":
44
+ return "error";
45
+ case void 0:
46
+ return "stop";
47
+ default:
48
+ return "other";
49
+ }
50
+ }
51
+ function extractToolUses(content) {
52
+ if (!Array.isArray(content))
53
+ return [];
54
+ return content.filter((item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_use").map((item) => ({
55
+ id: item.id || generateId(),
56
+ name: item.name || UNKNOWN_TOOL_NAME,
57
+ input: item.input
58
+ }));
59
+ }
60
+ var AISDKStreamConverter = class {
61
+ systemMessage;
62
+ hasEmittedStart = false;
63
+ accumulatedText = "";
64
+ textPartId;
65
+ streamedTextLength = 0;
66
+ // Track text already emitted via stream_events
67
+ hasReceivedStreamEvents = false;
68
+ sessionId;
69
+ partIdMap = /* @__PURE__ */ new Map();
70
+ /**
71
+ * Get the current session ID from the stream
72
+ */
73
+ get currentSessionId() {
74
+ if (!this.sessionId) {
75
+ throw new Error("Session ID is not set");
76
+ }
77
+ return this.sessionId;
78
+ }
79
+ /**
80
+ * Helper to emit SSE data
81
+ */
82
+ emit(data) {
83
+ return formatDataStream(data);
84
+ }
85
+ setPartId(index, partId) {
86
+ const partIdKey = `${this.currentSessionId}-${index}`;
87
+ this.partIdMap.set(partIdKey, partId);
88
+ }
89
+ getPartId(index) {
90
+ const partIdKey = `${this.currentSessionId}-${index}`;
91
+ if (this.partIdMap.has(partIdKey)) {
92
+ return this.partIdMap.get(partIdKey) ?? "";
93
+ }
94
+ throw new Error("Part ID not found");
95
+ }
96
+ /**
97
+ * Helper to emit tool call
98
+ */
99
+ *emitToolCall(message) {
100
+ const event = message.event;
101
+ if (event.type === "content_block_start" && event.content_block.type === "tool_use") {
102
+ const toolCallId = event.content_block.id;
103
+ this.setPartId(event.index, toolCallId);
104
+ yield this.emit({
105
+ type: "tool-input-start",
106
+ toolCallId,
107
+ toolName: event.content_block.name,
108
+ dynamic: true,
109
+ providerExecuted: true
110
+ });
111
+ }
112
+ if (event.type === "content_block_delta" && event.delta?.type === "input_json_delta") {
113
+ yield this.emit({
114
+ type: "tool-input-delta",
115
+ toolCallId: this.getPartId(event.index),
116
+ inputTextDelta: event.delta.partial_json
117
+ });
118
+ }
119
+ }
120
+ *emitTextBlockEvent(event) {
121
+ if (event.type === "content_block_start" && event.content_block.type === "text") {
122
+ const partId = `text_${generateId()}`;
123
+ this.setPartId(event.index, partId);
124
+ yield this.emit({
125
+ type: "text-start",
126
+ id: partId
127
+ });
128
+ }
129
+ if (event.type === "content_block_delta" && event.delta?.type === "text_delta") {
130
+ yield this.emit({
131
+ type: "text-delta",
132
+ id: this.getPartId(event.index),
133
+ delta: event.delta.text
134
+ });
135
+ }
136
+ if (event.type === "content_block_stop") {
137
+ const partId = this.getPartId(event.index);
138
+ if (partId.startsWith("text_")) {
139
+ yield this.emit({ type: "text-end", id: partId });
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Stream SDK messages and convert to AI SDK UI Data Stream format
145
+ */
146
+ async *stream(messageIterator, options) {
147
+ const debugMessages = [];
148
+ const debugFile = `ai-sdk-stream-debug-${Date.now()}.json`;
149
+ try {
150
+ for await (const message of messageIterator) {
151
+ debugMessages.push(message);
152
+ if (message.type === "system" && message.subtype === "init") {
153
+ this.systemMessage = message;
154
+ this.sessionId = this.systemMessage.session_id;
155
+ }
156
+ if (message.type === "stream_event") {
157
+ const streamEvent = message;
158
+ const event = streamEvent.event;
159
+ if (event.type === "message_start" && !this.hasEmittedStart) {
160
+ this.hasEmittedStart = true;
161
+ yield this.emit({ type: "start", messageId: event.message.id });
162
+ yield this.emit({
163
+ type: "message-metadata",
164
+ messageMetadata: {
165
+ tools: this.systemMessage?.tools,
166
+ model: this.systemMessage?.model,
167
+ sessionId: this.systemMessage?.session_id,
168
+ agents: this.systemMessage?.agents,
169
+ skills: this.systemMessage?.skills
170
+ }
171
+ });
172
+ }
173
+ yield* this.emitTextBlockEvent(event);
174
+ yield* this.emitToolCall(streamEvent);
175
+ }
176
+ if (message.type === "assistant") {
177
+ const assistantMsg = message;
178
+ const content = assistantMsg.message?.content;
179
+ if (!content)
180
+ continue;
181
+ const tools = extractToolUses(content);
182
+ for (const tool of tools) {
183
+ yield this.emit({
184
+ type: "tool-input-available",
185
+ toolCallId: tool.id,
186
+ toolName: tool.name,
187
+ input: tool.input,
188
+ dynamic: true,
189
+ providerExecuted: true
190
+ });
191
+ }
192
+ }
193
+ if (message.type === "user") {
194
+ const userMsg = message;
195
+ const content = userMsg.message?.content;
196
+ for (const part of content) {
197
+ if (part.type === "tool_result") {
198
+ yield this.emit({
199
+ type: "tool-output-available",
200
+ toolCallId: part.tool_use_id,
201
+ output: message.tool_use_result || part.content,
202
+ dynamic: true,
203
+ providerExecuted: true
204
+ });
205
+ }
206
+ }
207
+ }
208
+ if (message.type === "result") {
209
+ const resultMsg = message;
210
+ const finishTime = (/* @__PURE__ */ new Date()).toISOString();
211
+ console.error(`[AISDKStream] Processing result message at ${finishTime}`);
212
+ const finishEvent = this.emit({
213
+ type: "finish",
214
+ finishReason: mapFinishReason(resultMsg.subtype, resultMsg.is_error),
215
+ messageMetadata: {
216
+ usage: convertUsageToAISDK(resultMsg.usage ?? {})
217
+ }
218
+ });
219
+ console.error(`[AISDKStream] Emitting finish event at ${(/* @__PURE__ */ new Date()).toISOString()}`);
220
+ yield finishEvent;
221
+ console.error(`[AISDKStream] Emitted [DONE] at ${(/* @__PURE__ */ new Date()).toISOString()}`);
222
+ }
223
+ }
224
+ } catch (error) {
225
+ debugMessages.push(error);
226
+ } finally {
227
+ if (debugMessages.length > 0) {
228
+ writeFile(join(process.cwd(), debugFile), JSON.stringify(debugMessages, null, 2), "utf-8").catch((writeError) => {
229
+ console.error(`[AISDKStream] Failed to write debug file:`, writeError);
230
+ });
231
+ }
232
+ options?.onCleanup?.();
233
+ yield `data: [DONE]
234
+
235
+ `;
236
+ }
237
+ }
238
+ };
239
+ function streamSDKMessagesToAISDKUI(messageIterator, options) {
240
+ return new AISDKStreamConverter().stream(messageIterator, options);
241
+ }
242
+
6
243
  // ../../packages/runner-claude/dist/claude-runner.js
7
244
  function createCanUseToolCallback(claudeOptions) {
8
245
  return async (toolName, input, options) => {
@@ -43,7 +280,7 @@ function createCanUseToolCallback(claudeOptions) {
43
280
  }
44
281
  };
45
282
  }
46
- } catch (error) {
283
+ } catch {
47
284
  }
48
285
  await new Promise((resolve) => setTimeout(resolve, 500));
49
286
  }
@@ -78,22 +315,19 @@ var OPTIONAL_MODULES = {
78
315
  };
79
316
  function createClaudeRunner(options) {
80
317
  return {
81
- async *run(userInput, signal) {
82
- if (signal?.aborted) {
83
- return;
84
- }
318
+ async *run(userInput) {
85
319
  const apiKey = process.env.ANTHROPIC_API_KEY || process.env.AWS_BEARER_TOKEN_BEDROCK;
86
320
  if (!apiKey) {
87
321
  console.error("[SandAgent] Warning: ANTHROPIC_API_KEY or AWS_BEARER_TOKEN_BEDROCK not set. Using mock response.\nTo use the real Claude Agent SDK:\n1. Set ANTHROPIC_API_KEY or AWS_BEARER_TOKEN_BEDROCK environment variable\n2. Install the SDK: npm install @anthropic-ai/claude-agent-sdk");
88
- yield* runMockAgent(options, userInput, signal);
322
+ yield* runMockAgent(options, userInput, options.abortController?.signal);
89
323
  return;
90
324
  }
91
325
  const sdk = await loadClaudeAgentSDK();
92
326
  if (sdk) {
93
- yield* runWithClaudeAgentSDK(sdk, options, userInput, signal);
327
+ yield* runWithClaudeAgentSDK(sdk, options, userInput);
94
328
  } else {
95
329
  console.error("[SandAgent] Warning: @anthropic-ai/claude-agent-sdk not installed. Using mock response.\nInstall the SDK: npm install @anthropic-ai/claude-agent-sdk");
96
- yield* runMockAgent(options, userInput, signal);
330
+ yield* runMockAgent(options, userInput, options.abortController?.signal);
97
331
  }
98
332
  }
99
333
  };
@@ -110,21 +344,21 @@ async function loadClaudeAgentSDK() {
110
344
  return null;
111
345
  }
112
346
  }
113
- async function* runWithClaudeAgentSDK(sdk, options, userInput, signal) {
347
+ async function* runWithClaudeAgentSDK(sdk, options, userInput) {
114
348
  const outputFormat = options.outputFormat || "stream-json";
115
349
  switch (outputFormat) {
116
350
  case "text":
117
- yield* runWithTextOutput(sdk, options, userInput, signal);
351
+ yield* runWithTextOutput(sdk, options, userInput);
118
352
  break;
119
353
  case "json":
120
- yield* runWithJSONOutput(sdk, options, userInput, signal);
354
+ yield* runWithJSONOutput(sdk, options, userInput);
121
355
  break;
122
356
  case "stream-json":
123
- yield* runWithStreamJSONOutput(sdk, options, userInput, signal);
357
+ yield* runWithStreamJSONOutput(sdk, options, userInput);
124
358
  break;
125
359
  // case "stream":
126
360
  default:
127
- yield* runWithAISDKUIOutput(sdk, options, userInput, signal);
361
+ yield* runWithAISDKUIOutput(sdk, options, userInput);
128
362
  break;
129
363
  }
130
364
  }
@@ -133,7 +367,12 @@ function createSDKOptions(options) {
133
367
  model: options.model,
134
368
  systemPrompt: options.systemPrompt,
135
369
  maxTurns: options.maxTurns,
136
- allowedTools: [...options.allowedTools ?? [], "Skill"],
370
+ allowedTools: [
371
+ ...options.allowedTools ?? [],
372
+ "Skill",
373
+ "WebSearch",
374
+ "WebFetch"
375
+ ],
137
376
  cwd: options.cwd,
138
377
  env: options.env,
139
378
  resume: options.resume,
@@ -141,13 +380,16 @@ function createSDKOptions(options) {
141
380
  canUseTool: createCanUseToolCallback(options),
142
381
  // Bypass all permission checks for automated execution
143
382
  permissionMode: "bypassPermissions",
144
- allowDangerouslySkipPermissions: true
383
+ allowDangerouslySkipPermissions: true,
384
+ // Enable partial messages for streaming
385
+ includePartialMessages: options.includePartialMessages
145
386
  };
146
387
  }
147
388
  function setupAbortHandler(queryIterator, signal) {
148
389
  const abortHandler = async () => {
149
- console.error("[ClaudeRunner] Operation aborted, calling query.interrupt()");
390
+ console.error("[ClaudeRunner] Abort signal received, will call query.interrupt()...");
150
391
  await queryIterator.interrupt();
392
+ console.error("[ClaudeRunner] query.interrupt() completed");
151
393
  };
152
394
  if (signal) {
153
395
  console.error("[ClaudeRunner] Signal provided, adding abort listener");
@@ -163,7 +405,7 @@ function setupAbortHandler(queryIterator, signal) {
163
405
  async function* runWithTextOutput(sdk, options, userInput, signal) {
164
406
  const sdkOptions = createSDKOptions(options);
165
407
  const queryIterator = sdk.query({ prompt: userInput, options: sdkOptions });
166
- const abortHandler = setupAbortHandler(queryIterator, signal);
408
+ const abortHandler = setupAbortHandler(queryIterator, options.abortController?.signal);
167
409
  try {
168
410
  let resultText = "";
169
411
  for await (const message of queryIterator) {
@@ -215,170 +457,14 @@ async function* runWithStreamJSONOutput(sdk, options, userInput, signal) {
215
457
  }
216
458
  }
217
459
  }
218
- async function* runWithAISDKUIOutput(sdk, options, userInput, signal) {
219
- const usage = { inputTokens: 0, outputTokens: 0 };
220
- let systemMessage;
221
- let messageId;
222
- const sdkOptions = createSDKOptions(options);
460
+ async function* runWithAISDKUIOutput(sdk, options, userInput) {
461
+ const sdkOptions = createSDKOptions({
462
+ ...options,
463
+ includePartialMessages: true
464
+ });
223
465
  const queryIterator = sdk.query({ prompt: userInput, options: sdkOptions });
224
- const abortHandler = setupAbortHandler(queryIterator, signal);
225
- try {
226
- for await (const message of queryIterator) {
227
- if (message.type === "system" && message.subtype === "init") {
228
- systemMessage = message;
229
- continue;
230
- }
231
- if (message.type === "assistant" && !messageId && systemMessage) {
232
- messageId = message.message.id;
233
- yield formatDataStream({
234
- type: "start",
235
- messageId
236
- });
237
- yield formatDataStream({
238
- type: "message-metadata",
239
- messageMetadata: {
240
- tools: systemMessage.tools,
241
- model: systemMessage.model,
242
- sessionId: systemMessage.session_id
243
- }
244
- });
245
- }
246
- const chunks = convertSDKMessageToAISDKUI(message);
247
- for (const chunk of chunks) {
248
- yield chunk;
249
- }
250
- }
251
- } catch (error) {
252
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
253
- console.error("[ClaudeRunner] Error:", errorMessage);
254
- yield formatDataStream({ type: "error", errorText: errorMessage });
255
- yield formatDataStream({
256
- type: "finish",
257
- finishReason: "error",
258
- usage: {
259
- promptTokens: usage.inputTokens,
260
- completionTokens: usage.outputTokens
261
- }
262
- });
263
- } finally {
264
- if (signal) {
265
- signal.removeEventListener("abort", abortHandler);
266
- }
267
- yield `data: [DONE]
268
-
269
- `;
270
- }
271
- }
272
- function convertSDKMessageToAISDKUI(message) {
273
- const chunks = [];
274
- switch (message.type) {
275
- case "assistant": {
276
- const assistantMsg = message;
277
- if (assistantMsg.error) {
278
- const errorDetail = message.message.content.map((c) => c.text).join("\n");
279
- chunks.push(formatDataStream({
280
- type: "error",
281
- errorText: `${assistantMsg.error}: ${errorDetail}`
282
- }));
283
- break;
284
- }
285
- if (assistantMsg.message) {
286
- if (typeof assistantMsg.message === "string") {
287
- const textId = generateId();
288
- chunks.push(formatDataStream({ type: "text-start", id: textId }));
289
- chunks.push(formatDataStream({
290
- type: "text-delta",
291
- id: textId,
292
- delta: assistantMsg.message
293
- }));
294
- chunks.push(formatDataStream({ type: "text-end", id: textId }));
295
- } else if (assistantMsg.message.content && Array.isArray(assistantMsg.message.content)) {
296
- for (const block of assistantMsg.message.content) {
297
- if (block.type === "text" && block.text) {
298
- const textId = generateId();
299
- chunks.push(formatDataStream({ type: "text-start", id: textId }));
300
- chunks.push(formatDataStream({
301
- type: "text-delta",
302
- id: textId,
303
- delta: block.text
304
- }));
305
- chunks.push(formatDataStream({ type: "text-end", id: textId }));
306
- } else if (block.type === "tool_use") {
307
- const toolCallId = block.id || generateId();
308
- chunks.push(formatDataStream({
309
- type: "tool-input-start",
310
- toolCallId,
311
- toolName: block.name,
312
- dynamic: true
313
- }));
314
- if (block.input) {
315
- chunks.push(formatDataStream({
316
- type: "tool-input-available",
317
- toolCallId,
318
- toolName: block.name,
319
- dynamic: true,
320
- input: block.input
321
- }));
322
- }
323
- }
324
- }
325
- }
326
- }
327
- break;
328
- }
329
- case "result": {
330
- const resultMsg = message;
331
- chunks.push(formatDataStream({
332
- type: "finish",
333
- finishReason: resultMsg.is_error ? "error" : "stop",
334
- messageMetadata: {
335
- usage: resultMsg.usage,
336
- duration_ms: resultMsg.duration_ms,
337
- num_turns: resultMsg.num_turns,
338
- total_cost_usd: resultMsg.total_cost_usd
339
- }
340
- }));
341
- break;
342
- }
343
- case "user": {
344
- const usrMsg = message;
345
- if (usrMsg.isSynthetic) {
346
- break;
347
- }
348
- const contentArray = usrMsg.message.content;
349
- if (usrMsg.tool_use_result || Array.isArray(contentArray) && contentArray.some((c) => c.type === "tool_result")) {
350
- for (const tool of contentArray) {
351
- if (tool.is_error) {
352
- chunks.push(formatDataStream({
353
- type: "tool-output-error",
354
- toolCallId: tool.tool_use_id,
355
- errorText: tool.content,
356
- dynamic: true
357
- }));
358
- } else {
359
- chunks.push(formatDataStream({
360
- type: "tool-output-available",
361
- toolCallId: tool.tool_use_id,
362
- output: usrMsg.tool_use_result || tool.content,
363
- dynamic: true
364
- }));
365
- }
366
- }
367
- }
368
- break;
369
- }
370
- default:
371
- break;
372
- }
373
- return chunks;
374
- }
375
- function formatDataStream(data) {
376
- return `data: ${JSON.stringify(data)}
377
-
378
- `;
379
- }
380
- function generateId() {
381
- return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
466
+ setupAbortHandler(queryIterator, options.abortController?.signal);
467
+ yield* streamSDKMessagesToAISDKUI(queryIterator);
382
468
  }
383
469
  async function* runMockAgent(options, userInput, signal) {
384
470
  if (signal?.aborted) {
@@ -386,6 +472,11 @@ async function* runMockAgent(options, userInput, signal) {
386
472
  return;
387
473
  }
388
474
  try {
475
+ const messageId = generateId();
476
+ yield formatDataStream({
477
+ type: "start",
478
+ messageId
479
+ });
389
480
  const response = `I received your request: "${userInput}"
390
481
 
391
482
  Model: ${options.model}
@@ -413,7 +504,13 @@ Documentation: https://platform.claude.com/docs/en/agent-sdk/typescript-v2-previ
413
504
  yield formatDataStream({ type: "text-end", id: textId });
414
505
  yield formatDataStream({
415
506
  type: "finish",
416
- finishReason: "stop"
507
+ finishReason: mapFinishReason("success"),
508
+ usage: convertUsageToAISDK({
509
+ input_tokens: 0,
510
+ output_tokens: 0,
511
+ cache_creation_input_tokens: 0,
512
+ cache_read_input_tokens: 0
513
+ })
417
514
  });
418
515
  yield `data: [DONE]
419
516
 
@@ -424,7 +521,13 @@ Documentation: https://platform.claude.com/docs/en/agent-sdk/typescript-v2-previ
424
521
  yield formatDataStream({ type: "error", errorText: errorMessage });
425
522
  yield formatDataStream({
426
523
  type: "finish",
427
- finishReason: "error"
524
+ finishReason: mapFinishReason("error_during_execution", true),
525
+ usage: convertUsageToAISDK({
526
+ input_tokens: 0,
527
+ output_tokens: 0,
528
+ cache_creation_input_tokens: 0,
529
+ cache_read_input_tokens: 0
530
+ })
428
531
  });
429
532
  yield `data: [DONE]
430
533
 
@@ -435,29 +538,47 @@ Documentation: https://platform.claude.com/docs/en/agent-sdk/typescript-v2-previ
435
538
  // src/runner.ts
436
539
  async function runAgent(options) {
437
540
  const abortController = new AbortController();
438
- const signalHandler = () => {
541
+ const signalHandler = async () => {
439
542
  console.error("[Runner] Received termination signal, stopping...");
440
543
  abortController.abort();
441
- console.error("[Runner] AbortController.abort() called");
544
+ console.error(
545
+ "[Runner] AbortController.abort() completed (listeners triggered)"
546
+ );
442
547
  };
443
548
  process.on("SIGTERM", signalHandler);
444
549
  process.on("SIGINT", signalHandler);
445
550
  console.error("[Runner] Signal handlers registered");
446
551
  try {
447
- const runnerOptions = {
448
- model: options.model,
449
- systemPrompt: options.systemPrompt,
450
- maxTurns: options.maxTurns,
451
- allowedTools: options.allowedTools,
452
- resume: options.resume,
453
- approvalDir: options.approvalDir,
454
- outputFormat: options.outputFormat
455
- };
456
- const runner = createClaudeRunner(runnerOptions);
457
- for await (const chunk of runner.run(
458
- options.userInput,
459
- abortController.signal
460
- )) {
552
+ let runner;
553
+ switch (options.runner) {
554
+ case "claude": {
555
+ const runnerOptions = {
556
+ model: options.model,
557
+ systemPrompt: options.systemPrompt,
558
+ maxTurns: options.maxTurns,
559
+ allowedTools: options.allowedTools,
560
+ resume: options.resume,
561
+ approvalDir: options.approvalDir,
562
+ outputFormat: options.outputFormat,
563
+ abortController
564
+ };
565
+ runner = createClaudeRunner(runnerOptions);
566
+ break;
567
+ }
568
+ case "codex":
569
+ throw new Error(
570
+ "Codex runner not yet implemented. Use --runner=claude for now."
571
+ );
572
+ case "copilot":
573
+ throw new Error(
574
+ "Copilot runner not yet implemented. Use --runner=claude for now."
575
+ );
576
+ default:
577
+ throw new Error(
578
+ `Unknown runner: ${options.runner}. Supported runners: claude, codex, copilot`
579
+ );
580
+ }
581
+ for await (const chunk of runner.run(options.userInput)) {
461
582
  process.stdout.write(chunk);
462
583
  }
463
584
  } finally {
@@ -470,6 +591,11 @@ async function runAgent(options) {
470
591
  function parseCliArgs() {
471
592
  const { values, positionals } = parseArgs({
472
593
  options: {
594
+ runner: {
595
+ type: "string",
596
+ short: "r",
597
+ default: "claude"
598
+ },
473
599
  model: {
474
600
  type: "string",
475
601
  short: "m",
@@ -532,6 +658,13 @@ function parseCliArgs() {
532
658
  console.error('Usage: sandagent run [options] -- "<user input>"');
533
659
  process.exit(1);
534
660
  }
661
+ const runner = values.runner;
662
+ if (!["claude", "codex", "copilot"].includes(runner)) {
663
+ console.error(
664
+ 'Error: --runner must be one of: "claude", "codex", "copilot"'
665
+ );
666
+ process.exit(1);
667
+ }
535
668
  const outputFormat = values["output-format"];
536
669
  if (outputFormat && !["text", "json", "stream-json", "stream"].includes(outputFormat)) {
537
670
  console.error(
@@ -540,6 +673,7 @@ function parseCliArgs() {
540
673
  process.exit(1);
541
674
  }
542
675
  return {
676
+ runner,
543
677
  model: values.model,
544
678
  cwd: values.cwd,
545
679
  systemPrompt: values["system-prompt"],
@@ -562,6 +696,7 @@ Usage:
562
696
  sandagent run [options] -- "<user input>"
563
697
 
564
698
  Options:
699
+ -r, --runner <runner> Runner to use: claude, codex, copilot (default: claude)
565
700
  -m, --model <model> Model to use (default: claude-sonnet-4-20250514)
566
701
  -c, --cwd <path> Working directory (default: current directory)
567
702
  -s, --system-prompt <prompt> Custom system prompt
@@ -592,6 +727,7 @@ async function main() {
592
727
  const args = parseCliArgs();
593
728
  process.chdir(args.cwd);
594
729
  await runAgent({
730
+ runner: args.runner,
595
731
  model: args.model,
596
732
  userInput: args.userInput,
597
733
  systemPrompt: args.systemPrompt,
package/dist/cli.js CHANGED
@@ -16,6 +16,11 @@ import { runAgent } from "./runner.js";
16
16
  function parseCliArgs() {
17
17
  const { values, positionals } = parseArgs({
18
18
  options: {
19
+ runner: {
20
+ type: "string",
21
+ short: "r",
22
+ default: "claude",
23
+ },
19
24
  model: {
20
25
  type: "string",
21
26
  short: "m",
@@ -81,6 +86,12 @@ function parseCliArgs() {
81
86
  console.error('Usage: sandagent run [options] -- "<user input>"');
82
87
  process.exit(1);
83
88
  }
89
+ // Validate runner
90
+ const runner = values.runner;
91
+ if (!["claude", "codex", "copilot"].includes(runner)) {
92
+ console.error('Error: --runner must be one of: "claude", "codex", "copilot"');
93
+ process.exit(1);
94
+ }
84
95
  // Validate output-format
85
96
  const outputFormat = values["output-format"];
86
97
  if (outputFormat &&
@@ -89,6 +100,7 @@ function parseCliArgs() {
89
100
  process.exit(1);
90
101
  }
91
102
  return {
103
+ runner,
92
104
  model: values.model,
93
105
  cwd: values.cwd,
94
106
  systemPrompt: values["system-prompt"],
@@ -113,6 +125,7 @@ Usage:
113
125
  sandagent run [options] -- "<user input>"
114
126
 
115
127
  Options:
128
+ -r, --runner <runner> Runner to use: claude, codex, copilot (default: claude)
116
129
  -m, --model <model> Model to use (default: claude-sonnet-4-20250514)
117
130
  -c, --cwd <path> Working directory (default: current directory)
118
131
  -s, --system-prompt <prompt> Custom system prompt
@@ -145,6 +158,7 @@ async function main() {
145
158
  process.chdir(args.cwd);
146
159
  // Run the agent and stream output to stdout
147
160
  await runAgent({
161
+ runner: args.runner,
148
162
  model: args.model,
149
163
  userInput: args.userInput,
150
164
  systemPrompt: args.systemPrompt,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAevC,SAAS,YAAY;IACnB,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;QACxC,OAAO,EAAE;YACP,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;gBACV,OAAO,EAAE,QAAQ;aAClB;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;gBACV,OAAO,EAAE,0BAA0B;aACpC;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;gBACV,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE;aAC1D;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;aACX;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;aACX;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;aACX;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;aACX;YACD,cAAc,EAAE;gBACd,IAAI,EAAE,QAAQ;aACf;YACD,eAAe,EAAE;gBACf,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,GAAG;aACX;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,GAAG;aACX;SACF;QACD,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,0BAA0B;IAC1B,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6CAA6C;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,SAAS,GAAG,EAAE,CAAC;IAEnB,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;SAAM,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kBAAkB;IAClB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAO,CAAC;IAC9B,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,CAAC,KAAK,CACX,8DAA8D,CAC/D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,yBAAyB;IACzB,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,CAA6B,CAAC;IACzE,IACE,YAAY;QACZ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EACjE,CAAC;QACD,OAAO,CAAC,KAAK,CACX,gFAAgF,CACjF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO;QACL,MAAM;QACN,KAAK,EAAE,MAAM,CAAC,KAAM;QACpB,GAAG,EAAE,MAAM,CAAC,GAAI;QAChB,YAAY,EAAE,MAAM,CAAC,eAAe,CAAC;QACrC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC;YAC3B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;YAC1C,CAAC,CAAC,SAAS;QACb,YAAY,EAAE,MAAM,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtE,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACnC,YAAY,EAAG,YAA6B,IAAI,QAAQ;QACxD,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCb,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAE5B,4CAA4C;IAC5C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAExB,4CAA4C;IAC5C,MAAM,QAAQ,CAAC;QACb,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;KAChC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,kCAAkC;IAClC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/dist/runner.d.ts CHANGED
@@ -4,6 +4,8 @@ import { type BaseRunnerOptions } from "@sandagent/runner-claude";
4
4
  * Extends BaseRunnerOptions with CLI-specific fields
5
5
  */
6
6
  export interface RunAgentOptions extends BaseRunnerOptions {
7
+ /** Which runner to use: claude, codex, copilot */
8
+ runner: string;
7
9
  /** User input/task */
8
10
  userInput: string;
9
11
  /** Template to use (e.g., "default", "coder", "analyst", "researcher") */
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAGvB,MAAM,0BAA0B,CAAC;AAElC;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CtE"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAGvB,MAAM,0BAA0B,CAAC;AAElC;;;GAGG;AACH,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkEtE"}
package/dist/runner.js CHANGED
@@ -15,28 +15,45 @@ export async function runAgent(options) {
15
15
  // Create an AbortController to handle process signals
16
16
  const abortController = new AbortController();
17
17
  // Handle SIGTERM and SIGINT signals
18
- const signalHandler = () => {
18
+ const signalHandler = async () => {
19
19
  console.error("[Runner] Received termination signal, stopping...");
20
+ // Note: abort() synchronously triggers all abort event listeners,
20
21
  abortController.abort();
21
- console.error("[Runner] AbortController.abort() called");
22
+ console.error("[Runner] AbortController.abort() completed (listeners triggered)");
22
23
  };
23
24
  process.on("SIGTERM", signalHandler);
24
25
  process.on("SIGINT", signalHandler);
25
26
  console.error("[Runner] Signal handlers registered");
26
27
  try {
27
- // Build runner options - cwd is already set by cli.ts via process.chdir()
28
- const runnerOptions = {
29
- model: options.model,
30
- systemPrompt: options.systemPrompt,
31
- maxTurns: options.maxTurns,
32
- allowedTools: options.allowedTools,
33
- resume: options.resume,
34
- approvalDir: options.approvalDir,
35
- outputFormat: options.outputFormat,
36
- };
37
- const runner = createClaudeRunner(runnerOptions);
28
+ // Select the appropriate runner based on options.runner
29
+ let runner;
30
+ switch (options.runner) {
31
+ case "claude": {
32
+ // Build runner options - cwd is already set by cli.ts via process.chdir()
33
+ const runnerOptions = {
34
+ model: options.model,
35
+ systemPrompt: options.systemPrompt,
36
+ maxTurns: options.maxTurns,
37
+ allowedTools: options.allowedTools,
38
+ resume: options.resume,
39
+ approvalDir: options.approvalDir,
40
+ outputFormat: options.outputFormat,
41
+ abortController: abortController,
42
+ };
43
+ runner = createClaudeRunner(runnerOptions);
44
+ break;
45
+ }
46
+ case "codex":
47
+ // TODO: Implement Codex runner
48
+ throw new Error("Codex runner not yet implemented. Use --runner=claude for now.");
49
+ case "copilot":
50
+ // TODO: Implement Copilot runner
51
+ throw new Error("Copilot runner not yet implemented. Use --runner=claude for now.");
52
+ default:
53
+ throw new Error(`Unknown runner: ${options.runner}. Supported runners: claude, codex, copilot`);
54
+ }
38
55
  // Stream AI SDK UI messages to stdout
39
- for await (const chunk of runner.run(options.userInput, abortController.signal)) {
56
+ for await (const chunk of runner.run(options.userInput)) {
40
57
  // Write directly to stdout without modification
41
58
  // This ensures the stream is a valid AI SDK UI stream
42
59
  process.stdout.write(chunk);
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAalC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB;IACrD,sDAAsD;IACtD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAE9C,oCAAoC;IACpC,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,eAAe,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC3D,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEpC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,0EAA0E;QAC1E,MAAM,aAAa,GAAwB;YACzC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,OAAO,CAAC,YAAY;SACnC,CAAC;QAEF,MAAM,MAAM,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAEjD,sCAAsC;QACtC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,CAAC,GAAG,CAClC,OAAO,CAAC,SAAS,EACjB,eAAe,CAAC,MAAM,CACvB,EAAE,CAAC;YACF,gDAAgD;YAChD,sDAAsD;YACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;YAAS,CAAC;QACT,2BAA2B;QAC3B,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAelC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB;IACrD,sDAAsD;IACtD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAE9C,oCAAoC;IACpC,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,kEAAkE;QAClE,eAAe,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CACX,kEAAkE,CACnE,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEpC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,wDAAwD;QACxD,IAAI,MAAyD,CAAC;QAE9D,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;YACvB,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,0EAA0E;gBAC1E,MAAM,aAAa,GAAwB;oBACzC,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,eAAe,EAAE,eAAe;iBACjC,CAAC;gBACF,MAAM,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;gBAC3C,MAAM;YACR,CAAC;YACD,KAAK,OAAO;gBACV,+BAA+B;gBAC/B,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;YACJ,KAAK,SAAS;gBACZ,iCAAiC;gBACjC,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;YACJ;gBACE,MAAM,IAAI,KAAK,CACb,mBAAmB,OAAO,CAAC,MAAM,6CAA6C,CAC/E,CAAC;QACN,CAAC;QAED,sCAAsC;QACtC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,gDAAgD;YAChD,sDAAsD;YACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;YAAS,CAAC;QACT,2BAA2B;QAC3B,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sandagent/runner-cli",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "SandAgent Runner CLI - Like gemini-cli or claude-code, runs in your local terminal with AI SDK UI streaming",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,7 +24,24 @@
24
24
  "directory": "apps/runner-cli"
25
25
  },
26
26
  "license": "Apache-2.0",
27
- "dependencies": {},
27
+ "publishConfig": {
28
+ "access": "public",
29
+ "tag": "beta"
30
+ },
31
+ "engines": {
32
+ "node": ">=20.0.0"
33
+ },
34
+ "keywords": [
35
+ "cli",
36
+ "agent",
37
+ "sandagent",
38
+ "runner",
39
+ "claude",
40
+ "anthropic"
41
+ ],
42
+ "dependencies": {
43
+ "@anthropic-ai/claude-agent-sdk": ">=0.1.70"
44
+ },
28
45
  "devDependencies": {
29
46
  "@types/node": "^20.10.0",
30
47
  "esbuild": "^0.27.2",