@tangle-network/sandbox 0.0.3
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/LICENSE +11 -0
- package/README.md +610 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth-BI8GUdn2.js +1 -0
- package/dist/client-C61BaimX.js +1 -0
- package/dist/collaboration/index.d.ts +2 -0
- package/dist/collaboration/index.js +1 -0
- package/dist/collaboration-oyXScjoL.js +1 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +1 -0
- package/dist/errors-BxSeoGx4.js +1 -0
- package/dist/errors-WHP1v4xn.d.ts +449 -0
- package/dist/index-A6QuCBt3.d.ts +189 -0
- package/dist/index-CIkhycpG.d.ts +131 -0
- package/dist/index-DAcOU3eO.d.ts +356 -0
- package/dist/index.d.ts +427 -0
- package/dist/index.js +1 -0
- package/dist/sandbox-CoBxtmZ0.js +1 -0
- package/dist/sandbox-D-1E98ow.d.ts +3332 -0
- package/dist/session-gateway/index.d.ts +448 -0
- package/dist/session-gateway/index.js +1 -0
- package/dist/tangle/index.d.ts +2 -0
- package/dist/tangle/index.js +1 -0
- package/dist/tangle-D5R08WfG.js +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,3332 @@
|
|
|
1
|
+
//#region src/agent-profile.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Provider-neutral agent profile types for public SDK consumers.
|
|
4
|
+
*
|
|
5
|
+
* These model portable agent intent at the application boundary.
|
|
6
|
+
* Individual backends can translate this shape into their own native
|
|
7
|
+
* profile/configuration formats internally.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Permission policy value for a capability.
|
|
11
|
+
*/
|
|
12
|
+
type AgentProfilePermissionValue = "allow" | "ask" | "deny";
|
|
13
|
+
/**
|
|
14
|
+
* Generic resource reference that can be resolved into a file or instruction.
|
|
15
|
+
*/
|
|
16
|
+
type AgentProfileResourceRef = {
|
|
17
|
+
kind: "inline";
|
|
18
|
+
name: string;
|
|
19
|
+
content: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "github";
|
|
22
|
+
path: string;
|
|
23
|
+
ref?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Helper for creating typed inline resource refs.
|
|
28
|
+
*/
|
|
29
|
+
declare function defineInlineResource(name: string, content: string): AgentProfileResourceRef;
|
|
30
|
+
/**
|
|
31
|
+
* Helper for creating typed GitHub-backed resource refs.
|
|
32
|
+
*/
|
|
33
|
+
declare function defineGitHubResource(path: string, options?: {
|
|
34
|
+
ref?: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
}): AgentProfileResourceRef;
|
|
37
|
+
/**
|
|
38
|
+
* Resource mounted into a backend workspace.
|
|
39
|
+
*/
|
|
40
|
+
interface AgentProfileFileMount {
|
|
41
|
+
path: string;
|
|
42
|
+
resource: AgentProfileResourceRef;
|
|
43
|
+
executable?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Provider-neutral resource bundle.
|
|
47
|
+
*
|
|
48
|
+
* Provider-specific concepts such as "skills" or "commands" should be modeled
|
|
49
|
+
* under `extensions` unless they become portable across multiple backends.
|
|
50
|
+
*/
|
|
51
|
+
interface AgentProfileResources {
|
|
52
|
+
/**
|
|
53
|
+
* Generic files to materialize into the agent workspace before execution.
|
|
54
|
+
*/
|
|
55
|
+
files?: AgentProfileFileMount[];
|
|
56
|
+
/**
|
|
57
|
+
* Additional instructions injected into the agent context.
|
|
58
|
+
*/
|
|
59
|
+
instructions?: string | AgentProfileResourceRef;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Model selection hints for backends.
|
|
63
|
+
*/
|
|
64
|
+
interface AgentProfileModelHints {
|
|
65
|
+
/**
|
|
66
|
+
* Preferred default model (format depends on backend, commonly "provider/model").
|
|
67
|
+
*/
|
|
68
|
+
default?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Preferred small/cheap model for lightweight work.
|
|
71
|
+
*/
|
|
72
|
+
small?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Optional provider preference hint.
|
|
75
|
+
*/
|
|
76
|
+
provider?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Backend-agnostic model metadata/hints.
|
|
79
|
+
*/
|
|
80
|
+
metadata?: Record<string, unknown>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Prompt shaping for an agent.
|
|
84
|
+
*/
|
|
85
|
+
interface AgentProfilePrompt {
|
|
86
|
+
/**
|
|
87
|
+
* Full system prompt replacement, when supported.
|
|
88
|
+
*/
|
|
89
|
+
systemPrompt?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Additional instruction lines appended to the active prompt.
|
|
92
|
+
*/
|
|
93
|
+
instructions?: string[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Generic subagent definition.
|
|
97
|
+
*/
|
|
98
|
+
interface AgentSubagentProfile {
|
|
99
|
+
description?: string;
|
|
100
|
+
prompt?: string;
|
|
101
|
+
model?: string;
|
|
102
|
+
tools?: Record<string, boolean>;
|
|
103
|
+
permissions?: Record<string, AgentProfilePermissionValue>;
|
|
104
|
+
maxSteps?: number;
|
|
105
|
+
metadata?: Record<string, unknown>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Generic MCP server configuration.
|
|
109
|
+
*/
|
|
110
|
+
interface AgentProfileMcpServer {
|
|
111
|
+
transport?: "stdio" | "sse" | "http";
|
|
112
|
+
command?: string;
|
|
113
|
+
args?: string[];
|
|
114
|
+
env?: Record<string, string>;
|
|
115
|
+
cwd?: string;
|
|
116
|
+
url?: string;
|
|
117
|
+
headers?: Record<string, string>;
|
|
118
|
+
enabled?: boolean;
|
|
119
|
+
metadata?: Record<string, unknown>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Public provider-neutral agent profile contract.
|
|
123
|
+
*/
|
|
124
|
+
interface AgentProfile {
|
|
125
|
+
name?: string;
|
|
126
|
+
description?: string;
|
|
127
|
+
version?: string;
|
|
128
|
+
tags?: string[];
|
|
129
|
+
prompt?: AgentProfilePrompt;
|
|
130
|
+
model?: AgentProfileModelHints;
|
|
131
|
+
permissions?: Record<string, AgentProfilePermissionValue>;
|
|
132
|
+
tools?: Record<string, boolean>;
|
|
133
|
+
mcp?: Record<string, AgentProfileMcpServer>;
|
|
134
|
+
subagents?: Record<string, AgentSubagentProfile>;
|
|
135
|
+
resources?: AgentProfileResources;
|
|
136
|
+
metadata?: Record<string, unknown>;
|
|
137
|
+
/**
|
|
138
|
+
* Non-portable backend-specific extensions.
|
|
139
|
+
*
|
|
140
|
+
* Use this only for features that cannot be expressed generically.
|
|
141
|
+
* SDK consumers should treat extension keys as backend namespaces.
|
|
142
|
+
*/
|
|
143
|
+
extensions?: Record<string, Record<string, unknown> | undefined>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Helper for declaring typed profiles in application code.
|
|
147
|
+
*/
|
|
148
|
+
declare function defineAgentProfile<T extends AgentProfile>(profile: T): T;
|
|
149
|
+
/**
|
|
150
|
+
* Capabilities describing how a backend interprets AgentProfile.
|
|
151
|
+
*/
|
|
152
|
+
interface AgentProfileCapabilities {
|
|
153
|
+
namedProfiles: boolean;
|
|
154
|
+
systemPrompt: boolean;
|
|
155
|
+
instructions: boolean;
|
|
156
|
+
tools: boolean;
|
|
157
|
+
permissions: boolean;
|
|
158
|
+
mcp: boolean;
|
|
159
|
+
subagents: boolean;
|
|
160
|
+
resources: {
|
|
161
|
+
files: boolean;
|
|
162
|
+
instructions: boolean;
|
|
163
|
+
};
|
|
164
|
+
runtimeUpdate: boolean;
|
|
165
|
+
validation: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Backend extension namespaces understood by this backend.
|
|
168
|
+
*/
|
|
169
|
+
extensions?: string[];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validation issue for a profile/backend pairing.
|
|
173
|
+
*/
|
|
174
|
+
interface AgentProfileValidationIssue {
|
|
175
|
+
level: "error" | "warning" | "info";
|
|
176
|
+
code: string;
|
|
177
|
+
message: string;
|
|
178
|
+
path?: string;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Validation output for a provider adapter.
|
|
182
|
+
*/
|
|
183
|
+
interface AgentProfileValidationResult {
|
|
184
|
+
ok: boolean;
|
|
185
|
+
issues: AgentProfileValidationIssue[];
|
|
186
|
+
normalizedProfile?: AgentProfile;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Merge two public AgentProfile values.
|
|
190
|
+
*
|
|
191
|
+
* Overlay fields win on conflicts. Array-like instruction sets are appended.
|
|
192
|
+
*/
|
|
193
|
+
declare function mergeAgentProfiles(base: AgentProfile | undefined, overlay: AgentProfile | undefined): AgentProfile | undefined;
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/types.d.ts
|
|
196
|
+
/**
|
|
197
|
+
* A development environment.
|
|
198
|
+
*
|
|
199
|
+
* Environments provide toolchains provisioned via Nix profiles mounted into
|
|
200
|
+
* a shared base container. The default "universal" environment includes all
|
|
201
|
+
* common toolchains (Node.js, Python, Rust, Go, etc.).
|
|
202
|
+
*/
|
|
203
|
+
interface SandboxEnvironment {
|
|
204
|
+
/** Environment identifier (e.g., "universal") */
|
|
205
|
+
id: string;
|
|
206
|
+
/** Human-readable description */
|
|
207
|
+
description?: string;
|
|
208
|
+
/** Base template this environment extends */
|
|
209
|
+
base?: string;
|
|
210
|
+
/** Environment version tag */
|
|
211
|
+
version: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Git authentication configuration.
|
|
215
|
+
*
|
|
216
|
+
* @example HTTPS token
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const auth: GitAuth = {
|
|
219
|
+
* token: process.env.GITHUB_TOKEN,
|
|
220
|
+
* };
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
interface GitAuth {
|
|
224
|
+
/** HTTPS auth token (e.g., GitHub PAT) */
|
|
225
|
+
token?: string;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Git repository configuration for cloning at sandbox creation.
|
|
229
|
+
*
|
|
230
|
+
* When provided, the repository is cloned during sandbox provisioning,
|
|
231
|
+
* before the sandbox becomes ready. This is more efficient than cloning
|
|
232
|
+
* after the sandbox starts.
|
|
233
|
+
*
|
|
234
|
+
* @example Basic clone
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const git: GitConfig = {
|
|
237
|
+
* url: "https://github.com/user/repo.git",
|
|
238
|
+
* };
|
|
239
|
+
* ```
|
|
240
|
+
*
|
|
241
|
+
* @example Clone specific branch with auth
|
|
242
|
+
* ```typescript
|
|
243
|
+
* const git: GitConfig = {
|
|
244
|
+
* url: "https://github.com/user/private-repo.git",
|
|
245
|
+
* ref: "develop",
|
|
246
|
+
* auth: { token: process.env.GITHUB_TOKEN },
|
|
247
|
+
* };
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @example Sparse checkout for monorepo
|
|
251
|
+
* ```typescript
|
|
252
|
+
* const git: GitConfig = {
|
|
253
|
+
* url: "https://github.com/org/monorepo.git",
|
|
254
|
+
* sparse: ["packages/my-package", "shared"],
|
|
255
|
+
* depth: 1,
|
|
256
|
+
* };
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
interface GitConfig {
|
|
260
|
+
/** Repository URL (HTTPS or SSH) */
|
|
261
|
+
url: string;
|
|
262
|
+
/** Branch, tag, or commit SHA to checkout (default: default branch) */
|
|
263
|
+
ref?: string;
|
|
264
|
+
/** Shallow clone depth (default: 1 for faster clones) */
|
|
265
|
+
depth?: number;
|
|
266
|
+
/** Sparse checkout paths - only clone these directories */
|
|
267
|
+
sparse?: string[];
|
|
268
|
+
/** Authentication for private repositories */
|
|
269
|
+
auth?: GitAuth;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Tool version specifications for mise (polyglot version manager).
|
|
273
|
+
*
|
|
274
|
+
* Mise is pre-installed in all managed sandboxes and can install any
|
|
275
|
+
* language runtime or tool on demand. Specify versions here to have
|
|
276
|
+
* them pre-installed when the sandbox starts.
|
|
277
|
+
*
|
|
278
|
+
* @see https://mise.jdx.dev for supported tools
|
|
279
|
+
*
|
|
280
|
+
* @example Common tools
|
|
281
|
+
* ```typescript
|
|
282
|
+
* const tools: ToolsConfig = {
|
|
283
|
+
* node: "22", // Node.js 22.x (latest minor/patch)
|
|
284
|
+
* python: "3.12", // Python 3.12.x
|
|
285
|
+
* rust: "1.75", // Rust 1.75.x
|
|
286
|
+
* go: "1.22", // Go 1.22.x
|
|
287
|
+
* };
|
|
288
|
+
* ```
|
|
289
|
+
*
|
|
290
|
+
* @example Exact versions
|
|
291
|
+
* ```typescript
|
|
292
|
+
* const tools: ToolsConfig = {
|
|
293
|
+
* node: "20.11.0", // Exact version
|
|
294
|
+
* pnpm: "8.15.1",
|
|
295
|
+
* deno: "1.40",
|
|
296
|
+
* };
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
interface ToolsConfig {
|
|
300
|
+
/** Node.js version (e.g., "22", "20.11.0", "lts") */
|
|
301
|
+
node?: string;
|
|
302
|
+
/** Python version (e.g., "3.12", "3.11.7") */
|
|
303
|
+
python?: string;
|
|
304
|
+
/** Rust version (e.g., "1.75", "stable", "nightly") */
|
|
305
|
+
rust?: string;
|
|
306
|
+
/** Go version (e.g., "1.22", "1.21.6") */
|
|
307
|
+
go?: string;
|
|
308
|
+
/** Java version (e.g., "21", "17") */
|
|
309
|
+
java?: string;
|
|
310
|
+
/** Ruby version (e.g., "3.3", "3.2.2") */
|
|
311
|
+
ruby?: string;
|
|
312
|
+
/** Any other mise-supported tool and version */
|
|
313
|
+
[tool: string]: string | undefined;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Configuration for initializing the Sandbox client.
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* const client = new Sandbox({
|
|
321
|
+
* apiKey: "sk_sandbox_abc123",
|
|
322
|
+
* baseUrl: "https://your-sandbox-api.example.com",
|
|
323
|
+
* timeoutMs: 60000,
|
|
324
|
+
* });
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
interface SandboxClientConfig {
|
|
328
|
+
/** API key for authentication. Must start with `sk_sandbox_` */
|
|
329
|
+
apiKey: string;
|
|
330
|
+
/** Base URL for the Sandbox API */
|
|
331
|
+
baseUrl: string;
|
|
332
|
+
/** Request timeout in milliseconds. Defaults to 30000 (30 seconds) */
|
|
333
|
+
timeoutMs?: number;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Status of a sandbox instance.
|
|
337
|
+
*
|
|
338
|
+
* Lifecycle: `pending` -> `provisioning` -> `running` -> `stopped` -> (deleted)
|
|
339
|
+
*
|
|
340
|
+
* - `pending` - Sandbox created but not yet provisioning
|
|
341
|
+
* - `provisioning` - Container and resources being allocated
|
|
342
|
+
* - `running` - Sandbox is active and accepting commands
|
|
343
|
+
* - `stopped` - Sandbox is paused (can be resumed)
|
|
344
|
+
* - `failed` - Sandbox encountered an error
|
|
345
|
+
* - `expired` - Sandbox exceeded its lifetime limit
|
|
346
|
+
*/
|
|
347
|
+
type SandboxStatus = "pending" | "provisioning" | "running" | "stopped" | "failed" | "expired";
|
|
348
|
+
/**
|
|
349
|
+
* Resource limits for a sandbox.
|
|
350
|
+
*/
|
|
351
|
+
interface SandboxResources {
|
|
352
|
+
/** Number of CPU cores */
|
|
353
|
+
cpuCores?: number;
|
|
354
|
+
/** Memory in megabytes */
|
|
355
|
+
memoryMB?: number;
|
|
356
|
+
/** Disk space in gigabytes */
|
|
357
|
+
diskGB?: number;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Configuration for creating a new sandbox.
|
|
361
|
+
*
|
|
362
|
+
* Sandboxes can run in two modes:
|
|
363
|
+
* - **Managed** (default): Full-featured with agent, files, terminal, git, tools
|
|
364
|
+
* - **Bare**: Minimal container with only exec() and lifecycle methods
|
|
365
|
+
*
|
|
366
|
+
* @example Minimal sandbox (managed mode with defaults)
|
|
367
|
+
* ```typescript
|
|
368
|
+
* const box = await client.create();
|
|
369
|
+
* // Uses 'universal' image, managed mode, sane defaults
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* @example Sandbox with pre-built image and git
|
|
373
|
+
* ```typescript
|
|
374
|
+
* const box = await client.create({
|
|
375
|
+
* image: "ethereum", // Stack name — tools provisioned via Nix profile
|
|
376
|
+
* git: {
|
|
377
|
+
* url: "https://github.com/user/dapp.git",
|
|
378
|
+
* ref: "main",
|
|
379
|
+
* },
|
|
380
|
+
* tools: { node: "22", python: "3.12" },
|
|
381
|
+
* });
|
|
382
|
+
* ```
|
|
383
|
+
*
|
|
384
|
+
* @example Sandbox with custom Docker image
|
|
385
|
+
* ```typescript
|
|
386
|
+
* const box = await client.create({
|
|
387
|
+
* image: "python:3.12-slim",
|
|
388
|
+
* git: { url: "https://github.com/user/ml-project.git" },
|
|
389
|
+
* tools: { python: "3.12" },
|
|
390
|
+
* });
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* @example Bare sandbox (no managed runtime, just exec)
|
|
394
|
+
* ```typescript
|
|
395
|
+
* const box = await client.create({
|
|
396
|
+
* image: "ubuntu:24.04",
|
|
397
|
+
* bare: true,
|
|
398
|
+
* });
|
|
399
|
+
* // Only box.exec(), box.stop(), box.resume(), box.delete() available
|
|
400
|
+
* ```
|
|
401
|
+
*
|
|
402
|
+
* @example With BYOS3 storage for snapshots
|
|
403
|
+
* ```typescript
|
|
404
|
+
* const box = await client.create({
|
|
405
|
+
* image: "universal",
|
|
406
|
+
* storage: {
|
|
407
|
+
* type: "s3",
|
|
408
|
+
* bucket: "my-snapshots",
|
|
409
|
+
* credentials: { accessKeyId: "...", secretAccessKey: "..." },
|
|
410
|
+
* },
|
|
411
|
+
* fromSnapshot: "snap_abc123",
|
|
412
|
+
* });
|
|
413
|
+
* ```
|
|
414
|
+
*/
|
|
415
|
+
interface CreateSandboxOptions {
|
|
416
|
+
/**
|
|
417
|
+
* Development environment name.
|
|
418
|
+
*
|
|
419
|
+
* Environments provision toolchains via Nix profiles mounted into a
|
|
420
|
+
* shared base container. Use `client.environments.list()` to discover
|
|
421
|
+
* available environments.
|
|
422
|
+
*
|
|
423
|
+
* Takes precedence over `image` if both are specified.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```typescript
|
|
427
|
+
* environment: "universal" // Multi-language (default)
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
environment?: string;
|
|
431
|
+
/**
|
|
432
|
+
* Container image to use for the sandbox.
|
|
433
|
+
*
|
|
434
|
+
* For most use cases the default "universal" environment is sufficient.
|
|
435
|
+
* Use this field for custom images; the SDK runtime integration is applied
|
|
436
|
+
* automatically.
|
|
437
|
+
*
|
|
438
|
+
* **Resolution rules:**
|
|
439
|
+
* - Full image paths → Used as-is
|
|
440
|
+
* - Simple names without `/` or `:` → Treated as environment name
|
|
441
|
+
* (equivalent to setting `environment`)
|
|
442
|
+
*
|
|
443
|
+
* When neither `environment` nor `image` is set the SDK omits the
|
|
444
|
+
* field entirely and the server applies its own default.
|
|
445
|
+
*/
|
|
446
|
+
image?: string;
|
|
447
|
+
/**
|
|
448
|
+
* Create a bare sandbox without the managed runtime.
|
|
449
|
+
*
|
|
450
|
+
* Bare sandboxes only have:
|
|
451
|
+
* - `exec()` - Execute commands
|
|
452
|
+
* - `stop()` / `resume()` - Lifecycle control
|
|
453
|
+
* - `delete()` - Cleanup
|
|
454
|
+
*
|
|
455
|
+
* Use bare mode when you need a clean container without the managed
|
|
456
|
+
* runtime integration.
|
|
457
|
+
*
|
|
458
|
+
* @default false
|
|
459
|
+
*/
|
|
460
|
+
bare?: boolean;
|
|
461
|
+
/**
|
|
462
|
+
* Infrastructure driver selection.
|
|
463
|
+
* Controls how the sandbox is provisioned and isolated.
|
|
464
|
+
*
|
|
465
|
+
* @example Firecracker with CRIU
|
|
466
|
+
* ```typescript
|
|
467
|
+
* driver: { type: "firecracker", enableCriu: true }
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
driver?: DriverConfig;
|
|
471
|
+
/**
|
|
472
|
+
* AI coding agent backend configuration.
|
|
473
|
+
* Determines which agent runs inside the sandbox.
|
|
474
|
+
*
|
|
475
|
+
* @example OpenCode with profile
|
|
476
|
+
* ```typescript
|
|
477
|
+
* backend: { type: "opencode", profile: "with-web-search" }
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
480
|
+
backend?: BackendConfig;
|
|
481
|
+
/**
|
|
482
|
+
* Initial permissions and access control settings.
|
|
483
|
+
*
|
|
484
|
+
* @example Multi-user sandbox
|
|
485
|
+
* ```typescript
|
|
486
|
+
* permissions: {
|
|
487
|
+
* defaultRole: "developer",
|
|
488
|
+
* initialUsers: [{ userId: "user_xyz", role: "developer" }],
|
|
489
|
+
* }
|
|
490
|
+
* ```
|
|
491
|
+
*/
|
|
492
|
+
permissions?: SandboxPermissionsConfig;
|
|
493
|
+
/**
|
|
494
|
+
* Network security configuration.
|
|
495
|
+
* Controls outbound network access from the sandbox.
|
|
496
|
+
*
|
|
497
|
+
* @example Block all outbound traffic
|
|
498
|
+
* ```typescript
|
|
499
|
+
* network: { blockOutbound: true }
|
|
500
|
+
* ```
|
|
501
|
+
*
|
|
502
|
+
* @example Allow only specific destinations
|
|
503
|
+
* ```typescript
|
|
504
|
+
* network: {
|
|
505
|
+
* allowList: ["8.8.8.8/32", "10.0.0.0/8"],
|
|
506
|
+
* ports: [8000, 8080], // Pre-expose ports
|
|
507
|
+
* }
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
510
|
+
network?: NetworkConfig;
|
|
511
|
+
/**
|
|
512
|
+
* Git repository to clone at sandbox creation.
|
|
513
|
+
*
|
|
514
|
+
* The repository is cloned during provisioning, before the sandbox
|
|
515
|
+
* becomes ready. This is more efficient than cloning after start.
|
|
516
|
+
*
|
|
517
|
+
* @example { url: "https://github.com/user/repo.git", ref: "main" }
|
|
518
|
+
*/
|
|
519
|
+
git?: GitConfig;
|
|
520
|
+
/**
|
|
521
|
+
* Tool versions to pre-install via mise.
|
|
522
|
+
*
|
|
523
|
+
* Mise (polyglot version manager) is pre-installed in managed sandboxes.
|
|
524
|
+
* Specify versions here to have them ready when the sandbox starts.
|
|
525
|
+
*
|
|
526
|
+
* @example { node: "22", python: "3.12", rust: "1.75" }
|
|
527
|
+
*/
|
|
528
|
+
tools?: ToolsConfig;
|
|
529
|
+
/** Human-readable name for the sandbox */
|
|
530
|
+
name?: string;
|
|
531
|
+
/** Resource limits (CPU cores, memory, disk) */
|
|
532
|
+
resources?: SandboxResources;
|
|
533
|
+
/** Environment variables injected into the sandbox */
|
|
534
|
+
env?: Record<string, string>;
|
|
535
|
+
/**
|
|
536
|
+
* Maximum lifetime in seconds.
|
|
537
|
+
* Sandbox is automatically deleted after this time.
|
|
538
|
+
* @default 3600 (1 hour)
|
|
539
|
+
*/
|
|
540
|
+
maxLifetimeSeconds?: number;
|
|
541
|
+
/**
|
|
542
|
+
* Idle timeout in seconds.
|
|
543
|
+
* Sandbox is suspended after this period of inactivity.
|
|
544
|
+
* @default 900 (15 minutes)
|
|
545
|
+
*/
|
|
546
|
+
idleTimeoutSeconds?: number;
|
|
547
|
+
/**
|
|
548
|
+
* Enable SSH access to the sandbox.
|
|
549
|
+
* Use `sandbox.ssh()` to get connection credentials.
|
|
550
|
+
* @default false
|
|
551
|
+
*/
|
|
552
|
+
sshEnabled?: boolean;
|
|
553
|
+
/** Custom SSH public key for access (optional) */
|
|
554
|
+
sshPublicKey?: string;
|
|
555
|
+
/**
|
|
556
|
+
* Enable web terminal access.
|
|
557
|
+
* Provides a browser-based terminal via websocket.
|
|
558
|
+
* @default false
|
|
559
|
+
*/
|
|
560
|
+
webTerminalEnabled?: boolean;
|
|
561
|
+
/**
|
|
562
|
+
* Customer-provided S3-compatible storage for snapshots (BYOS3).
|
|
563
|
+
*
|
|
564
|
+
* When configured, snapshots are stored in your own bucket
|
|
565
|
+
* instead of Tangle's managed storage.
|
|
566
|
+
*/
|
|
567
|
+
storage?: StorageConfig;
|
|
568
|
+
/** Snapshot ID to restore from when creating the sandbox */
|
|
569
|
+
fromSnapshot?: string;
|
|
570
|
+
/** Source sandbox ID that owns the snapshot (required when fromSnapshot is set) */
|
|
571
|
+
fromSandboxId?: string;
|
|
572
|
+
/**
|
|
573
|
+
* Names of secrets to inject as environment variables.
|
|
574
|
+
*
|
|
575
|
+
* Secrets must be created via `client.secrets.create()` before use.
|
|
576
|
+
* They are injected as environment variables with the same name.
|
|
577
|
+
*
|
|
578
|
+
* @example
|
|
579
|
+
* ```typescript
|
|
580
|
+
* // First, create the secrets
|
|
581
|
+
* await client.secrets.create("HF_TOKEN", "hf_xxx");
|
|
582
|
+
* await client.secrets.create("AWS_ACCESS_KEY", "AKIA...");
|
|
583
|
+
*
|
|
584
|
+
* // Then use them in a sandbox
|
|
585
|
+
* const box = await client.create({
|
|
586
|
+
* secrets: ["HF_TOKEN", "AWS_ACCESS_KEY"],
|
|
587
|
+
* });
|
|
588
|
+
*
|
|
589
|
+
* // Secrets are available as env vars
|
|
590
|
+
* const result = await box.exec("echo $HF_TOKEN");
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
secrets?: string[];
|
|
594
|
+
/** Custom metadata to store with the sandbox */
|
|
595
|
+
metadata?: Record<string, unknown>;
|
|
596
|
+
/**
|
|
597
|
+
* Share this sandbox with a team. The caller must be an active
|
|
598
|
+
* member of the team — the API rejects requests from non-members
|
|
599
|
+
* before provisioning. When omitted the sandbox is personal
|
|
600
|
+
* (accessible only to the creator).
|
|
601
|
+
*/
|
|
602
|
+
teamId?: string;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* SSH connection credentials.
|
|
606
|
+
*/
|
|
607
|
+
interface SSHCredentials {
|
|
608
|
+
/** SSH server hostname */
|
|
609
|
+
host: string;
|
|
610
|
+
/** SSH server port */
|
|
611
|
+
port: number;
|
|
612
|
+
/** Username for SSH authentication */
|
|
613
|
+
username: string;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Connection information for a sandbox.
|
|
617
|
+
*
|
|
618
|
+
* Most code should use `SandboxInstance` methods (`exec`, `prompt`, etc.).
|
|
619
|
+
* The raw `runtimeUrl` and `authToken` are surfaced only for advanced
|
|
620
|
+
* lower-level use cases such as custom protocol clients.
|
|
621
|
+
*/
|
|
622
|
+
interface SandboxConnection {
|
|
623
|
+
/** Sandbox runtime API URL for programmatic access */
|
|
624
|
+
runtimeUrl?: string;
|
|
625
|
+
/** Access token for authenticating directly with the runtime (Bearer token) */
|
|
626
|
+
authToken?: string;
|
|
627
|
+
/** Token expiration timestamp (ISO 8601). Refresh before this time. */
|
|
628
|
+
authTokenExpiresAt?: string;
|
|
629
|
+
/** SSH connection info if `sshEnabled` was true during creation */
|
|
630
|
+
ssh?: SSHCredentials;
|
|
631
|
+
/** Web terminal URL if `webTerminalEnabled` was true during creation */
|
|
632
|
+
webTerminalUrl?: string;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Full sandbox information returned from the API.
|
|
636
|
+
*/
|
|
637
|
+
interface SandboxInfo {
|
|
638
|
+
/** Unique sandbox identifier */
|
|
639
|
+
id: string;
|
|
640
|
+
/** Human-readable name */
|
|
641
|
+
name?: string;
|
|
642
|
+
/** Current status */
|
|
643
|
+
status: SandboxStatus;
|
|
644
|
+
/** Connection information */
|
|
645
|
+
connection?: SandboxConnection;
|
|
646
|
+
/** Custom metadata */
|
|
647
|
+
metadata?: Record<string, unknown>;
|
|
648
|
+
/** When the sandbox was created */
|
|
649
|
+
createdAt: Date;
|
|
650
|
+
/** When the sandbox started running */
|
|
651
|
+
startedAt?: Date;
|
|
652
|
+
/** Last activity timestamp */
|
|
653
|
+
lastActivityAt?: Date;
|
|
654
|
+
/** When the sandbox will expire */
|
|
655
|
+
expiresAt?: Date;
|
|
656
|
+
/** Error message if status is 'failed' */
|
|
657
|
+
error?: string;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Options for listing sandboxes.
|
|
661
|
+
*/
|
|
662
|
+
interface ListSandboxOptions {
|
|
663
|
+
/** Filter by status */
|
|
664
|
+
status?: SandboxStatus | SandboxStatus[];
|
|
665
|
+
/** Maximum number of results */
|
|
666
|
+
limit?: number;
|
|
667
|
+
/** Offset for pagination */
|
|
668
|
+
offset?: number;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Result of executing a command.
|
|
672
|
+
*/
|
|
673
|
+
interface ExecResult {
|
|
674
|
+
/** Exit code (0 = success) */
|
|
675
|
+
exitCode: number;
|
|
676
|
+
/** Standard output */
|
|
677
|
+
stdout: string;
|
|
678
|
+
/** Standard error */
|
|
679
|
+
stderr: string;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Options for executing a command.
|
|
683
|
+
*/
|
|
684
|
+
interface ExecOptions {
|
|
685
|
+
/** Working directory for the command */
|
|
686
|
+
cwd?: string;
|
|
687
|
+
/** Environment variables */
|
|
688
|
+
env?: Record<string, string>;
|
|
689
|
+
/** Timeout in milliseconds */
|
|
690
|
+
timeoutMs?: number;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Options for code search.
|
|
694
|
+
*
|
|
695
|
+
* @example Search TypeScript files
|
|
696
|
+
* ```typescript
|
|
697
|
+
* const matches = await box.search("TODO", {
|
|
698
|
+
* glob: "**\/*.ts",
|
|
699
|
+
* maxResults: 100,
|
|
700
|
+
* });
|
|
701
|
+
* ```
|
|
702
|
+
*/
|
|
703
|
+
interface SearchOptions {
|
|
704
|
+
/** Glob pattern to filter files (e.g., "**\/*.ts") */
|
|
705
|
+
glob?: string;
|
|
706
|
+
/** Directory to search in (default: workspace root) */
|
|
707
|
+
cwd?: string;
|
|
708
|
+
/** Maximum number of results */
|
|
709
|
+
maxResults?: number;
|
|
710
|
+
/** Case-insensitive search */
|
|
711
|
+
ignoreCase?: boolean;
|
|
712
|
+
/** Include line context (lines before/after match) */
|
|
713
|
+
context?: number;
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* A single search match from ripgrep.
|
|
717
|
+
*/
|
|
718
|
+
interface SearchMatch {
|
|
719
|
+
/** File path relative to search root */
|
|
720
|
+
path: string;
|
|
721
|
+
/** Line number (1-indexed) */
|
|
722
|
+
line: number;
|
|
723
|
+
/** Column number (1-indexed) */
|
|
724
|
+
column: number;
|
|
725
|
+
/** The matching line text */
|
|
726
|
+
text: string;
|
|
727
|
+
/** Context lines before the match */
|
|
728
|
+
before?: string[];
|
|
729
|
+
/** Context lines after the match */
|
|
730
|
+
after?: string[];
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Git repository status.
|
|
734
|
+
*/
|
|
735
|
+
interface GitStatus {
|
|
736
|
+
/** Current branch name */
|
|
737
|
+
branch: string;
|
|
738
|
+
/** Commit SHA of HEAD */
|
|
739
|
+
head: string;
|
|
740
|
+
/** Whether there are uncommitted changes */
|
|
741
|
+
isDirty: boolean;
|
|
742
|
+
/** Number of commits ahead of upstream */
|
|
743
|
+
ahead: number;
|
|
744
|
+
/** Number of commits behind upstream */
|
|
745
|
+
behind: number;
|
|
746
|
+
/** Staged files */
|
|
747
|
+
staged: string[];
|
|
748
|
+
/** Modified but unstaged files */
|
|
749
|
+
modified: string[];
|
|
750
|
+
/** Untracked files */
|
|
751
|
+
untracked: string[];
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Git commit information.
|
|
755
|
+
*/
|
|
756
|
+
interface GitCommit {
|
|
757
|
+
/** Commit SHA */
|
|
758
|
+
sha: string;
|
|
759
|
+
/** Short SHA (7 chars) */
|
|
760
|
+
shortSha: string;
|
|
761
|
+
/** Commit message */
|
|
762
|
+
message: string;
|
|
763
|
+
/** Author name */
|
|
764
|
+
author: string;
|
|
765
|
+
/** Author email */
|
|
766
|
+
email: string;
|
|
767
|
+
/** Commit date */
|
|
768
|
+
date: Date;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Git branch information.
|
|
772
|
+
*/
|
|
773
|
+
interface GitBranch {
|
|
774
|
+
/** Branch name */
|
|
775
|
+
name: string;
|
|
776
|
+
/** Whether this is the current branch */
|
|
777
|
+
current: boolean;
|
|
778
|
+
/** Upstream branch (if tracking) */
|
|
779
|
+
upstream?: string;
|
|
780
|
+
/** Latest commit SHA */
|
|
781
|
+
commit: string;
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Git diff information.
|
|
785
|
+
*/
|
|
786
|
+
interface GitDiff {
|
|
787
|
+
/** Files changed */
|
|
788
|
+
files: Array<{
|
|
789
|
+
path: string;
|
|
790
|
+
status: "added" | "modified" | "deleted" | "renamed";
|
|
791
|
+
additions: number;
|
|
792
|
+
deletions: number;
|
|
793
|
+
}>;
|
|
794
|
+
/** Total additions */
|
|
795
|
+
additions: number;
|
|
796
|
+
/** Total deletions */
|
|
797
|
+
deletions: number;
|
|
798
|
+
/** Raw diff output */
|
|
799
|
+
raw: string;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Information about an installed tool.
|
|
803
|
+
*/
|
|
804
|
+
interface InstalledTool {
|
|
805
|
+
/** Tool name (e.g., "node", "python") */
|
|
806
|
+
name: string;
|
|
807
|
+
/** Installed version */
|
|
808
|
+
version: string;
|
|
809
|
+
/** Path to the tool binary */
|
|
810
|
+
path: string;
|
|
811
|
+
/** Whether this is the active/default version */
|
|
812
|
+
active: boolean;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Result of an agent prompt.
|
|
816
|
+
*/
|
|
817
|
+
interface PromptResult {
|
|
818
|
+
/** Whether the prompt completed successfully */
|
|
819
|
+
success: boolean;
|
|
820
|
+
/** Agent's response text */
|
|
821
|
+
response?: string;
|
|
822
|
+
/** Error message if failed */
|
|
823
|
+
error?: string;
|
|
824
|
+
/** Trace ID for debugging */
|
|
825
|
+
traceId?: string;
|
|
826
|
+
/** Duration in milliseconds */
|
|
827
|
+
durationMs: number;
|
|
828
|
+
/** Token usage */
|
|
829
|
+
usage?: {
|
|
830
|
+
inputTokens: number;
|
|
831
|
+
outputTokens: number;
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
type PromptInputPart = {
|
|
835
|
+
type: "text";
|
|
836
|
+
text: string;
|
|
837
|
+
} | {
|
|
838
|
+
type: "image";
|
|
839
|
+
filename?: string;
|
|
840
|
+
mediaType?: string;
|
|
841
|
+
url?: string;
|
|
842
|
+
path?: string;
|
|
843
|
+
} | {
|
|
844
|
+
type: "file";
|
|
845
|
+
filename?: string;
|
|
846
|
+
mediaType?: string;
|
|
847
|
+
url?: string;
|
|
848
|
+
path?: string;
|
|
849
|
+
content?: string;
|
|
850
|
+
};
|
|
851
|
+
/**
|
|
852
|
+
* Options for sending a prompt.
|
|
853
|
+
*/
|
|
854
|
+
interface PromptOptions {
|
|
855
|
+
/** Session ID for conversation continuity */
|
|
856
|
+
sessionId?: string;
|
|
857
|
+
/** Model to use (format: provider/model, e.g., anthropic/claude-sonnet-4-20250514) */
|
|
858
|
+
model?: string;
|
|
859
|
+
/**
|
|
860
|
+
* Per-run backend override.
|
|
861
|
+
*
|
|
862
|
+
* Use `backend.profile` with a string for a named profile or a provider-neutral
|
|
863
|
+
* `AgentProfile` object for inline profile configuration.
|
|
864
|
+
*/
|
|
865
|
+
backend?: Partial<BackendConfig>;
|
|
866
|
+
/** Timeout in milliseconds */
|
|
867
|
+
timeoutMs?: number;
|
|
868
|
+
/** Additional context */
|
|
869
|
+
context?: Record<string, unknown>;
|
|
870
|
+
/** AbortSignal for cancellation */
|
|
871
|
+
signal?: AbortSignal;
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* SSE event from sandbox streaming.
|
|
875
|
+
*/
|
|
876
|
+
interface SandboxEvent {
|
|
877
|
+
/** Event type */
|
|
878
|
+
type: string;
|
|
879
|
+
/** Event data */
|
|
880
|
+
data: Record<string, unknown>;
|
|
881
|
+
/** Event ID */
|
|
882
|
+
id?: string;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Options for event streaming.
|
|
886
|
+
*/
|
|
887
|
+
interface EventStreamOptions {
|
|
888
|
+
/** AbortSignal for cancellation */
|
|
889
|
+
signal?: AbortSignal;
|
|
890
|
+
/** Filter to specific event types */
|
|
891
|
+
eventTypes?: string[];
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Provisioning step identifier for progress reporting.
|
|
895
|
+
*/
|
|
896
|
+
type ProvisionStep = "match" | "networking" | "git" | "host-select" | "storage" | "image-check" | "image-pull" | "image-build" | "container-create" | "container-start" | "health-check" | "runtime-ready" | "workspace";
|
|
897
|
+
/**
|
|
898
|
+
* Status of a provisioning step.
|
|
899
|
+
*/
|
|
900
|
+
type ProvisionStatus = "started" | "progress" | "completed" | "skipped" | "error";
|
|
901
|
+
/**
|
|
902
|
+
* Provisioning progress event emitted during sandbox creation.
|
|
903
|
+
*
|
|
904
|
+
* Subscribe via `box.watchProvisioning()` or pass `onProgress` to `box.waitFor()`.
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```typescript
|
|
908
|
+
* for await (const event of box.watchProvisioning()) {
|
|
909
|
+
* console.log(`[${event.step}] ${event.status} — ${event.message}`);
|
|
910
|
+
* if (event.percent !== undefined) {
|
|
911
|
+
* updateProgressBar(event.percent);
|
|
912
|
+
* }
|
|
913
|
+
* }
|
|
914
|
+
* ```
|
|
915
|
+
*/
|
|
916
|
+
interface ProvisionEvent {
|
|
917
|
+
/** The provisioning step (e.g., "image-pull", "container-start") */
|
|
918
|
+
step: ProvisionStep;
|
|
919
|
+
/** Status of this step */
|
|
920
|
+
status: ProvisionStatus;
|
|
921
|
+
/** Human-readable progress message */
|
|
922
|
+
message?: string;
|
|
923
|
+
/** Overall progress percentage (0-100) */
|
|
924
|
+
percent?: number;
|
|
925
|
+
/** Additional detail for the step */
|
|
926
|
+
detail?: Record<string, unknown>;
|
|
927
|
+
/** ISO timestamp */
|
|
928
|
+
timestamp: string;
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Terminal provisioning event indicating success or failure.
|
|
932
|
+
*/
|
|
933
|
+
type ProvisionResult = {
|
|
934
|
+
type: "complete";
|
|
935
|
+
containerId: string;
|
|
936
|
+
timestamp: string;
|
|
937
|
+
} | {
|
|
938
|
+
type: "failed";
|
|
939
|
+
error: string;
|
|
940
|
+
timestamp: string;
|
|
941
|
+
};
|
|
942
|
+
/**
|
|
943
|
+
* Options for `waitFor()`.
|
|
944
|
+
*/
|
|
945
|
+
interface WaitForOptions {
|
|
946
|
+
/** Timeout in milliseconds (default: 120000) */
|
|
947
|
+
timeoutMs?: number;
|
|
948
|
+
/** Poll interval in milliseconds when SSE is unavailable (default: 2000) */
|
|
949
|
+
pollIntervalMs?: number;
|
|
950
|
+
/** AbortSignal for cancellation */
|
|
951
|
+
signal?: AbortSignal;
|
|
952
|
+
/**
|
|
953
|
+
* Callback invoked with real-time provisioning progress events.
|
|
954
|
+
* When provided and the sandbox is provisioning, `waitFor()` uses SSE
|
|
955
|
+
* instead of polling for faster, more granular updates.
|
|
956
|
+
*/
|
|
957
|
+
onProgress?: (event: ProvisionEvent) => void;
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Usage information for the account.
|
|
961
|
+
*/
|
|
962
|
+
interface UsageInfo {
|
|
963
|
+
/** Total compute minutes used today */
|
|
964
|
+
computeMinutes: number;
|
|
965
|
+
/** Number of currently active sandboxes */
|
|
966
|
+
activeSandboxes: number;
|
|
967
|
+
/** Total sandboxes created (lifetime) */
|
|
968
|
+
totalSandboxes: number;
|
|
969
|
+
/** Period start date (current day UTC) */
|
|
970
|
+
periodStart: Date;
|
|
971
|
+
/** Period end date (next day UTC) */
|
|
972
|
+
periodEnd: Date;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Subscription and billing information for the account.
|
|
976
|
+
*/
|
|
977
|
+
interface SubscriptionInfo {
|
|
978
|
+
/** Current plan tier */
|
|
979
|
+
plan: "free" | "pro" | "enterprise";
|
|
980
|
+
/** Subscription status */
|
|
981
|
+
status: "active" | "canceled" | "past_due";
|
|
982
|
+
/**
|
|
983
|
+
* Available credit balance in USD.
|
|
984
|
+
*
|
|
985
|
+
* **May be negative** for overage-enabled plans (pro/enterprise):
|
|
986
|
+
* overage charges can push the stored balance below zero. Free-tier
|
|
987
|
+
* plans cap at 0 at the charge path (`capAtZero: true`).
|
|
988
|
+
*
|
|
989
|
+
* Freshness semantics differ by deployment backend: the
|
|
990
|
+
* Cloudflare/D1 backend includes real-time projected cost of
|
|
991
|
+
* currently-running sandboxes; the Node/Redis backend returns the
|
|
992
|
+
* last-deducted stored balance and reflects running sandboxes only
|
|
993
|
+
* once their usage is recorded. Consumers should not assume this
|
|
994
|
+
* value is non-negative — use `>= 0` checks rather than truthiness.
|
|
995
|
+
*/
|
|
996
|
+
creditsAvailableUsd: number;
|
|
997
|
+
/** Credits used in USD */
|
|
998
|
+
creditsUsedUsd: number;
|
|
999
|
+
/** Monthly included balance in USD */
|
|
1000
|
+
monthlyBalanceUsd: number;
|
|
1001
|
+
/** Max concurrent sandboxes (0 = unlimited) */
|
|
1002
|
+
maxConcurrentSandboxes: number;
|
|
1003
|
+
/** Whether overage billing is allowed */
|
|
1004
|
+
overageAllowed: boolean;
|
|
1005
|
+
/** Resource limits */
|
|
1006
|
+
limits: {
|
|
1007
|
+
maxCpuCores: number;
|
|
1008
|
+
maxRamGB: number;
|
|
1009
|
+
maxStorageGB: number;
|
|
1010
|
+
};
|
|
1011
|
+
/** Current billing period end (epoch ms) */
|
|
1012
|
+
currentPeriodEnd: number;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* S3-compatible storage provider configuration (BYOS3 - Bring Your Own S3).
|
|
1016
|
+
*
|
|
1017
|
+
* Allows customers to store snapshots in their own S3-compatible storage.
|
|
1018
|
+
* Supports AWS S3, Google Cloud Storage (GCS), and Cloudflare R2.
|
|
1019
|
+
*
|
|
1020
|
+
* @example AWS S3
|
|
1021
|
+
* ```typescript
|
|
1022
|
+
* const storage: StorageConfig = {
|
|
1023
|
+
* type: "s3",
|
|
1024
|
+
* bucket: "my-snapshots",
|
|
1025
|
+
* region: "us-east-1",
|
|
1026
|
+
* credentials: {
|
|
1027
|
+
* accessKeyId: "AKIA...",
|
|
1028
|
+
* secretAccessKey: "...",
|
|
1029
|
+
* },
|
|
1030
|
+
* };
|
|
1031
|
+
* ```
|
|
1032
|
+
*
|
|
1033
|
+
* @example Cloudflare R2
|
|
1034
|
+
* ```typescript
|
|
1035
|
+
* const storage: StorageConfig = {
|
|
1036
|
+
* type: "r2",
|
|
1037
|
+
* bucket: "my-snapshots",
|
|
1038
|
+
* endpoint: "https://<account>.r2.cloudflarestorage.com",
|
|
1039
|
+
* credentials: {
|
|
1040
|
+
* accessKeyId: "...",
|
|
1041
|
+
* secretAccessKey: "...",
|
|
1042
|
+
* },
|
|
1043
|
+
* };
|
|
1044
|
+
* ```
|
|
1045
|
+
*
|
|
1046
|
+
* @example Google Cloud Storage
|
|
1047
|
+
* ```typescript
|
|
1048
|
+
* const storage: StorageConfig = {
|
|
1049
|
+
* type: "gcs",
|
|
1050
|
+
* bucket: "my-snapshots",
|
|
1051
|
+
* credentials: {
|
|
1052
|
+
* accessKeyId: "...", // HMAC key
|
|
1053
|
+
* secretAccessKey: "...",
|
|
1054
|
+
* },
|
|
1055
|
+
* };
|
|
1056
|
+
* ```
|
|
1057
|
+
*/
|
|
1058
|
+
interface StorageConfig {
|
|
1059
|
+
/** Storage provider type */
|
|
1060
|
+
type: "s3" | "gcs" | "r2";
|
|
1061
|
+
/** Bucket name */
|
|
1062
|
+
bucket: string;
|
|
1063
|
+
/** Custom endpoint URL (required for R2, optional for S3/GCS) */
|
|
1064
|
+
endpoint?: string;
|
|
1065
|
+
/** Region (e.g., us-east-1) */
|
|
1066
|
+
region?: string;
|
|
1067
|
+
/** Access credentials */
|
|
1068
|
+
credentials: {
|
|
1069
|
+
accessKeyId: string;
|
|
1070
|
+
secretAccessKey: string;
|
|
1071
|
+
};
|
|
1072
|
+
/** Path prefix within bucket (default: sandbox-snapshots/) */
|
|
1073
|
+
prefix?: string;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Options for running a multi-turn task.
|
|
1077
|
+
*/
|
|
1078
|
+
interface TaskOptions extends PromptOptions {
|
|
1079
|
+
/** Maximum number of agent turns (default: 10, 0 = unlimited) */
|
|
1080
|
+
maxTurns?: number;
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Result of a multi-turn task execution.
|
|
1084
|
+
*/
|
|
1085
|
+
interface TaskResult extends PromptResult {
|
|
1086
|
+
/** Number of agent turns used */
|
|
1087
|
+
turnsUsed: number;
|
|
1088
|
+
/** Session ID for the task (can be used to continue) */
|
|
1089
|
+
sessionId: string;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Options for creating a snapshot.
|
|
1093
|
+
*/
|
|
1094
|
+
interface SnapshotOptions {
|
|
1095
|
+
/** Tags to apply to the snapshot */
|
|
1096
|
+
tags?: string[];
|
|
1097
|
+
/** Specific paths to include (default: entire workspace) */
|
|
1098
|
+
paths?: string[];
|
|
1099
|
+
/** Customer-provided storage for BYOS3 (calls the runtime directly) */
|
|
1100
|
+
storage?: StorageConfig;
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Result of a snapshot operation.
|
|
1104
|
+
*/
|
|
1105
|
+
interface SnapshotResult {
|
|
1106
|
+
/** Unique snapshot identifier */
|
|
1107
|
+
snapshotId: string;
|
|
1108
|
+
/** When the snapshot was created */
|
|
1109
|
+
createdAt: Date;
|
|
1110
|
+
/** Size in bytes */
|
|
1111
|
+
sizeBytes?: number;
|
|
1112
|
+
/** Tags applied to the snapshot */
|
|
1113
|
+
tags: string[];
|
|
1114
|
+
}
|
|
1115
|
+
interface RestoreSnapshotOptions {
|
|
1116
|
+
destinationPath?: string;
|
|
1117
|
+
snapshotId?: string;
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Metadata about an existing snapshot.
|
|
1121
|
+
*/
|
|
1122
|
+
interface SnapshotInfo {
|
|
1123
|
+
/** Unique snapshot identifier */
|
|
1124
|
+
snapshotId: string;
|
|
1125
|
+
/** Sandbox this snapshot belongs to */
|
|
1126
|
+
sandboxId: string;
|
|
1127
|
+
/** When the snapshot was created */
|
|
1128
|
+
createdAt: Date;
|
|
1129
|
+
/** Tags applied to the snapshot */
|
|
1130
|
+
tags: string[];
|
|
1131
|
+
/** Paths included in the snapshot */
|
|
1132
|
+
paths: string[];
|
|
1133
|
+
/** Size in bytes */
|
|
1134
|
+
sizeBytes?: number;
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* A single task in a batch execution.
|
|
1138
|
+
*/
|
|
1139
|
+
interface BatchTask {
|
|
1140
|
+
/** Unique task identifier */
|
|
1141
|
+
id: string;
|
|
1142
|
+
/** Task prompt/message */
|
|
1143
|
+
message: string;
|
|
1144
|
+
/** Additional context for this task */
|
|
1145
|
+
context?: Record<string, unknown>;
|
|
1146
|
+
/** Per-task timeout in milliseconds */
|
|
1147
|
+
timeoutMs?: number;
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Options for batch execution.
|
|
1151
|
+
*/
|
|
1152
|
+
interface BatchOptions {
|
|
1153
|
+
/** Timeout for entire batch in milliseconds (default: 300000 = 5 min) */
|
|
1154
|
+
timeoutMs?: number;
|
|
1155
|
+
/** Scaling mode: fastest, balanced, or cheapest (default: balanced) */
|
|
1156
|
+
scalingMode?: "fastest" | "balanced" | "cheapest";
|
|
1157
|
+
/**
|
|
1158
|
+
* Shared backend override for the batch.
|
|
1159
|
+
*
|
|
1160
|
+
* Use `backend.profile` with a string for a named profile or a provider-neutral
|
|
1161
|
+
* `AgentProfile` object for inline profile configuration.
|
|
1162
|
+
*/
|
|
1163
|
+
backend?: Partial<BackendConfig>;
|
|
1164
|
+
/** Keep sandboxes alive after completion (default: false) */
|
|
1165
|
+
persistent?: boolean;
|
|
1166
|
+
/**
|
|
1167
|
+
* AbortSignal to cancel the batch mid-stream. When aborted, the HTTP
|
|
1168
|
+
* request to `/batch/run` is torn down; the SSE generator stops
|
|
1169
|
+
* yielding and `runBatch`/`streamBatch` reject with an `AbortError`.
|
|
1170
|
+
*
|
|
1171
|
+
* Note: the server-side batch may continue running to completion —
|
|
1172
|
+
* the signal is strictly for disconnecting the client from the
|
|
1173
|
+
* stream, not for halting server work.
|
|
1174
|
+
*/
|
|
1175
|
+
signal?: AbortSignal;
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Result of a single task in a batch.
|
|
1179
|
+
*/
|
|
1180
|
+
interface BatchTaskResult {
|
|
1181
|
+
/** Task identifier */
|
|
1182
|
+
taskId: string;
|
|
1183
|
+
/** Whether the task succeeded */
|
|
1184
|
+
success: boolean;
|
|
1185
|
+
/** Task response if successful */
|
|
1186
|
+
response?: string;
|
|
1187
|
+
/** Error message if failed */
|
|
1188
|
+
error?: string;
|
|
1189
|
+
/** Duration in milliseconds */
|
|
1190
|
+
durationMs: number;
|
|
1191
|
+
/** Number of retries */
|
|
1192
|
+
retries: number;
|
|
1193
|
+
/** Token usage if available */
|
|
1194
|
+
tokensUsed?: number;
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Summary of batch execution.
|
|
1198
|
+
*/
|
|
1199
|
+
interface BatchResult {
|
|
1200
|
+
/** Total tasks executed */
|
|
1201
|
+
totalTasks: number;
|
|
1202
|
+
/** Number of successful tasks */
|
|
1203
|
+
succeeded: number;
|
|
1204
|
+
/** Number of failed tasks */
|
|
1205
|
+
failed: number;
|
|
1206
|
+
/** Total retries across all tasks */
|
|
1207
|
+
totalRetries: number;
|
|
1208
|
+
/** Success rate (0-100) */
|
|
1209
|
+
successRate: number;
|
|
1210
|
+
/** Individual task results */
|
|
1211
|
+
results: BatchTaskResult[];
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* SSE event from batch streaming.
|
|
1215
|
+
*/
|
|
1216
|
+
interface BatchEvent {
|
|
1217
|
+
/** Event type (batch.started, task.completed, etc.) */
|
|
1218
|
+
type: string;
|
|
1219
|
+
/** Event data */
|
|
1220
|
+
data: Record<string, unknown>;
|
|
1221
|
+
/**
|
|
1222
|
+
* Optional `id:` from the SSE frame. Present at runtime whenever
|
|
1223
|
+
* the server emits an `id:` line (used by EventSource-style
|
|
1224
|
+
* reconnection). Declared optional because the batch protocol
|
|
1225
|
+
* doesn't currently emit it — downstream consumers that want to
|
|
1226
|
+
* implement resume should feature-detect.
|
|
1227
|
+
*/
|
|
1228
|
+
id?: string;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Options for creating a checkpoint.
|
|
1232
|
+
*/
|
|
1233
|
+
interface CheckpointOptions {
|
|
1234
|
+
/** Tags to apply to the checkpoint */
|
|
1235
|
+
tags?: string[];
|
|
1236
|
+
/** Keep sandbox running after checkpoint (default: false - sandbox stops) */
|
|
1237
|
+
leaveRunning?: boolean;
|
|
1238
|
+
/** Also create a filesystem snapshot for data consistency */
|
|
1239
|
+
includeSnapshot?: boolean;
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Result of a checkpoint operation.
|
|
1243
|
+
*/
|
|
1244
|
+
interface CheckpointResult {
|
|
1245
|
+
/** Unique checkpoint identifier */
|
|
1246
|
+
checkpointId: string;
|
|
1247
|
+
/** When the checkpoint was created */
|
|
1248
|
+
createdAt: Date;
|
|
1249
|
+
/** Size of checkpoint in bytes (memory state) */
|
|
1250
|
+
sizeBytes?: number;
|
|
1251
|
+
/** Tags applied to the checkpoint */
|
|
1252
|
+
tags: string[];
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Information about an existing checkpoint.
|
|
1256
|
+
*/
|
|
1257
|
+
interface CheckpointInfo {
|
|
1258
|
+
/** Unique checkpoint identifier */
|
|
1259
|
+
checkpointId: string;
|
|
1260
|
+
/** Sandbox this checkpoint belongs to */
|
|
1261
|
+
sandboxId: string;
|
|
1262
|
+
/** When the checkpoint was created */
|
|
1263
|
+
createdAt: Date;
|
|
1264
|
+
/** Tags applied to the checkpoint */
|
|
1265
|
+
tags: string[];
|
|
1266
|
+
/** Size of checkpoint in bytes */
|
|
1267
|
+
sizeBytes?: number;
|
|
1268
|
+
/** Whether checkpoint includes memory state */
|
|
1269
|
+
hasMemoryState: boolean;
|
|
1270
|
+
/** Whether checkpoint includes filesystem snapshot */
|
|
1271
|
+
hasFilesystemSnapshot: boolean;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Options for forking a sandbox from a checkpoint.
|
|
1275
|
+
*/
|
|
1276
|
+
interface ForkOptions {
|
|
1277
|
+
/** Name for the forked sandbox */
|
|
1278
|
+
name?: string;
|
|
1279
|
+
/** Override environment variables in the fork */
|
|
1280
|
+
env?: Record<string, string>;
|
|
1281
|
+
/** Override resource limits in the fork */
|
|
1282
|
+
resources?: SandboxResources;
|
|
1283
|
+
/** Custom metadata for the fork */
|
|
1284
|
+
metadata?: Record<string, unknown>;
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Result of a fork operation.
|
|
1288
|
+
*/
|
|
1289
|
+
interface ForkResult {
|
|
1290
|
+
/** The newly created sandbox instance */
|
|
1291
|
+
sandbox: SandboxInfo;
|
|
1292
|
+
/** The checkpoint that was forked from */
|
|
1293
|
+
sourceCheckpoint: CheckpointInfo;
|
|
1294
|
+
/** ID of the source sandbox */
|
|
1295
|
+
sourceId: string;
|
|
1296
|
+
/** Time taken to fork in milliseconds */
|
|
1297
|
+
forkTimeMs: number;
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Infrastructure driver identifier.
|
|
1301
|
+
*
|
|
1302
|
+
* Most callers should omit `driver` and let the platform select automatically.
|
|
1303
|
+
*/
|
|
1304
|
+
type DriverType = "docker" | "firecracker" | "host-agent" | "tangle";
|
|
1305
|
+
/**
|
|
1306
|
+
* Accelerator class for GPU-enabled sandboxes.
|
|
1307
|
+
*/
|
|
1308
|
+
type GpuType = "nvidia-a100" | "nvidia-h100" | "nvidia-l4" | "amd-mi250";
|
|
1309
|
+
/**
|
|
1310
|
+
* Infrastructure driver configuration.
|
|
1311
|
+
*
|
|
1312
|
+
* @example Default
|
|
1313
|
+
* ```typescript
|
|
1314
|
+
* driver: { type: "docker" }
|
|
1315
|
+
* ```
|
|
1316
|
+
*
|
|
1317
|
+
* @example With pause/resume support
|
|
1318
|
+
* ```typescript
|
|
1319
|
+
* driver: { type: "firecracker", enableCriu: true }
|
|
1320
|
+
* ```
|
|
1321
|
+
*
|
|
1322
|
+
* @example GPU-enabled sandbox
|
|
1323
|
+
* ```typescript
|
|
1324
|
+
* driver: {
|
|
1325
|
+
* type: "host-agent",
|
|
1326
|
+
* gpuRequired: true,
|
|
1327
|
+
* gpuType: "nvidia-a100",
|
|
1328
|
+
* }
|
|
1329
|
+
* ```
|
|
1330
|
+
*/
|
|
1331
|
+
interface DriverConfig {
|
|
1332
|
+
/**
|
|
1333
|
+
* Driver type identifier.
|
|
1334
|
+
* @default "docker"
|
|
1335
|
+
*/
|
|
1336
|
+
type: DriverType;
|
|
1337
|
+
/**
|
|
1338
|
+
* Enable checkpointing for pause/resume and fork operations.
|
|
1339
|
+
* Support depends on the selected driver.
|
|
1340
|
+
*/
|
|
1341
|
+
enableCriu?: boolean;
|
|
1342
|
+
/** Require a GPU for this sandbox. */
|
|
1343
|
+
gpuRequired?: boolean;
|
|
1344
|
+
/** Accelerator class preference. */
|
|
1345
|
+
gpuType?: GpuType;
|
|
1346
|
+
/**
|
|
1347
|
+
* Number of GPUs required.
|
|
1348
|
+
* @default 1 (when gpuRequired is true)
|
|
1349
|
+
*/
|
|
1350
|
+
gpuCount?: number;
|
|
1351
|
+
/**
|
|
1352
|
+
* Preferred placement region.
|
|
1353
|
+
* e.g., "us-east-1", "eu-west-1".
|
|
1354
|
+
*/
|
|
1355
|
+
preferredRegion?: string;
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Driver capabilities and status.
|
|
1359
|
+
*/
|
|
1360
|
+
interface DriverInfo {
|
|
1361
|
+
/** Driver type */
|
|
1362
|
+
type: DriverType;
|
|
1363
|
+
/** Whether driver is available */
|
|
1364
|
+
available: boolean;
|
|
1365
|
+
/** Driver version string */
|
|
1366
|
+
version: string;
|
|
1367
|
+
/** Driver capabilities */
|
|
1368
|
+
capabilities: {
|
|
1369
|
+
/** Checkpoint/restore support */criu: boolean; /** GPU support */
|
|
1370
|
+
gpu: boolean; /** Filesystem snapshots */
|
|
1371
|
+
snapshots: boolean; /** Multi-user management */
|
|
1372
|
+
userManagement: boolean; /** Network isolation */
|
|
1373
|
+
networkIsolation: boolean;
|
|
1374
|
+
};
|
|
1375
|
+
/** Current capacity */
|
|
1376
|
+
capacity?: {
|
|
1377
|
+
available: number;
|
|
1378
|
+
total: number;
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Backend type identifier. Controls which AI agent runtime runs inside the sandbox.
|
|
1383
|
+
*
|
|
1384
|
+
* The public-SDK source of truth. Kept in lock-step with the private
|
|
1385
|
+
* `@tangle-network/cli-agent-registry` spec list via the parity check in
|
|
1386
|
+
* `packages/cli-agent-registry/tests/specs.test.ts` (adding a new CLI spec
|
|
1387
|
+
* without updating this union surfaces as a test failure at PR review
|
|
1388
|
+
* time). Inlined here so the published SDK doesn't carry an unpublished
|
|
1389
|
+
* internal package as a runtime dep.
|
|
1390
|
+
*
|
|
1391
|
+
* - `"opencode"` — Default. Multi-provider, profile system, MCP support.
|
|
1392
|
+
* - `"claude-code"` — Anthropic Claude Code CLI. Requires an Anthropic API key.
|
|
1393
|
+
* - `"codex"` — OpenAI Codex CLI. Requires an OpenAI API key.
|
|
1394
|
+
* - `"amp"` — Sourcegraph AMP agent.
|
|
1395
|
+
* - `"factory-droids"` — Factory Droid agent.
|
|
1396
|
+
* - `"pi"` — Pi coding-agent CLI.
|
|
1397
|
+
* - `"hermes"` — Hermes inference-router agent.
|
|
1398
|
+
* - `"forge"` — Forge (forgecode.dev, tailcallhq) multi-provider coding agent.
|
|
1399
|
+
* - `"openclaw"` — OpenClaw dispatcher that routes to claude-cli/codex-cli/gemini-cli.
|
|
1400
|
+
* - `"acp"` — Agent Client Protocol bridge — fronts any ACP-compliant
|
|
1401
|
+
* agent binary (claude-agent-acp, codex-acp, gemini, openclaw acp).
|
|
1402
|
+
* Pick the backing agent via config.subAgent.
|
|
1403
|
+
* - `"cli-base"` — Minimal CLI-only (no AI agent).
|
|
1404
|
+
*/
|
|
1405
|
+
type BackendType = "opencode" | "claude-code" | "codex" | "amp" | "factory-droids" | "pi" | "hermes" | "forge" | "openclaw" | "acp" | "cli-base";
|
|
1406
|
+
/**
|
|
1407
|
+
* MCP (Model Context Protocol) server configuration.
|
|
1408
|
+
*/
|
|
1409
|
+
interface McpServerConfig {
|
|
1410
|
+
/** Command to run (e.g., "npx", "node") */
|
|
1411
|
+
command: string;
|
|
1412
|
+
/** Command arguments */
|
|
1413
|
+
args?: string[];
|
|
1414
|
+
/** Environment variables */
|
|
1415
|
+
env?: Record<string, string>;
|
|
1416
|
+
/** Working directory */
|
|
1417
|
+
cwd?: string;
|
|
1418
|
+
/** Remote URL (for remote MCP servers via SSE) */
|
|
1419
|
+
url?: string;
|
|
1420
|
+
/** Headers for remote connections */
|
|
1421
|
+
headers?: Record<string, string>;
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* AI coding agent backend configuration.
|
|
1425
|
+
*
|
|
1426
|
+
* @example OpenCode with default settings
|
|
1427
|
+
* ```typescript
|
|
1428
|
+
* backend: { type: "opencode" }
|
|
1429
|
+
* ```
|
|
1430
|
+
*
|
|
1431
|
+
* @example OpenCode with named profile
|
|
1432
|
+
* ```typescript
|
|
1433
|
+
* backend: {
|
|
1434
|
+
* type: "opencode",
|
|
1435
|
+
* profile: "with-web-search",
|
|
1436
|
+
* }
|
|
1437
|
+
* ```
|
|
1438
|
+
*
|
|
1439
|
+
* @example Claude Code with BYOK
|
|
1440
|
+
* ```typescript
|
|
1441
|
+
* backend: {
|
|
1442
|
+
* type: "claude-code",
|
|
1443
|
+
* model: {
|
|
1444
|
+
* provider: "anthropic",
|
|
1445
|
+
* model: "claude-sonnet-4-20250514",
|
|
1446
|
+
* apiKey: process.env.ANTHROPIC_API_KEY,
|
|
1447
|
+
* }
|
|
1448
|
+
* }
|
|
1449
|
+
* ```
|
|
1450
|
+
*/
|
|
1451
|
+
interface BackendConfig {
|
|
1452
|
+
/**
|
|
1453
|
+
* Backend type identifier.
|
|
1454
|
+
* @default "opencode"
|
|
1455
|
+
*/
|
|
1456
|
+
type: BackendType;
|
|
1457
|
+
/**
|
|
1458
|
+
* Backend profile selection.
|
|
1459
|
+
*
|
|
1460
|
+
* Use a string for a named provider/backend profile, or an `AgentProfile`
|
|
1461
|
+
* object for an inline provider-neutral profile definition.
|
|
1462
|
+
*/
|
|
1463
|
+
profile?: string | AgentProfile;
|
|
1464
|
+
/**
|
|
1465
|
+
* Model configuration override.
|
|
1466
|
+
*/
|
|
1467
|
+
model?: {
|
|
1468
|
+
/** Provider name (e.g., "anthropic", "openai", "google") */provider?: string; /** Model identifier (e.g., "claude-sonnet-4-20250514") */
|
|
1469
|
+
model?: string; /** BYOK (Bring Your Own Key) API key */
|
|
1470
|
+
apiKey?: string; /** Custom API base URL (for proxies or on-prem) */
|
|
1471
|
+
baseUrl?: string; /** Maximum thinking tokens for extended reasoning */
|
|
1472
|
+
maxThinkingTokens?: number; /** API mode: "api" for direct calls, "cli" for CLI wrapper */
|
|
1473
|
+
mode?: "api" | "cli"; /** Authentication mode for CLI-native backends */
|
|
1474
|
+
authMode?: "api-key" | "oauth"; /** Auth files to write into the sandbox home directory before CLI startup */
|
|
1475
|
+
authFiles?: Array<{
|
|
1476
|
+
path: string;
|
|
1477
|
+
content: string;
|
|
1478
|
+
mode?: number;
|
|
1479
|
+
}>;
|
|
1480
|
+
};
|
|
1481
|
+
/**
|
|
1482
|
+
* Backend server configuration.
|
|
1483
|
+
*/
|
|
1484
|
+
server?: {
|
|
1485
|
+
/** Server port (auto-assigned if not specified) */port?: number; /** Server hostname */
|
|
1486
|
+
hostname?: string;
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Backend capabilities.
|
|
1491
|
+
*/
|
|
1492
|
+
interface BackendCapabilities {
|
|
1493
|
+
/** Supports streaming responses */
|
|
1494
|
+
streaming: boolean;
|
|
1495
|
+
/** Supports tool/function use */
|
|
1496
|
+
toolUse: boolean;
|
|
1497
|
+
/** Supports extended thinking/reasoning */
|
|
1498
|
+
reasoning: boolean;
|
|
1499
|
+
/** Supports multimodal (images, etc) */
|
|
1500
|
+
multimodal: boolean;
|
|
1501
|
+
/** Context window size in tokens */
|
|
1502
|
+
contextWindow: number;
|
|
1503
|
+
/** Support details for provider-neutral `AgentProfile` values */
|
|
1504
|
+
profile?: AgentProfileCapabilities;
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* Backend status information.
|
|
1508
|
+
*/
|
|
1509
|
+
interface BackendStatus {
|
|
1510
|
+
/** Backend type */
|
|
1511
|
+
type: BackendType;
|
|
1512
|
+
/** Current status */
|
|
1513
|
+
status: "running" | "stopped" | "starting" | "stopping" | "unknown";
|
|
1514
|
+
/** Backend version */
|
|
1515
|
+
version?: string;
|
|
1516
|
+
/** Error message if failed */
|
|
1517
|
+
error?: string;
|
|
1518
|
+
/** Additional metadata */
|
|
1519
|
+
metadata?: Record<string, unknown>;
|
|
1520
|
+
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Backend information.
|
|
1523
|
+
*/
|
|
1524
|
+
interface BackendInfo {
|
|
1525
|
+
/** Backend type */
|
|
1526
|
+
type: BackendType;
|
|
1527
|
+
/** Whether backend is available */
|
|
1528
|
+
available: boolean;
|
|
1529
|
+
/** Backend capabilities */
|
|
1530
|
+
capabilities: BackendCapabilities;
|
|
1531
|
+
/** Available profiles (for opencode) */
|
|
1532
|
+
profiles?: Array<{
|
|
1533
|
+
name: string;
|
|
1534
|
+
description?: string;
|
|
1535
|
+
tags?: string[];
|
|
1536
|
+
}>;
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Network configuration for sandbox network isolation.
|
|
1540
|
+
*
|
|
1541
|
+
* Supports two modes:
|
|
1542
|
+
* - `blockOutbound: true` - Block all egress traffic (ports still work for inbound)
|
|
1543
|
+
* - `allowList: ["cidr", ...]` - Allow only specific destinations
|
|
1544
|
+
*
|
|
1545
|
+
* These modes are mutually exclusive.
|
|
1546
|
+
*
|
|
1547
|
+
* @example Block all outbound traffic
|
|
1548
|
+
* ```typescript
|
|
1549
|
+
* const box = await client.create({
|
|
1550
|
+
* network: { blockOutbound: true }
|
|
1551
|
+
* });
|
|
1552
|
+
* ```
|
|
1553
|
+
*
|
|
1554
|
+
* @example Allow only specific destinations
|
|
1555
|
+
* ```typescript
|
|
1556
|
+
* const box = await client.create({
|
|
1557
|
+
* network: {
|
|
1558
|
+
* allowList: [
|
|
1559
|
+
* "8.8.8.8/32", // Google DNS
|
|
1560
|
+
* "10.0.0.0/8", // Private network
|
|
1561
|
+
* ]
|
|
1562
|
+
* }
|
|
1563
|
+
* });
|
|
1564
|
+
* ```
|
|
1565
|
+
*
|
|
1566
|
+
* @example Pre-expose ports at creation
|
|
1567
|
+
* ```typescript
|
|
1568
|
+
* const box = await client.create({
|
|
1569
|
+
* network: {
|
|
1570
|
+
* blockOutbound: true,
|
|
1571
|
+
* ports: [8000, 8080], // Pre-expose these ports
|
|
1572
|
+
* }
|
|
1573
|
+
* });
|
|
1574
|
+
* ```
|
|
1575
|
+
*/
|
|
1576
|
+
interface NetworkConfig {
|
|
1577
|
+
/**
|
|
1578
|
+
* Block all outbound network traffic.
|
|
1579
|
+
* Exposed ports still work for inbound connections.
|
|
1580
|
+
* Mutually exclusive with `allowList`.
|
|
1581
|
+
*/
|
|
1582
|
+
blockOutbound?: boolean;
|
|
1583
|
+
/**
|
|
1584
|
+
* CIDR allowlist for outbound traffic.
|
|
1585
|
+
* Only traffic to these destinations is allowed.
|
|
1586
|
+
* Maximum 10 entries. Mutually exclusive with `blockOutbound`.
|
|
1587
|
+
*
|
|
1588
|
+
* Supports both IPv4 and IPv6 CIDR notation:
|
|
1589
|
+
* - "8.8.8.8/32" - Single IPv4 address
|
|
1590
|
+
* - "10.0.0.0/8" - IPv4 subnet
|
|
1591
|
+
* - "2001:db8::/32" - IPv6 subnet
|
|
1592
|
+
*/
|
|
1593
|
+
allowList?: string[];
|
|
1594
|
+
/**
|
|
1595
|
+
* Ports to expose at creation time.
|
|
1596
|
+
* These ports will be accessible regardless of network restrictions.
|
|
1597
|
+
*/
|
|
1598
|
+
ports?: number[];
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Network manager for runtime network configuration.
|
|
1602
|
+
* Access via `sandbox.network`.
|
|
1603
|
+
*
|
|
1604
|
+
* @example Update network restrictions
|
|
1605
|
+
* ```typescript
|
|
1606
|
+
* // Block all outbound traffic
|
|
1607
|
+
* await box.network.update({ blockOutbound: true });
|
|
1608
|
+
*
|
|
1609
|
+
* // Or switch to allowlist mode
|
|
1610
|
+
* await box.network.update({
|
|
1611
|
+
* allowList: ["192.168.1.0/24", "8.8.8.8/32"]
|
|
1612
|
+
* });
|
|
1613
|
+
*
|
|
1614
|
+
* // Remove restrictions
|
|
1615
|
+
* await box.network.update({ blockOutbound: false });
|
|
1616
|
+
* ```
|
|
1617
|
+
*
|
|
1618
|
+
* @example Expose ports dynamically
|
|
1619
|
+
* ```typescript
|
|
1620
|
+
* const url = await box.network.exposePort(8000);
|
|
1621
|
+
* console.log(`Service available at: ${url}`);
|
|
1622
|
+
*
|
|
1623
|
+
* const allUrls = await box.network.listUrls();
|
|
1624
|
+
* ```
|
|
1625
|
+
*/
|
|
1626
|
+
interface NetworkManager {
|
|
1627
|
+
/**
|
|
1628
|
+
* Update network permissions at runtime.
|
|
1629
|
+
* Changes apply immediately without container restart.
|
|
1630
|
+
*
|
|
1631
|
+
* @param config - Partial network configuration to apply
|
|
1632
|
+
* @throws Error if blockOutbound and allowList are both specified
|
|
1633
|
+
* @throws Error if allowList exceeds 10 entries
|
|
1634
|
+
* @throws Error if CIDR format is invalid
|
|
1635
|
+
*/
|
|
1636
|
+
update(config: Partial<NetworkConfig>): Promise<void>;
|
|
1637
|
+
/**
|
|
1638
|
+
* Expose a port dynamically.
|
|
1639
|
+
* Returns a publicly accessible URL for the port.
|
|
1640
|
+
* Works regardless of network restrictions.
|
|
1641
|
+
*
|
|
1642
|
+
* @param port - Port number to expose (1-65535)
|
|
1643
|
+
* @returns Public URL for accessing the exposed port
|
|
1644
|
+
*/
|
|
1645
|
+
exposePort(port: number): Promise<string>;
|
|
1646
|
+
/**
|
|
1647
|
+
* List all exposed port URLs.
|
|
1648
|
+
*
|
|
1649
|
+
* @returns Map of port numbers to their public URLs
|
|
1650
|
+
*/
|
|
1651
|
+
listUrls(): Promise<Record<number, string>>;
|
|
1652
|
+
/**
|
|
1653
|
+
* Get current network configuration.
|
|
1654
|
+
*
|
|
1655
|
+
* @returns Current network config including any runtime changes
|
|
1656
|
+
*/
|
|
1657
|
+
getConfig(): Promise<NetworkConfig>;
|
|
1658
|
+
}
|
|
1659
|
+
interface PreviewLinkInfo {
|
|
1660
|
+
previewId: string;
|
|
1661
|
+
sandboxId: string;
|
|
1662
|
+
port: number;
|
|
1663
|
+
protocol: "tcp" | "udp";
|
|
1664
|
+
hostname: string;
|
|
1665
|
+
url: string;
|
|
1666
|
+
status: "provisioning" | "ready" | "error" | "disabled";
|
|
1667
|
+
lastSyncAt: string;
|
|
1668
|
+
createdAt: string;
|
|
1669
|
+
updatedAt: string;
|
|
1670
|
+
metadata?: Record<string, unknown>;
|
|
1671
|
+
}
|
|
1672
|
+
/**
|
|
1673
|
+
* Preview link management.
|
|
1674
|
+
*
|
|
1675
|
+
* Create publicly accessible HTTPS URLs for TCP ports inside the sandbox.
|
|
1676
|
+
*
|
|
1677
|
+
* @example
|
|
1678
|
+
* ```typescript
|
|
1679
|
+
* // Expose a dev server
|
|
1680
|
+
* const link = await box.previewLinks.create(3000);
|
|
1681
|
+
* console.log(link.url);
|
|
1682
|
+
*
|
|
1683
|
+
* // List all preview links
|
|
1684
|
+
* const links = await box.previewLinks.list();
|
|
1685
|
+
*
|
|
1686
|
+
* // Remove a preview link
|
|
1687
|
+
* await box.previewLinks.remove(link.previewId);
|
|
1688
|
+
* ```
|
|
1689
|
+
*/
|
|
1690
|
+
interface PreviewLinkManager {
|
|
1691
|
+
/**
|
|
1692
|
+
* Create a preview link for a port.
|
|
1693
|
+
* Returns the preview link with its public URL.
|
|
1694
|
+
* If a link already exists for this port, returns the existing one.
|
|
1695
|
+
*
|
|
1696
|
+
* @param port - Port number to expose (1-65535)
|
|
1697
|
+
* @param options - Optional protocol and metadata
|
|
1698
|
+
*/
|
|
1699
|
+
create(port: number, options?: {
|
|
1700
|
+
protocol?: "tcp" | "udp";
|
|
1701
|
+
metadata?: Record<string, unknown>;
|
|
1702
|
+
}): Promise<PreviewLinkInfo>;
|
|
1703
|
+
/**
|
|
1704
|
+
* List all preview links for this sandbox.
|
|
1705
|
+
*/
|
|
1706
|
+
list(): Promise<PreviewLinkInfo[]>;
|
|
1707
|
+
/**
|
|
1708
|
+
* Remove a preview link by ID.
|
|
1709
|
+
*
|
|
1710
|
+
* @param previewId - The preview link ID to remove
|
|
1711
|
+
*/
|
|
1712
|
+
remove(previewId: string): Promise<void>;
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Permission level for sandbox users.
|
|
1716
|
+
*
|
|
1717
|
+
* - `owner` — Full access, can manage users.
|
|
1718
|
+
* - `admin` — Read/write workspace, can manage users.
|
|
1719
|
+
* - `developer` — Read/write workspace.
|
|
1720
|
+
* - `viewer` — Read-only workspace.
|
|
1721
|
+
*/
|
|
1722
|
+
type PermissionLevel = "owner" | "admin" | "developer" | "viewer";
|
|
1723
|
+
/**
|
|
1724
|
+
* Directory-level permission override.
|
|
1725
|
+
*/
|
|
1726
|
+
interface DirectoryPermission {
|
|
1727
|
+
/** Directory path (absolute, e.g. "/workspace/shared") */
|
|
1728
|
+
path: string;
|
|
1729
|
+
/** Read access */
|
|
1730
|
+
read: boolean;
|
|
1731
|
+
/** Write access */
|
|
1732
|
+
write: boolean;
|
|
1733
|
+
/** Execute/traverse access */
|
|
1734
|
+
execute: boolean;
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Glob-based access policy rule.
|
|
1738
|
+
*
|
|
1739
|
+
* @example Block all .env files
|
|
1740
|
+
* ```typescript
|
|
1741
|
+
* { pattern: "*.env", permission: "none" }
|
|
1742
|
+
* ```
|
|
1743
|
+
*
|
|
1744
|
+
* @example Read-only secrets directory
|
|
1745
|
+
* ```typescript
|
|
1746
|
+
* { pattern: "/secrets/**", permission: "read" }
|
|
1747
|
+
* ```
|
|
1748
|
+
*/
|
|
1749
|
+
interface AccessPolicyRule {
|
|
1750
|
+
/** Glob pattern for matching (e.g., "*.env", "/secrets/**") */
|
|
1751
|
+
pattern: string;
|
|
1752
|
+
/** Access level for matching paths */
|
|
1753
|
+
permission: "read" | "write" | "none";
|
|
1754
|
+
/** Priority when patterns overlap (higher wins) */
|
|
1755
|
+
priority?: number;
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* User in a sandbox.
|
|
1759
|
+
*/
|
|
1760
|
+
interface SandboxUser {
|
|
1761
|
+
/** Unique user ID (from auth system) */
|
|
1762
|
+
userId: string;
|
|
1763
|
+
/** Username inside sandbox (Unix username) */
|
|
1764
|
+
username: string;
|
|
1765
|
+
/** Home directory path */
|
|
1766
|
+
homeDir: string;
|
|
1767
|
+
/** Permission level */
|
|
1768
|
+
role: PermissionLevel;
|
|
1769
|
+
/** SSH public keys */
|
|
1770
|
+
sshKeys: string[];
|
|
1771
|
+
/** Directory permission overrides */
|
|
1772
|
+
directoryPermissions?: DirectoryPermission[];
|
|
1773
|
+
/** Access policy rules */
|
|
1774
|
+
accessPolicies?: AccessPolicyRule[];
|
|
1775
|
+
/** When user was added */
|
|
1776
|
+
createdAt: Date;
|
|
1777
|
+
}
|
|
1778
|
+
/**
|
|
1779
|
+
* Options for adding a user to a sandbox.
|
|
1780
|
+
*/
|
|
1781
|
+
interface AddUserOptions {
|
|
1782
|
+
/** Unique user ID (from your auth system) */
|
|
1783
|
+
userId: string;
|
|
1784
|
+
/** Preferred username (will be sanitized for Unix) */
|
|
1785
|
+
username?: string;
|
|
1786
|
+
/** Permission level (default: developer) */
|
|
1787
|
+
role?: PermissionLevel;
|
|
1788
|
+
/** SSH public keys for remote access */
|
|
1789
|
+
sshKeys?: string[];
|
|
1790
|
+
/** Custom directory permissions */
|
|
1791
|
+
directoryPermissions?: DirectoryPermission[];
|
|
1792
|
+
}
|
|
1793
|
+
/**
|
|
1794
|
+
* Options for updating a user.
|
|
1795
|
+
*/
|
|
1796
|
+
interface UpdateUserOptions {
|
|
1797
|
+
/** New permission level */
|
|
1798
|
+
role?: PermissionLevel;
|
|
1799
|
+
/** SSH keys to add */
|
|
1800
|
+
addSshKeys?: string[];
|
|
1801
|
+
/** SSH keys to remove */
|
|
1802
|
+
removeSshKeys?: string[];
|
|
1803
|
+
/** Directory permissions to add/update */
|
|
1804
|
+
directoryPermissions?: DirectoryPermission[];
|
|
1805
|
+
}
|
|
1806
|
+
/**
|
|
1807
|
+
* Initial permissions configuration for sandbox creation.
|
|
1808
|
+
*/
|
|
1809
|
+
interface SandboxPermissionsConfig {
|
|
1810
|
+
/**
|
|
1811
|
+
* Default role for invited users.
|
|
1812
|
+
* @default "developer"
|
|
1813
|
+
*/
|
|
1814
|
+
defaultRole?: PermissionLevel;
|
|
1815
|
+
/**
|
|
1816
|
+
* Users to invite at creation time.
|
|
1817
|
+
* Owner is automatically added from the API key.
|
|
1818
|
+
*/
|
|
1819
|
+
initialUsers?: Array<{
|
|
1820
|
+
userId: string;
|
|
1821
|
+
role?: PermissionLevel;
|
|
1822
|
+
sshKeys?: string[];
|
|
1823
|
+
}>;
|
|
1824
|
+
/**
|
|
1825
|
+
* Default access policies for all users.
|
|
1826
|
+
*/
|
|
1827
|
+
defaultPolicies?: AccessPolicyRule[];
|
|
1828
|
+
/**
|
|
1829
|
+
* Enable multi-user mode.
|
|
1830
|
+
* @default true when initialUsers is provided
|
|
1831
|
+
*/
|
|
1832
|
+
multiUser?: boolean;
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1835
|
+
* Permissions manager interface.
|
|
1836
|
+
* Access via `sandbox.permissions`.
|
|
1837
|
+
*/
|
|
1838
|
+
interface PermissionsManager {
|
|
1839
|
+
/** List all users in the sandbox */
|
|
1840
|
+
list(): Promise<SandboxUser[]>;
|
|
1841
|
+
/** Get a specific user */
|
|
1842
|
+
get(userId: string): Promise<SandboxUser | null>;
|
|
1843
|
+
/** Add a user to the sandbox */
|
|
1844
|
+
add(options: AddUserOptions): Promise<SandboxUser>;
|
|
1845
|
+
/** Update a user's permissions */
|
|
1846
|
+
update(userId: string, options: UpdateUserOptions): Promise<SandboxUser>;
|
|
1847
|
+
/** Remove a user from the sandbox */
|
|
1848
|
+
remove(userId: string, options?: {
|
|
1849
|
+
preserveHomeDir?: boolean;
|
|
1850
|
+
}): Promise<void>;
|
|
1851
|
+
/** Set access policies for a user */
|
|
1852
|
+
setAccessPolicies(userId: string, rules: AccessPolicyRule[]): Promise<void>;
|
|
1853
|
+
/** Get access policies for a user */
|
|
1854
|
+
getAccessPolicies(userId: string): Promise<AccessPolicyRule[]>;
|
|
1855
|
+
/** Check if a user can perform an action on a path */
|
|
1856
|
+
checkAccess(userId: string, path: string, action: "read" | "write" | "execute"): Promise<boolean>;
|
|
1857
|
+
}
|
|
1858
|
+
/**
|
|
1859
|
+
* Backend manager for runtime agent configuration.
|
|
1860
|
+
* Access via `sandbox.backend`.
|
|
1861
|
+
*/
|
|
1862
|
+
interface BackendManager {
|
|
1863
|
+
/** Get current backend status */
|
|
1864
|
+
status(): Promise<BackendStatus>;
|
|
1865
|
+
/** Get backend capabilities */
|
|
1866
|
+
capabilities(): Promise<BackendCapabilities>;
|
|
1867
|
+
/** Add MCP server at runtime (opencode only) */
|
|
1868
|
+
addMcp(name: string, config: McpServerConfig): Promise<void>;
|
|
1869
|
+
/** Get MCP server status */
|
|
1870
|
+
getMcpStatus(): Promise<Record<string, {
|
|
1871
|
+
status: "running" | "stopped" | "error";
|
|
1872
|
+
error?: string;
|
|
1873
|
+
}>>;
|
|
1874
|
+
/** Update backend configuration */
|
|
1875
|
+
updateConfig(config: Partial<BackendConfig>): Promise<void>;
|
|
1876
|
+
/**
|
|
1877
|
+
* Validate a provider-neutral profile against the active backend.
|
|
1878
|
+
*
|
|
1879
|
+
* Optional while backends adopt the public `AgentProfile` contract.
|
|
1880
|
+
*/
|
|
1881
|
+
validateProfile?(profile: AgentProfile): Promise<AgentProfileValidationResult>;
|
|
1882
|
+
/** Restart the backend agent */
|
|
1883
|
+
restart(): Promise<void>;
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Options for spawning a process.
|
|
1887
|
+
*
|
|
1888
|
+
* @example Basic spawn
|
|
1889
|
+
* ```typescript
|
|
1890
|
+
* const proc = await box.process.spawn("python train.py");
|
|
1891
|
+
* ```
|
|
1892
|
+
*
|
|
1893
|
+
* @example With options
|
|
1894
|
+
* ```typescript
|
|
1895
|
+
* const proc = await box.process.spawn("python train.py", {
|
|
1896
|
+
* cwd: "/workspace/ml",
|
|
1897
|
+
* env: { "CUDA_VISIBLE_DEVICES": "0" },
|
|
1898
|
+
* timeoutMs: 3600000, // 1 hour
|
|
1899
|
+
* });
|
|
1900
|
+
* ```
|
|
1901
|
+
*/
|
|
1902
|
+
interface ProcessSpawnOptions {
|
|
1903
|
+
/** Working directory for the process */
|
|
1904
|
+
cwd?: string;
|
|
1905
|
+
/** Environment variables to set */
|
|
1906
|
+
env?: Record<string, string>;
|
|
1907
|
+
/** Timeout in milliseconds (0 = no timeout) */
|
|
1908
|
+
timeoutMs?: number;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* Options for running Python code.
|
|
1912
|
+
*
|
|
1913
|
+
* @example Simple code execution
|
|
1914
|
+
* ```typescript
|
|
1915
|
+
* const result = await box.process.runCode(`
|
|
1916
|
+
* import numpy as np
|
|
1917
|
+
* print(np.random.rand(10))
|
|
1918
|
+
* `);
|
|
1919
|
+
* ```
|
|
1920
|
+
*/
|
|
1921
|
+
interface RunCodeOptions {
|
|
1922
|
+
/** Working directory */
|
|
1923
|
+
cwd?: string;
|
|
1924
|
+
/** Environment variables */
|
|
1925
|
+
env?: Record<string, string>;
|
|
1926
|
+
/** Timeout in milliseconds */
|
|
1927
|
+
timeoutMs?: number;
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Status of a spawned process.
|
|
1931
|
+
*/
|
|
1932
|
+
interface ProcessStatus {
|
|
1933
|
+
/** Process ID */
|
|
1934
|
+
pid: number;
|
|
1935
|
+
/** Command that was executed */
|
|
1936
|
+
command: string;
|
|
1937
|
+
/** Working directory */
|
|
1938
|
+
cwd?: string;
|
|
1939
|
+
/** Whether the process is still running */
|
|
1940
|
+
running: boolean;
|
|
1941
|
+
/** Exit code (-1 if still running) */
|
|
1942
|
+
exitCode: number;
|
|
1943
|
+
/** Signal that killed the process (if any) */
|
|
1944
|
+
exitSignal?: string;
|
|
1945
|
+
/** When the process started */
|
|
1946
|
+
startedAt: Date;
|
|
1947
|
+
/** When the process exited (if exited) */
|
|
1948
|
+
exitedAt?: Date;
|
|
1949
|
+
}
|
|
1950
|
+
/**
|
|
1951
|
+
* Full process information including environment.
|
|
1952
|
+
*/
|
|
1953
|
+
interface ProcessInfo extends ProcessStatus {
|
|
1954
|
+
/** Environment variables used */
|
|
1955
|
+
env?: Record<string, string>;
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* A log entry from process stdout/stderr.
|
|
1959
|
+
*/
|
|
1960
|
+
interface ProcessLogEntry {
|
|
1961
|
+
/** Log source: stdout or stderr */
|
|
1962
|
+
type: "stdout" | "stderr";
|
|
1963
|
+
/** Log content */
|
|
1964
|
+
data: string;
|
|
1965
|
+
/** Timestamp in milliseconds */
|
|
1966
|
+
timestamp: number;
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Result of running code or a blocking process.
|
|
1970
|
+
*/
|
|
1971
|
+
interface CodeResult {
|
|
1972
|
+
/** Process ID */
|
|
1973
|
+
pid: number;
|
|
1974
|
+
/** Exit code */
|
|
1975
|
+
exitCode: number;
|
|
1976
|
+
/** Standard output */
|
|
1977
|
+
stdout: string;
|
|
1978
|
+
/** Standard error */
|
|
1979
|
+
stderr: string;
|
|
1980
|
+
/** Execution duration in milliseconds */
|
|
1981
|
+
durationMs: number;
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Signal types for killing processes.
|
|
1985
|
+
*/
|
|
1986
|
+
type ProcessSignal = "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP" | "SIGQUIT" | "SIGUSR1" | "SIGUSR2";
|
|
1987
|
+
/**
|
|
1988
|
+
* A handle to a spawned process with control methods.
|
|
1989
|
+
*
|
|
1990
|
+
* @example Non-blocking process with log streaming
|
|
1991
|
+
* ```typescript
|
|
1992
|
+
* const proc = await box.process.spawn("python train.py", {
|
|
1993
|
+
* cwd: "/workspace",
|
|
1994
|
+
* env: { "CUDA_VISIBLE_DEVICES": "0" }
|
|
1995
|
+
* });
|
|
1996
|
+
*
|
|
1997
|
+
* console.log(`Started PID: ${proc.pid}`);
|
|
1998
|
+
*
|
|
1999
|
+
* // Stream logs in real-time
|
|
2000
|
+
* for await (const line of proc.logs()) {
|
|
2001
|
+
* console.log(line);
|
|
2002
|
+
* }
|
|
2003
|
+
*
|
|
2004
|
+
* // Or wait for completion
|
|
2005
|
+
* const exitCode = await proc.wait();
|
|
2006
|
+
* ```
|
|
2007
|
+
*
|
|
2008
|
+
* @example Check status and kill
|
|
2009
|
+
* ```typescript
|
|
2010
|
+
* const status = await proc.status();
|
|
2011
|
+
* if (status.running) {
|
|
2012
|
+
* await proc.kill("SIGKILL");
|
|
2013
|
+
* }
|
|
2014
|
+
* ```
|
|
2015
|
+
*/
|
|
2016
|
+
interface Process {
|
|
2017
|
+
/** Process ID */
|
|
2018
|
+
readonly pid: number;
|
|
2019
|
+
/** Command that was executed */
|
|
2020
|
+
readonly command: string;
|
|
2021
|
+
/**
|
|
2022
|
+
* Get current process status.
|
|
2023
|
+
*/
|
|
2024
|
+
status(): Promise<ProcessStatus>;
|
|
2025
|
+
/**
|
|
2026
|
+
* Wait for the process to exit.
|
|
2027
|
+
* @returns Exit code
|
|
2028
|
+
*/
|
|
2029
|
+
wait(): Promise<number>;
|
|
2030
|
+
/**
|
|
2031
|
+
* Kill the process.
|
|
2032
|
+
* @param signal - Signal to send (default: SIGTERM)
|
|
2033
|
+
*/
|
|
2034
|
+
kill(signal?: ProcessSignal): Promise<void>;
|
|
2035
|
+
/**
|
|
2036
|
+
* Stream stdout/stderr logs in real-time.
|
|
2037
|
+
* Includes buffered logs from process start.
|
|
2038
|
+
*/
|
|
2039
|
+
logs(): AsyncIterable<ProcessLogEntry>;
|
|
2040
|
+
/**
|
|
2041
|
+
* Stream only stdout.
|
|
2042
|
+
*/
|
|
2043
|
+
stdout(): AsyncIterable<string>;
|
|
2044
|
+
/**
|
|
2045
|
+
* Stream only stderr.
|
|
2046
|
+
*/
|
|
2047
|
+
stderr(): AsyncIterable<string>;
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Process manager for spawning and controlling processes.
|
|
2051
|
+
* Access via `sandbox.process`.
|
|
2052
|
+
*
|
|
2053
|
+
* Provides non-blocking process execution with real-time log streaming,
|
|
2054
|
+
* ideal for long-running tasks like ML training or dev servers.
|
|
2055
|
+
*
|
|
2056
|
+
* @example Non-blocking process
|
|
2057
|
+
* ```typescript
|
|
2058
|
+
* const proc = await box.process.spawn("python train.py", {
|
|
2059
|
+
* cwd: "/workspace",
|
|
2060
|
+
* env: { "CUDA_VISIBLE_DEVICES": "0" }
|
|
2061
|
+
* });
|
|
2062
|
+
*
|
|
2063
|
+
* // Stream logs
|
|
2064
|
+
* for await (const entry of proc.logs()) {
|
|
2065
|
+
* console.log(`[${entry.type}] ${entry.data}`);
|
|
2066
|
+
* }
|
|
2067
|
+
*
|
|
2068
|
+
* // Check status
|
|
2069
|
+
* const status = await proc.status();
|
|
2070
|
+
* console.log(`Running: ${status.running}`);
|
|
2071
|
+
*
|
|
2072
|
+
* // Kill if needed
|
|
2073
|
+
* await proc.kill();
|
|
2074
|
+
* ```
|
|
2075
|
+
*
|
|
2076
|
+
* @example Run Python code directly
|
|
2077
|
+
* ```typescript
|
|
2078
|
+
* const result = await box.process.runCode(`
|
|
2079
|
+
* import numpy as np
|
|
2080
|
+
* print(np.random.rand(10).mean())
|
|
2081
|
+
* `);
|
|
2082
|
+
* console.log(result.stdout); // Prints the mean
|
|
2083
|
+
* ```
|
|
2084
|
+
*
|
|
2085
|
+
* @example List and manage processes
|
|
2086
|
+
* ```typescript
|
|
2087
|
+
* const procs = await box.process.list();
|
|
2088
|
+
* for (const p of procs) {
|
|
2089
|
+
* console.log(`PID ${p.pid}: ${p.command} (${p.running ? 'running' : 'exited'})`);
|
|
2090
|
+
* }
|
|
2091
|
+
*
|
|
2092
|
+
* // Get specific process
|
|
2093
|
+
* const proc = await box.process.get(1234);
|
|
2094
|
+
* if (proc) {
|
|
2095
|
+
* await proc.kill();
|
|
2096
|
+
* }
|
|
2097
|
+
* ```
|
|
2098
|
+
*/
|
|
2099
|
+
interface ProcessManager {
|
|
2100
|
+
/**
|
|
2101
|
+
* Spawn a process without blocking.
|
|
2102
|
+
* Returns immediately with a Process handle.
|
|
2103
|
+
*
|
|
2104
|
+
* @param command - Shell command to execute
|
|
2105
|
+
* @param options - Spawn options (cwd, env, timeout)
|
|
2106
|
+
* @returns Process handle for control and monitoring
|
|
2107
|
+
*/
|
|
2108
|
+
spawn(command: string, options?: ProcessSpawnOptions): Promise<Process>;
|
|
2109
|
+
/**
|
|
2110
|
+
* Run Python code directly.
|
|
2111
|
+
* Blocks until completion and returns result.
|
|
2112
|
+
*
|
|
2113
|
+
* @param code - Python code to execute
|
|
2114
|
+
* @param options - Execution options
|
|
2115
|
+
* @returns Execution result with stdout/stderr
|
|
2116
|
+
*/
|
|
2117
|
+
runCode(code: string, options?: RunCodeOptions): Promise<CodeResult>;
|
|
2118
|
+
/**
|
|
2119
|
+
* List all tracked processes.
|
|
2120
|
+
*
|
|
2121
|
+
* @returns Array of process status objects
|
|
2122
|
+
*/
|
|
2123
|
+
list(): Promise<ProcessStatus[]>;
|
|
2124
|
+
/**
|
|
2125
|
+
* Get a process by PID.
|
|
2126
|
+
*
|
|
2127
|
+
* @param pid - Process ID
|
|
2128
|
+
* @returns Process handle or null if not found
|
|
2129
|
+
*/
|
|
2130
|
+
get(pid: number): Promise<Process | null>;
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Information about a stored secret (without the value).
|
|
2134
|
+
*/
|
|
2135
|
+
interface SecretInfo {
|
|
2136
|
+
/** Secret name (e.g., HF_TOKEN, AWS_ACCESS_KEY) */
|
|
2137
|
+
name: string;
|
|
2138
|
+
/** When the secret was created */
|
|
2139
|
+
createdAt: Date;
|
|
2140
|
+
/** When the secret was last updated */
|
|
2141
|
+
updatedAt: Date;
|
|
2142
|
+
}
|
|
2143
|
+
/**
|
|
2144
|
+
* Secrets manager for storing and retrieving encrypted secrets.
|
|
2145
|
+
* Access via `client.secrets`.
|
|
2146
|
+
*
|
|
2147
|
+
* Secrets are encrypted at rest and can be injected into sandboxes
|
|
2148
|
+
* as environment variables.
|
|
2149
|
+
*
|
|
2150
|
+
* @example Create and manage secrets
|
|
2151
|
+
* ```typescript
|
|
2152
|
+
* // Create a secret
|
|
2153
|
+
* await client.secrets.create("HF_TOKEN", "hf_xxx");
|
|
2154
|
+
*
|
|
2155
|
+
* // List all secrets (names only, not values)
|
|
2156
|
+
* const secrets = await client.secrets.list();
|
|
2157
|
+
* console.log(secrets.map(s => s.name)); // ["HF_TOKEN"]
|
|
2158
|
+
*
|
|
2159
|
+
* // Get a secret value (audited operation)
|
|
2160
|
+
* const value = await client.secrets.get("HF_TOKEN");
|
|
2161
|
+
*
|
|
2162
|
+
* // Update a secret
|
|
2163
|
+
* await client.secrets.update("HF_TOKEN", "hf_new_value");
|
|
2164
|
+
*
|
|
2165
|
+
* // Delete a secret
|
|
2166
|
+
* await client.secrets.delete("HF_TOKEN");
|
|
2167
|
+
* ```
|
|
2168
|
+
*
|
|
2169
|
+
* @example Use secrets in a sandbox
|
|
2170
|
+
* ```typescript
|
|
2171
|
+
* // Create sandbox with secrets injected as env vars
|
|
2172
|
+
* const box = await client.create({
|
|
2173
|
+
* secrets: ["HF_TOKEN", "AWS_ACCESS_KEY"],
|
|
2174
|
+
* });
|
|
2175
|
+
*
|
|
2176
|
+
* // Secrets are available as environment variables
|
|
2177
|
+
* const result = await box.exec("echo $HF_TOKEN");
|
|
2178
|
+
* ```
|
|
2179
|
+
*/
|
|
2180
|
+
interface SecretsManager {
|
|
2181
|
+
/**
|
|
2182
|
+
* Create a new secret.
|
|
2183
|
+
*
|
|
2184
|
+
* @param name - Secret name (uppercase, alphanumeric + underscore, max 63 chars)
|
|
2185
|
+
* @param value - Secret value (max 64KB)
|
|
2186
|
+
* @returns Created secret info
|
|
2187
|
+
* @throws If secret already exists or name is invalid
|
|
2188
|
+
*
|
|
2189
|
+
* @example
|
|
2190
|
+
* ```typescript
|
|
2191
|
+
* await client.secrets.create("HF_TOKEN", "hf_xxx");
|
|
2192
|
+
* await client.secrets.create("AWS_ACCESS_KEY", "AKIA...");
|
|
2193
|
+
* ```
|
|
2194
|
+
*/
|
|
2195
|
+
create(name: string, value: string): Promise<SecretInfo>;
|
|
2196
|
+
/**
|
|
2197
|
+
* List all secrets (names and metadata only, not values).
|
|
2198
|
+
*
|
|
2199
|
+
* @returns Array of secret info objects
|
|
2200
|
+
*
|
|
2201
|
+
* @example
|
|
2202
|
+
* ```typescript
|
|
2203
|
+
* const secrets = await client.secrets.list();
|
|
2204
|
+
* for (const s of secrets) {
|
|
2205
|
+
* console.log(`${s.name} - created ${s.createdAt}`);
|
|
2206
|
+
* }
|
|
2207
|
+
* ```
|
|
2208
|
+
*/
|
|
2209
|
+
list(): Promise<SecretInfo[]>;
|
|
2210
|
+
/**
|
|
2211
|
+
* Get a secret's decrypted value.
|
|
2212
|
+
*
|
|
2213
|
+
* This is an audited operation - access is logged.
|
|
2214
|
+
*
|
|
2215
|
+
* @param name - Secret name
|
|
2216
|
+
* @returns Secret value
|
|
2217
|
+
* @throws If secret not found
|
|
2218
|
+
*
|
|
2219
|
+
* @example
|
|
2220
|
+
* ```typescript
|
|
2221
|
+
* const token = await client.secrets.get("HF_TOKEN");
|
|
2222
|
+
* ```
|
|
2223
|
+
*/
|
|
2224
|
+
get(name: string): Promise<string>;
|
|
2225
|
+
/**
|
|
2226
|
+
* Update an existing secret's value.
|
|
2227
|
+
*
|
|
2228
|
+
* @param name - Secret name
|
|
2229
|
+
* @param value - New secret value
|
|
2230
|
+
* @returns Updated secret info
|
|
2231
|
+
* @throws If secret not found
|
|
2232
|
+
*
|
|
2233
|
+
* @example
|
|
2234
|
+
* ```typescript
|
|
2235
|
+
* await client.secrets.update("HF_TOKEN", "hf_new_value");
|
|
2236
|
+
* ```
|
|
2237
|
+
*/
|
|
2238
|
+
update(name: string, value: string): Promise<SecretInfo>;
|
|
2239
|
+
/**
|
|
2240
|
+
* Delete a secret.
|
|
2241
|
+
*
|
|
2242
|
+
* @param name - Secret name
|
|
2243
|
+
* @throws If secret not found
|
|
2244
|
+
*
|
|
2245
|
+
* @example
|
|
2246
|
+
* ```typescript
|
|
2247
|
+
* await client.secrets.delete("HF_TOKEN");
|
|
2248
|
+
* ```
|
|
2249
|
+
*/
|
|
2250
|
+
delete(name: string): Promise<void>;
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Detailed file/directory information.
|
|
2254
|
+
*/
|
|
2255
|
+
interface FileInfo {
|
|
2256
|
+
/** File/directory name */
|
|
2257
|
+
name: string;
|
|
2258
|
+
/** Full path relative to workspace */
|
|
2259
|
+
path: string;
|
|
2260
|
+
/** Size in bytes */
|
|
2261
|
+
size: number;
|
|
2262
|
+
/** Whether this is a directory */
|
|
2263
|
+
isDir: boolean;
|
|
2264
|
+
/** Whether this is a regular file */
|
|
2265
|
+
isFile: boolean;
|
|
2266
|
+
/** Whether this is a symbolic link */
|
|
2267
|
+
isSymlink: boolean;
|
|
2268
|
+
/** Unix permissions (e.g., 0o755) */
|
|
2269
|
+
permissions: number;
|
|
2270
|
+
/** Owner user ID/name */
|
|
2271
|
+
owner: string;
|
|
2272
|
+
/** Group ID/name */
|
|
2273
|
+
group: string;
|
|
2274
|
+
/** Last modification time */
|
|
2275
|
+
modTime: Date;
|
|
2276
|
+
/** Last access time */
|
|
2277
|
+
accessTime: Date;
|
|
2278
|
+
}
|
|
2279
|
+
/**
|
|
2280
|
+
* Options for uploading files.
|
|
2281
|
+
*/
|
|
2282
|
+
interface UploadOptions {
|
|
2283
|
+
/** Overwrite if file exists (default: true) */
|
|
2284
|
+
overwrite?: boolean;
|
|
2285
|
+
/** Set file permissions (Unix mode, e.g., 0o644) */
|
|
2286
|
+
permissions?: number;
|
|
2287
|
+
/** Progress callback for large files */
|
|
2288
|
+
onProgress?: (progress: UploadProgress) => void;
|
|
2289
|
+
}
|
|
2290
|
+
/**
|
|
2291
|
+
* Upload progress information.
|
|
2292
|
+
*/
|
|
2293
|
+
interface UploadProgress {
|
|
2294
|
+
/** Bytes uploaded so far */
|
|
2295
|
+
bytesUploaded: number;
|
|
2296
|
+
/** Total bytes to upload */
|
|
2297
|
+
totalBytes: number;
|
|
2298
|
+
/** Percentage complete (0-100) */
|
|
2299
|
+
percentage: number;
|
|
2300
|
+
}
|
|
2301
|
+
/**
|
|
2302
|
+
* Options for downloading files.
|
|
2303
|
+
*/
|
|
2304
|
+
interface DownloadOptions {
|
|
2305
|
+
/** Overwrite local file if exists (default: true) */
|
|
2306
|
+
overwrite?: boolean;
|
|
2307
|
+
/** Progress callback for large files */
|
|
2308
|
+
onProgress?: (progress: DownloadProgress) => void;
|
|
2309
|
+
}
|
|
2310
|
+
/**
|
|
2311
|
+
* Download progress information.
|
|
2312
|
+
*/
|
|
2313
|
+
interface DownloadProgress {
|
|
2314
|
+
/** Bytes downloaded so far */
|
|
2315
|
+
bytesDownloaded: number;
|
|
2316
|
+
/** Total bytes to download */
|
|
2317
|
+
totalBytes: number;
|
|
2318
|
+
/** Percentage complete (0-100) */
|
|
2319
|
+
percentage: number;
|
|
2320
|
+
}
|
|
2321
|
+
/**
|
|
2322
|
+
* Options for listing directories.
|
|
2323
|
+
*/
|
|
2324
|
+
interface ListOptions {
|
|
2325
|
+
/** Include hidden files (starting with .) */
|
|
2326
|
+
all?: boolean;
|
|
2327
|
+
/** Include full metadata (like ls -l) */
|
|
2328
|
+
long?: boolean;
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2331
|
+
* Options for creating directories.
|
|
2332
|
+
*/
|
|
2333
|
+
interface MkdirOptions {
|
|
2334
|
+
/** Create parent directories as needed (like mkdir -p) */
|
|
2335
|
+
recursive?: boolean;
|
|
2336
|
+
/** Set directory permissions (Unix mode, e.g., 0o755) */
|
|
2337
|
+
mode?: number;
|
|
2338
|
+
}
|
|
2339
|
+
/**
|
|
2340
|
+
* Options for deleting files/directories.
|
|
2341
|
+
*/
|
|
2342
|
+
interface DeleteOptions {
|
|
2343
|
+
/** Recursively delete directories (like rm -rf) */
|
|
2344
|
+
recursive?: boolean;
|
|
2345
|
+
}
|
|
2346
|
+
/**
|
|
2347
|
+
* Enhanced file system operations for sandboxes.
|
|
2348
|
+
* Access via `sandbox.fs`.
|
|
2349
|
+
*
|
|
2350
|
+
* Provides comprehensive file operations beyond basic read/write,
|
|
2351
|
+
* including binary file upload/download, directory operations,
|
|
2352
|
+
* and progress reporting for large files.
|
|
2353
|
+
*
|
|
2354
|
+
* @example Upload and download files
|
|
2355
|
+
* ```typescript
|
|
2356
|
+
* // Upload a local file
|
|
2357
|
+
* await box.fs.upload("./model.bin", "/workspace/models/model.bin");
|
|
2358
|
+
*
|
|
2359
|
+
* // Download a file
|
|
2360
|
+
* await box.fs.download("/workspace/results.zip", "./local/results.zip");
|
|
2361
|
+
*
|
|
2362
|
+
* // With progress reporting
|
|
2363
|
+
* await box.fs.upload("./large-file.bin", "/workspace/data.bin", {
|
|
2364
|
+
* onProgress: (p) => console.log(`${p.percentage}%`),
|
|
2365
|
+
* });
|
|
2366
|
+
* ```
|
|
2367
|
+
*
|
|
2368
|
+
* @example Directory operations
|
|
2369
|
+
* ```typescript
|
|
2370
|
+
* // Upload entire directory
|
|
2371
|
+
* await box.fs.uploadDir("./local/project", "/workspace/project");
|
|
2372
|
+
*
|
|
2373
|
+
* // Download entire directory
|
|
2374
|
+
* await box.fs.downloadDir("/workspace/output", "./local/output");
|
|
2375
|
+
*
|
|
2376
|
+
* // List directory contents
|
|
2377
|
+
* const files = await box.fs.list("/workspace");
|
|
2378
|
+
* for (const f of files) {
|
|
2379
|
+
* console.log(`${f.name} - ${f.size} bytes`);
|
|
2380
|
+
* }
|
|
2381
|
+
* ```
|
|
2382
|
+
*
|
|
2383
|
+
* @example File management
|
|
2384
|
+
* ```typescript
|
|
2385
|
+
* // Check if file exists
|
|
2386
|
+
* if (await box.fs.exists("/workspace/config.json")) {
|
|
2387
|
+
* const info = await box.fs.stat("/workspace/config.json");
|
|
2388
|
+
* console.log(`Size: ${info.size}, Modified: ${info.modTime}`);
|
|
2389
|
+
* }
|
|
2390
|
+
*
|
|
2391
|
+
* // Create directory
|
|
2392
|
+
* await box.fs.mkdir("/workspace/output/images", { recursive: true });
|
|
2393
|
+
*
|
|
2394
|
+
* // Delete file or directory
|
|
2395
|
+
* await box.fs.delete("/workspace/temp", { recursive: true });
|
|
2396
|
+
* ```
|
|
2397
|
+
*/
|
|
2398
|
+
interface FileSystem {
|
|
2399
|
+
/**
|
|
2400
|
+
* Read a file's contents as a string.
|
|
2401
|
+
* For binary files, use download() instead.
|
|
2402
|
+
*
|
|
2403
|
+
* @param path - Path to file (relative to workspace)
|
|
2404
|
+
* @returns File contents as UTF-8 string
|
|
2405
|
+
* @throws NotFoundError if file doesn't exist
|
|
2406
|
+
*/
|
|
2407
|
+
read(path: string): Promise<string>;
|
|
2408
|
+
/**
|
|
2409
|
+
* Write string content to a file.
|
|
2410
|
+
* For binary files, use upload() instead.
|
|
2411
|
+
* Creates parent directories as needed.
|
|
2412
|
+
*
|
|
2413
|
+
* @param path - Path to file (relative to workspace)
|
|
2414
|
+
* @param content - Content to write
|
|
2415
|
+
*/
|
|
2416
|
+
write(path: string, content: string): Promise<void>;
|
|
2417
|
+
/**
|
|
2418
|
+
* Search for text patterns in files using ripgrep.
|
|
2419
|
+
* @see SearchOptions for available options
|
|
2420
|
+
*/
|
|
2421
|
+
search(query: string, options?: SearchOptions): AsyncIterable<SearchMatch>;
|
|
2422
|
+
/**
|
|
2423
|
+
* Upload a local file to the sandbox.
|
|
2424
|
+
* Handles binary files correctly using multipart upload.
|
|
2425
|
+
* Creates parent directories as needed.
|
|
2426
|
+
*
|
|
2427
|
+
* @param localPath - Path to local file
|
|
2428
|
+
* @param remotePath - Destination path in sandbox
|
|
2429
|
+
* @param options - Upload options (overwrite, permissions, progress)
|
|
2430
|
+
* @throws Error if local file doesn't exist
|
|
2431
|
+
*
|
|
2432
|
+
* @example
|
|
2433
|
+
* ```typescript
|
|
2434
|
+
* await box.fs.upload("./model.bin", "/workspace/models/model.bin");
|
|
2435
|
+
*
|
|
2436
|
+
* // With progress
|
|
2437
|
+
* await box.fs.upload("./large-file.bin", "/data/file.bin", {
|
|
2438
|
+
* onProgress: (p) => console.log(`${p.percentage.toFixed(1)}%`),
|
|
2439
|
+
* });
|
|
2440
|
+
* ```
|
|
2441
|
+
*/
|
|
2442
|
+
upload(localPath: string, remotePath: string, options?: UploadOptions): Promise<void>;
|
|
2443
|
+
/**
|
|
2444
|
+
* Download a file from the sandbox.
|
|
2445
|
+
* Handles binary files correctly.
|
|
2446
|
+
* Creates local parent directories as needed.
|
|
2447
|
+
*
|
|
2448
|
+
* @param remotePath - Path to file in sandbox
|
|
2449
|
+
* @param localPath - Local destination path
|
|
2450
|
+
* @param options - Download options (overwrite, progress)
|
|
2451
|
+
* @throws NotFoundError if remote file doesn't exist
|
|
2452
|
+
*
|
|
2453
|
+
* @example
|
|
2454
|
+
* ```typescript
|
|
2455
|
+
* await box.fs.download("/workspace/output.zip", "./results.zip");
|
|
2456
|
+
* ```
|
|
2457
|
+
*/
|
|
2458
|
+
download(remotePath: string, localPath: string, options?: DownloadOptions): Promise<void>;
|
|
2459
|
+
/**
|
|
2460
|
+
* Upload a local directory to the sandbox.
|
|
2461
|
+
* Uses tar for efficient transfer.
|
|
2462
|
+
* Preserves directory structure and file permissions.
|
|
2463
|
+
*
|
|
2464
|
+
* @param localDir - Path to local directory
|
|
2465
|
+
* @param remoteDir - Destination directory in sandbox
|
|
2466
|
+
* @throws Error if local directory doesn't exist
|
|
2467
|
+
*
|
|
2468
|
+
* @example
|
|
2469
|
+
* ```typescript
|
|
2470
|
+
* await box.fs.uploadDir("./project", "/workspace/project");
|
|
2471
|
+
* ```
|
|
2472
|
+
*/
|
|
2473
|
+
uploadDir(localDir: string, remoteDir: string): Promise<void>;
|
|
2474
|
+
/**
|
|
2475
|
+
* Download a directory from the sandbox.
|
|
2476
|
+
* Uses tar for efficient transfer.
|
|
2477
|
+
* Preserves directory structure and file permissions.
|
|
2478
|
+
*
|
|
2479
|
+
* @param remoteDir - Directory path in sandbox
|
|
2480
|
+
* @param localDir - Local destination directory
|
|
2481
|
+
* @throws NotFoundError if remote directory doesn't exist
|
|
2482
|
+
*
|
|
2483
|
+
* @example
|
|
2484
|
+
* ```typescript
|
|
2485
|
+
* await box.fs.downloadDir("/workspace/output", "./local-output");
|
|
2486
|
+
* ```
|
|
2487
|
+
*/
|
|
2488
|
+
downloadDir(remoteDir: string, localDir: string): Promise<void>;
|
|
2489
|
+
/**
|
|
2490
|
+
* List directory contents with metadata.
|
|
2491
|
+
*
|
|
2492
|
+
* @param path - Directory path (relative to workspace)
|
|
2493
|
+
* @param options - List options (all, long)
|
|
2494
|
+
* @returns Array of file/directory info
|
|
2495
|
+
* @throws NotFoundError if directory doesn't exist
|
|
2496
|
+
*
|
|
2497
|
+
* @example
|
|
2498
|
+
* ```typescript
|
|
2499
|
+
* const entries = await box.fs.list("/workspace", { all: true });
|
|
2500
|
+
* for (const e of entries) {
|
|
2501
|
+
* const type = e.isDir ? "DIR" : "FILE";
|
|
2502
|
+
* console.log(`[${type}] ${e.name} (${e.size} bytes)`);
|
|
2503
|
+
* }
|
|
2504
|
+
* ```
|
|
2505
|
+
*/
|
|
2506
|
+
list(path: string, options?: ListOptions): Promise<FileInfo[]>;
|
|
2507
|
+
/**
|
|
2508
|
+
* Get detailed information about a file or directory.
|
|
2509
|
+
*
|
|
2510
|
+
* @param path - Path to file/directory
|
|
2511
|
+
* @returns File/directory metadata
|
|
2512
|
+
* @throws NotFoundError if path doesn't exist
|
|
2513
|
+
*
|
|
2514
|
+
* @example
|
|
2515
|
+
* ```typescript
|
|
2516
|
+
* const info = await box.fs.stat("/workspace/model.bin");
|
|
2517
|
+
* console.log(`Size: ${info.size}, Modified: ${info.modTime}`);
|
|
2518
|
+
* ```
|
|
2519
|
+
*/
|
|
2520
|
+
stat(path: string): Promise<FileInfo>;
|
|
2521
|
+
/**
|
|
2522
|
+
* Delete a file or directory.
|
|
2523
|
+
*
|
|
2524
|
+
* @param path - Path to delete
|
|
2525
|
+
* @param options - Delete options (recursive for directories)
|
|
2526
|
+
* @throws NotFoundError if path doesn't exist
|
|
2527
|
+
* @throws Error if deleting non-empty directory without recursive
|
|
2528
|
+
*
|
|
2529
|
+
* @example
|
|
2530
|
+
* ```typescript
|
|
2531
|
+
* // Delete file
|
|
2532
|
+
* await box.fs.delete("/workspace/temp.txt");
|
|
2533
|
+
*
|
|
2534
|
+
* // Delete directory recursively
|
|
2535
|
+
* await box.fs.delete("/workspace/cache", { recursive: true });
|
|
2536
|
+
* ```
|
|
2537
|
+
*/
|
|
2538
|
+
delete(path: string, options?: DeleteOptions): Promise<void>;
|
|
2539
|
+
/**
|
|
2540
|
+
* Create a directory.
|
|
2541
|
+
*
|
|
2542
|
+
* @param path - Directory path to create
|
|
2543
|
+
* @param options - Options (recursive to create parents)
|
|
2544
|
+
*
|
|
2545
|
+
* @example
|
|
2546
|
+
* ```typescript
|
|
2547
|
+
* // Create with parents
|
|
2548
|
+
* await box.fs.mkdir("/workspace/output/images", { recursive: true });
|
|
2549
|
+
* ```
|
|
2550
|
+
*/
|
|
2551
|
+
mkdir(path: string, options?: MkdirOptions): Promise<void>;
|
|
2552
|
+
/**
|
|
2553
|
+
* Check if a path exists.
|
|
2554
|
+
*
|
|
2555
|
+
* @param path - Path to check
|
|
2556
|
+
* @returns true if path exists, false otherwise
|
|
2557
|
+
*
|
|
2558
|
+
* @example
|
|
2559
|
+
* ```typescript
|
|
2560
|
+
* if (await box.fs.exists("/workspace/config.json")) {
|
|
2561
|
+
* // File exists
|
|
2562
|
+
* }
|
|
2563
|
+
* ```
|
|
2564
|
+
*/
|
|
2565
|
+
exists(path: string): Promise<boolean>;
|
|
2566
|
+
}
|
|
2567
|
+
//#endregion
|
|
2568
|
+
//#region src/sandbox.d.ts
|
|
2569
|
+
/**
|
|
2570
|
+
* HTTP client interface for making requests.
|
|
2571
|
+
*/
|
|
2572
|
+
interface HttpClient {
|
|
2573
|
+
fetch(path: string, options?: RequestInit): Promise<Response>;
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Git capability for repository operations.
|
|
2577
|
+
*/
|
|
2578
|
+
interface GitCapability {
|
|
2579
|
+
/** Get repository status */
|
|
2580
|
+
status(): Promise<GitStatus>;
|
|
2581
|
+
/** Get commit log */
|
|
2582
|
+
log(limit?: number): Promise<GitCommit[]>;
|
|
2583
|
+
/** Get diff (optionally against a ref) */
|
|
2584
|
+
diff(ref?: string): Promise<GitDiff>;
|
|
2585
|
+
/** Stage files */
|
|
2586
|
+
add(paths: string[]): Promise<void>;
|
|
2587
|
+
/** Create a commit */
|
|
2588
|
+
commit(message: string, options?: {
|
|
2589
|
+
amend?: boolean;
|
|
2590
|
+
}): Promise<GitCommit>;
|
|
2591
|
+
/** Push to remote */
|
|
2592
|
+
push(options?: {
|
|
2593
|
+
force?: boolean;
|
|
2594
|
+
}): Promise<void>;
|
|
2595
|
+
/** Pull from remote */
|
|
2596
|
+
pull(options?: {
|
|
2597
|
+
rebase?: boolean;
|
|
2598
|
+
}): Promise<void>;
|
|
2599
|
+
/** List branches */
|
|
2600
|
+
branches(): Promise<GitBranch[]>;
|
|
2601
|
+
/** Checkout a branch or ref */
|
|
2602
|
+
checkout(ref: string, options?: {
|
|
2603
|
+
create?: boolean;
|
|
2604
|
+
}): Promise<void>;
|
|
2605
|
+
}
|
|
2606
|
+
/**
|
|
2607
|
+
* Tools capability for managing language runtimes via mise.
|
|
2608
|
+
*/
|
|
2609
|
+
interface ToolsCapability {
|
|
2610
|
+
/** Install a tool version */
|
|
2611
|
+
install(tool: string, version: string): Promise<void>;
|
|
2612
|
+
/** Activate a tool version for the session */
|
|
2613
|
+
use(tool: string, version: string): Promise<void>;
|
|
2614
|
+
/** List installed tools */
|
|
2615
|
+
list(): Promise<InstalledTool[]>;
|
|
2616
|
+
/** Run a command with a specific tool */
|
|
2617
|
+
run(tool: string, args: string[]): Promise<ExecResult>;
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* A sandbox instance with methods for interaction.
|
|
2621
|
+
*/
|
|
2622
|
+
declare class SandboxInstance {
|
|
2623
|
+
private readonly client;
|
|
2624
|
+
private info;
|
|
2625
|
+
constructor(client: HttpClient, info: SandboxInfo);
|
|
2626
|
+
/** Unique sandbox identifier */
|
|
2627
|
+
get id(): string;
|
|
2628
|
+
/** Human-readable name */
|
|
2629
|
+
get name(): string | undefined;
|
|
2630
|
+
/** Current status */
|
|
2631
|
+
get status(): SandboxStatus;
|
|
2632
|
+
/** Connection information */
|
|
2633
|
+
get connection(): SandboxConnection | undefined;
|
|
2634
|
+
/** Custom metadata */
|
|
2635
|
+
get metadata(): Record<string, unknown> | undefined;
|
|
2636
|
+
/** When the sandbox was created */
|
|
2637
|
+
get createdAt(): Date;
|
|
2638
|
+
/** When the sandbox started running */
|
|
2639
|
+
get startedAt(): Date | undefined;
|
|
2640
|
+
/** Last activity timestamp */
|
|
2641
|
+
get lastActivityAt(): Date | undefined;
|
|
2642
|
+
/** When the sandbox will expire */
|
|
2643
|
+
get expiresAt(): Date | undefined;
|
|
2644
|
+
/** Error message if status is 'failed' */
|
|
2645
|
+
get error(): string | undefined;
|
|
2646
|
+
/** Web terminal URL for browser-based access */
|
|
2647
|
+
get url(): string | undefined;
|
|
2648
|
+
/**
|
|
2649
|
+
* Serialize to the public sandbox shape for CLI JSON output.
|
|
2650
|
+
*/
|
|
2651
|
+
toJSON(): SandboxInfo;
|
|
2652
|
+
/**
|
|
2653
|
+
* Create an advanced direct-runtime view of this sandbox.
|
|
2654
|
+
*
|
|
2655
|
+
* Runtime methods on the returned instance talk to the sandbox runtime
|
|
2656
|
+
* directly using `connection.runtimeUrl` and `connection.authToken`.
|
|
2657
|
+
* Lifecycle methods still go through the parent SDK client.
|
|
2658
|
+
*/
|
|
2659
|
+
direct(): SandboxInstance;
|
|
2660
|
+
/**
|
|
2661
|
+
* Refresh sandbox information from the server.
|
|
2662
|
+
*/
|
|
2663
|
+
refresh(): Promise<void>;
|
|
2664
|
+
/**
|
|
2665
|
+
* Bootstrap a real-time collaboration session for a file.
|
|
2666
|
+
* Returns the WebSocket URL and auth token needed to connect a
|
|
2667
|
+
* Hocuspocus/Yjs provider for live multi-user editing.
|
|
2668
|
+
*
|
|
2669
|
+
* @example
|
|
2670
|
+
* ```typescript
|
|
2671
|
+
* const collab = await box.collaborate("src/index.ts")
|
|
2672
|
+
* // Use collab.transport.websocketUrl + collab.transport.token
|
|
2673
|
+
* // with @hocuspocus/provider to connect
|
|
2674
|
+
* ```
|
|
2675
|
+
*/
|
|
2676
|
+
collaborate(path: string, options?: {
|
|
2677
|
+
access?: "read" | "write";
|
|
2678
|
+
}): Promise<{
|
|
2679
|
+
documentId: string;
|
|
2680
|
+
transport: {
|
|
2681
|
+
websocketUrl: string;
|
|
2682
|
+
token: string;
|
|
2683
|
+
expiresAt: number;
|
|
2684
|
+
};
|
|
2685
|
+
permissions: {
|
|
2686
|
+
access: "read" | "write";
|
|
2687
|
+
canSnapshot: boolean;
|
|
2688
|
+
};
|
|
2689
|
+
}>;
|
|
2690
|
+
/**
|
|
2691
|
+
* Refresh a collaboration token for an existing document session.
|
|
2692
|
+
*/
|
|
2693
|
+
/**
|
|
2694
|
+
* Refresh a collaboration token. Access level is preserved from the original
|
|
2695
|
+
* token — cannot be escalated (read stays read, write stays write).
|
|
2696
|
+
*/
|
|
2697
|
+
refreshCollaborationToken(documentId: string, currentToken: string): Promise<{
|
|
2698
|
+
token: string;
|
|
2699
|
+
expiresAt: number;
|
|
2700
|
+
access: "read" | "write";
|
|
2701
|
+
}>;
|
|
2702
|
+
/**
|
|
2703
|
+
* Get SSH credentials for connecting to the sandbox.
|
|
2704
|
+
* Throws if SSH is not enabled or sandbox is not running.
|
|
2705
|
+
*/
|
|
2706
|
+
ssh(): Promise<SSHCredentials>;
|
|
2707
|
+
/**
|
|
2708
|
+
* Execute a command in the sandbox.
|
|
2709
|
+
*/
|
|
2710
|
+
exec(command: string, options?: ExecOptions): Promise<ExecResult>;
|
|
2711
|
+
/**
|
|
2712
|
+
* Read a file from the sandbox.
|
|
2713
|
+
*
|
|
2714
|
+
* @param path - Path to the file. Relative paths resolve from the workspace root.
|
|
2715
|
+
* Absolute paths (e.g., `/tmp/output.json`) access the container filesystem directly.
|
|
2716
|
+
* @returns File content as string
|
|
2717
|
+
*
|
|
2718
|
+
* @example
|
|
2719
|
+
* ```typescript
|
|
2720
|
+
* const content = await box.read("src/index.ts");
|
|
2721
|
+
* const report = await box.read("/output/report.json");
|
|
2722
|
+
* ```
|
|
2723
|
+
*/
|
|
2724
|
+
read(path: string): Promise<string>;
|
|
2725
|
+
/**
|
|
2726
|
+
* Write content to a file in the sandbox.
|
|
2727
|
+
*
|
|
2728
|
+
* @param path - Path to the file. Relative paths resolve from the workspace root.
|
|
2729
|
+
* Absolute paths (e.g., `/tmp/cases.json`) write to the container filesystem directly.
|
|
2730
|
+
* @param content - Content to write
|
|
2731
|
+
*
|
|
2732
|
+
* @example
|
|
2733
|
+
* ```typescript
|
|
2734
|
+
* await box.write("src/fix.ts", "export const fix = () => {}");
|
|
2735
|
+
* await box.write("/tmp/config.json", JSON.stringify(config));
|
|
2736
|
+
* ```
|
|
2737
|
+
*/
|
|
2738
|
+
write(path: string, content: string): Promise<void>;
|
|
2739
|
+
/**
|
|
2740
|
+
* Send a prompt to the agent running in the sandbox.
|
|
2741
|
+
* Returns the complete response after the agent finishes.
|
|
2742
|
+
*/
|
|
2743
|
+
prompt(message: string | PromptInputPart[], options?: PromptOptions): Promise<PromptResult>;
|
|
2744
|
+
/**
|
|
2745
|
+
* Stream events from an agent prompt.
|
|
2746
|
+
* Use this for real-time updates during agent execution.
|
|
2747
|
+
*
|
|
2748
|
+
* Automatically reconnects via the runtime event replay endpoint if the
|
|
2749
|
+
* SSE stream drops before a terminal event (`result` or `done`) is received.
|
|
2750
|
+
* Reconnection is transparent — replayed events that were already yielded
|
|
2751
|
+
* (based on event ID tracking) are deduplicated.
|
|
2752
|
+
*/
|
|
2753
|
+
streamPrompt(message: string | PromptInputPart[], options?: PromptOptions): AsyncGenerator<SandboxEvent>;
|
|
2754
|
+
/**
|
|
2755
|
+
* Stream sandbox lifecycle and activity events.
|
|
2756
|
+
*/
|
|
2757
|
+
events(options?: EventStreamOptions): AsyncGenerator<SandboxEvent>;
|
|
2758
|
+
/**
|
|
2759
|
+
* Stream real-time provisioning progress events.
|
|
2760
|
+
*
|
|
2761
|
+
* Connects to the SSE events stream and yields typed `ProvisionEvent` objects
|
|
2762
|
+
* for each provisioning step. The generator completes when provisioning
|
|
2763
|
+
* finishes (success or failure) and returns the terminal result.
|
|
2764
|
+
*
|
|
2765
|
+
* @returns AsyncGenerator of ProvisionEvent, with a ProvisionResult return value
|
|
2766
|
+
*
|
|
2767
|
+
* @example
|
|
2768
|
+
* ```typescript
|
|
2769
|
+
* const box = await client.create({ image: "ethereum" });
|
|
2770
|
+
*
|
|
2771
|
+
* const stream = box.watchProvisioning();
|
|
2772
|
+
* for await (const event of stream) {
|
|
2773
|
+
* console.log(`[${event.step}] ${event.status} — ${event.message}`);
|
|
2774
|
+
* }
|
|
2775
|
+
* // stream.return value contains the terminal result
|
|
2776
|
+
* ```
|
|
2777
|
+
*/
|
|
2778
|
+
watchProvisioning(options?: {
|
|
2779
|
+
signal?: AbortSignal;
|
|
2780
|
+
}): AsyncGenerator<ProvisionEvent, ProvisionResult | undefined>;
|
|
2781
|
+
/**
|
|
2782
|
+
* Run an agentic task until completion.
|
|
2783
|
+
*
|
|
2784
|
+
* Unlike prompt(), task() is designed for autonomous agent work:
|
|
2785
|
+
* - The agent works until it completes the task or hits an error
|
|
2786
|
+
* - Session state is maintained for context continuity
|
|
2787
|
+
* - Token usage is aggregated across the execution
|
|
2788
|
+
*
|
|
2789
|
+
* Note: The agent (OpenCode/Claude) handles multi-turn execution internally.
|
|
2790
|
+
* Most tasks complete in a single call. The maxTurns option is for edge cases
|
|
2791
|
+
* where the agent explicitly signals it needs additional input.
|
|
2792
|
+
*
|
|
2793
|
+
* @param prompt - Task description for the agent
|
|
2794
|
+
* @param options - Task options
|
|
2795
|
+
* @returns Task result with response and execution metadata
|
|
2796
|
+
*/
|
|
2797
|
+
task(prompt: string, options?: TaskOptions): Promise<TaskResult>;
|
|
2798
|
+
/**
|
|
2799
|
+
* Stream events from a task execution.
|
|
2800
|
+
*
|
|
2801
|
+
* Use this for real-time updates as the agent works:
|
|
2802
|
+
* - Tool calls and results
|
|
2803
|
+
* - Thinking/reasoning steps
|
|
2804
|
+
* - File operations
|
|
2805
|
+
* - Final response
|
|
2806
|
+
*
|
|
2807
|
+
* @param prompt - Task description for the agent
|
|
2808
|
+
* @param options - Task options
|
|
2809
|
+
*/
|
|
2810
|
+
streamTask(prompt: string, options?: TaskOptions): AsyncGenerator<SandboxEvent>;
|
|
2811
|
+
/**
|
|
2812
|
+
* Search for text patterns in files using ripgrep.
|
|
2813
|
+
*
|
|
2814
|
+
* This is a first-class code search capability, not a shell wrapper.
|
|
2815
|
+
* Ripgrep is pre-installed in all managed sandboxes.
|
|
2816
|
+
*
|
|
2817
|
+
* @param pattern - Regular expression pattern to search for
|
|
2818
|
+
* @param options - Search options
|
|
2819
|
+
* @returns Async iterator of search matches
|
|
2820
|
+
*
|
|
2821
|
+
* @example Search for task-marker comments
|
|
2822
|
+
* ```typescript
|
|
2823
|
+
* for await (const match of box.search("TASK:", { glob: "**\/*.ts" })) {
|
|
2824
|
+
* console.log(`${match.path}:${match.line}: ${match.text}`);
|
|
2825
|
+
* }
|
|
2826
|
+
* ```
|
|
2827
|
+
*
|
|
2828
|
+
* @example Collect all matches
|
|
2829
|
+
* ```typescript
|
|
2830
|
+
* const matches = [];
|
|
2831
|
+
* for await (const match of box.search("function.*async")) {
|
|
2832
|
+
* matches.push(match);
|
|
2833
|
+
* }
|
|
2834
|
+
* ```
|
|
2835
|
+
*/
|
|
2836
|
+
search(pattern: string, options?: SearchOptions): AsyncGenerator<SearchMatch>;
|
|
2837
|
+
/**
|
|
2838
|
+
* Git capability object for repository operations.
|
|
2839
|
+
*
|
|
2840
|
+
* All git operations are executed in the sandbox workspace.
|
|
2841
|
+
*
|
|
2842
|
+
* @example Check status and commit
|
|
2843
|
+
* ```typescript
|
|
2844
|
+
* const status = await box.git.status();
|
|
2845
|
+
* if (status.isDirty) {
|
|
2846
|
+
* await box.git.add(["."]);
|
|
2847
|
+
* await box.git.commit("Update files");
|
|
2848
|
+
* await box.git.push();
|
|
2849
|
+
* }
|
|
2850
|
+
* ```
|
|
2851
|
+
*/
|
|
2852
|
+
get git(): GitCapability;
|
|
2853
|
+
private gitStatus;
|
|
2854
|
+
private gitLog;
|
|
2855
|
+
private gitDiff;
|
|
2856
|
+
private gitAdd;
|
|
2857
|
+
private gitCommit;
|
|
2858
|
+
private gitPush;
|
|
2859
|
+
private gitPull;
|
|
2860
|
+
private gitBranches;
|
|
2861
|
+
private gitCheckout;
|
|
2862
|
+
/**
|
|
2863
|
+
* Tools capability object for managing language runtimes.
|
|
2864
|
+
*
|
|
2865
|
+
* Uses mise (polyglot version manager) to install and manage tools.
|
|
2866
|
+
*
|
|
2867
|
+
* @example Install and use Node.js
|
|
2868
|
+
* ```typescript
|
|
2869
|
+
* await box.tools.install("node", "22");
|
|
2870
|
+
* await box.tools.use("node", "22");
|
|
2871
|
+
* const list = await box.tools.list();
|
|
2872
|
+
* ```
|
|
2873
|
+
*/
|
|
2874
|
+
get tools(): ToolsCapability;
|
|
2875
|
+
/**
|
|
2876
|
+
* Enhanced file system operations.
|
|
2877
|
+
*
|
|
2878
|
+
* Provides comprehensive file operations beyond basic read/write:
|
|
2879
|
+
* - Binary file upload/download
|
|
2880
|
+
* - Directory operations (uploadDir, downloadDir, list, mkdir)
|
|
2881
|
+
* - File metadata (stat, exists)
|
|
2882
|
+
* - Progress reporting for large files
|
|
2883
|
+
*
|
|
2884
|
+
* @example Upload and download
|
|
2885
|
+
* ```typescript
|
|
2886
|
+
* await box.fs.upload("./model.bin", "/workspace/models/model.bin");
|
|
2887
|
+
* await box.fs.download("/workspace/results.zip", "./results.zip");
|
|
2888
|
+
* ```
|
|
2889
|
+
*
|
|
2890
|
+
* @example Directory operations
|
|
2891
|
+
* ```typescript
|
|
2892
|
+
* await box.fs.uploadDir("./project", "/workspace/project");
|
|
2893
|
+
* const files = await box.fs.list("/workspace");
|
|
2894
|
+
* ```
|
|
2895
|
+
*
|
|
2896
|
+
* @example File management
|
|
2897
|
+
* ```typescript
|
|
2898
|
+
* if (await box.fs.exists("/workspace/config.json")) {
|
|
2899
|
+
* const info = await box.fs.stat("/workspace/config.json");
|
|
2900
|
+
* console.log(`Size: ${info.size}`);
|
|
2901
|
+
* }
|
|
2902
|
+
* await box.fs.mkdir("/workspace/output", { recursive: true });
|
|
2903
|
+
* await box.fs.delete("/workspace/temp", { recursive: true });
|
|
2904
|
+
* ```
|
|
2905
|
+
*/
|
|
2906
|
+
get fs(): FileSystem;
|
|
2907
|
+
private fsUpload;
|
|
2908
|
+
private fsDownload;
|
|
2909
|
+
private fsUploadDir;
|
|
2910
|
+
private fsDownloadDir;
|
|
2911
|
+
private fsList;
|
|
2912
|
+
private fsStat;
|
|
2913
|
+
private fsDelete;
|
|
2914
|
+
private fsMkdir;
|
|
2915
|
+
private fsExists;
|
|
2916
|
+
/**
|
|
2917
|
+
* Permissions manager for multi-user access control.
|
|
2918
|
+
*
|
|
2919
|
+
* @example List users
|
|
2920
|
+
* ```typescript
|
|
2921
|
+
* const users = await box.permissions.list();
|
|
2922
|
+
* for (const user of users) {
|
|
2923
|
+
* console.log(`${user.username}: ${user.role}`);
|
|
2924
|
+
* }
|
|
2925
|
+
* ```
|
|
2926
|
+
*
|
|
2927
|
+
* @example Add a developer
|
|
2928
|
+
* ```typescript
|
|
2929
|
+
* await box.permissions.add({
|
|
2930
|
+
* userId: "user_abc",
|
|
2931
|
+
* role: "developer",
|
|
2932
|
+
* sshKeys: ["ssh-ed25519 AAAA..."],
|
|
2933
|
+
* });
|
|
2934
|
+
* ```
|
|
2935
|
+
*/
|
|
2936
|
+
get permissions(): PermissionsManager;
|
|
2937
|
+
private permissionsList;
|
|
2938
|
+
private permissionsGet;
|
|
2939
|
+
private permissionsAdd;
|
|
2940
|
+
private permissionsUpdate;
|
|
2941
|
+
private permissionsRemove;
|
|
2942
|
+
private permissionsSetAccessPolicies;
|
|
2943
|
+
private permissionsGetAccessPolicies;
|
|
2944
|
+
private permissionsCheckAccess;
|
|
2945
|
+
/**
|
|
2946
|
+
* Backend manager for runtime agent configuration.
|
|
2947
|
+
*
|
|
2948
|
+
* @example Check backend status
|
|
2949
|
+
* ```typescript
|
|
2950
|
+
* const status = await box.backend.status();
|
|
2951
|
+
* console.log(`Backend: ${status.type}, Status: ${status.status}`);
|
|
2952
|
+
* ```
|
|
2953
|
+
*
|
|
2954
|
+
* @example Add MCP server at runtime
|
|
2955
|
+
* ```typescript
|
|
2956
|
+
* await box.backend.addMcp("web-search", {
|
|
2957
|
+
* command: "npx",
|
|
2958
|
+
* args: ["-y", "@anthropic/web-search"],
|
|
2959
|
+
* });
|
|
2960
|
+
* ```
|
|
2961
|
+
*/
|
|
2962
|
+
get backend(): BackendManager;
|
|
2963
|
+
private backendStatus;
|
|
2964
|
+
private backendCapabilities;
|
|
2965
|
+
private backendAddMcp;
|
|
2966
|
+
private backendGetMcpStatus;
|
|
2967
|
+
private backendUpdateConfig;
|
|
2968
|
+
private backendRestart;
|
|
2969
|
+
/**
|
|
2970
|
+
* Process manager for spawning and controlling processes.
|
|
2971
|
+
*
|
|
2972
|
+
* Provides non-blocking process execution with real-time log streaming,
|
|
2973
|
+
* ideal for long-running tasks like ML training or dev servers.
|
|
2974
|
+
*
|
|
2975
|
+
* @example Non-blocking process
|
|
2976
|
+
* ```typescript
|
|
2977
|
+
* const proc = await box.process.spawn("python train.py", {
|
|
2978
|
+
* cwd: "/workspace",
|
|
2979
|
+
* env: { "CUDA_VISIBLE_DEVICES": "0" }
|
|
2980
|
+
* });
|
|
2981
|
+
*
|
|
2982
|
+
* // Stream logs
|
|
2983
|
+
* for await (const entry of proc.logs()) {
|
|
2984
|
+
* console.log(`[${entry.type}] ${entry.data}`);
|
|
2985
|
+
* }
|
|
2986
|
+
*
|
|
2987
|
+
* // Check status
|
|
2988
|
+
* const status = await proc.status();
|
|
2989
|
+
* console.log(`Running: ${status.running}`);
|
|
2990
|
+
*
|
|
2991
|
+
* // Kill if needed
|
|
2992
|
+
* await proc.kill();
|
|
2993
|
+
* ```
|
|
2994
|
+
*
|
|
2995
|
+
* @example Run Python code directly
|
|
2996
|
+
* ```typescript
|
|
2997
|
+
* const result = await box.process.runCode(`
|
|
2998
|
+
* import numpy as np
|
|
2999
|
+
* print(np.random.rand(10).mean())
|
|
3000
|
+
* `);
|
|
3001
|
+
* console.log(result.stdout);
|
|
3002
|
+
* ```
|
|
3003
|
+
*/
|
|
3004
|
+
get process(): ProcessManager;
|
|
3005
|
+
private processSpawn;
|
|
3006
|
+
private processRunCode;
|
|
3007
|
+
private processList;
|
|
3008
|
+
private processGet;
|
|
3009
|
+
private createProcessHandle;
|
|
3010
|
+
private parseProcessLogStream;
|
|
3011
|
+
/**
|
|
3012
|
+
* Network manager for runtime network configuration.
|
|
3013
|
+
*
|
|
3014
|
+
* @example Update network restrictions
|
|
3015
|
+
* ```typescript
|
|
3016
|
+
* // Block all outbound traffic
|
|
3017
|
+
* await box.network.update({ blockOutbound: true });
|
|
3018
|
+
*
|
|
3019
|
+
* // Or switch to allowlist mode
|
|
3020
|
+
* await box.network.update({
|
|
3021
|
+
* allowList: ["192.168.1.0/24", "8.8.8.8/32"]
|
|
3022
|
+
* });
|
|
3023
|
+
* ```
|
|
3024
|
+
*
|
|
3025
|
+
* @example Expose ports dynamically
|
|
3026
|
+
* ```typescript
|
|
3027
|
+
* const url = await box.network.exposePort(8000);
|
|
3028
|
+
* console.log(`Service available at: ${url}`);
|
|
3029
|
+
* ```
|
|
3030
|
+
*/
|
|
3031
|
+
get network(): NetworkManager;
|
|
3032
|
+
private networkUpdate;
|
|
3033
|
+
private networkExposePort;
|
|
3034
|
+
private networkListUrls;
|
|
3035
|
+
private networkGetConfig;
|
|
3036
|
+
/**
|
|
3037
|
+
* Validate CIDR notation (IPv4 and IPv6)
|
|
3038
|
+
*/
|
|
3039
|
+
private isValidCidr;
|
|
3040
|
+
/**
|
|
3041
|
+
* Preview link management.
|
|
3042
|
+
*
|
|
3043
|
+
* Create publicly accessible HTTPS URLs for TCP ports inside the sandbox.
|
|
3044
|
+
*
|
|
3045
|
+
* @example
|
|
3046
|
+
* ```typescript
|
|
3047
|
+
* const link = await box.previewLinks.create(3000);
|
|
3048
|
+
* console.log(link.url);
|
|
3049
|
+
*
|
|
3050
|
+
* const links = await box.previewLinks.list();
|
|
3051
|
+
* await box.previewLinks.remove(link.previewId);
|
|
3052
|
+
* ```
|
|
3053
|
+
*/
|
|
3054
|
+
get previewLinks(): PreviewLinkManager;
|
|
3055
|
+
private previewLinkCreate;
|
|
3056
|
+
private previewLinkList;
|
|
3057
|
+
private previewLinkRemove;
|
|
3058
|
+
/**
|
|
3059
|
+
* Get information about the infrastructure driver for this sandbox.
|
|
3060
|
+
*
|
|
3061
|
+
* @example
|
|
3062
|
+
* ```typescript
|
|
3063
|
+
* const info = await box.getDriverInfo();
|
|
3064
|
+
* console.log(`Driver: ${info.type}, CRIU: ${info.capabilities.criu}`);
|
|
3065
|
+
* ```
|
|
3066
|
+
*/
|
|
3067
|
+
getDriverInfo(): Promise<DriverInfo>;
|
|
3068
|
+
private toolsInstall;
|
|
3069
|
+
private toolsUse;
|
|
3070
|
+
private toolsList;
|
|
3071
|
+
private toolsRun;
|
|
3072
|
+
/**
|
|
3073
|
+
* Create a snapshot of the sandbox state.
|
|
3074
|
+
* Snapshots can be used to save workspace state for later restoration.
|
|
3075
|
+
*
|
|
3076
|
+
* If `storage` is provided (BYOS3), the snapshot is created directly
|
|
3077
|
+
* directly on the sandbox and uploaded to customer-provided S3 storage.
|
|
3078
|
+
*
|
|
3079
|
+
* @param options - Snapshot options (tags, paths, storage)
|
|
3080
|
+
* @returns Snapshot result with ID and metadata
|
|
3081
|
+
*
|
|
3082
|
+
* @example Standard snapshot (our storage)
|
|
3083
|
+
* ```typescript
|
|
3084
|
+
* const snap = await box.snapshot({
|
|
3085
|
+
* tags: ["v1.0", "stable"],
|
|
3086
|
+
* });
|
|
3087
|
+
* console.log(`Snapshot: ${snap.snapshotId}`);
|
|
3088
|
+
* ```
|
|
3089
|
+
*
|
|
3090
|
+
* @example BYOS3 snapshot (customer storage)
|
|
3091
|
+
* ```typescript
|
|
3092
|
+
* const snap = await box.snapshot({
|
|
3093
|
+
* tags: ["production"],
|
|
3094
|
+
* storage: {
|
|
3095
|
+
* type: "s3",
|
|
3096
|
+
* bucket: "my-snapshots",
|
|
3097
|
+
* credentials: { accessKeyId: "...", secretAccessKey: "..." },
|
|
3098
|
+
* },
|
|
3099
|
+
* });
|
|
3100
|
+
* ```
|
|
3101
|
+
*/
|
|
3102
|
+
snapshot(options?: SnapshotOptions): Promise<SnapshotResult>;
|
|
3103
|
+
/**
|
|
3104
|
+
* List all snapshots for this sandbox.
|
|
3105
|
+
*
|
|
3106
|
+
* If `storage` is provided (BYOS3), lists snapshots from customer-provided
|
|
3107
|
+
* S3 storage.
|
|
3108
|
+
*
|
|
3109
|
+
* @param storage - Optional customer storage config for BYOS3
|
|
3110
|
+
* @returns Array of snapshot metadata
|
|
3111
|
+
*
|
|
3112
|
+
* @example List from our storage
|
|
3113
|
+
* ```typescript
|
|
3114
|
+
* const snapshots = await box.listSnapshots();
|
|
3115
|
+
* for (const snap of snapshots) {
|
|
3116
|
+
* console.log(`${snap.snapshotId}: ${snap.createdAt}`);
|
|
3117
|
+
* }
|
|
3118
|
+
* ```
|
|
3119
|
+
*
|
|
3120
|
+
* @example List from customer S3 (BYOS3)
|
|
3121
|
+
* ```typescript
|
|
3122
|
+
* const snapshots = await box.listSnapshots({
|
|
3123
|
+
* type: "s3",
|
|
3124
|
+
* bucket: "my-snapshots",
|
|
3125
|
+
* credentials: { accessKeyId: "...", secretAccessKey: "..." },
|
|
3126
|
+
* });
|
|
3127
|
+
* ```
|
|
3128
|
+
*/
|
|
3129
|
+
listSnapshots(storage?: SnapshotOptions["storage"]): Promise<SnapshotInfo[]>;
|
|
3130
|
+
revertToSnapshot(snapshotId: string): Promise<SnapshotResult>;
|
|
3131
|
+
private waitForSnapshotRestore;
|
|
3132
|
+
deleteSnapshot(snapshotId: string): Promise<void>;
|
|
3133
|
+
/**
|
|
3134
|
+
* Restore from the latest snapshot in customer-provided storage.
|
|
3135
|
+
* Only available when using BYOS3 (calls the runtime directly).
|
|
3136
|
+
*
|
|
3137
|
+
* @param storage - Customer storage config (required)
|
|
3138
|
+
* @param destinationPath - Optional path to restore to
|
|
3139
|
+
* @returns Snapshot info if restored, null if no snapshot found
|
|
3140
|
+
*
|
|
3141
|
+
* @example Restore from customer S3
|
|
3142
|
+
* ```typescript
|
|
3143
|
+
* const result = await box.restoreFromStorage({
|
|
3144
|
+
* type: "s3",
|
|
3145
|
+
* bucket: "my-snapshots",
|
|
3146
|
+
* credentials: { accessKeyId: "...", secretAccessKey: "..." },
|
|
3147
|
+
* });
|
|
3148
|
+
*
|
|
3149
|
+
* if (result) {
|
|
3150
|
+
* console.log(`Restored from ${result.snapshotId}`);
|
|
3151
|
+
* } else {
|
|
3152
|
+
* console.log("No snapshot found");
|
|
3153
|
+
* }
|
|
3154
|
+
* ```
|
|
3155
|
+
*/
|
|
3156
|
+
restoreFromStorage(storage: SnapshotOptions["storage"], options?: RestoreSnapshotOptions): Promise<SnapshotResult | null>;
|
|
3157
|
+
/**
|
|
3158
|
+
* Create a CRIU checkpoint of the sandbox's memory state.
|
|
3159
|
+
*
|
|
3160
|
+
* Checkpoints capture the complete memory state of the running sandbox,
|
|
3161
|
+
* enabling true pause/resume and fork operations. Unlike snapshots which
|
|
3162
|
+
* only preserve filesystem state, checkpoints preserve process memory,
|
|
3163
|
+
* open file descriptors, and execution state.
|
|
3164
|
+
*
|
|
3165
|
+
* **Requirements:** CRIU must be available on the host. Check availability
|
|
3166
|
+
* with `client.criuStatus()` before calling.
|
|
3167
|
+
*
|
|
3168
|
+
* **Note:** By default, checkpoint stops the sandbox. Use `leaveRunning: true`
|
|
3169
|
+
* to keep it running (creates a copy-on-write checkpoint).
|
|
3170
|
+
*
|
|
3171
|
+
* @param options - Checkpoint options
|
|
3172
|
+
* @returns Checkpoint result with ID and metadata
|
|
3173
|
+
*
|
|
3174
|
+
* @example Basic checkpoint (stops sandbox)
|
|
3175
|
+
* ```typescript
|
|
3176
|
+
* const checkpoint = await box.checkpoint();
|
|
3177
|
+
* console.log(`Checkpoint: ${checkpoint.checkpointId}`);
|
|
3178
|
+
* // Sandbox is now stopped, resume with box.resume()
|
|
3179
|
+
* ```
|
|
3180
|
+
*
|
|
3181
|
+
* @example Checkpoint without stopping
|
|
3182
|
+
* ```typescript
|
|
3183
|
+
* const checkpoint = await box.checkpoint({
|
|
3184
|
+
* tags: ["before-deploy"],
|
|
3185
|
+
* leaveRunning: true,
|
|
3186
|
+
* });
|
|
3187
|
+
* // Sandbox continues running
|
|
3188
|
+
* ```
|
|
3189
|
+
*/
|
|
3190
|
+
checkpoint(options?: CheckpointOptions): Promise<CheckpointResult>;
|
|
3191
|
+
/**
|
|
3192
|
+
* List all checkpoints for this sandbox.
|
|
3193
|
+
*
|
|
3194
|
+
* @returns Array of checkpoint metadata
|
|
3195
|
+
*
|
|
3196
|
+
* @example
|
|
3197
|
+
* ```typescript
|
|
3198
|
+
* const checkpoints = await box.listCheckpoints();
|
|
3199
|
+
* for (const cp of checkpoints) {
|
|
3200
|
+
* console.log(`${cp.checkpointId}: ${cp.createdAt}`);
|
|
3201
|
+
* }
|
|
3202
|
+
* ```
|
|
3203
|
+
*/
|
|
3204
|
+
listCheckpoints(): Promise<CheckpointInfo[]>;
|
|
3205
|
+
/**
|
|
3206
|
+
* Delete a checkpoint.
|
|
3207
|
+
*
|
|
3208
|
+
* @param checkpointId - ID of the checkpoint to delete
|
|
3209
|
+
*/
|
|
3210
|
+
deleteCheckpoint(checkpointId: string): Promise<void>;
|
|
3211
|
+
/**
|
|
3212
|
+
* Fork a new sandbox from a checkpoint.
|
|
3213
|
+
*
|
|
3214
|
+
* Creates a new sandbox with the same memory state as this sandbox
|
|
3215
|
+
* at the time of the checkpoint. The fork has a new identity but
|
|
3216
|
+
* preserves the execution state.
|
|
3217
|
+
*
|
|
3218
|
+
* **Use cases:**
|
|
3219
|
+
* - Branch workflows: Create parallel execution paths
|
|
3220
|
+
* - A/B testing: Run same state with different configurations
|
|
3221
|
+
* - Debugging: Fork at a specific point to investigate
|
|
3222
|
+
*
|
|
3223
|
+
* @param checkpointId - ID of the checkpoint to fork from
|
|
3224
|
+
* @param options - Fork configuration
|
|
3225
|
+
* @returns The new sandbox instance
|
|
3226
|
+
*
|
|
3227
|
+
* @example Basic fork
|
|
3228
|
+
* ```typescript
|
|
3229
|
+
* const checkpoint = await box.checkpoint({ leaveRunning: true });
|
|
3230
|
+
* const forked = await box.fork(checkpoint.checkpointId);
|
|
3231
|
+
* // forked has same memory state as box at checkpoint time
|
|
3232
|
+
* ```
|
|
3233
|
+
*
|
|
3234
|
+
* @example Fork with custom config
|
|
3235
|
+
* ```typescript
|
|
3236
|
+
* const forked = await box.fork(checkpointId, {
|
|
3237
|
+
* name: "experiment-branch",
|
|
3238
|
+
* env: { EXPERIMENT: "true" },
|
|
3239
|
+
* });
|
|
3240
|
+
* ```
|
|
3241
|
+
*/
|
|
3242
|
+
fork(checkpointId: string, options?: ForkOptions): Promise<SandboxInstance>;
|
|
3243
|
+
/**
|
|
3244
|
+
* Stop the sandbox (keeps state for resume).
|
|
3245
|
+
*/
|
|
3246
|
+
stop(): Promise<void>;
|
|
3247
|
+
/**
|
|
3248
|
+
* Resume a stopped sandbox.
|
|
3249
|
+
*/
|
|
3250
|
+
resume(): Promise<void>;
|
|
3251
|
+
/**
|
|
3252
|
+
* Delete the sandbox permanently.
|
|
3253
|
+
*/
|
|
3254
|
+
delete(): Promise<void>;
|
|
3255
|
+
/**
|
|
3256
|
+
* keepAlive is intentionally unavailable until the API exposes timeout updates.
|
|
3257
|
+
* @param seconds - Reserved for future support
|
|
3258
|
+
*/
|
|
3259
|
+
keepAlive(_seconds?: number): Promise<void>;
|
|
3260
|
+
/**
|
|
3261
|
+
* Upload a local directory to the sandbox via tar.
|
|
3262
|
+
* @param localPath - Local directory path to upload
|
|
3263
|
+
* @param remotePath - Destination path in the sandbox (default: /home/user)
|
|
3264
|
+
*/
|
|
3265
|
+
uploadDirectory(localPath: string, remotePath?: string): Promise<void>;
|
|
3266
|
+
/**
|
|
3267
|
+
* Wait for the sandbox to reach a specific status.
|
|
3268
|
+
*
|
|
3269
|
+
* When `onProgress` is provided and the sandbox is still provisioning,
|
|
3270
|
+
* uses SSE events for real-time progress instead of polling. Falls back
|
|
3271
|
+
* to polling if the SSE connection fails or is unavailable.
|
|
3272
|
+
*
|
|
3273
|
+
* @example Basic wait
|
|
3274
|
+
* ```typescript
|
|
3275
|
+
* await box.waitFor("running");
|
|
3276
|
+
* ```
|
|
3277
|
+
*
|
|
3278
|
+
* @example Wait with progress tracking
|
|
3279
|
+
* ```typescript
|
|
3280
|
+
* await box.waitFor("running", {
|
|
3281
|
+
* onProgress: (event) => {
|
|
3282
|
+
* console.log(`[${event.step}] ${event.status} — ${event.message}`);
|
|
3283
|
+
* if (event.percent !== undefined) {
|
|
3284
|
+
* updateProgressBar(event.percent);
|
|
3285
|
+
* }
|
|
3286
|
+
* },
|
|
3287
|
+
* });
|
|
3288
|
+
* ```
|
|
3289
|
+
*/
|
|
3290
|
+
waitFor(status: SandboxStatus | SandboxStatus[], options?: WaitForOptions): Promise<void>;
|
|
3291
|
+
/**
|
|
3292
|
+
* SSE-based wait implementation. Subscribes to provisioning events and
|
|
3293
|
+
* delivers progress callbacks while waiting for a target status.
|
|
3294
|
+
*/
|
|
3295
|
+
private waitForWithSSE;
|
|
3296
|
+
private parseCheckpointInfo;
|
|
3297
|
+
private ensureRunning;
|
|
3298
|
+
private runtimeFetch;
|
|
3299
|
+
/**
|
|
3300
|
+
* Delegates to the shared `parseSSEStream` in `lib/sse-parser.ts`
|
|
3301
|
+
* — one canonical SSE implementation for the whole SDK. The
|
|
3302
|
+
* shared parser throws `AbortError` on cancellation (so consumers
|
|
3303
|
+
* can distinguish cancel from clean EOF), but agent/task streaming
|
|
3304
|
+
* callers of this method historically relied on a silent-return
|
|
3305
|
+
* abort: they check `options?.signal?.aborted` AFTER the loop and
|
|
3306
|
+
* decide whether to reconnect. The try/catch below preserves that
|
|
3307
|
+
* legacy contract by swallowing AbortError at the delegate layer.
|
|
3308
|
+
*/
|
|
3309
|
+
private parseSSEStream;
|
|
3310
|
+
/**
|
|
3311
|
+
* Associate a session ID with a user ID so the Sandbox API can route
|
|
3312
|
+
* subsequent WebSocket connections to this sandbox.
|
|
3313
|
+
*
|
|
3314
|
+
* @param opts - Session and user identifiers
|
|
3315
|
+
*
|
|
3316
|
+
* @example
|
|
3317
|
+
* ```typescript
|
|
3318
|
+
* await box.registerSessionMapping({
|
|
3319
|
+
* sessionId: "sess_abc",
|
|
3320
|
+
* userId: "user_123",
|
|
3321
|
+
* });
|
|
3322
|
+
* ```
|
|
3323
|
+
*/
|
|
3324
|
+
registerSessionMapping(opts: {
|
|
3325
|
+
sessionId: string;
|
|
3326
|
+
userId: string;
|
|
3327
|
+
}): Promise<void>;
|
|
3328
|
+
private parseInfo;
|
|
3329
|
+
private sleep;
|
|
3330
|
+
}
|
|
3331
|
+
//#endregion
|
|
3332
|
+
export { Process as $, defineGitHubResource as $t, ExecResult as A, StorageConfig as At, GitStatus as B, AgentProfile as Bt, DownloadOptions as C, SearchMatch as Ct, DriverType as D, SnapshotInfo as Dt, DriverInfo as E, SecretsManager as Et, GitAuth as F, UpdateUserOptions as Ft, McpServerConfig as G, AgentProfilePermissionValue as Gt, InstalledTool as H, AgentProfileFileMount as Ht, GitBranch as I, UploadOptions as It, NetworkManager as J, AgentProfileResources as Jt, MkdirOptions as K, AgentProfilePrompt as Kt, GitCommit as L, UploadProgress as Lt, FileSystem as M, TaskOptions as Mt, ForkOptions as N, TaskResult as Nt, EventStreamOptions as O, SnapshotOptions as Ot, ForkResult as P, ToolsConfig as Pt, PreviewLinkManager as Q, defineAgentProfile as Qt, GitConfig as R, UsageInfo as Rt, DirectoryPermission as S, SandboxUser as St, DriverConfig as T, SecretInfo as Tt, ListOptions as U, AgentProfileMcpServer as Ut, GpuType as V, AgentProfileCapabilities as Vt, ListSandboxOptions as W, AgentProfileModelHints as Wt, PermissionsManager as X, AgentProfileValidationResult as Xt, PermissionLevel as Y, AgentProfileValidationIssue as Yt, PreviewLinkInfo as Z, AgentSubagentProfile as Zt, CheckpointOptions as _, SandboxEvent as _t, BackendCapabilities as a, ProcessStatus as at, CreateSandboxOptions as b, SandboxResources as bt, BackendManager as c, ProvisionEvent as ct, BatchEvent as d, ProvisionStep as dt, defineInlineResource as en, ProcessInfo as et, BatchOptions as f, RunCodeOptions as ft, CheckpointInfo as g, SandboxEnvironment as gt, BatchTaskResult as h, SandboxConnection as ht, AddUserOptions as i, ProcessSpawnOptions as it, FileInfo as j, SubscriptionInfo as jt, ExecOptions as k, SnapshotResult as kt, BackendStatus as l, ProvisionResult as lt, BatchTask as m, SandboxClientConfig as mt, SandboxInstance as n, ProcessManager as nt, BackendConfig as o, PromptOptions as ot, BatchResult as p, SSHCredentials as pt, NetworkConfig as q, AgentProfileResourceRef as qt, AccessPolicyRule as r, ProcessSignal as rt, BackendInfo as s, PromptResult as st, HttpClient as t, mergeAgentProfiles as tn, ProcessLogEntry as tt, BackendType as u, ProvisionStatus as ut, CheckpointResult as v, SandboxInfo as vt, DownloadProgress as w, SearchOptions as wt, DeleteOptions as x, SandboxStatus as xt, CodeResult as y, SandboxPermissionsConfig as yt, GitDiff as z, WaitForOptions as zt };
|