@sandagent/sdk 0.9.7 → 0.9.9
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 +9 -10
- package/dist/index.d.ts +24 -50
- package/dist/index.js +180 -271
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
-
####
|
|
273
|
+
#### Daemon HTTP transport (same provider)
|
|
274
274
|
|
|
275
|
-
|
|
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 {
|
|
278
|
+
import { createSandAgent, DEFAULT_SANDAGENT_DAEMON_URL } from "@sandagent/sdk";
|
|
279
279
|
|
|
280
|
-
const sandagent =
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
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`, `
|
|
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,7 +158,7 @@ interface SandAgentLanguageModelOptions {
|
|
|
141
158
|
*/
|
|
142
159
|
declare class SandAgentLanguageModel implements LanguageModelV3 {
|
|
143
160
|
readonly specificationVersion: "v3";
|
|
144
|
-
readonly provider
|
|
161
|
+
readonly provider: string;
|
|
145
162
|
readonly modelId: string;
|
|
146
163
|
readonly supportedUrls: Record<string, RegExp[]>;
|
|
147
164
|
private readonly options;
|
|
@@ -151,6 +168,10 @@ declare class SandAgentLanguageModel implements LanguageModelV3 {
|
|
|
151
168
|
constructor(modelOptions: SandAgentLanguageModelOptions);
|
|
152
169
|
doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
|
|
153
170
|
doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
|
|
171
|
+
private resetStreamState;
|
|
172
|
+
private buildCodingRunBody;
|
|
173
|
+
private buildStreamResult;
|
|
174
|
+
private createLanguageModelStreamFromSseReader;
|
|
154
175
|
private parseSSEBuffer;
|
|
155
176
|
private parseSSEData;
|
|
156
177
|
private convertPromptToMessages;
|
|
@@ -193,53 +214,6 @@ interface SandAgentProvider extends ProviderV3 {
|
|
|
193
214
|
*/
|
|
194
215
|
declare function createSandAgent(defaultOptions: SandAgentProviderSettings): SandAgentProvider;
|
|
195
216
|
|
|
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
217
|
/**
|
|
244
218
|
* @sandagent/sdk
|
|
245
219
|
*
|
|
@@ -263,4 +237,4 @@ declare function createSandAgentDaemon(settings: DaemonProviderSettings): {
|
|
|
263
237
|
|
|
264
238
|
declare const VERSION = "0.1.0";
|
|
265
239
|
|
|
266
|
-
export { type ArtifactProcessor, type ArtifactResult,
|
|
240
|
+
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 {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
121
|
+
provider;
|
|
87
122
|
modelId;
|
|
88
123
|
supportedUrls = {
|
|
89
124
|
"image/*": [/.*/]
|
|
@@ -95,7 +130,8 @@ var SandAgentLanguageModel = class {
|
|
|
95
130
|
constructor(modelOptions) {
|
|
96
131
|
this.modelId = modelOptions.id;
|
|
97
132
|
this.options = modelOptions.options;
|
|
98
|
-
this.logger =
|
|
133
|
+
this.logger = getProviderLogger(modelOptions.options);
|
|
134
|
+
this.provider = modelOptions.options.daemonUrl ? "sandagent-daemon" : "sandagent";
|
|
99
135
|
}
|
|
100
136
|
async doGenerate(options) {
|
|
101
137
|
const { stream, request } = await this.doStream(options);
|
|
@@ -187,19 +223,42 @@ var SandAgentLanguageModel = class {
|
|
|
187
223
|
async doStream(options) {
|
|
188
224
|
const { prompt, abortSignal } = options;
|
|
189
225
|
const messages = this.convertPromptToMessages(prompt);
|
|
226
|
+
this.resetStreamState();
|
|
190
227
|
this.logger.debug(
|
|
191
228
|
`[sandagent] Starting stream with ${messages.length} messages`
|
|
192
229
|
);
|
|
193
230
|
const sandbox = this.options.sandbox;
|
|
231
|
+
if (!sandbox) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
"SandAgent language model requires a sandbox adapter (set `sandbox` on the provider)."
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
const daemonUrl = this.options.daemonUrl;
|
|
237
|
+
if (daemonUrl) {
|
|
238
|
+
const handle = await sandbox.attach();
|
|
239
|
+
const body = this.buildCodingRunBody(messages, handle.getWorkdir());
|
|
240
|
+
const execOpts = {
|
|
241
|
+
cwd: this.options.cwd ?? handle.getWorkdir(),
|
|
242
|
+
signal: abortSignal
|
|
243
|
+
};
|
|
244
|
+
const iterable = streamCodingRunFromSandbox(
|
|
245
|
+
handle,
|
|
246
|
+
daemonUrl,
|
|
247
|
+
body,
|
|
248
|
+
execOpts
|
|
249
|
+
);
|
|
250
|
+
const bytesStream = asyncIterableToReadableStream(iterable);
|
|
251
|
+
return this.buildStreamResult(bytesStream, messages);
|
|
252
|
+
}
|
|
194
253
|
const sandboxEnv = sandbox.getEnv?.() ?? {};
|
|
195
254
|
const sandboxWorkdir = this.options.cwd ?? sandbox.getWorkdir?.() ?? "/workspace";
|
|
196
255
|
const agent = new SandAgent({
|
|
197
|
-
sandbox
|
|
256
|
+
sandbox,
|
|
198
257
|
runner: this.options.runner,
|
|
199
258
|
env: { ...sandboxEnv, ...this.options.env }
|
|
200
259
|
});
|
|
201
260
|
try {
|
|
202
|
-
const
|
|
261
|
+
const bytesStream = await agent.stream({
|
|
203
262
|
messages,
|
|
204
263
|
workspace: {
|
|
205
264
|
path: sandboxWorkdir
|
|
@@ -207,94 +266,115 @@ var SandAgentLanguageModel = class {
|
|
|
207
266
|
resume: this.options.resume,
|
|
208
267
|
signal: abortSignal
|
|
209
268
|
});
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
269
|
+
return this.buildStreamResult(bytesStream, messages);
|
|
270
|
+
} catch (error) {
|
|
271
|
+
await agent.destroy().catch(() => {
|
|
272
|
+
});
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
resetStreamState() {
|
|
277
|
+
this.sessionId = void 0;
|
|
278
|
+
this.toolNameMap = /* @__PURE__ */ new Map();
|
|
279
|
+
}
|
|
280
|
+
buildCodingRunBody(messages, cwdFallback) {
|
|
281
|
+
const runner = this.options.runner;
|
|
282
|
+
const cwd = this.options.cwd ?? cwdFallback;
|
|
283
|
+
return {
|
|
284
|
+
runner: runner.runnerType ?? "claude",
|
|
285
|
+
model: this.modelId,
|
|
286
|
+
userInput: getLastUserTextFromMessages(messages),
|
|
287
|
+
cwd,
|
|
288
|
+
resume: this.options.resume,
|
|
289
|
+
systemPrompt: this.options.systemPrompt ?? runner.systemPrompt,
|
|
290
|
+
maxTurns: this.options.maxTurns ?? runner.maxTurns,
|
|
291
|
+
allowedTools: runner.allowedTools ?? this.options.allowedTools,
|
|
292
|
+
skillPaths: runner.skillPaths ?? this.options.skillPaths
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
buildStreamResult(bytesStream, messages) {
|
|
296
|
+
const reader = bytesStream.getReader();
|
|
297
|
+
return {
|
|
298
|
+
stream: this.createLanguageModelStreamFromSseReader(reader),
|
|
299
|
+
request: {
|
|
300
|
+
body: JSON.stringify({ messages })
|
|
214
301
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
createLanguageModelStreamFromSseReader(reader) {
|
|
305
|
+
const self = this;
|
|
306
|
+
return new ReadableStream({
|
|
307
|
+
async start(controller) {
|
|
308
|
+
try {
|
|
309
|
+
let buffer = "";
|
|
310
|
+
while (true) {
|
|
311
|
+
const { done, value } = await reader.read();
|
|
312
|
+
if (done) {
|
|
313
|
+
if (buffer.trim()) {
|
|
314
|
+
const parts = self.parseSSEBuffer(buffer);
|
|
315
|
+
for (const part of parts) {
|
|
316
|
+
controller.enqueue(part);
|
|
227
317
|
}
|
|
228
|
-
controller.close();
|
|
229
|
-
break;
|
|
230
318
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
319
|
+
controller.close();
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
const text = new TextDecoder().decode(value);
|
|
323
|
+
buffer += text;
|
|
324
|
+
const lines = buffer.split("\n");
|
|
325
|
+
buffer = lines.pop() ?? "";
|
|
326
|
+
let foundDone = false;
|
|
327
|
+
for (const line of lines) {
|
|
328
|
+
if (line.startsWith("data: ")) {
|
|
329
|
+
const data = line.slice(6);
|
|
330
|
+
if (data === "[DONE]") {
|
|
331
|
+
foundDone = true;
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
try {
|
|
335
|
+
const parts = self.parseSSEData(data);
|
|
336
|
+
for (const part of parts) {
|
|
337
|
+
controller.enqueue(part);
|
|
338
|
+
if (self.sessionId) {
|
|
339
|
+
const sessionId = self.sessionId;
|
|
340
|
+
if (self.options.artifactProcessors?.length) {
|
|
341
|
+
for (const processor of self.options.artifactProcessors) {
|
|
342
|
+
Promise.resolve().then(() => processor.onChange(part, sessionId)).catch((e) => {
|
|
343
|
+
self.logger.error(
|
|
344
|
+
`[sandagent] Artifact processor error: ${e}`
|
|
345
|
+
);
|
|
346
|
+
});
|
|
257
347
|
}
|
|
258
348
|
}
|
|
259
349
|
}
|
|
260
|
-
} catch (e) {
|
|
261
|
-
self.logger.error(
|
|
262
|
-
`[sandagent] Failed to parse SSE data: ${e}`
|
|
263
|
-
);
|
|
264
350
|
}
|
|
351
|
+
} catch (e) {
|
|
352
|
+
self.logger.error(
|
|
353
|
+
`[sandagent] Failed to parse SSE data: ${e}`
|
|
354
|
+
);
|
|
265
355
|
}
|
|
266
356
|
}
|
|
267
|
-
if (foundDone) {
|
|
268
|
-
controller.close();
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
357
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} else {
|
|
276
|
-
self.logger.error(
|
|
277
|
-
`[sandagent] Stream error: ${formatErrorForLog(error)}`
|
|
278
|
-
);
|
|
358
|
+
if (foundDone) {
|
|
359
|
+
controller.close();
|
|
360
|
+
return;
|
|
279
361
|
}
|
|
280
|
-
controller.error(error);
|
|
281
362
|
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
363
|
+
} catch (error) {
|
|
364
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
365
|
+
self.logger.info("[sandagent] Stream aborted by user");
|
|
366
|
+
} else {
|
|
367
|
+
self.logger.error(
|
|
368
|
+
`[sandagent] Stream error: ${formatErrorForLog(error)}`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
controller.error(error);
|
|
291
372
|
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
}
|
|
373
|
+
},
|
|
374
|
+
cancel() {
|
|
375
|
+
reader.cancel();
|
|
376
|
+
}
|
|
377
|
+
});
|
|
298
378
|
}
|
|
299
379
|
parseSSEBuffer(buffer) {
|
|
300
380
|
const parts = [];
|
|
@@ -580,42 +660,20 @@ import { NoSuchModelError } from "@ai-sdk/provider";
|
|
|
580
660
|
function getRunnerKindForModel(_modelId) {
|
|
581
661
|
return "claude-agent-sdk";
|
|
582
662
|
}
|
|
663
|
+
var DEFAULT_SANDAGENT_DAEMON_URL = "http://127.0.0.1:3080";
|
|
583
664
|
|
|
584
665
|
// 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
666
|
function createSandAgent(defaultOptions) {
|
|
610
|
-
const logger =
|
|
667
|
+
const logger = getProviderLogger(defaultOptions);
|
|
611
668
|
if (!defaultOptions.sandbox) {
|
|
612
669
|
throw new Error(
|
|
613
|
-
"
|
|
670
|
+
"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
671
|
);
|
|
615
672
|
}
|
|
616
673
|
const createModel = (modelId, options = {}) => {
|
|
617
674
|
const runnerKind = getRunnerKindForModel(modelId);
|
|
618
675
|
const mergedSkillPaths = options.skillPaths !== void 0 ? options.skillPaths : defaultOptions.skillPaths;
|
|
676
|
+
const mergedAllowedTools = options.allowedTools !== void 0 ? options.allowedTools : defaultOptions.allowedTools;
|
|
619
677
|
const runner = {
|
|
620
678
|
kind: runnerKind,
|
|
621
679
|
model: modelId,
|
|
@@ -623,7 +681,8 @@ function createSandAgent(defaultOptions) {
|
|
|
623
681
|
outputFormat: "stream",
|
|
624
682
|
maxTurns: options.maxTurns ?? defaultOptions.maxTurns,
|
|
625
683
|
...options.systemPrompt ?? defaultOptions.systemPrompt ? { systemPrompt: options.systemPrompt ?? defaultOptions.systemPrompt } : {},
|
|
626
|
-
...mergedSkillPaths && mergedSkillPaths.length > 0 ? { skillPaths: mergedSkillPaths } : {}
|
|
684
|
+
...mergedSkillPaths && mergedSkillPaths.length > 0 ? { skillPaths: mergedSkillPaths } : {},
|
|
685
|
+
...mergedAllowedTools !== void 0 ? { allowedTools: mergedAllowedTools } : {}
|
|
627
686
|
};
|
|
628
687
|
const mergedOptions = {
|
|
629
688
|
...defaultOptions,
|
|
@@ -678,165 +737,15 @@ function createSandAgent(defaultOptions) {
|
|
|
678
737
|
return provider;
|
|
679
738
|
}
|
|
680
739
|
|
|
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
740
|
// src/index.ts
|
|
832
741
|
var VERSION = "0.1.0";
|
|
833
742
|
export {
|
|
743
|
+
DEFAULT_SANDAGENT_DAEMON_URL,
|
|
834
744
|
LocalSandbox,
|
|
835
745
|
SandAgentLanguageModel,
|
|
836
746
|
VERSION,
|
|
837
747
|
buildRunnerEnv,
|
|
838
748
|
createSandAgent,
|
|
839
|
-
createSandAgentDaemon,
|
|
840
749
|
submitAnswer
|
|
841
750
|
};
|
|
842
751
|
//# 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 {\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\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\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 \"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 body = this.buildCodingRunBody(messages, handle.getWorkdir());\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 }\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 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\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 { 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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sandagent/sdk",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.9",
|
|
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.
|
|
55
|
+
"@sandagent/manager": "0.9.9"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/node": "^20.10.0",
|