@sandagent/sdk 0.9.8 → 0.9.9-beta.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
@@ -270,29 +270,28 @@ const sandagent = createSandAgent({
270
270
  const model = sandagent("claude-sonnet-4-20250514");
271
271
  ```
272
272
 
273
- #### `createSandAgentDaemon` — daemon HTTP transport (local dev / buda embed)
273
+ #### Daemon HTTP transport (same provider)
274
274
 
275
- Use this when `sandagent-daemon` is running either as a standalone process in a container, or embedded in a Next.js app via `createNextHandler`.
275
+ **With any sandbox adapter** (E2B, Sandock, `LocalSandbox`, etc.): pass **`sandbox` + `daemonUrl`**. The URL is resolved **inside** the sandbox (the `vikadata/sandagent` image starts `sandagent-daemon` on port 3080). The SDK always streams via `streamCodingRunFromSandbox` (`curl -N` in the sandbox, including `LocalSandbox`), not `fetch` from your server.
276
276
 
277
277
  ```typescript
278
- import { createSandAgentDaemon } from "@sandagent/sdk";
278
+ import { createSandAgent, DEFAULT_SANDAGENT_DAEMON_URL } from "@sandagent/sdk";
279
279
 
280
- const sandagent = createSandAgentDaemon({
281
- daemonUrl: "http://localhost:3080", // or /api/daemon when embedded in Next.js
282
- runner: "claude", // claude · pi · gemini · codex · opencode
280
+ const sandagent = createSandAgent({
281
+ sandbox: mySandboxAdapter,
282
+ daemonUrl: DEFAULT_SANDAGENT_DAEMON_URL, // http://127.0.0.1:3080 inside the container
283
+ runnerType: "claude",
283
284
  cwd: "/workspace",
284
285
  });
285
-
286
- const model = sandagent("claude-sonnet-4-20250514");
287
286
  ```
288
287
 
289
- Both return the same `LanguageModelV3` interface swap transports without changing any other code.
288
+ Omit `daemonUrl` to use the **CLI runner** in the same sandbox. `createSandAgent` always requires a `sandbox` adapter.
290
289
 
291
290
  ### Exports
292
291
 
293
292
  | Entry Point | Exports |
294
293
  |-------------|---------|
295
- | `@sandagent/sdk` | `createSandAgent`, `createSandAgentDaemon`, `LocalSandbox`, `SandAgentLanguageModel`, `submitAnswer` |
294
+ | `@sandagent/sdk` | `createSandAgent`, `LocalSandbox`, `SandAgentLanguageModel`, `submitAnswer`, `DEFAULT_SANDAGENT_DAEMON_URL` |
296
295
  | `@sandagent/sdk/react` | `useSandAgentChat`, `useArtifacts`, `useWriteTool`, `useAskUserQuestion` |
297
296
 
298
297
  ---
package/dist/index.d.ts CHANGED
@@ -71,8 +71,18 @@ interface Logger {
71
71
  type SandAgentRunnerType = "claude" | "pi" | "codex" | "gemini" | "opencode";
72
72
  /**
73
73
  * AI Provider specific settings that extend SandAgentOptions.
74
+ * Requires a `sandbox`. Optional `daemonUrl` streams via sandagent-daemon
75
+ * **inside** that sandbox; without it, the CLI runner is used in the sandbox.
74
76
  */
75
- interface SandAgentProviderSettings extends Omit<SandAgentOptions, "runner" | "sandboxId"> {
77
+ interface SandAgentProviderSettings extends Omit<SandAgentOptions, "runner" | "sandboxId" | "sandbox"> {
78
+ /** Required. All transports run relative to this adapter. */
79
+ sandbox: SandboxAdapter;
80
+ /**
81
+ * sandagent-daemon base URL **inside** the sandbox (e.g. SandAgent image:
82
+ * `http://127.0.0.1:3080`). When set, the SDK uses `streamCodingRunFromSandbox`
83
+ * instead of the CLI runner.
84
+ */
85
+ daemonUrl?: string;
76
86
  /**
77
87
  * Which runner implementation to use: claude (default), pi, codex, gemini, opencode.
78
88
  * Maps to `sandagent run --runner <runnerType>`.
@@ -94,11 +104,18 @@ interface SandAgentProviderSettings extends Omit<SandAgentOptions, "runner" | "s
94
104
  systemPrompt?: string;
95
105
  /** Additional skill paths (files or directories) for pi runner */
96
106
  skillPaths?: string[];
107
+ /** Allowed tools for the runner (undefined = template defaults). */
108
+ allowedTools?: string[];
97
109
  }
98
110
  /**
99
111
  * Model identifier: user passes whatever the runner expects (e.g. Claude model id, Pi model id).
100
112
  */
101
113
  type SandAgentModelId = string;
114
+ /**
115
+ * Default sandagent-daemon base URL inside the SandAgent Docker image / local
116
+ * daemon (`http://127.0.0.1:3080`). Pass as `daemonUrl` with a `sandbox`.
117
+ */
118
+ declare const DEFAULT_SANDAGENT_DAEMON_URL = "http://127.0.0.1:3080";
102
119
 
103
120
  /**
104
121
  * Options for submitAnswer
@@ -141,16 +158,21 @@ interface SandAgentLanguageModelOptions {
141
158
  */
142
159
  declare class SandAgentLanguageModel implements LanguageModelV3 {
143
160
  readonly specificationVersion: "v3";
144
- readonly provider = "sandagent";
161
+ readonly provider: string;
145
162
  readonly modelId: string;
146
163
  readonly supportedUrls: Record<string, RegExp[]>;
147
164
  private readonly options;
148
165
  private readonly logger;
149
166
  private sessionId;
150
167
  private toolNameMap;
168
+ private legacyTextPartCounter;
151
169
  constructor(modelOptions: SandAgentLanguageModelOptions);
152
170
  doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
153
171
  doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
172
+ private resetStreamState;
173
+ private buildCodingRunBody;
174
+ private buildStreamResult;
175
+ private createLanguageModelStreamFromSseReader;
154
176
  private parseSSEBuffer;
155
177
  private parseSSEData;
156
178
  private convertPromptToMessages;
@@ -193,53 +215,6 @@ interface SandAgentProvider extends ProviderV3 {
193
215
  */
194
216
  declare function createSandAgent(defaultOptions: SandAgentProviderSettings): SandAgentProvider;
195
217
 
196
- interface DaemonProviderSettings {
197
- /** Base URL of the sandagent-daemon, e.g. "http://localhost:3080" */
198
- daemonUrl: string;
199
- /** Runner to use: claude, pi, gemini, codex, opencode (default: claude) */
200
- runner?: string;
201
- /** Working directory inside the sandbox (default: SANDAGENT_ROOT) */
202
- cwd?: string;
203
- /** Resume session ID */
204
- resume?: string;
205
- /** Override system prompt */
206
- systemPrompt?: string;
207
- /** Max agent turns */
208
- maxTurns?: number;
209
- /** Allowed tools */
210
- allowedTools?: string[];
211
- /** Extra skill paths (pi runner) */
212
- skillPaths?: string[];
213
- }
214
- /**
215
- * Create a SandAgent provider that uses sandagent-daemon as transport.
216
- * Use this for local dev (Next.js embed) or when daemon is running in a container.
217
- *
218
- * @example
219
- * ```ts
220
- * import { createSandAgentDaemon } from "@sandagent/sdk";
221
- *
222
- * const sandagent = createSandAgentDaemon({
223
- * daemonUrl: "http://localhost:3080",
224
- * runner: "claude",
225
- * });
226
- *
227
- * const { text } = await generateText({
228
- * model: sandagent("claude-sonnet-4-20250514"),
229
- * prompt: "Build a REST API",
230
- * });
231
- * ```
232
- */
233
- declare function createSandAgentDaemon(settings: DaemonProviderSettings): {
234
- (modelId: SandAgentModelId, overrides?: Partial<DaemonProviderSettings>): LanguageModelV3;
235
- languageModel: (modelId: SandAgentModelId, overrides?: Partial<DaemonProviderSettings>) => LanguageModelV3;
236
- chat: (modelId: SandAgentModelId, overrides?: Partial<DaemonProviderSettings>) => LanguageModelV3;
237
- specificationVersion: "v3";
238
- embeddingModel(): never;
239
- textEmbeddingModel(): never;
240
- imageModel(): never;
241
- };
242
-
243
218
  /**
244
219
  * @sandagent/sdk
245
220
  *
@@ -263,4 +238,4 @@ declare function createSandAgentDaemon(settings: DaemonProviderSettings): {
263
238
 
264
239
  declare const VERSION = "0.1.0";
265
240
 
266
- export { type ArtifactProcessor, type ArtifactResult, type DaemonProviderSettings, type Logger, type Question, SandAgentLanguageModel, type SandAgentLanguageModelOptions, type SandAgentModelId, type SandAgentProvider, type SandAgentProviderSettings, type StreamWriter, type SubmitAnswerOptions, type SubmitAnswerParams, VERSION, createSandAgent, createSandAgentDaemon, submitAnswer };
241
+ export { type ArtifactProcessor, type ArtifactResult, DEFAULT_SANDAGENT_DAEMON_URL, type Logger, type Question, SandAgentLanguageModel, type SandAgentLanguageModelOptions, type SandAgentModelId, type SandAgentProvider, type SandAgentProviderSettings, type StreamWriter, type SubmitAnswerOptions, type SubmitAnswerParams, VERSION, createSandAgent, submitAnswer };
package/dist/index.js CHANGED
@@ -28,20 +28,13 @@ async function submitAnswer(sandbox, params, options) {
28
28
  }
29
29
 
30
30
  // src/provider/sandagent-language-model.ts
31
- import { SandAgent } from "@sandagent/manager";
32
- function formatErrorForLog(error) {
33
- if (error instanceof Error) {
34
- const parts = [error.message];
35
- let cause = error.cause;
36
- while (cause instanceof Error) {
37
- parts.push(cause.message);
38
- cause = cause.cause;
39
- }
40
- return parts.join(" | cause: ");
41
- }
42
- return String(error);
43
- }
44
- function getLogger(settings) {
31
+ import {
32
+ SandAgent,
33
+ streamCodingRunFromSandbox
34
+ } from "@sandagent/manager";
35
+
36
+ // src/provider/logging.ts
37
+ function getProviderLogger(settings) {
45
38
  if (settings.logger === false) {
46
39
  return {
47
40
  debug: () => {
@@ -65,6 +58,48 @@ function getLogger(settings) {
65
58
  error: (msg) => console.error(msg)
66
59
  };
67
60
  }
61
+
62
+ // src/provider/sandagent-language-model.ts
63
+ function formatErrorForLog(error) {
64
+ if (error instanceof Error) {
65
+ const parts = [error.message];
66
+ let cause = error.cause;
67
+ while (cause instanceof Error) {
68
+ parts.push(cause.message);
69
+ cause = cause.cause;
70
+ }
71
+ return parts.join(" | cause: ");
72
+ }
73
+ return String(error);
74
+ }
75
+ function asyncIterableToReadableStream(iterable) {
76
+ const iterator = iterable[Symbol.asyncIterator]();
77
+ return new ReadableStream({
78
+ async pull(controller) {
79
+ while (true) {
80
+ const { done, value } = await iterator.next();
81
+ if (done) {
82
+ controller.close();
83
+ return;
84
+ }
85
+ if (value.byteLength > 0) {
86
+ controller.enqueue(value);
87
+ return;
88
+ }
89
+ }
90
+ },
91
+ async cancel(reason) {
92
+ await iterator.return?.(reason);
93
+ }
94
+ });
95
+ }
96
+ function getLastUserTextFromMessages(messages) {
97
+ const lastUser = [...messages].reverse().find((m) => m.role === "user");
98
+ if (!lastUser) return "";
99
+ const c = lastUser.content;
100
+ if (typeof c === "string") return c;
101
+ return c.filter((p) => p.type === "text").map((p) => p.text).join("\n");
102
+ }
68
103
  function createEmptyUsage() {
69
104
  return {
70
105
  inputTokens: {
@@ -83,7 +118,7 @@ function createEmptyUsage() {
83
118
  }
84
119
  var SandAgentLanguageModel = class {
85
120
  specificationVersion = "v3";
86
- provider = "sandagent";
121
+ provider;
87
122
  modelId;
88
123
  supportedUrls = {
89
124
  "image/*": [/.*/]
@@ -92,10 +127,12 @@ var SandAgentLanguageModel = class {
92
127
  logger;
93
128
  sessionId;
94
129
  toolNameMap = /* @__PURE__ */ new Map();
130
+ legacyTextPartCounter = 0;
95
131
  constructor(modelOptions) {
96
132
  this.modelId = modelOptions.id;
97
133
  this.options = modelOptions.options;
98
- this.logger = getLogger(modelOptions.options);
134
+ this.logger = getProviderLogger(modelOptions.options);
135
+ this.provider = modelOptions.options.daemonUrl ? "sandagent-daemon" : "sandagent";
99
136
  }
100
137
  async doGenerate(options) {
101
138
  const { stream, request } = await this.doStream(options);
@@ -164,6 +201,12 @@ var SandAgentLanguageModel = class {
164
201
  warnings.push(...value.warnings);
165
202
  break;
166
203
  }
204
+ case "error": {
205
+ const message = value.error instanceof Error ? value.error.message : typeof value.error === "string" ? value.error : value.error ? String(value.error) : "Unknown error";
206
+ content.push({ type: "text", text: message });
207
+ finishReason = { unified: "error", raw: "error" };
208
+ break;
209
+ }
167
210
  case "finish": {
168
211
  finishReason = value.finishReason;
169
212
  usage = value.usage;
@@ -187,19 +230,47 @@ var SandAgentLanguageModel = class {
187
230
  async doStream(options) {
188
231
  const { prompt, abortSignal } = options;
189
232
  const messages = this.convertPromptToMessages(prompt);
233
+ this.resetStreamState();
190
234
  this.logger.debug(
191
235
  `[sandagent] Starting stream with ${messages.length} messages`
192
236
  );
193
237
  const sandbox = this.options.sandbox;
238
+ if (!sandbox) {
239
+ throw new Error(
240
+ "SandAgent language model requires a sandbox adapter (set `sandbox` on the provider)."
241
+ );
242
+ }
243
+ const daemonUrl = this.options.daemonUrl;
244
+ if (daemonUrl) {
245
+ const handle = await sandbox.attach();
246
+ const sandboxEnv2 = sandbox.getEnv?.() ?? {};
247
+ const runnerEnv = { ...sandboxEnv2, ...this.options.env };
248
+ const body = {
249
+ ...this.buildCodingRunBody(messages, handle.getWorkdir()),
250
+ ...Object.keys(runnerEnv).length > 0 ? { env: runnerEnv } : {}
251
+ };
252
+ const execOpts = {
253
+ cwd: this.options.cwd ?? handle.getWorkdir(),
254
+ signal: abortSignal
255
+ };
256
+ const iterable = streamCodingRunFromSandbox(
257
+ handle,
258
+ daemonUrl,
259
+ body,
260
+ execOpts
261
+ );
262
+ const bytesStream = asyncIterableToReadableStream(iterable);
263
+ return this.buildStreamResult(bytesStream, messages);
264
+ }
194
265
  const sandboxEnv = sandbox.getEnv?.() ?? {};
195
266
  const sandboxWorkdir = this.options.cwd ?? sandbox.getWorkdir?.() ?? "/workspace";
196
267
  const agent = new SandAgent({
197
- sandbox: this.options.sandbox,
268
+ sandbox,
198
269
  runner: this.options.runner,
199
270
  env: { ...sandboxEnv, ...this.options.env }
200
271
  });
201
272
  try {
202
- const stream = await agent.stream({
273
+ const bytesStream = await agent.stream({
203
274
  messages,
204
275
  workspace: {
205
276
  path: sandboxWorkdir
@@ -207,110 +278,127 @@ var SandAgentLanguageModel = class {
207
278
  resume: this.options.resume,
208
279
  signal: abortSignal
209
280
  });
210
- const self = this;
211
- const reader = stream.getReader();
212
- if (!reader) {
213
- throw new Error("Response body is not readable");
281
+ return this.buildStreamResult(bytesStream, messages);
282
+ } catch (error) {
283
+ await agent.destroy().catch(() => {
284
+ });
285
+ throw error;
286
+ }
287
+ }
288
+ resetStreamState() {
289
+ this.sessionId = void 0;
290
+ this.toolNameMap = /* @__PURE__ */ new Map();
291
+ this.legacyTextPartCounter = 0;
292
+ }
293
+ buildCodingRunBody(messages, cwdFallback) {
294
+ const runner = this.options.runner;
295
+ const cwd = this.options.cwd ?? cwdFallback;
296
+ return {
297
+ runner: runner.runnerType ?? "claude",
298
+ model: this.modelId,
299
+ userInput: getLastUserTextFromMessages(messages),
300
+ cwd,
301
+ resume: this.options.resume,
302
+ systemPrompt: this.options.systemPrompt ?? runner.systemPrompt,
303
+ maxTurns: this.options.maxTurns ?? runner.maxTurns,
304
+ allowedTools: runner.allowedTools ?? this.options.allowedTools,
305
+ skillPaths: runner.skillPaths ?? this.options.skillPaths
306
+ };
307
+ }
308
+ buildStreamResult(bytesStream, messages) {
309
+ const reader = bytesStream.getReader();
310
+ return {
311
+ stream: this.createLanguageModelStreamFromSseReader(reader),
312
+ request: {
313
+ body: JSON.stringify({ messages })
214
314
  }
215
- const outputStream = new ReadableStream({
216
- async start(controller) {
217
- try {
218
- let buffer = "";
219
- while (true) {
220
- const { done, value } = await reader.read();
221
- if (done) {
222
- if (buffer.trim()) {
223
- const parts = self.parseSSEBuffer(buffer);
224
- for (const part of parts) {
225
- controller.enqueue(part);
226
- }
315
+ };
316
+ }
317
+ createLanguageModelStreamFromSseReader(reader) {
318
+ const self = this;
319
+ return new ReadableStream({
320
+ async start(controller) {
321
+ try {
322
+ let buffer = "";
323
+ while (true) {
324
+ const { done, value } = await reader.read();
325
+ if (done) {
326
+ if (buffer.trim()) {
327
+ const parts = self.parseSSEBuffer(buffer);
328
+ for (const part of parts) {
329
+ controller.enqueue(part);
227
330
  }
228
- controller.close();
229
- break;
230
331
  }
231
- const text = new TextDecoder().decode(value);
232
- buffer += text;
233
- const lines = buffer.split("\n");
234
- buffer = lines.pop() ?? "";
235
- let foundDone = false;
236
- for (const line of lines) {
237
- if (line.startsWith("data: ")) {
238
- const data = line.slice(6);
239
- if (data === "[DONE]") {
240
- foundDone = true;
241
- continue;
242
- }
243
- try {
244
- const parts = self.parseSSEData(data);
245
- for (const part of parts) {
246
- controller.enqueue(part);
247
- if (self.sessionId) {
248
- const sessionId = self.sessionId;
249
- if (self.options.artifactProcessors?.length) {
250
- for (const processor of self.options.artifactProcessors) {
251
- Promise.resolve().then(() => processor.onChange(part, sessionId)).catch((e) => {
252
- self.logger.error(
253
- `[sandagent] Artifact processor error: ${e}`
254
- );
255
- });
256
- }
257
- }
332
+ controller.close();
333
+ break;
334
+ }
335
+ const text = new TextDecoder().decode(value);
336
+ buffer += text;
337
+ const lines = buffer.split("\n");
338
+ buffer = lines.pop() ?? "";
339
+ let foundDone = false;
340
+ for (const line of lines) {
341
+ const candidate = line.startsWith("data: ") ? line.slice(6) : line.trim();
342
+ if (!candidate) continue;
343
+ if (candidate === "[DONE]") {
344
+ foundDone = true;
345
+ continue;
346
+ }
347
+ try {
348
+ const parts = self.parseSSEData(candidate);
349
+ for (const part of parts) {
350
+ controller.enqueue(part);
351
+ if (self.sessionId) {
352
+ const sessionId = self.sessionId;
353
+ if (self.options.artifactProcessors?.length) {
354
+ for (const processor of self.options.artifactProcessors) {
355
+ Promise.resolve().then(() => processor.onChange(part, sessionId)).catch((e) => {
356
+ self.logger.error(
357
+ `[sandagent] Artifact processor error: ${e}`
358
+ );
359
+ });
258
360
  }
259
361
  }
260
- } catch (e) {
261
- self.logger.error(
262
- `[sandagent] Failed to parse SSE data: ${e}`
263
- );
264
362
  }
265
363
  }
266
- }
267
- if (foundDone) {
268
- controller.close();
269
- return;
364
+ } catch (e) {
365
+ const msg = e instanceof Error ? e.message : String(e);
366
+ if (!msg.includes("Unexpected token")) {
367
+ self.logger.error(`[sandagent] Failed to parse stream data: ${e}`);
368
+ }
270
369
  }
271
370
  }
272
- } catch (error) {
273
- if (error instanceof Error && error.name === "AbortError") {
274
- self.logger.info("[sandagent] Stream aborted by user");
275
- } else {
276
- self.logger.error(
277
- `[sandagent] Stream error: ${formatErrorForLog(error)}`
278
- );
371
+ if (foundDone) {
372
+ controller.close();
373
+ return;
279
374
  }
280
- controller.error(error);
281
375
  }
282
- },
283
- cancel() {
284
- reader.cancel();
285
- }
286
- });
287
- return {
288
- stream: outputStream,
289
- request: {
290
- body: JSON.stringify({ messages })
376
+ } catch (error) {
377
+ if (error instanceof Error && error.name === "AbortError") {
378
+ self.logger.info("[sandagent] Stream aborted by user");
379
+ } else {
380
+ self.logger.error(
381
+ `[sandagent] Stream error: ${formatErrorForLog(error)}`
382
+ );
383
+ }
384
+ controller.error(error);
291
385
  }
292
- };
293
- } catch (error) {
294
- await agent.destroy().catch(() => {
295
- });
296
- throw error;
297
- }
386
+ },
387
+ cancel() {
388
+ reader.cancel();
389
+ }
390
+ });
298
391
  }
299
392
  parseSSEBuffer(buffer) {
300
393
  const parts = [];
301
394
  const lines = buffer.split("\n");
302
395
  for (const line of lines) {
303
- if (line.startsWith("data: ")) {
304
- const data = line.slice(6);
305
- if (data === "[DONE]") {
306
- continue;
307
- }
308
- try {
309
- const parsedParts = this.parseSSEData(data);
310
- parts.push(...parsedParts);
311
- } catch (e) {
312
- this.logger.error(`[sandagent] Failed to parse SSE data: ${e}`);
313
- }
396
+ const candidate = line.startsWith("data: ") ? line.slice(6) : line.trim();
397
+ if (!candidate || candidate === "[DONE]") continue;
398
+ try {
399
+ const parsedParts = this.parseSSEData(candidate);
400
+ parts.push(...parsedParts);
401
+ } catch {
314
402
  }
315
403
  }
316
404
  return parts;
@@ -318,10 +406,40 @@ var SandAgentLanguageModel = class {
318
406
  parseSSEData(data) {
319
407
  const parts = [];
320
408
  const parsed = JSON.parse(data);
321
- switch (parsed.type) {
409
+ const parsedType = typeof parsed.type === "string" ? parsed.type : void 0;
410
+ if (!parsedType && typeof parsed.error === "string") {
411
+ return [
412
+ {
413
+ type: "error",
414
+ error: new Error(parsed.error)
415
+ }
416
+ ];
417
+ }
418
+ switch (parsedType) {
322
419
  case "start": {
323
420
  break;
324
421
  }
422
+ // Backward-compatible NDJSON chunk from daemon tests/mock runners.
423
+ case "text": {
424
+ const text = typeof parsed.text === "string" ? parsed.text : "";
425
+ if (text.length > 0) {
426
+ const id = `legacy-text-${++this.legacyTextPartCounter}`;
427
+ parts.push(
428
+ {
429
+ type: "text-start",
430
+ id,
431
+ providerMetadata: {
432
+ sandagent: {
433
+ sessionId: this.sessionId
434
+ }
435
+ }
436
+ },
437
+ { type: "text-delta", id, delta: text },
438
+ { type: "text-end", id }
439
+ );
440
+ }
441
+ break;
442
+ }
325
443
  case "message-metadata": {
326
444
  const metadata = parsed.messageMetadata;
327
445
  if (metadata?.sessionId && typeof metadata.sessionId === "string") {
@@ -411,7 +529,9 @@ var SandAgentLanguageModel = class {
411
529
  case "error": {
412
530
  parts.push({
413
531
  type: "error",
414
- error: new Error(parsed.errorText)
532
+ error: new Error(
533
+ parsed.errorText || parsed.error || "Unknown stream error"
534
+ )
415
535
  });
416
536
  break;
417
537
  }
@@ -580,42 +700,20 @@ import { NoSuchModelError } from "@ai-sdk/provider";
580
700
  function getRunnerKindForModel(_modelId) {
581
701
  return "claude-agent-sdk";
582
702
  }
703
+ var DEFAULT_SANDAGENT_DAEMON_URL = "http://127.0.0.1:3080";
583
704
 
584
705
  // src/provider/sandagent-provider.ts
585
- function getLogger2(settings) {
586
- if (settings.logger === false) {
587
- return {
588
- debug: () => {
589
- },
590
- info: () => {
591
- },
592
- warn: () => {
593
- },
594
- error: () => {
595
- }
596
- };
597
- }
598
- if (settings.logger) {
599
- return settings.logger;
600
- }
601
- const isVerbose = settings.verbose ?? false;
602
- return {
603
- debug: (msg) => isVerbose && console.debug(msg),
604
- info: (msg) => isVerbose && console.info(msg),
605
- warn: (msg) => console.warn(msg),
606
- error: (msg) => console.error(msg)
607
- };
608
- }
609
706
  function createSandAgent(defaultOptions) {
610
- const logger = getLogger2(defaultOptions);
707
+ const logger = getProviderLogger(defaultOptions);
611
708
  if (!defaultOptions.sandbox) {
612
709
  throw new Error(
613
- "SandAgent provider requires a sandbox adapter. Please provide one, e.g.: new E2BSandbox({ apiKey: 'xxx' })"
710
+ "Provide a `sandbox` adapter (e.g. E2BSandbox, LocalSandbox). Optional `daemonUrl` selects in-sandbox HTTP to sandagent-daemon (e.g. `http://127.0.0.1:3080`); omit it to use the CLI runner in the sandbox."
614
711
  );
615
712
  }
616
713
  const createModel = (modelId, options = {}) => {
617
714
  const runnerKind = getRunnerKindForModel(modelId);
618
715
  const mergedSkillPaths = options.skillPaths !== void 0 ? options.skillPaths : defaultOptions.skillPaths;
716
+ const mergedAllowedTools = options.allowedTools !== void 0 ? options.allowedTools : defaultOptions.allowedTools;
619
717
  const runner = {
620
718
  kind: runnerKind,
621
719
  model: modelId,
@@ -623,7 +721,8 @@ function createSandAgent(defaultOptions) {
623
721
  outputFormat: "stream",
624
722
  maxTurns: options.maxTurns ?? defaultOptions.maxTurns,
625
723
  ...options.systemPrompt ?? defaultOptions.systemPrompt ? { systemPrompt: options.systemPrompt ?? defaultOptions.systemPrompt } : {},
626
- ...mergedSkillPaths && mergedSkillPaths.length > 0 ? { skillPaths: mergedSkillPaths } : {}
724
+ ...mergedSkillPaths && mergedSkillPaths.length > 0 ? { skillPaths: mergedSkillPaths } : {},
725
+ ...mergedAllowedTools !== void 0 ? { allowedTools: mergedAllowedTools } : {}
627
726
  };
628
727
  const mergedOptions = {
629
728
  ...defaultOptions,
@@ -678,165 +777,15 @@ function createSandAgent(defaultOptions) {
678
777
  return provider;
679
778
  }
680
779
 
681
- // src/provider/sandagent-daemon-provider.ts
682
- var emptyUsage = {
683
- inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
684
- outputTokens: { total: 0, text: void 0, reasoning: void 0 }
685
- };
686
- var DaemonLanguageModel = class {
687
- constructor(modelId, settings) {
688
- this.settings = settings;
689
- this.modelId = modelId;
690
- }
691
- specificationVersion = "v3";
692
- provider = "sandagent-daemon";
693
- modelId;
694
- supportedUrls = {};
695
- async doGenerate(options) {
696
- const { stream, request } = await this.doStream(options);
697
- const reader = stream.getReader();
698
- const parts = [];
699
- try {
700
- while (true) {
701
- const { done, value } = await reader.read();
702
- if (done) break;
703
- parts.push(value);
704
- }
705
- } finally {
706
- reader.releaseLock();
707
- }
708
- const textMap = /* @__PURE__ */ new Map();
709
- for (const part of parts) {
710
- if (part.type === "text-start") textMap.set(part.id, "");
711
- if (part.type === "text-delta") {
712
- textMap.set(part.id, (textMap.get(part.id) ?? "") + part.delta);
713
- }
714
- }
715
- const content = [...textMap.entries()].map(([, text]) => ({
716
- type: "text",
717
- text
718
- }));
719
- const finish = parts.find((p) => p.type === "finish");
720
- return {
721
- content,
722
- finishReason: finish?.type === "finish" ? finish.finishReason : { unified: "other", raw: void 0 },
723
- usage: finish?.type === "finish" ? finish.usage : emptyUsage,
724
- warnings: [],
725
- request
726
- };
727
- }
728
- async doStream(options) {
729
- const { prompt, abortSignal } = options;
730
- const lastUser = [...prompt].reverse().find((m) => m.role === "user");
731
- const userInput = lastUser?.content.filter((p) => p.type === "text").map((p) => p.text).join("\n") ?? "";
732
- const body = {
733
- runner: this.settings.runner ?? "claude",
734
- model: this.modelId,
735
- userInput,
736
- cwd: this.settings.cwd,
737
- resume: this.settings.resume,
738
- systemPrompt: this.settings.systemPrompt,
739
- maxTurns: this.settings.maxTurns,
740
- allowedTools: this.settings.allowedTools,
741
- skillPaths: this.settings.skillPaths
742
- };
743
- const response = await fetch(`${this.settings.daemonUrl}/api/coding/run`, {
744
- method: "POST",
745
- headers: { "Content-Type": "application/json" },
746
- body: JSON.stringify(body),
747
- signal: abortSignal
748
- });
749
- if (!response.ok || !response.body) {
750
- throw new Error(
751
- `daemon error: ${response.status} ${response.statusText}`
752
- );
753
- }
754
- const reader = response.body.getReader();
755
- const decoder = new TextDecoder();
756
- const stream = new ReadableStream({
757
- async start(controller) {
758
- let buffer = "";
759
- try {
760
- while (true) {
761
- const { done, value } = await reader.read();
762
- if (done) {
763
- controller.close();
764
- break;
765
- }
766
- buffer += decoder.decode(value, { stream: true });
767
- const lines = buffer.split("\n");
768
- buffer = lines.pop() ?? "";
769
- for (const line of lines) {
770
- if (!line.trim()) continue;
771
- try {
772
- const msg = JSON.parse(line);
773
- if (msg.type === "text-delta") {
774
- controller.enqueue({
775
- type: "text-delta",
776
- id: msg.id,
777
- delta: msg.delta
778
- });
779
- } else if (msg.type === "text-start") {
780
- controller.enqueue({
781
- type: "text-start",
782
- id: msg.id
783
- });
784
- } else if (msg.type === "text-end") {
785
- controller.enqueue({
786
- type: "text-end",
787
- id: msg.id
788
- });
789
- } else if (msg.type === "finish") {
790
- controller.enqueue({
791
- type: "finish",
792
- finishReason: { unified: "stop", raw: "stop" },
793
- usage: emptyUsage
794
- });
795
- }
796
- } catch {
797
- }
798
- }
799
- }
800
- } catch (err) {
801
- controller.error(err);
802
- }
803
- },
804
- cancel() {
805
- reader.cancel();
806
- }
807
- });
808
- return { stream, request: { body: JSON.stringify(body) } };
809
- }
810
- };
811
- function createSandAgentDaemon(settings) {
812
- const createModel = (modelId, overrides = {}) => {
813
- return new DaemonLanguageModel(modelId, { ...settings, ...overrides });
814
- };
815
- const provider = (modelId, overrides) => createModel(modelId, overrides);
816
- provider.languageModel = createModel;
817
- provider.chat = createModel;
818
- provider.specificationVersion = "v3";
819
- provider.embeddingModel = () => {
820
- throw new Error("not supported");
821
- };
822
- provider.textEmbeddingModel = () => {
823
- throw new Error("not supported");
824
- };
825
- provider.imageModel = () => {
826
- throw new Error("not supported");
827
- };
828
- return provider;
829
- }
830
-
831
780
  // src/index.ts
832
781
  var VERSION = "0.1.0";
833
782
  export {
783
+ DEFAULT_SANDAGENT_DAEMON_URL,
834
784
  LocalSandbox,
835
785
  SandAgentLanguageModel,
836
786
  VERSION,
837
787
  buildRunnerEnv,
838
788
  createSandAgent,
839
- createSandAgentDaemon,
840
789
  submitAnswer
841
790
  };
842
791
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/provider/question-processor.ts","../src/provider/sandagent-language-model.ts","../src/provider/sandagent-provider.ts","../src/provider/types.ts","../src/provider/sandagent-daemon-provider.ts"],"sourcesContent":["/**\n * @sandagent/sdk\n *\n * SandAgent SDK - AI Provider and React hooks for building AI chat interfaces.\n *\n * Main entry point exports the AI provider (backend).\n * React hooks are available via \"@sandagent/sdk/react\".\n *\n * @example\n * ```typescript\n * // Backend - Provider\n * import { createSandAgent } from \"@sandagent/sdk\";\n * const sandagent = createSandAgent({ sandbox, env });\n * const model = sandagent(\"sonnet\");\n *\n * // Frontend - React hooks\n * import { useSandAgentChat } from \"@sandagent/sdk/react\";\n * const { messages, sendMessage } = useSandAgentChat({ apiEndpoint: \"/api/ai\" });\n * ```\n */\n\nexport type {\n LocalSandboxOptions,\n RunnerEnvParams,\n RunnerType,\n} from \"@sandagent/manager\";\n// Re-export LocalSandbox for convenience\n// Re-export env helpers\nexport { buildRunnerEnv, LocalSandbox } from \"@sandagent/manager\";\nexport type {\n ArtifactProcessor,\n ArtifactResult,\n // Re-exports from @ai-sdk/provider\n LanguageModelV3StreamPart,\n Logger,\n Message,\n Question,\n SandAgentLanguageModelOptions,\n SandAgentModelId,\n SandAgentProvider,\n SandAgentProviderSettings,\n // Re-exports from @sandagent/manager\n SandboxAdapter,\n SandboxHandle,\n StreamWriter,\n SubmitAnswerOptions,\n SubmitAnswerParams,\n TranscriptEntry,\n} from \"./provider\";\n// Provider exports\nexport {\n createSandAgent,\n SandAgentLanguageModel,\n submitAnswer,\n} from \"./provider\";\nexport type { DaemonProviderSettings } from \"./provider/sandagent-daemon-provider\";\nexport { createSandAgentDaemon } from \"./provider/sandagent-daemon-provider\";\n\nexport const VERSION = \"0.1.0\";\n","import type { SandboxAdapter } from \"@sandagent/manager\";\nimport type { SubmitAnswerParams } from \"./types\";\n\n/**\n * Options for submitAnswer\n */\nexport interface SubmitAnswerOptions {\n /**\n * Optional base path prefix for approval files\n * @default \".sandagent/approvals\"\n */\n basePath?: string;\n}\n\n/**\n * Submit user's answer for an AskUserQuestion tool call.\n * Writes the answer file to `.sandagent/approvals/{toolCallId}.json` in the sandbox workdir.\n *\n * @example\n * ```typescript\n * import { submitAnswer } from \"@sandagent/sdk\";\n *\n * await submitAnswer(sandbox, {\n * toolCallId: \"tool-456\",\n * questions: [...],\n * answers: { \"Question 1\": \"Answer 1\" },\n * });\n * ```\n */\nexport async function submitAnswer(\n sandbox: SandboxAdapter,\n params: SubmitAnswerParams,\n options?: SubmitAnswerOptions,\n): Promise<void> {\n const { toolCallId, questions, answers } = params;\n const basePath = options?.basePath ?? \".sandagent/approvals\";\n\n const allAnswered = questions.every(\n (q) => answers[q.question] !== undefined && answers[q.question] !== \"\",\n );\n\n const answerData = {\n questions,\n answers,\n status: allAnswered ? \"completed\" : \"pending\",\n timestamp: new Date().toISOString(),\n };\n\n const filename = `${toolCallId}.json`;\n const handle = sandbox.getHandle() ?? (await sandbox.attach());\n // Absolute path so remote sandboxes (Sandock) write to the same path the runner reads (/workspace/.sandagent/approvals).\n const workdir = handle.getWorkdir();\n const targetDir = workdir\n ? `${workdir.replace(/\\/$/, \"\")}/${basePath}`\n : basePath;\n\n await handle.upload(\n [{ path: filename, content: JSON.stringify(answerData, null, 2) }],\n targetDir,\n );\n\n console.log(\n `[submitAnswer] Answer submitted: ${targetDir}/${filename} (status: ${answerData.status}, workdir: ${workdir ?? \"(none)\"})`,\n );\n}\n","import type {\n JSONObject,\n JSONValue,\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3GenerateResult,\n LanguageModelV3Prompt,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n SharedV3ProviderMetadata,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport { type Message, type RunnerSpec, SandAgent } from \"@sandagent/manager\";\nimport type {\n Logger,\n SandAgentModelId,\n SandAgentProviderSettings,\n} from \"./types\";\n\n/**\n * Options for creating a SandAgent language model instance.\n */\nexport interface SandAgentLanguageModelOptions {\n id: SandAgentModelId;\n options: SandAgentProviderSettings & { runner: RunnerSpec };\n}\n\n/** Format error so message and cause chain are visible (e.g. includes \"Fatal error: ...\" from runner). */\nfunction formatErrorForLog(error: unknown): string {\n if (error instanceof Error) {\n const parts = [error.message];\n let cause: unknown = error.cause;\n while (cause instanceof Error) {\n parts.push(cause.message);\n cause = cause.cause;\n }\n return parts.join(\" | cause: \");\n }\n return String(error);\n}\n\nfunction getLogger(settings: SandAgentProviderSettings): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n\nfunction createEmptyUsage(): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: 0,\n noCache: 0,\n cacheRead: 0,\n cacheWrite: 0,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n}\n\n/**\n * SandAgent Language Model implementation for AI SDK.\n */\nexport class SandAgentLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider = \"sandagent\";\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {\n \"image/*\": [/.*/],\n };\n\n private readonly options: SandAgentProviderSettings & { runner: RunnerSpec };\n private readonly logger: Logger;\n private sessionId: string | undefined;\n private toolNameMap: Map<string, string> = new Map();\n\n constructor(modelOptions: SandAgentLanguageModelOptions) {\n this.modelId = modelOptions.id;\n this.options = modelOptions.options;\n this.logger = getLogger(modelOptions.options);\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n const { stream, request } = await this.doStream(options);\n const reader = stream.getReader();\n\n const content: LanguageModelV3Content[] = [];\n const warnings: SharedV3Warning[] = [];\n let finishReason: LanguageModelV3FinishReason = {\n unified: \"other\",\n raw: undefined,\n };\n let usage: LanguageModelV3Usage = createEmptyUsage();\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n\n const textParts: Map<string, { text: string }> = new Map();\n const toolInputs: Map<string, { toolName: string; input: string }> =\n new Map();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n switch (value.type) {\n case \"text-start\": {\n textParts.set(value.id, { text: \"\" });\n break;\n }\n case \"text-delta\": {\n const part = textParts.get(value.id);\n if (part) {\n part.text += value.delta;\n }\n break;\n }\n case \"text-end\": {\n const part = textParts.get(value.id);\n if (part) {\n content.push({\n type: \"text\",\n text: part.text,\n });\n }\n break;\n }\n case \"tool-input-start\": {\n toolInputs.set(value.id, { toolName: value.toolName, input: \"\" });\n break;\n }\n case \"tool-input-delta\": {\n const tool = toolInputs.get(value.id);\n if (tool) {\n tool.input += value.delta;\n }\n break;\n }\n case \"tool-input-end\": {\n break;\n }\n case \"tool-call\": {\n content.push({\n type: \"tool-call\",\n toolCallId: value.toolCallId,\n toolName: value.toolName,\n input: value.input,\n providerExecuted: value.providerExecuted,\n });\n break;\n }\n case \"stream-start\": {\n warnings.push(...value.warnings);\n break;\n }\n case \"finish\": {\n finishReason = value.finishReason;\n usage = value.usage;\n providerMetadata = value.providerMetadata;\n break;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n return {\n content,\n finishReason,\n usage,\n providerMetadata,\n request,\n warnings,\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n const { prompt, abortSignal } = options;\n const messages = this.convertPromptToMessages(prompt);\n\n this.logger.debug(\n `[sandagent] Starting stream with ${messages.length} messages`,\n );\n\n const sandbox = this.options.sandbox;\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const sandboxWorkdir =\n this.options.cwd ?? sandbox.getWorkdir?.() ?? \"/workspace\";\n\n const agent = new SandAgent({\n sandbox: this.options.sandbox,\n runner: this.options.runner,\n env: { ...sandboxEnv, ...this.options.env },\n });\n\n try {\n const stream = await agent.stream({\n messages,\n workspace: {\n path: sandboxWorkdir,\n },\n resume: this.options.resume,\n signal: abortSignal,\n });\n\n const self = this;\n const reader = stream.getReader();\n\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const outputStream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n try {\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n if (buffer.trim()) {\n const parts = self.parseSSEBuffer(buffer);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n controller.close();\n break;\n }\n\n const text = new TextDecoder().decode(value);\n buffer += text;\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n let foundDone = false;\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n\n if (data === \"[DONE]\") {\n foundDone = true;\n continue;\n }\n try {\n const parts = self.parseSSEData(data);\n for (const part of parts) {\n controller.enqueue(part);\n\n if (self.sessionId) {\n const sessionId: string = self.sessionId;\n\n if (self.options.artifactProcessors?.length) {\n for (const processor of self.options\n .artifactProcessors) {\n Promise.resolve()\n .then(() => processor.onChange(part, sessionId))\n .catch((e) => {\n self.logger.error(\n `[sandagent] Artifact processor error: ${e}`,\n );\n });\n }\n }\n }\n }\n } catch (e) {\n self.logger.error(\n `[sandagent] Failed to parse SSE data: ${e}`,\n );\n }\n }\n }\n\n if (foundDone) {\n controller.close();\n return;\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n self.logger.info(\"[sandagent] Stream aborted by user\");\n } else {\n self.logger.error(\n `[sandagent] Stream error: ${formatErrorForLog(error)}`,\n );\n }\n controller.error(error);\n }\n },\n\n cancel() {\n reader.cancel();\n },\n });\n\n return {\n stream: outputStream,\n request: {\n body: JSON.stringify({ messages }),\n },\n };\n } catch (error) {\n await agent.destroy().catch(() => {});\n throw error;\n }\n }\n\n private parseSSEBuffer(buffer: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const lines = buffer.split(\"\\n\");\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n const data = line.slice(6);\n\n if (data === \"[DONE]\") {\n continue;\n }\n\n try {\n const parsedParts = this.parseSSEData(data);\n parts.push(...parsedParts);\n } catch (e) {\n this.logger.error(`[sandagent] Failed to parse SSE data: ${e}`);\n }\n }\n }\n\n return parts;\n }\n\n private parseSSEData(data: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const parsed = JSON.parse(data) as Record<string, unknown>;\n\n switch (parsed.type) {\n case \"start\": {\n break;\n }\n\n case \"message-metadata\": {\n const metadata = parsed.messageMetadata as Record<string, unknown>;\n if (metadata?.sessionId && typeof metadata.sessionId === \"string\") {\n this.sessionId = metadata.sessionId;\n this.logger.debug(\n `[sandagent] Session ID extracted: ${this.sessionId}`,\n );\n parts.push({\n type: \"raw\",\n rawValue: this.sessionId,\n });\n }\n break;\n }\n\n case \"text-start\": {\n parts.push({\n type: \"text-start\",\n id: parsed.id as string,\n providerMetadata: {\n sandagent: {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n\n case \"text-delta\": {\n parts.push({\n type: \"text-delta\",\n id: parsed.id as string,\n delta: parsed.delta as string,\n });\n break;\n }\n\n case \"text-end\": {\n parts.push({\n type: \"text-end\",\n id: parsed.id as string,\n });\n break;\n }\n\n case \"tool-input-start\": {\n parts.push({\n type: \"tool-input-start\",\n id: parsed.toolCallId as string,\n toolName: parsed.toolName as string,\n dynamic: parsed.dynamic as boolean,\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-input-delta\": {\n parts.push({\n type: \"tool-input-delta\",\n id: parsed.toolCallId as string,\n delta: parsed.inputTextDelta as string,\n });\n break;\n }\n case \"tool-input-available\": {\n const toolCallId = parsed.toolCallId as string;\n const toolName = parsed.toolName as string;\n const input = parsed.input as Record<string, unknown>;\n this.toolNameMap.set(toolCallId, toolName);\n parts.push({\n type: \"tool-call\",\n toolCallId,\n toolName,\n input: JSON.stringify(input),\n dynamic: parsed.dynamic as boolean,\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-output-available\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: parsed.output as NonNullable<JSONValue>,\n isError: parsed.isError as boolean,\n dynamic: parsed.dynamic as boolean,\n });\n break;\n }\n case \"error\": {\n parts.push({\n type: \"error\",\n error: new Error(parsed.errorText as string),\n });\n break;\n }\n\n case \"finish\": {\n const rawFinishReason = parsed.finishReason;\n let finishReason: LanguageModelV3FinishReason;\n\n if (\n typeof rawFinishReason === \"object\" &&\n rawFinishReason !== null &&\n \"unified\" in rawFinishReason\n ) {\n finishReason = rawFinishReason as LanguageModelV3FinishReason;\n } else {\n finishReason = this.mapFinishReason(rawFinishReason as string);\n }\n\n const messageMetadata = parsed.messageMetadata as\n | { usage?: Record<string, unknown> }\n | undefined;\n const rawUsage = messageMetadata?.usage;\n const usage = this.convertUsage(rawUsage);\n\n parts.push({\n type: \"finish\",\n finishReason,\n usage,\n providerMetadata: {\n sandagent: {\n ...((parsed.messageMetadata as Record<string, unknown>) ?? {}),\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n }\n\n return parts;\n }\n\n private convertPromptToMessages(prompt: LanguageModelV3Prompt): Message[] {\n const messages: Message[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case \"system\": {\n messages.push({\n role: \"system\",\n content: message.content,\n });\n break;\n }\n\n case \"user\": {\n const parts = message.content\n .map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n if (part.type === \"file\") {\n // LanguageModelV3FilePart: data is Uint8Array | string | URL, mediaType is IANA type\n let dataStr = \"\";\n if (part.data instanceof Uint8Array) {\n dataStr = `data:${part.mediaType};base64,${Buffer.from(part.data).toString(\"base64\")}`;\n } else if (part.data instanceof URL) {\n dataStr = part.data.toString();\n } else if (typeof part.data === \"string\") {\n // Already a data URL or base64 string\n dataStr = part.data;\n }\n return {\n type: \"image\" as const,\n mimeType: part.mediaType || \"image/png\",\n data: dataStr,\n };\n }\n return null;\n })\n .filter(\n (\n p,\n ): p is\n | { type: \"text\"; text: string }\n | { type: \"image\"; mimeType: string; data: string } =>\n p !== null,\n );\n\n if (parts.length > 0) {\n // If only text parts, combine them into a string for cleaner payload, else pass array\n const isAllText = parts.every((p) => p.type === \"text\");\n messages.push({\n role: \"user\",\n content: isAllText\n ? parts\n .map((p) => (p as { type: \"text\"; text: string }).text)\n .join(\"\\n\")\n : parts,\n });\n }\n break;\n }\n\n case \"assistant\": {\n const textParts = message.content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part.type === \"text\",\n )\n .map((part) => part.text);\n\n if (textParts.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textParts.join(\"\\n\"),\n });\n }\n break;\n }\n\n case \"tool\": {\n break;\n }\n }\n }\n\n return messages;\n }\n\n private mapFinishReason(\n reason: string | undefined,\n ): LanguageModelV3FinishReason {\n switch (reason) {\n case \"stop\":\n return { unified: \"stop\", raw: reason };\n case \"length\":\n return { unified: \"length\", raw: reason };\n case \"tool_calls\":\n case \"tool-calls\":\n return { unified: \"tool-calls\", raw: reason };\n case \"content_filter\":\n case \"content-filter\":\n return { unified: \"content-filter\", raw: reason };\n case \"error\":\n return { unified: \"error\", raw: reason };\n default:\n return { unified: \"other\", raw: reason ?? \"unknown\" };\n }\n }\n\n private convertUsage(\n data: Record<string, unknown> | undefined,\n ): LanguageModelV3Usage {\n if (!data) {\n return createEmptyUsage();\n }\n\n if (\"inputTokens\" in data && \"outputTokens\" in data) {\n const inputTokens = data.inputTokens as Record<string, number>;\n const outputTokens = data.outputTokens as Record<string, number>;\n // Check if there's a raw field in the data\n const rawData =\n \"raw\" in data ? (data.raw as Record<string, unknown>) : data;\n\n return {\n inputTokens: {\n total: inputTokens.total ?? 0,\n noCache: inputTokens.noCache ?? 0,\n cacheRead: inputTokens.cacheRead ?? 0,\n cacheWrite: inputTokens.cacheWrite ?? 0,\n },\n outputTokens: {\n total: outputTokens.total ?? 0,\n text: outputTokens.text ?? outputTokens.textTokens ?? undefined,\n reasoning:\n outputTokens.reasoning ?? outputTokens.reasoningTokens ?? undefined,\n },\n raw: rawData as JSONObject,\n };\n }\n\n const usage = (data.usage ?? data) as Record<string, number | undefined>;\n\n if (\"input_tokens\" in usage || \"output_tokens\" in usage) {\n const inputTokens = (usage.input_tokens as number) ?? 0;\n const outputTokens = (usage.output_tokens as number) ?? 0;\n const cacheWrite = (usage.cache_creation_input_tokens as number) ?? 0;\n const cacheRead = (usage.cache_read_input_tokens as number) ?? 0;\n // Check for text/reasoning tokens if available\n const textTokens = (usage.text_tokens as number) ?? undefined;\n const reasoningTokens = (usage.reasoning_tokens as number) ?? undefined;\n\n return {\n inputTokens: {\n total: inputTokens + cacheWrite + cacheRead,\n noCache: inputTokens,\n cacheRead,\n cacheWrite,\n },\n outputTokens: {\n total: outputTokens,\n text: textTokens,\n reasoning: reasoningTokens,\n },\n raw: usage as JSONObject,\n };\n }\n\n return createEmptyUsage();\n }\n}\n","import type {\n EmbeddingModelV3,\n ImageModelV3,\n LanguageModelV3,\n ProviderV3,\n} from \"@ai-sdk/provider\";\nimport { NoSuchModelError } from \"@ai-sdk/provider\";\nimport type { RunnerSpec } from \"@sandagent/manager\";\nimport { SandAgentLanguageModel } from \"./sandagent-language-model\";\nimport type { Logger, SandAgentModelId } from \"./types\";\nimport { getRunnerKindForModel, type SandAgentProviderSettings } from \"./types\";\n\nexport type { SandAgentProviderSettings } from \"./types\";\n\n/**\n * SandAgent provider interface that extends the AI SDK's ProviderV3.\n */\nexport interface SandAgentProvider extends ProviderV3 {\n (\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n languageModel(\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n chat(\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n embeddingModel(modelId: string): EmbeddingModelV3;\n textEmbeddingModel(modelId: string): EmbeddingModelV3;\n imageModel(modelId: string): ImageModelV3;\n}\n\nfunction getLogger(settings: Partial<SandAgentProviderSettings>): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n\n/**\n * Creates a SandAgent provider instance with the specified configuration.\n *\n * @example\n * ```typescript\n * import { createSandAgent } from '@sandagent/sdk';\n * import { E2BSandbox } from '@sandagent/sandbox-e2b';\n * import { generateText } from 'ai';\n *\n * const sandagent = createSandAgent({\n * sandbox: new E2BSandbox({ apiKey: process.env.E2B_API_KEY! }),\n * env: {\n * ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,\n * },\n * });\n *\n * const { text } = await generateText({\n * model: sandagent('sonnet'),\n * prompt: 'Create a hello world program',\n * });\n * ```\n */\nexport function createSandAgent(\n defaultOptions: SandAgentProviderSettings,\n): SandAgentProvider {\n const logger = getLogger(defaultOptions);\n\n if (!defaultOptions.sandbox) {\n throw new Error(\n \"SandAgent provider requires a sandbox adapter. \" +\n \"Please provide one, e.g.: new E2BSandbox({ apiKey: 'xxx' })\",\n );\n }\n\n const createModel = (\n modelId: SandAgentModelId,\n options: Partial<SandAgentProviderSettings> = {},\n ): LanguageModelV3 => {\n const runnerKind = getRunnerKindForModel(modelId);\n\n const mergedSkillPaths =\n options.skillPaths !== undefined\n ? options.skillPaths\n : defaultOptions.skillPaths;\n\n const runner: RunnerSpec = {\n kind: runnerKind,\n model: modelId,\n runnerType: options.runnerType ?? defaultOptions.runnerType,\n outputFormat: \"stream\",\n maxTurns: options.maxTurns ?? defaultOptions.maxTurns,\n ...((options.systemPrompt ?? defaultOptions.systemPrompt)\n ? { systemPrompt: options.systemPrompt ?? defaultOptions.systemPrompt }\n : {}),\n ...(mergedSkillPaths && mergedSkillPaths.length > 0\n ? { skillPaths: mergedSkillPaths }\n : {}),\n };\n\n const mergedOptions = {\n ...defaultOptions,\n ...options,\n runner,\n env: {\n ...defaultOptions.env,\n ...options.env,\n },\n artifactProcessors: [\n ...(defaultOptions.artifactProcessors ?? []),\n ...(options.artifactProcessors ?? []),\n ],\n } as SandAgentProviderSettings & { runner: RunnerSpec };\n\n logger.debug(\n `[sandagent] Creating model: ${modelId} with runner: ${runner.kind}${runner.runnerType ? ` (runnerType: ${runner.runnerType})` : \"\"}${runner.skillPaths?.length ? ` skillPaths=${runner.skillPaths.length}` : \"\"}`,\n );\n\n return new SandAgentLanguageModel({\n id: modelId,\n options: mergedOptions,\n });\n };\n\n const provider = function (\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ) {\n if (new.target) {\n throw new Error(\n \"The SandAgent model function cannot be called with the new keyword.\",\n );\n }\n\n return createModel(modelId, options);\n };\n\n provider.languageModel = createModel;\n provider.chat = createModel;\n provider.specificationVersion = \"v3\" as const;\n\n provider.embeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.textEmbeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.imageModel = (modelId: string): ImageModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"imageModel\",\n });\n };\n\n return provider as SandAgentProvider;\n}\n","import type { LanguageModelV3StreamPart } from \"@ai-sdk/provider\";\nimport type { SandAgentOptions } from \"@sandagent/manager\";\n\n/**\n * Artifact Processor result\n */\nexport interface ArtifactResult {\n artifactId: string;\n content: string;\n mimeType?: string;\n}\n\n/**\n * Stream writer interface for writing data parts\n */\nexport interface StreamWriter {\n write(chunk: {\n type: string;\n id?: string;\n data?: unknown;\n transient?: boolean;\n }): void;\n}\n\n/**\n * Artifact Processor interface\n */\nexport interface ArtifactProcessor {\n /**\n * Invoked when a stream part is received\n * @param event - Stream part event\n * @param sessionId - Current session ID (taskId)\n */\n onChange(event: LanguageModelV3StreamPart, sessionId: string): Promise<void>;\n}\n\n/**\n * Question structure for AskUserQuestion tool\n */\nexport interface Question {\n question: string;\n header?: string;\n options?: Array<{ label: string; description?: string }>;\n multiSelect?: boolean;\n}\n\n/**\n * Parameters for submitting an answer\n */\nexport interface SubmitAnswerParams {\n /** Tool call ID from the AskUserQuestion tool */\n toolCallId: string;\n /** Original questions from the tool */\n questions: Question[];\n /** User's answers keyed by question text */\n answers: Record<string, string>;\n}\n\n/**\n * Logger interface for custom logging.\n */\nexport interface Logger {\n debug: (message: string) => void;\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\n/**\n * CLI runner type passed to `sandagent run --runner <runnerType>`.\n */\nexport type SandAgentRunnerType =\n | \"claude\"\n | \"pi\"\n | \"codex\"\n | \"gemini\"\n | \"opencode\";\n\n/**\n * AI Provider specific settings that extend SandAgentOptions.\n */\nexport interface SandAgentProviderSettings\n extends Omit<SandAgentOptions, \"runner\" | \"sandboxId\"> {\n /**\n * Which runner implementation to use: claude (default), pi, codex, gemini, opencode.\n * Maps to `sandagent run --runner <runnerType>`.\n */\n runnerType?: SandAgentRunnerType;\n /** Working directory for CLI operations inside the sandbox. */\n cwd?: string;\n /** Resume session ID for multi-turn conversation. */\n resume?: string;\n /** Enable verbose logging for debugging. */\n verbose?: boolean;\n /** Custom logger for handling warnings and errors. */\n logger?: Logger | false;\n /** Artifact processors for handling artifact events. */\n artifactProcessors?: ArtifactProcessor[];\n /** Limit the number of back-and-forth iterations */\n maxTurns?: number;\n /** Optional system prompt override (overrides template's default) */\n systemPrompt?: string;\n /** Additional skill paths (files or directories) for pi runner */\n skillPaths?: string[];\n}\n\n/**\n * Model identifier: user passes whatever the runner expects (e.g. Claude model id, Pi model id).\n */\nexport type SandAgentModelId = string;\n\n/**\n * Determine the runner kind based on model ID (for future multi-runner support).\n */\nexport function getRunnerKindForModel(\n _modelId: SandAgentModelId,\n): \"claude-agent-sdk\" {\n return \"claude-agent-sdk\";\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n} from \"@ai-sdk/provider\";\nimport type { SandAgentModelId } from \"./types\";\n\nexport interface DaemonProviderSettings {\n /** Base URL of the sandagent-daemon, e.g. \"http://localhost:3080\" */\n daemonUrl: string;\n /** Runner to use: claude, pi, gemini, codex, opencode (default: claude) */\n runner?: string;\n /** Working directory inside the sandbox (default: SANDAGENT_ROOT) */\n cwd?: string;\n /** Resume session ID */\n resume?: string;\n /** Override system prompt */\n systemPrompt?: string;\n /** Max agent turns */\n maxTurns?: number;\n /** Allowed tools */\n allowedTools?: string[];\n /** Extra skill paths (pi runner) */\n skillPaths?: string[];\n}\n\nconst emptyUsage = {\n inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },\n outputTokens: { total: 0, text: undefined, reasoning: undefined },\n} as const;\nclass DaemonLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider = \"sandagent-daemon\";\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n constructor(\n modelId: string,\n private settings: DaemonProviderSettings,\n ) {\n this.modelId = modelId;\n }\n\n async doGenerate(options: LanguageModelV3CallOptions) {\n const { stream, request } = await this.doStream(options);\n const reader = stream.getReader();\n const parts: LanguageModelV3StreamPart[] = [];\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n parts.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n // Extract text content from parts\n const textMap = new Map<string, string>();\n for (const part of parts) {\n if (part.type === \"text-start\") textMap.set(part.id, \"\");\n if (part.type === \"text-delta\") {\n textMap.set(part.id, (textMap.get(part.id) ?? \"\") + part.delta);\n }\n }\n const content = [...textMap.entries()].map(([, text]) => ({\n type: \"text\" as const,\n text,\n }));\n const finish = parts.find((p) => p.type === \"finish\");\n return {\n content,\n finishReason:\n finish?.type === \"finish\"\n ? finish.finishReason\n : { unified: \"other\" as const, raw: undefined },\n usage: finish?.type === \"finish\" ? finish.usage : emptyUsage,\n warnings: [],\n request: request,\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n const { prompt, abortSignal } = options;\n\n // Extract user input from the last user message\n const lastUser = [...prompt].reverse().find((m) => m.role === \"user\");\n const userInput =\n lastUser?.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\") ?? \"\";\n\n const body = {\n runner: this.settings.runner ?? \"claude\",\n model: this.modelId,\n userInput,\n cwd: this.settings.cwd,\n resume: this.settings.resume,\n systemPrompt: this.settings.systemPrompt,\n maxTurns: this.settings.maxTurns,\n allowedTools: this.settings.allowedTools,\n skillPaths: this.settings.skillPaths,\n };\n\n const response = await fetch(`${this.settings.daemonUrl}/api/coding/run`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n if (!response.ok || !response.body) {\n throw new Error(\n `daemon error: ${response.status} ${response.statusText}`,\n );\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n\n const stream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n let buffer = \"\";\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n controller.close();\n break;\n }\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const msg = JSON.parse(line) as Record<string, unknown>;\n // Map daemon NDJSON to AI SDK stream parts\n if (msg.type === \"text-delta\") {\n controller.enqueue({\n type: \"text-delta\",\n id: msg.id as string,\n delta: msg.delta as string,\n });\n } else if (msg.type === \"text-start\") {\n controller.enqueue({\n type: \"text-start\",\n id: msg.id as string,\n });\n } else if (msg.type === \"text-end\") {\n controller.enqueue({\n type: \"text-end\",\n id: msg.id as string,\n });\n } else if (msg.type === \"finish\") {\n controller.enqueue({\n type: \"finish\",\n finishReason: { unified: \"stop\", raw: \"stop\" },\n usage: emptyUsage,\n });\n }\n } catch {\n /* skip unparseable lines */\n }\n }\n }\n } catch (err) {\n controller.error(err);\n }\n },\n cancel() {\n reader.cancel();\n },\n });\n\n return { stream, request: { body: JSON.stringify(body) } };\n }\n}\n\n/**\n * Create a SandAgent provider that uses sandagent-daemon as transport.\n * Use this for local dev (Next.js embed) or when daemon is running in a container.\n *\n * @example\n * ```ts\n * import { createSandAgentDaemon } from \"@sandagent/sdk\";\n *\n * const sandagent = createSandAgentDaemon({\n * daemonUrl: \"http://localhost:3080\",\n * runner: \"claude\",\n * });\n *\n * const { text } = await generateText({\n * model: sandagent(\"claude-sonnet-4-20250514\"),\n * prompt: \"Build a REST API\",\n * });\n * ```\n */\nexport function createSandAgentDaemon(settings: DaemonProviderSettings) {\n const createModel = (\n modelId: SandAgentModelId,\n overrides: Partial<DaemonProviderSettings> = {},\n ): LanguageModelV3 => {\n return new DaemonLanguageModel(modelId, { ...settings, ...overrides });\n };\n\n const provider = (\n modelId: SandAgentModelId,\n overrides?: Partial<DaemonProviderSettings>,\n ) => createModel(modelId, overrides);\n provider.languageModel = createModel;\n provider.chat = createModel;\n provider.specificationVersion = \"v3\" as const;\n provider.embeddingModel = () => {\n throw new Error(\"not supported\");\n };\n provider.textEmbeddingModel = () => {\n throw new Error(\"not supported\");\n };\n provider.imageModel = () => {\n throw new Error(\"not supported\");\n };\n\n return provider;\n}\n"],"mappings":"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","names":["getLogger"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/provider/question-processor.ts","../src/provider/sandagent-language-model.ts","../src/provider/logging.ts","../src/provider/sandagent-provider.ts","../src/provider/types.ts"],"sourcesContent":["/**\n * @sandagent/sdk\n *\n * SandAgent SDK - AI Provider and React hooks for building AI chat interfaces.\n *\n * Main entry point exports the AI provider (backend).\n * React hooks are available via \"@sandagent/sdk/react\".\n *\n * @example\n * ```typescript\n * // Backend - Provider\n * import { createSandAgent } from \"@sandagent/sdk\";\n * const sandagent = createSandAgent({ sandbox, env });\n * const model = sandagent(\"sonnet\");\n *\n * // Frontend - React hooks\n * import { useSandAgentChat } from \"@sandagent/sdk/react\";\n * const { messages, sendMessage } = useSandAgentChat({ apiEndpoint: \"/api/ai\" });\n * ```\n */\n\nexport type {\n LocalSandboxOptions,\n RunnerEnvParams,\n RunnerType,\n} from \"@sandagent/manager\";\n// Re-export LocalSandbox for convenience\n// Re-export env helpers\nexport { buildRunnerEnv, LocalSandbox } from \"@sandagent/manager\";\nexport type {\n ArtifactProcessor,\n ArtifactResult,\n // Re-exports from @ai-sdk/provider\n LanguageModelV3StreamPart,\n Logger,\n Message,\n Question,\n SandAgentLanguageModelOptions,\n SandAgentModelId,\n SandAgentProvider,\n SandAgentProviderSettings,\n // Re-exports from @sandagent/manager\n SandboxAdapter,\n SandboxHandle,\n StreamWriter,\n SubmitAnswerOptions,\n SubmitAnswerParams,\n TranscriptEntry,\n} from \"./provider\";\n// Provider exports\nexport {\n createSandAgent,\n DEFAULT_SANDAGENT_DAEMON_URL,\n SandAgentLanguageModel,\n submitAnswer,\n} from \"./provider\";\n\nexport const VERSION = \"0.1.0\";\n","import type { SandboxAdapter } from \"@sandagent/manager\";\nimport type { SubmitAnswerParams } from \"./types\";\n\n/**\n * Options for submitAnswer\n */\nexport interface SubmitAnswerOptions {\n /**\n * Optional base path prefix for approval files\n * @default \".sandagent/approvals\"\n */\n basePath?: string;\n}\n\n/**\n * Submit user's answer for an AskUserQuestion tool call.\n * Writes the answer file to `.sandagent/approvals/{toolCallId}.json` in the sandbox workdir.\n *\n * @example\n * ```typescript\n * import { submitAnswer } from \"@sandagent/sdk\";\n *\n * await submitAnswer(sandbox, {\n * toolCallId: \"tool-456\",\n * questions: [...],\n * answers: { \"Question 1\": \"Answer 1\" },\n * });\n * ```\n */\nexport async function submitAnswer(\n sandbox: SandboxAdapter,\n params: SubmitAnswerParams,\n options?: SubmitAnswerOptions,\n): Promise<void> {\n const { toolCallId, questions, answers } = params;\n const basePath = options?.basePath ?? \".sandagent/approvals\";\n\n const allAnswered = questions.every(\n (q) => answers[q.question] !== undefined && answers[q.question] !== \"\",\n );\n\n const answerData = {\n questions,\n answers,\n status: allAnswered ? \"completed\" : \"pending\",\n timestamp: new Date().toISOString(),\n };\n\n const filename = `${toolCallId}.json`;\n const handle = sandbox.getHandle() ?? (await sandbox.attach());\n // Absolute path so remote sandboxes (Sandock) write to the same path the runner reads (/workspace/.sandagent/approvals).\n const workdir = handle.getWorkdir();\n const targetDir = workdir\n ? `${workdir.replace(/\\/$/, \"\")}/${basePath}`\n : basePath;\n\n await handle.upload(\n [{ path: filename, content: JSON.stringify(answerData, null, 2) }],\n targetDir,\n );\n\n console.log(\n `[submitAnswer] Answer submitted: ${targetDir}/${filename} (status: ${answerData.status}, workdir: ${workdir ?? \"(none)\"})`,\n );\n}\n","import type {\n JSONObject,\n JSONValue,\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3GenerateResult,\n LanguageModelV3Prompt,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n SharedV3ProviderMetadata,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport {\n type Message,\n type RunnerSpec,\n SandAgent,\n type SandAgentCodingRunBody,\n streamCodingRunFromSandbox,\n} from \"@sandagent/manager\";\nimport { getProviderLogger } from \"./logging\";\nimport type { Logger, SandAgentModelId, SandAgentProviderSettings } from \"./types\";\n\n/**\n * Options for creating a SandAgent language model instance.\n */\nexport interface SandAgentLanguageModelOptions {\n id: SandAgentModelId;\n options: SandAgentProviderSettings & { runner: RunnerSpec };\n}\n\n/** Format error so message and cause chain are visible (e.g. includes \"Fatal error: ...\" from runner). */\nfunction formatErrorForLog(error: unknown): string {\n if (error instanceof Error) {\n const parts = [error.message];\n let cause: unknown = error.cause;\n while (cause instanceof Error) {\n parts.push(cause.message);\n cause = cause.cause;\n }\n return parts.join(\" | cause: \");\n }\n return String(error);\n}\n\n/** Bridge async iterable (sandbox exec / curl) to Web ReadableStream for SSE parsing. */\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]();\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n while (true) {\n const { done, value } = await iterator.next();\n if (done) {\n controller.close();\n return;\n }\n if (value.byteLength > 0) {\n controller.enqueue(value);\n return;\n }\n }\n },\n async cancel(reason) {\n await iterator.return?.(reason);\n },\n });\n}\n\nfunction getLastUserTextFromMessages(messages: Message[]): string {\n const lastUser = [...messages].reverse().find((m) => m.role === \"user\");\n if (!lastUser) return \"\";\n const c = lastUser.content;\n if (typeof c === \"string\") return c;\n return c\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n}\n\nfunction createEmptyUsage(): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: 0,\n noCache: 0,\n cacheRead: 0,\n cacheWrite: 0,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n}\n\n/**\n * SandAgent Language Model implementation for AI SDK.\n */\nexport class SandAgentLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider: string;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {\n \"image/*\": [/.*/],\n };\n\n private readonly options: SandAgentProviderSettings & { runner: RunnerSpec };\n private readonly logger: Logger;\n private sessionId: string | undefined;\n private toolNameMap: Map<string, string> = new Map();\n private legacyTextPartCounter = 0;\n\n constructor(modelOptions: SandAgentLanguageModelOptions) {\n this.modelId = modelOptions.id;\n this.options = modelOptions.options;\n this.logger = getProviderLogger(modelOptions.options);\n this.provider = modelOptions.options.daemonUrl\n ? \"sandagent-daemon\"\n : \"sandagent\";\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n const { stream, request } = await this.doStream(options);\n const reader = stream.getReader();\n\n const content: LanguageModelV3Content[] = [];\n const warnings: SharedV3Warning[] = [];\n let finishReason: LanguageModelV3FinishReason = {\n unified: \"other\",\n raw: undefined,\n };\n let usage: LanguageModelV3Usage = createEmptyUsage();\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n\n const textParts: Map<string, { text: string }> = new Map();\n const toolInputs: Map<string, { toolName: string; input: string }> =\n new Map();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n switch (value.type) {\n case \"text-start\": {\n textParts.set(value.id, { text: \"\" });\n break;\n }\n case \"text-delta\": {\n const part = textParts.get(value.id);\n if (part) {\n part.text += value.delta;\n }\n break;\n }\n case \"text-end\": {\n const part = textParts.get(value.id);\n if (part) {\n content.push({\n type: \"text\",\n text: part.text,\n });\n }\n break;\n }\n case \"tool-input-start\": {\n toolInputs.set(value.id, { toolName: value.toolName, input: \"\" });\n break;\n }\n case \"tool-input-delta\": {\n const tool = toolInputs.get(value.id);\n if (tool) {\n tool.input += value.delta;\n }\n break;\n }\n case \"tool-input-end\": {\n break;\n }\n case \"tool-call\": {\n content.push({\n type: \"tool-call\",\n toolCallId: value.toolCallId,\n toolName: value.toolName,\n input: value.input,\n providerExecuted: value.providerExecuted,\n });\n break;\n }\n case \"stream-start\": {\n warnings.push(...value.warnings);\n break;\n }\n case \"error\": {\n // `value.error` type comes from AI SDK and can be `{}`-shaped.\n // Convert it to a readable string safely.\n const message =\n value.error instanceof Error\n ? value.error.message\n : typeof value.error === \"string\"\n ? value.error\n : value.error\n ? String(value.error)\n : \"Unknown error\";\n\n // Surface errors as assistant text + mark finishReason=error.\n content.push({ type: \"text\", text: message });\n finishReason = { unified: \"error\", raw: \"error\" };\n break;\n }\n case \"finish\": {\n finishReason = value.finishReason;\n usage = value.usage;\n providerMetadata = value.providerMetadata;\n break;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n return {\n content,\n finishReason,\n usage,\n providerMetadata,\n request,\n warnings,\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n const { prompt, abortSignal } = options;\n const messages = this.convertPromptToMessages(prompt);\n\n this.resetStreamState();\n\n this.logger.debug(\n `[sandagent] Starting stream with ${messages.length} messages`,\n );\n\n const sandbox = this.options.sandbox;\n if (!sandbox) {\n throw new Error(\n \"SandAgent language model requires a sandbox adapter (set `sandbox` on the provider).\",\n );\n }\n\n const daemonUrl = this.options.daemonUrl;\n\n if (daemonUrl) {\n const handle = await sandbox.attach();\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const runnerEnv = { ...sandboxEnv, ...this.options.env };\n const body: SandAgentCodingRunBody = {\n ...this.buildCodingRunBody(messages, handle.getWorkdir()),\n ...(Object.keys(runnerEnv).length > 0 ? { env: runnerEnv } : {}),\n };\n const execOpts = {\n cwd: this.options.cwd ?? handle.getWorkdir(),\n signal: abortSignal,\n };\n const iterable = streamCodingRunFromSandbox(\n handle,\n daemonUrl,\n body,\n execOpts,\n );\n const bytesStream = asyncIterableToReadableStream(iterable);\n return this.buildStreamResult(bytesStream, messages);\n }\n\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const sandboxWorkdir =\n this.options.cwd ?? sandbox.getWorkdir?.() ?? \"/workspace\";\n\n const agent = new SandAgent({\n sandbox,\n runner: this.options.runner,\n env: { ...sandboxEnv, ...this.options.env },\n });\n\n try {\n const bytesStream = await agent.stream({\n messages,\n workspace: {\n path: sandboxWorkdir,\n },\n resume: this.options.resume,\n signal: abortSignal,\n });\n return this.buildStreamResult(bytesStream, messages);\n } catch (error) {\n await agent.destroy().catch(() => {});\n throw error;\n }\n }\n\n private resetStreamState(): void {\n this.sessionId = undefined;\n this.toolNameMap = new Map();\n this.legacyTextPartCounter = 0;\n }\n\n private buildCodingRunBody(\n messages: Message[],\n cwdFallback: string,\n ): SandAgentCodingRunBody {\n const runner = this.options.runner;\n const cwd = this.options.cwd ?? cwdFallback;\n return {\n runner: runner.runnerType ?? \"claude\",\n model: this.modelId,\n userInput: getLastUserTextFromMessages(messages),\n cwd,\n resume: this.options.resume,\n systemPrompt: this.options.systemPrompt ?? runner.systemPrompt,\n maxTurns: this.options.maxTurns ?? runner.maxTurns,\n allowedTools: runner.allowedTools ?? this.options.allowedTools,\n skillPaths: runner.skillPaths ?? this.options.skillPaths,\n };\n }\n\n private buildStreamResult(\n bytesStream: ReadableStream<Uint8Array>,\n messages: Message[],\n ): LanguageModelV3StreamResult {\n const reader = bytesStream.getReader();\n\n return {\n stream: this.createLanguageModelStreamFromSseReader(reader),\n request: {\n body: JSON.stringify({ messages }),\n },\n };\n }\n\n private createLanguageModelStreamFromSseReader(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n ): ReadableStream<LanguageModelV3StreamPart> {\n const self = this;\n\n return new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n try {\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n if (buffer.trim()) {\n const parts = self.parseSSEBuffer(buffer);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n controller.close();\n break;\n }\n\n const text = new TextDecoder().decode(value);\n buffer += text;\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n let foundDone = false;\n for (const line of lines) {\n const candidate = line.startsWith(\"data: \")\n ? line.slice(6)\n : line.trim();\n if (!candidate) continue;\n if (candidate === \"[DONE]\") {\n foundDone = true;\n continue;\n }\n\n try {\n const parts = self.parseSSEData(candidate);\n for (const part of parts) {\n controller.enqueue(part);\n\n if (self.sessionId) {\n const sessionId: string = self.sessionId;\n\n if (self.options.artifactProcessors?.length) {\n for (const processor of self.options\n .artifactProcessors) {\n Promise.resolve()\n .then(() => processor.onChange(part, sessionId))\n .catch((e) => {\n self.logger.error(\n `[sandagent] Artifact processor error: ${e}`,\n );\n });\n }\n }\n }\n }\n } catch (e) {\n // daemon /api/coding/run may emit plain text lines; ignore non-JSON fragments.\n const msg = e instanceof Error ? e.message : String(e);\n if (!msg.includes(\"Unexpected token\")) {\n self.logger.error(`[sandagent] Failed to parse stream data: ${e}`);\n }\n }\n }\n\n if (foundDone) {\n controller.close();\n return;\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n self.logger.info(\"[sandagent] Stream aborted by user\");\n } else {\n self.logger.error(\n `[sandagent] Stream error: ${formatErrorForLog(error)}`,\n );\n }\n controller.error(error);\n }\n },\n\n cancel() {\n reader.cancel();\n },\n });\n }\n\n private parseSSEBuffer(buffer: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const lines = buffer.split(\"\\n\");\n\n for (const line of lines) {\n const candidate = line.startsWith(\"data: \")\n ? line.slice(6)\n : line.trim();\n if (!candidate || candidate === \"[DONE]\") continue;\n try {\n const parsedParts = this.parseSSEData(candidate);\n parts.push(...parsedParts);\n } catch {\n // ignore trailing non-JSON lines on stream close\n }\n }\n\n return parts;\n }\n\n private parseSSEData(data: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const parsed = JSON.parse(data) as Record<string, unknown>;\n const parsedType =\n typeof parsed.type === \"string\" ? parsed.type : undefined;\n\n // daemon NDJSON errors may arrive as: {\"error\":\"...\"} (without type)\n if (!parsedType && typeof parsed.error === \"string\") {\n return [\n {\n type: \"error\",\n error: new Error(parsed.error),\n },\n ];\n }\n\n switch (parsedType) {\n case \"start\": {\n break;\n }\n\n // Backward-compatible NDJSON chunk from daemon tests/mock runners.\n case \"text\": {\n const text = typeof parsed.text === \"string\" ? parsed.text : \"\";\n if (text.length > 0) {\n const id = `legacy-text-${++this.legacyTextPartCounter}`;\n parts.push(\n {\n type: \"text-start\",\n id,\n providerMetadata: {\n sandagent: {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n },\n { type: \"text-delta\", id, delta: text },\n { type: \"text-end\", id },\n );\n }\n break;\n }\n\n case \"message-metadata\": {\n const metadata = parsed.messageMetadata as Record<string, unknown>;\n if (metadata?.sessionId && typeof metadata.sessionId === \"string\") {\n this.sessionId = metadata.sessionId;\n this.logger.debug(\n `[sandagent] Session ID extracted: ${this.sessionId}`,\n );\n parts.push({\n type: \"raw\",\n rawValue: this.sessionId,\n });\n }\n break;\n }\n\n case \"text-start\": {\n parts.push({\n type: \"text-start\",\n id: parsed.id as string,\n providerMetadata: {\n sandagent: {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n\n case \"text-delta\": {\n parts.push({\n type: \"text-delta\",\n id: parsed.id as string,\n delta: parsed.delta as string,\n });\n break;\n }\n\n case \"text-end\": {\n parts.push({\n type: \"text-end\",\n id: parsed.id as string,\n });\n break;\n }\n\n case \"tool-input-start\": {\n parts.push({\n type: \"tool-input-start\",\n id: parsed.toolCallId as string,\n toolName: parsed.toolName as string,\n dynamic: parsed.dynamic as boolean,\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-input-delta\": {\n parts.push({\n type: \"tool-input-delta\",\n id: parsed.toolCallId as string,\n delta: parsed.inputTextDelta as string,\n });\n break;\n }\n case \"tool-input-available\": {\n const toolCallId = parsed.toolCallId as string;\n const toolName = parsed.toolName as string;\n const input = parsed.input as Record<string, unknown>;\n this.toolNameMap.set(toolCallId, toolName);\n parts.push({\n type: \"tool-call\",\n toolCallId,\n toolName,\n input: JSON.stringify(input),\n dynamic: parsed.dynamic as boolean,\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-output-available\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: parsed.output as NonNullable<JSONValue>,\n isError: parsed.isError as boolean,\n dynamic: parsed.dynamic as boolean,\n });\n break;\n }\n case \"error\": {\n parts.push({\n type: \"error\",\n error: new Error(\n (parsed.errorText as string) ||\n (parsed.error as string) ||\n \"Unknown stream error\",\n ),\n });\n break;\n }\n\n case \"finish\": {\n const rawFinishReason = parsed.finishReason;\n let finishReason: LanguageModelV3FinishReason;\n\n if (\n typeof rawFinishReason === \"object\" &&\n rawFinishReason !== null &&\n \"unified\" in rawFinishReason\n ) {\n finishReason = rawFinishReason as LanguageModelV3FinishReason;\n } else {\n finishReason = this.mapFinishReason(rawFinishReason as string);\n }\n\n const messageMetadata = parsed.messageMetadata as\n | { usage?: Record<string, unknown> }\n | undefined;\n const rawUsage = messageMetadata?.usage;\n const usage = this.convertUsage(rawUsage);\n\n parts.push({\n type: \"finish\",\n finishReason,\n usage,\n providerMetadata: {\n sandagent: {\n ...((parsed.messageMetadata as Record<string, unknown>) ?? {}),\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n }\n\n return parts;\n }\n\n private convertPromptToMessages(prompt: LanguageModelV3Prompt): Message[] {\n const messages: Message[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case \"system\": {\n messages.push({\n role: \"system\",\n content: message.content,\n });\n break;\n }\n\n case \"user\": {\n const parts = message.content\n .map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n if (part.type === \"file\") {\n // LanguageModelV3FilePart: data is Uint8Array | string | URL, mediaType is IANA type\n let dataStr = \"\";\n if (part.data instanceof Uint8Array) {\n dataStr = `data:${part.mediaType};base64,${Buffer.from(part.data).toString(\"base64\")}`;\n } else if (part.data instanceof URL) {\n dataStr = part.data.toString();\n } else if (typeof part.data === \"string\") {\n // Already a data URL or base64 string\n dataStr = part.data;\n }\n return {\n type: \"image\" as const,\n mimeType: part.mediaType || \"image/png\",\n data: dataStr,\n };\n }\n return null;\n })\n .filter(\n (\n p,\n ): p is\n | { type: \"text\"; text: string }\n | { type: \"image\"; mimeType: string; data: string } =>\n p !== null,\n );\n\n if (parts.length > 0) {\n // If only text parts, combine them into a string for cleaner payload, else pass array\n const isAllText = parts.every((p) => p.type === \"text\");\n messages.push({\n role: \"user\",\n content: isAllText\n ? parts\n .map((p) => (p as { type: \"text\"; text: string }).text)\n .join(\"\\n\")\n : parts,\n });\n }\n break;\n }\n\n case \"assistant\": {\n const textParts = message.content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part.type === \"text\",\n )\n .map((part) => part.text);\n\n if (textParts.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textParts.join(\"\\n\"),\n });\n }\n break;\n }\n\n case \"tool\": {\n break;\n }\n }\n }\n\n return messages;\n }\n\n private mapFinishReason(\n reason: string | undefined,\n ): LanguageModelV3FinishReason {\n switch (reason) {\n case \"stop\":\n return { unified: \"stop\", raw: reason };\n case \"length\":\n return { unified: \"length\", raw: reason };\n case \"tool_calls\":\n case \"tool-calls\":\n return { unified: \"tool-calls\", raw: reason };\n case \"content_filter\":\n case \"content-filter\":\n return { unified: \"content-filter\", raw: reason };\n case \"error\":\n return { unified: \"error\", raw: reason };\n default:\n return { unified: \"other\", raw: reason ?? \"unknown\" };\n }\n }\n\n private convertUsage(\n data: Record<string, unknown> | undefined,\n ): LanguageModelV3Usage {\n if (!data) {\n return createEmptyUsage();\n }\n\n if (\"inputTokens\" in data && \"outputTokens\" in data) {\n const inputTokens = data.inputTokens as Record<string, number>;\n const outputTokens = data.outputTokens as Record<string, number>;\n // Check if there's a raw field in the data\n const rawData =\n \"raw\" in data ? (data.raw as Record<string, unknown>) : data;\n\n return {\n inputTokens: {\n total: inputTokens.total ?? 0,\n noCache: inputTokens.noCache ?? 0,\n cacheRead: inputTokens.cacheRead ?? 0,\n cacheWrite: inputTokens.cacheWrite ?? 0,\n },\n outputTokens: {\n total: outputTokens.total ?? 0,\n text: outputTokens.text ?? outputTokens.textTokens ?? undefined,\n reasoning:\n outputTokens.reasoning ?? outputTokens.reasoningTokens ?? undefined,\n },\n raw: rawData as JSONObject,\n };\n }\n\n const usage = (data.usage ?? data) as Record<string, number | undefined>;\n\n if (\"input_tokens\" in usage || \"output_tokens\" in usage) {\n const inputTokens = (usage.input_tokens as number) ?? 0;\n const outputTokens = (usage.output_tokens as number) ?? 0;\n const cacheWrite = (usage.cache_creation_input_tokens as number) ?? 0;\n const cacheRead = (usage.cache_read_input_tokens as number) ?? 0;\n // Check for text/reasoning tokens if available\n const textTokens = (usage.text_tokens as number) ?? undefined;\n const reasoningTokens = (usage.reasoning_tokens as number) ?? undefined;\n\n return {\n inputTokens: {\n total: inputTokens + cacheWrite + cacheRead,\n noCache: inputTokens,\n cacheRead,\n cacheWrite,\n },\n outputTokens: {\n total: outputTokens,\n text: textTokens,\n reasoning: reasoningTokens,\n },\n raw: usage as JSONObject,\n };\n }\n\n return createEmptyUsage();\n }\n}\n","import type { Logger, SandAgentProviderSettings } from \"./types\";\n\n/** Shared logger factory for provider and language model. */\nexport function getProviderLogger(\n settings: Partial<SandAgentProviderSettings>,\n): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n","import type {\n EmbeddingModelV3,\n ImageModelV3,\n LanguageModelV3,\n ProviderV3,\n} from \"@ai-sdk/provider\";\nimport { NoSuchModelError } from \"@ai-sdk/provider\";\nimport type { RunnerSpec } from \"@sandagent/manager\";\nimport { getProviderLogger } from \"./logging\";\nimport { SandAgentLanguageModel } from \"./sandagent-language-model\";\nimport type { SandAgentModelId } from \"./types\";\nimport { getRunnerKindForModel, type SandAgentProviderSettings } from \"./types\";\n\nexport type { SandAgentProviderSettings } from \"./types\";\n\n/**\n * SandAgent provider interface that extends the AI SDK's ProviderV3.\n */\nexport interface SandAgentProvider extends ProviderV3 {\n (\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n languageModel(\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n chat(\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ): LanguageModelV3;\n\n embeddingModel(modelId: string): EmbeddingModelV3;\n textEmbeddingModel(modelId: string): EmbeddingModelV3;\n imageModel(modelId: string): ImageModelV3;\n}\n\n/**\n * Creates a SandAgent provider instance with the specified configuration.\n *\n * @example\n * ```typescript\n * import { createSandAgent } from '@sandagent/sdk';\n * import { E2BSandbox } from '@sandagent/sandbox-e2b';\n * import { generateText } from 'ai';\n *\n * const sandagent = createSandAgent({\n * sandbox: new E2BSandbox({ apiKey: process.env.E2B_API_KEY! }),\n * env: {\n * ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,\n * },\n * });\n *\n * const { text } = await generateText({\n * model: sandagent('sonnet'),\n * prompt: 'Create a hello world program',\n * });\n * ```\n */\nexport function createSandAgent(\n defaultOptions: SandAgentProviderSettings,\n): SandAgentProvider {\n const logger = getProviderLogger(defaultOptions);\n\n if (!defaultOptions.sandbox) {\n throw new Error(\n \"Provide a `sandbox` adapter (e.g. E2BSandbox, LocalSandbox). \" +\n \"Optional `daemonUrl` selects in-sandbox HTTP to sandagent-daemon (e.g. `http://127.0.0.1:3080`); omit it to use the CLI runner in the sandbox.\",\n );\n }\n\n const createModel = (\n modelId: SandAgentModelId,\n options: Partial<SandAgentProviderSettings> = {},\n ): LanguageModelV3 => {\n const runnerKind = getRunnerKindForModel(modelId);\n\n const mergedSkillPaths =\n options.skillPaths !== undefined\n ? options.skillPaths\n : defaultOptions.skillPaths;\n\n const mergedAllowedTools =\n options.allowedTools !== undefined\n ? options.allowedTools\n : defaultOptions.allowedTools;\n\n const runner: RunnerSpec = {\n kind: runnerKind,\n model: modelId,\n runnerType: options.runnerType ?? defaultOptions.runnerType,\n outputFormat: \"stream\",\n maxTurns: options.maxTurns ?? defaultOptions.maxTurns,\n ...((options.systemPrompt ?? defaultOptions.systemPrompt)\n ? { systemPrompt: options.systemPrompt ?? defaultOptions.systemPrompt }\n : {}),\n ...(mergedSkillPaths && mergedSkillPaths.length > 0\n ? { skillPaths: mergedSkillPaths }\n : {}),\n ...(mergedAllowedTools !== undefined\n ? { allowedTools: mergedAllowedTools }\n : {}),\n };\n\n const mergedOptions = {\n ...defaultOptions,\n ...options,\n runner,\n env: {\n ...defaultOptions.env,\n ...options.env,\n },\n artifactProcessors: [\n ...(defaultOptions.artifactProcessors ?? []),\n ...(options.artifactProcessors ?? []),\n ],\n } as SandAgentProviderSettings & { runner: RunnerSpec };\n\n logger.debug(\n `[sandagent] Creating model: ${modelId} with runner: ${runner.kind}${runner.runnerType ? ` (runnerType: ${runner.runnerType})` : \"\"}${runner.skillPaths?.length ? ` skillPaths=${runner.skillPaths.length}` : \"\"}`,\n );\n\n return new SandAgentLanguageModel({\n id: modelId,\n options: mergedOptions,\n });\n };\n\n const provider = function (\n modelId: SandAgentModelId,\n options?: Partial<SandAgentProviderSettings>,\n ) {\n if (new.target) {\n throw new Error(\n \"The SandAgent model function cannot be called with the new keyword.\",\n );\n }\n\n return createModel(modelId, options);\n };\n\n provider.languageModel = createModel;\n provider.chat = createModel;\n provider.specificationVersion = \"v3\" as const;\n\n provider.embeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.textEmbeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.imageModel = (modelId: string): ImageModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"imageModel\",\n });\n };\n\n return provider as SandAgentProvider;\n}\n","import type { LanguageModelV3StreamPart } from \"@ai-sdk/provider\";\nimport type { SandAgentOptions, SandboxAdapter } from \"@sandagent/manager\";\n\n/**\n * Artifact Processor result\n */\nexport interface ArtifactResult {\n artifactId: string;\n content: string;\n mimeType?: string;\n}\n\n/**\n * Stream writer interface for writing data parts\n */\nexport interface StreamWriter {\n write(chunk: {\n type: string;\n id?: string;\n data?: unknown;\n transient?: boolean;\n }): void;\n}\n\n/**\n * Artifact Processor interface\n */\nexport interface ArtifactProcessor {\n /**\n * Invoked when a stream part is received\n * @param event - Stream part event\n * @param sessionId - Current session ID (taskId)\n */\n onChange(event: LanguageModelV3StreamPart, sessionId: string): Promise<void>;\n}\n\n/**\n * Question structure for AskUserQuestion tool\n */\nexport interface Question {\n question: string;\n header?: string;\n options?: Array<{ label: string; description?: string }>;\n multiSelect?: boolean;\n}\n\n/**\n * Parameters for submitting an answer\n */\nexport interface SubmitAnswerParams {\n /** Tool call ID from the AskUserQuestion tool */\n toolCallId: string;\n /** Original questions from the tool */\n questions: Question[];\n /** User's answers keyed by question text */\n answers: Record<string, string>;\n}\n\n/**\n * Logger interface for custom logging.\n */\nexport interface Logger {\n debug: (message: string) => void;\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\n/**\n * CLI runner type passed to `sandagent run --runner <runnerType>`.\n */\nexport type SandAgentRunnerType =\n | \"claude\"\n | \"pi\"\n | \"codex\"\n | \"gemini\"\n | \"opencode\";\n\n/**\n * AI Provider specific settings that extend SandAgentOptions.\n * Requires a `sandbox`. Optional `daemonUrl` streams via sandagent-daemon\n * **inside** that sandbox; without it, the CLI runner is used in the sandbox.\n */\nexport interface SandAgentProviderSettings\n extends Omit<SandAgentOptions, \"runner\" | \"sandboxId\" | \"sandbox\"> {\n /** Required. All transports run relative to this adapter. */\n sandbox: SandboxAdapter;\n /**\n * sandagent-daemon base URL **inside** the sandbox (e.g. SandAgent image:\n * `http://127.0.0.1:3080`). When set, the SDK uses `streamCodingRunFromSandbox`\n * instead of the CLI runner.\n */\n daemonUrl?: string;\n /**\n * Which runner implementation to use: claude (default), pi, codex, gemini, opencode.\n * Maps to `sandagent run --runner <runnerType>`.\n */\n runnerType?: SandAgentRunnerType;\n /** Working directory for CLI operations inside the sandbox. */\n cwd?: string;\n /** Resume session ID for multi-turn conversation. */\n resume?: string;\n /** Enable verbose logging for debugging. */\n verbose?: boolean;\n /** Custom logger for handling warnings and errors. */\n logger?: Logger | false;\n /** Artifact processors for handling artifact events. */\n artifactProcessors?: ArtifactProcessor[];\n /** Limit the number of back-and-forth iterations */\n maxTurns?: number;\n /** Optional system prompt override (overrides template's default) */\n systemPrompt?: string;\n /** Additional skill paths (files or directories) for pi runner */\n skillPaths?: string[];\n /** Allowed tools for the runner (undefined = template defaults). */\n allowedTools?: string[];\n}\n\n/**\n * Model identifier: user passes whatever the runner expects (e.g. Claude model id, Pi model id).\n */\nexport type SandAgentModelId = string;\n\n/**\n * Determine the runner kind based on model ID (for future multi-runner support).\n */\nexport function getRunnerKindForModel(\n _modelId: SandAgentModelId,\n): \"claude-agent-sdk\" {\n return \"claude-agent-sdk\";\n}\n\n/**\n * Default sandagent-daemon base URL inside the SandAgent Docker image / local\n * daemon (`http://127.0.0.1:3080`). Pass as `daemonUrl` with a `sandbox`.\n */\nexport const DEFAULT_SANDAGENT_DAEMON_URL = \"http://127.0.0.1:3080\";\n"],"mappings":"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","names":["sandboxEnv"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sandagent/sdk",
3
- "version": "0.9.8",
3
+ "version": "0.9.9-beta.0",
4
4
  "description": "SandAgent SDK - AI Provider and React hooks for building AI agents",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -52,7 +52,7 @@
52
52
  "dependencies": {
53
53
  "@ai-sdk/provider": "^3.0.8",
54
54
  "@ai-sdk/react": "^3.0.105",
55
- "@sandagent/manager": "0.9.8"
55
+ "@sandagent/manager": "0.9.9-beta.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/node": "^20.10.0",