@tangle-network/sandbox 0.0.0-develop.20260514223840.b2abd84

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.
@@ -0,0 +1,4857 @@
1
+ import { IntegrationActor, IntegrationManifest } from "@tangle-network/agent-integrations";
2
+
3
+ //#region src/mcp.d.ts
4
+ /**
5
+ * MCP (Model Context Protocol) helpers for sandbox capabilities.
6
+ *
7
+ * The sandbox exposes capabilities (currently `computer_use`, more
8
+ * later) as MCP tools over Streamable HTTP. Any MCP-capable client —
9
+ * Claude Desktop, Cursor, claude-code, codex, opencode, raw
10
+ * `@modelcontextprotocol/sdk` apps — can consume this surface by
11
+ * pasting the JSON returned from `Sandbox#getMcpEndpoint()` (or
12
+ * `buildSandboxMcpConfig` if you already have the URL + token) into
13
+ * the client's MCP config.
14
+ *
15
+ * Security model:
16
+ * - Tokens are capability-scoped JWTs (claim `cap: ["computer_use"]`).
17
+ * - Full sandbox runtime tokens are rejected on `/mcp`; only
18
+ * capability-scoped tokens work there.
19
+ * - A scoped token cannot pivot to admin endpoints (`/exec`, `/files`,
20
+ * etc.) — those routes reject scoped tokens.
21
+ * - Tokens are short-lived. Rotate via `Sandbox#getMcpEndpoint()`,
22
+ * which mints a fresh token each call.
23
+ */
24
+ /** Default name of the MCP server entry — surfaces in the host UI. */
25
+ declare const SANDBOX_MCP_SERVER_NAME = "tangle-sandbox";
26
+ /**
27
+ * MCP HTTP server entry — matches the Anthropic MCP HTTP transport
28
+ * schema (`type: "http"`, `url`, optional `headers`). Compatible with
29
+ * every MCP host that implements the spec.
30
+ */
31
+ interface SandboxMcpServerEntry {
32
+ type: "http";
33
+ url: string;
34
+ headers: Record<string, string>;
35
+ }
36
+ /**
37
+ * `.mcp.json`-shaped config any MCP host accepts. Drop the contents of
38
+ * `mcpServers` into your host's `mcpServers` block (Claude Desktop,
39
+ * Cursor, claude-code's `--mcp-config`, etc.) — no host-specific
40
+ * fields, no provider lock-in.
41
+ */
42
+ interface SandboxMcpConfig {
43
+ mcpServers: Record<string, SandboxMcpServerEntry>;
44
+ }
45
+ /**
46
+ * Endpoint payload returned by `GET /v1/sandboxes/:id/mcp`. Includes
47
+ * the canonical config plus token expiry so callers can plan
48
+ * refreshes.
49
+ */
50
+ interface SandboxMcpEndpoint {
51
+ /** MCP host config — paste this into Cursor/Claude Desktop/etc. */
52
+ config: SandboxMcpConfig;
53
+ /** Server entry name used inside `config.mcpServers`. */
54
+ serverName: string;
55
+ /** Reachable URL for the MCP HTTP transport. */
56
+ url: string;
57
+ /** Bearer token sent by the MCP host on every request. */
58
+ authToken: string;
59
+ /** ISO-8601 expiry — the host should refresh before this. */
60
+ expiresAt: string;
61
+ /** Capabilities the token is scoped to. */
62
+ capabilities: ReadonlyArray<"computer_use">;
63
+ }
64
+ interface BuildSandboxMcpConfigOptions {
65
+ /** Public sandbox URL where `/mcp` is reachable. No trailing slash. */
66
+ sandboxUrl: string;
67
+ /** Capability-scoped JWT minted by the Sandbox API. */
68
+ authToken: string;
69
+ /** Override the entry name. Defaults to SANDBOX_MCP_SERVER_NAME. */
70
+ serverName?: string;
71
+ }
72
+ /**
73
+ * Build the canonical `mcpServers` config for a sandbox MCP endpoint.
74
+ * Pure function — no I/O, no crypto. Use this when you already have a
75
+ * `{ url, authToken }` pair from the API and just want the JSON shape
76
+ * to paste into a host. Most callers should use
77
+ * `Sandbox#getMcpEndpoint()` instead, which fetches a freshly-minted
78
+ * token from the API.
79
+ */
80
+ declare function buildSandboxMcpConfig(options: BuildSandboxMcpConfigOptions): {
81
+ serverName: string;
82
+ config: SandboxMcpConfig;
83
+ };
84
+ //#endregion
85
+ //#region src/agent-profile.d.ts
86
+ /**
87
+ * Provider-neutral agent profile types for public SDK consumers.
88
+ *
89
+ * These model portable agent intent at the application boundary.
90
+ * Individual backends can translate this shape into their own native
91
+ * profile/configuration formats internally.
92
+ */
93
+ /**
94
+ * Permission policy value for a capability.
95
+ */
96
+ type AgentProfilePermissionValue = "allow" | "ask" | "deny";
97
+ type AgentProfilePermission = AgentProfilePermissionValue | Record<string, AgentProfilePermissionValue>;
98
+ /**
99
+ * Generic resource reference that can be resolved into a file or instruction.
100
+ */
101
+ type AgentProfileResourceRef = {
102
+ kind: "inline";
103
+ name: string;
104
+ content: string;
105
+ } | {
106
+ kind: "github";
107
+ /**
108
+ * Optional repository in "owner/repo" form. When omitted, providers may
109
+ * only resolve the path if they have an ambient repository context.
110
+ */
111
+ repository?: string;
112
+ path: string;
113
+ ref?: string;
114
+ name?: string;
115
+ };
116
+ /**
117
+ * Helper for creating typed inline resource refs.
118
+ */
119
+ declare function defineInlineResource(name: string, content: string): AgentProfileResourceRef;
120
+ /**
121
+ * Helper for creating typed GitHub-backed resource refs.
122
+ */
123
+ declare function defineGitHubResource(path: string, options?: {
124
+ repository?: string;
125
+ ref?: string;
126
+ name?: string;
127
+ }): AgentProfileResourceRef;
128
+ /**
129
+ * Resource mounted into a backend workspace.
130
+ */
131
+ interface AgentProfileFileMount {
132
+ path: string;
133
+ resource: AgentProfileResourceRef;
134
+ executable?: boolean;
135
+ }
136
+ /**
137
+ * Provider-neutral resource bundle.
138
+ */
139
+ interface AgentProfileResources {
140
+ /**
141
+ * Generic files to materialize into the agent workspace before execution.
142
+ */
143
+ files?: AgentProfileFileMount[];
144
+ /**
145
+ * Provider-native tool files. Backends materialize these into their standard
146
+ * discovery location when they support file-based tools.
147
+ */
148
+ tools?: AgentProfileResourceRef[];
149
+ /**
150
+ * Agent Skills (`SKILL.md`) packages. Supported by Cursor, Claude Code,
151
+ * Codex-compatible layouts, OpenCode, and Hermes-style skill harnesses.
152
+ */
153
+ skills?: AgentProfileResourceRef[];
154
+ /**
155
+ * Provider-native subagent definition files.
156
+ */
157
+ agents?: AgentProfileResourceRef[];
158
+ /**
159
+ * Provider-native slash command files.
160
+ */
161
+ commands?: AgentProfileResourceRef[];
162
+ /**
163
+ * Additional instructions injected into the agent context.
164
+ */
165
+ instructions?: string | AgentProfileResourceRef;
166
+ /**
167
+ * Fail initialization when a provider cannot materialize a resource.
168
+ */
169
+ failOnError?: boolean;
170
+ }
171
+ /**
172
+ * Model selection hints for backends.
173
+ */
174
+ interface AgentProfileModelHints {
175
+ /**
176
+ * Preferred default model (format depends on backend, commonly "provider/model").
177
+ */
178
+ default?: string;
179
+ /**
180
+ * Preferred small/cheap model for lightweight work.
181
+ */
182
+ small?: string;
183
+ /**
184
+ * Optional provider preference hint.
185
+ */
186
+ provider?: string;
187
+ /**
188
+ * Backend-agnostic model metadata/hints.
189
+ */
190
+ metadata?: Record<string, unknown>;
191
+ }
192
+ /**
193
+ * Prompt shaping for an agent.
194
+ */
195
+ interface AgentProfilePrompt {
196
+ /**
197
+ * Full system prompt replacement, when supported.
198
+ */
199
+ systemPrompt?: string;
200
+ /**
201
+ * Additional instruction lines appended to the active prompt.
202
+ */
203
+ instructions?: string[];
204
+ }
205
+ /**
206
+ * Generic subagent definition.
207
+ */
208
+ interface AgentSubagentProfile {
209
+ description?: string;
210
+ prompt?: string;
211
+ model?: string;
212
+ tools?: Record<string, boolean>;
213
+ permissions?: Record<string, AgentProfilePermission>;
214
+ maxSteps?: number;
215
+ metadata?: Record<string, unknown>;
216
+ }
217
+ interface AgentProfileHookCommand {
218
+ command: string;
219
+ timeoutMs?: number;
220
+ blocking?: boolean;
221
+ matcher?: string;
222
+ env?: Record<string, string>;
223
+ }
224
+ interface AgentProfileMode {
225
+ description?: string;
226
+ model?: string;
227
+ prompt?: string;
228
+ tools?: Record<string, boolean>;
229
+ permissions?: Record<string, AgentProfilePermission>;
230
+ metadata?: Record<string, unknown>;
231
+ }
232
+ /**
233
+ * Confidential-execution options for sandbox backends.
234
+ *
235
+ * The Tangle blueprint path translates this into TEE job parameters and fails
236
+ * closed when the requested TEE is unavailable. Callers should verify returned
237
+ * attestation evidence before treating a session as confidential.
238
+ */
239
+ interface AgentProfileConfidential {
240
+ /**
241
+ * TEE variant requested from the operator.
242
+ */
243
+ tee?: "tdx" | "nitro" | "phala-dstack" | "sev-snp" | "any" | (string & {});
244
+ /**
245
+ * Optional hex-encoded 32-64 byte challenge for deploy-time report data.
246
+ */
247
+ attestationNonce?: string;
248
+ /**
249
+ * Require no persistence across session end when supported by the backend.
250
+ */
251
+ sealed?: boolean;
252
+ /**
253
+ * Ask the SDK/backend to create or require a fresh attestation challenge.
254
+ */
255
+ attestationRefresh?: boolean;
256
+ }
257
+ /**
258
+ * Generic MCP server configuration.
259
+ */
260
+ interface AgentProfileMcpServer {
261
+ transport?: "stdio" | "sse" | "http";
262
+ command?: string;
263
+ args?: string[];
264
+ env?: Record<string, string>;
265
+ cwd?: string;
266
+ url?: string;
267
+ headers?: Record<string, string>;
268
+ enabled?: boolean;
269
+ metadata?: Record<string, unknown>;
270
+ }
271
+ /**
272
+ * Public provider-neutral agent profile contract.
273
+ */
274
+ interface AgentProfile {
275
+ name?: string;
276
+ description?: string;
277
+ version?: string;
278
+ tags?: string[];
279
+ prompt?: AgentProfilePrompt;
280
+ model?: AgentProfileModelHints;
281
+ permissions?: Record<string, AgentProfilePermission>;
282
+ tools?: Record<string, boolean>;
283
+ mcp?: Record<string, AgentProfileMcpServer>;
284
+ subagents?: Record<string, AgentSubagentProfile>;
285
+ resources?: AgentProfileResources;
286
+ hooks?: Record<string, AgentProfileHookCommand[]>;
287
+ modes?: Record<string, AgentProfileMode>;
288
+ confidential?: AgentProfileConfidential;
289
+ metadata?: Record<string, unknown>;
290
+ /**
291
+ * Non-portable backend-specific extensions.
292
+ *
293
+ * Use this only for features that cannot be expressed generically.
294
+ * SDK consumers should treat extension keys as backend namespaces.
295
+ */
296
+ extensions?: Record<string, Record<string, unknown> | undefined>;
297
+ }
298
+ /**
299
+ * Helper for declaring typed profiles in application code.
300
+ */
301
+ declare function defineAgentProfile<T extends AgentProfile>(profile: T): T;
302
+ /**
303
+ * Capabilities describing how a backend interprets AgentProfile.
304
+ */
305
+ interface AgentProfileCapabilities {
306
+ namedProfiles: boolean;
307
+ systemPrompt: boolean;
308
+ instructions: boolean;
309
+ tools: boolean;
310
+ permissions: boolean;
311
+ mcp: boolean;
312
+ subagents: boolean;
313
+ resources: {
314
+ files: boolean;
315
+ instructions: boolean;
316
+ tools?: boolean;
317
+ skills?: boolean;
318
+ agents?: boolean;
319
+ commands?: boolean;
320
+ };
321
+ hooks?: boolean;
322
+ modes?: boolean;
323
+ runtimeUpdate: boolean;
324
+ validation: boolean;
325
+ /**
326
+ * Backend extension namespaces understood by this backend.
327
+ */
328
+ extensions?: string[];
329
+ }
330
+ /**
331
+ * Validation issue for a profile/backend pairing.
332
+ */
333
+ interface AgentProfileValidationIssue {
334
+ level: "error" | "warning" | "info";
335
+ code: string;
336
+ message: string;
337
+ path?: string;
338
+ }
339
+ /**
340
+ * Validation output for a provider adapter.
341
+ */
342
+ interface AgentProfileValidationResult {
343
+ ok: boolean;
344
+ issues: AgentProfileValidationIssue[];
345
+ normalizedProfile?: AgentProfile;
346
+ }
347
+ /**
348
+ * Merge two public AgentProfile values.
349
+ *
350
+ * Overlay fields win on conflicts. Array-like instruction sets are appended.
351
+ */
352
+ declare function mergeAgentProfiles(base: AgentProfile | undefined, overlay: AgentProfile | undefined): AgentProfile | undefined;
353
+ //#endregion
354
+ //#region src/types.d.ts
355
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
356
+ [key: string]: JsonValue;
357
+ };
358
+ /**
359
+ * A development environment.
360
+ *
361
+ * Environments provide toolchains provisioned via Nix profiles mounted into
362
+ * a shared base container. The default "universal" environment includes all
363
+ * common toolchains (Node.js, Python, Rust, Go, etc.).
364
+ */
365
+ interface SandboxEnvironment {
366
+ /** Environment identifier (e.g., "universal") */
367
+ id: string;
368
+ /** Human-readable description */
369
+ description?: string;
370
+ /** Base template this environment extends */
371
+ base?: string;
372
+ /** Environment version tag */
373
+ version: string;
374
+ /** Public template identifier when this environment comes from a published template */
375
+ publicTemplateId?: string;
376
+ /** Snapshot identifier backing the environment when applicable */
377
+ snapshotId?: string;
378
+ }
379
+ interface PublicTemplateVersionInfo {
380
+ id: string;
381
+ templateId: string;
382
+ versionNumber: number;
383
+ snapshotId: string;
384
+ sourceSandboxId: string;
385
+ readmeMarkdown: string;
386
+ tags: string[];
387
+ releaseNotes: string;
388
+ createdByCustomerId: string;
389
+ createdAt: string;
390
+ }
391
+ interface PublicTemplateInfo {
392
+ id: string;
393
+ slug: string;
394
+ name: string;
395
+ description: string;
396
+ websiteUrl: string | null;
397
+ ownerCustomerId: string;
398
+ ownerTeamId: string | null;
399
+ forkedFromTemplateId: string | null;
400
+ latestVersionId: string | null;
401
+ isFeatured: boolean;
402
+ featuredRank: number | null;
403
+ forkCount: number;
404
+ sandboxCount: number;
405
+ createdAt: string;
406
+ updatedAt: string;
407
+ publishedAt: string;
408
+ latestVersion: PublicTemplateVersionInfo | null;
409
+ }
410
+ interface PublishPublicTemplateOptions {
411
+ name: string;
412
+ slug?: string;
413
+ description?: string;
414
+ websiteUrl?: string;
415
+ snapshotId: string;
416
+ sourceSandboxId: string;
417
+ teamId?: string;
418
+ readmeMarkdown?: string;
419
+ tags?: string[];
420
+ releaseNotes?: string;
421
+ forkedFromTemplateId?: string;
422
+ }
423
+ interface PublishPublicTemplateVersionOptions {
424
+ snapshotId: string;
425
+ sourceSandboxId: string;
426
+ readmeMarkdown?: string;
427
+ tags?: string[];
428
+ releaseNotes?: string;
429
+ }
430
+ /**
431
+ * Git authentication configuration.
432
+ *
433
+ * @example HTTPS token
434
+ * ```typescript
435
+ * const auth: GitAuth = {
436
+ * token: process.env.GITHUB_TOKEN,
437
+ * };
438
+ * ```
439
+ */
440
+ interface GitAuth {
441
+ /** HTTPS auth token (e.g., GitHub PAT) */
442
+ token?: string;
443
+ }
444
+ /**
445
+ * Git repository configuration for cloning at sandbox creation.
446
+ *
447
+ * When provided, the repository is cloned during sandbox provisioning,
448
+ * before the sandbox becomes ready. This is more efficient than cloning
449
+ * after the sandbox starts.
450
+ *
451
+ * @example Basic clone
452
+ * ```typescript
453
+ * const git: GitConfig = {
454
+ * url: "https://github.com/user/repo.git",
455
+ * };
456
+ * ```
457
+ *
458
+ * @example Clone specific branch with auth
459
+ * ```typescript
460
+ * const git: GitConfig = {
461
+ * url: "https://github.com/user/private-repo.git",
462
+ * ref: "develop",
463
+ * auth: { token: process.env.GITHUB_TOKEN },
464
+ * };
465
+ * ```
466
+ *
467
+ * @example Sparse checkout for monorepo
468
+ * ```typescript
469
+ * const git: GitConfig = {
470
+ * url: "https://github.com/org/monorepo.git",
471
+ * sparse: ["packages/my-package", "shared"],
472
+ * depth: 1,
473
+ * };
474
+ * ```
475
+ */
476
+ interface GitConfig {
477
+ /** Repository URL (HTTPS or SSH) */
478
+ url: string;
479
+ /** Branch, tag, or commit SHA to checkout (default: default branch) */
480
+ ref?: string;
481
+ /** Shallow clone depth (default: 1 for faster clones) */
482
+ depth?: number;
483
+ /** Sparse checkout paths - only clone these directories */
484
+ sparse?: string[];
485
+ /** Authentication for private repositories */
486
+ auth?: GitAuth;
487
+ }
488
+ /**
489
+ * Tool version specifications for mise (polyglot version manager).
490
+ *
491
+ * Mise is pre-installed in all managed sandboxes and can install any
492
+ * language runtime or tool on demand. Specify versions here to have
493
+ * them pre-installed when the sandbox starts.
494
+ *
495
+ * @see https://mise.jdx.dev for supported tools
496
+ *
497
+ * @example Common tools
498
+ * ```typescript
499
+ * const tools: ToolsConfig = {
500
+ * node: "22", // Node.js 22.x (latest minor/patch)
501
+ * python: "3.12", // Python 3.12.x
502
+ * rust: "1.75", // Rust 1.75.x
503
+ * go: "1.22", // Go 1.22.x
504
+ * };
505
+ * ```
506
+ *
507
+ * @example Exact versions
508
+ * ```typescript
509
+ * const tools: ToolsConfig = {
510
+ * node: "20.11.0", // Exact version
511
+ * pnpm: "8.15.1",
512
+ * deno: "1.40",
513
+ * };
514
+ * ```
515
+ */
516
+ interface ToolsConfig {
517
+ /** Node.js version (e.g., "22", "20.11.0", "lts") */
518
+ node?: string;
519
+ /** Python version (e.g., "3.12", "3.11.7") */
520
+ python?: string;
521
+ /** Rust version (e.g., "1.75", "stable", "nightly") */
522
+ rust?: string;
523
+ /** Go version (e.g., "1.22", "1.21.6") */
524
+ go?: string;
525
+ /** Java version (e.g., "21", "17") */
526
+ java?: string;
527
+ /** Ruby version (e.g., "3.3", "3.2.2") */
528
+ ruby?: string;
529
+ /** Any other mise-supported tool and version */
530
+ [tool: string]: string | undefined;
531
+ }
532
+ /**
533
+ * Configuration for initializing the Sandbox client.
534
+ *
535
+ * @example
536
+ * ```typescript
537
+ * const client = new Sandbox({
538
+ * apiKey: "sk_sandbox_abc123",
539
+ * baseUrl: "https://your-sandbox-api.example.com",
540
+ * timeoutMs: 60000,
541
+ * });
542
+ * ```
543
+ */
544
+ interface SandboxClientConfig {
545
+ /** API key for authentication. Must start with `sk_sandbox_` */
546
+ apiKey: string;
547
+ /** Base URL for the Sandbox API */
548
+ baseUrl: string;
549
+ /** Request timeout in milliseconds. Defaults to 30000 (30 seconds) */
550
+ timeoutMs?: number;
551
+ /**
552
+ * Permit the SDK to read CLI auth files from the host home directory
553
+ * (`~/.codex/auth.json`, `~/.claude/.credentials.json`,
554
+ * `~/.claude/settings.json`) and ship them to a `localhost` /
555
+ * `127.0.0.1` / `::1` `baseUrl` when creating a `codex` or
556
+ * `claude-code` backend without explicit credentials.
557
+ *
558
+ * Default `false`. Without this flag, any process bound to a
559
+ * localhost port (your sandbox-api or anything else) can impersonate
560
+ * the API and silently harvest those credentials. Set this to `true`
561
+ * only when the localhost endpoint is one you control. For non-local
562
+ * `baseUrl`s the flag is ignored — the SDK never reads home-dir auth
563
+ * files for remote endpoints.
564
+ */
565
+ trustLocalCliAuth?: boolean;
566
+ }
567
+ /**
568
+ * Status of a sandbox instance.
569
+ *
570
+ * Lifecycle: `pending` -> `provisioning` -> `running` -> `stopped` -> (deleted)
571
+ *
572
+ * - `pending` - Sandbox created but not yet provisioning
573
+ * - `provisioning` - Container and resources being allocated
574
+ * - `running` - Sandbox is active and accepting commands
575
+ * - `stopped` - Sandbox is paused (can be resumed)
576
+ * - `failed` - Sandbox encountered an error
577
+ * - `expired` - Sandbox exceeded its lifetime limit
578
+ */
579
+ type SandboxStatus = "pending" | "provisioning" | "running" | "stopped" | "failed" | "expired";
580
+ /**
581
+ * Resource limits for a sandbox.
582
+ */
583
+ interface SandboxResources {
584
+ /** Number of CPU cores */
585
+ cpuCores?: number;
586
+ /** Memory in megabytes */
587
+ memoryMB?: number;
588
+ /** Disk space in gigabytes */
589
+ diskGB?: number;
590
+ /** Accelerator request for GPU-class workloads. */
591
+ accelerator?: SandboxAccelerator;
592
+ }
593
+ /** @deprecated Use SandboxAccelerator.kind via SandboxResources.accelerator. */
594
+ type GpuType = string;
595
+ /**
596
+ * Configuration for creating a new sandbox.
597
+ *
598
+ * Sandboxes can run in two modes:
599
+ * - **Managed** (default): Full-featured with agent, files, terminal, git, tools
600
+ * - **Bare**: Minimal container with only exec() and lifecycle methods
601
+ *
602
+ * @example Minimal sandbox (managed mode with defaults)
603
+ * ```typescript
604
+ * const box = await client.create();
605
+ * // Uses 'universal' image, managed mode, sane defaults
606
+ * ```
607
+ *
608
+ * @example Sandbox with pre-built image and git
609
+ * ```typescript
610
+ * const box = await client.create({
611
+ * image: "ethereum", // Stack name — tools provisioned via Nix profile
612
+ * git: {
613
+ * url: "https://github.com/user/dapp.git",
614
+ * ref: "main",
615
+ * },
616
+ * tools: { node: "22", python: "3.12" },
617
+ * });
618
+ * ```
619
+ *
620
+ * @example Sandbox with custom Docker image
621
+ * ```typescript
622
+ * const box = await client.create({
623
+ * image: "python:3.12-slim",
624
+ * git: { url: "https://github.com/user/ml-project.git" },
625
+ * tools: { python: "3.12" },
626
+ * });
627
+ * ```
628
+ *
629
+ * @example Bare sandbox (no managed runtime, just exec)
630
+ * ```typescript
631
+ * const box = await client.create({
632
+ * image: "ubuntu:24.04",
633
+ * bare: true,
634
+ * });
635
+ * // Only box.exec(), box.stop(), box.resume(), box.delete() available
636
+ * ```
637
+ *
638
+ * @example With BYOS3 storage for snapshots
639
+ * ```typescript
640
+ * const box = await client.create({
641
+ * image: "universal",
642
+ * storage: {
643
+ * type: "s3",
644
+ * bucket: "my-snapshots",
645
+ * credentials: { accessKeyId: "...", secretAccessKey: "..." },
646
+ * },
647
+ * fromSnapshot: "snap_abc123",
648
+ * });
649
+ * ```
650
+ */
651
+ interface CreateSandboxOptions {
652
+ /**
653
+ * Development environment name.
654
+ *
655
+ * Environments provision toolchains via Nix profiles mounted into a
656
+ * shared base container. Use `client.environments.list()` to discover
657
+ * available environments.
658
+ *
659
+ * Takes precedence over `image` if both are specified.
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * environment: "universal" // Multi-language (default)
664
+ * ```
665
+ */
666
+ environment?: string;
667
+ /**
668
+ * Container image to use for the sandbox.
669
+ *
670
+ * For most use cases the default "universal" environment is sufficient.
671
+ * Use this field for custom images; the SDK runtime integration is applied
672
+ * automatically.
673
+ *
674
+ * **Resolution rules:**
675
+ * - Full image paths → Used as-is
676
+ * - Simple names without `/` or `:` → Treated as environment name
677
+ * (equivalent to setting `environment`)
678
+ *
679
+ * When neither `environment` nor `image` is set the SDK omits the
680
+ * field entirely and the server applies its own default.
681
+ */
682
+ image?: string;
683
+ /**
684
+ * Create a bare sandbox without the managed runtime.
685
+ *
686
+ * Bare sandboxes only have:
687
+ * - `exec()` - Execute commands
688
+ * - `stop()` / `resume()` - Lifecycle control
689
+ * - `delete()` - Cleanup
690
+ *
691
+ * Use bare mode when you need a clean container without the managed
692
+ * runtime integration.
693
+ *
694
+ * @default false
695
+ */
696
+ bare?: boolean;
697
+ /**
698
+ * Infrastructure driver selection.
699
+ * Controls how the sandbox is provisioned and isolated.
700
+ *
701
+ * @example Firecracker with CRIU
702
+ * ```typescript
703
+ * driver: { type: "firecracker", enableCriu: true }
704
+ * ```
705
+ */
706
+ driver?: DriverConfig;
707
+ /**
708
+ * AI coding agent backend configuration.
709
+ * Determines which agent runs inside the sandbox.
710
+ *
711
+ * @example OpenCode with profile
712
+ * ```typescript
713
+ * backend: { type: "opencode", profile: "with-web-search" }
714
+ * ```
715
+ */
716
+ backend?: BackendConfig;
717
+ /**
718
+ * Confidential execution requirements for this sandbox.
719
+ *
720
+ * This is equivalent to setting `backend.profile.confidential` on an inline
721
+ * AgentProfile. Tangle-backed creation translates it into blueprint TEE
722
+ * fields; operators that cannot satisfy the requested TEE fail closed.
723
+ */
724
+ confidential?: AgentProfileConfidential;
725
+ /**
726
+ * Initial permissions and access control settings.
727
+ *
728
+ * @example Multi-user sandbox
729
+ * ```typescript
730
+ * permissions: {
731
+ * defaultRole: "developer",
732
+ * initialUsers: [{ userId: "user_xyz", role: "developer" }],
733
+ * }
734
+ * ```
735
+ */
736
+ permissions?: SandboxPermissionsConfig;
737
+ /**
738
+ * Network security configuration.
739
+ * Controls outbound network access from the sandbox.
740
+ *
741
+ * @example Block all outbound traffic
742
+ * ```typescript
743
+ * network: { blockOutbound: true }
744
+ * ```
745
+ *
746
+ * @example Allow only specific destinations
747
+ * ```typescript
748
+ * network: {
749
+ * allowList: ["8.8.8.8/32", "10.0.0.0/8"],
750
+ * ports: [8000, 8080], // Pre-expose ports
751
+ * }
752
+ * ```
753
+ */
754
+ network?: NetworkConfig;
755
+ /**
756
+ * Git repository to clone at sandbox creation.
757
+ *
758
+ * The repository is cloned during provisioning, before the sandbox
759
+ * becomes ready. This is more efficient than cloning after start.
760
+ *
761
+ * @example { url: "https://github.com/user/repo.git", ref: "main" }
762
+ */
763
+ git?: GitConfig;
764
+ /**
765
+ * Tool versions to pre-install via mise.
766
+ *
767
+ * Mise (polyglot version manager) is pre-installed in managed sandboxes.
768
+ * Specify versions here to have them ready when the sandbox starts.
769
+ *
770
+ * @example { node: "22", python: "3.12", rust: "1.75" }
771
+ */
772
+ tools?: ToolsConfig;
773
+ /** Human-readable name for the sandbox */
774
+ name?: string;
775
+ /** Resource limits (CPU cores, memory, disk) */
776
+ resources?: SandboxResources;
777
+ /** Environment variables injected into the sandbox */
778
+ env?: Record<string, string>;
779
+ /**
780
+ * Integration requirements the sandbox app needs at launch.
781
+ *
782
+ * The sandbox API resolves this manifest through id.tangle.tools,
783
+ * creates owner-scoped grants, and injects only a short-lived
784
+ * `TANGLE_INTEGRATION_BUNDLE` capability payload. Raw provider OAuth
785
+ * tokens and API keys never enter the sandbox environment.
786
+ */
787
+ integrationManifest?: IntegrationManifest;
788
+ /**
789
+ * Existing platform grant ids to bind to this launch.
790
+ *
791
+ * Use this for installed templates or pre-consented apps where the
792
+ * installer owns the connection. The sandbox API still requires
793
+ * `integrationManifest` so platform can fail closed if a grant does not
794
+ * match the declared requirements.
795
+ */
796
+ integrationGrantIds?: string[];
797
+ /**
798
+ * Grant durability for `integrationManifest`.
799
+ *
800
+ * `preview` scopes consent to this sandbox preview/session,
801
+ * `durable-app` is for installed/generated app instances, and
802
+ * `one-shot` is for a single workflow run.
803
+ */
804
+ integrationGrantMode?: "preview" | "durable-app" | "one-shot";
805
+ /**
806
+ * Logical app/agent subject receiving the grant. When omitted, the
807
+ * sandbox itself is the grantee and runtime subject.
808
+ */
809
+ integrationSubject?: IntegrationActor;
810
+ /**
811
+ * Maximum lifetime in seconds.
812
+ * Sandbox is automatically deleted after this time.
813
+ * @default 3600 (1 hour)
814
+ */
815
+ maxLifetimeSeconds?: number;
816
+ /**
817
+ * Idle timeout in seconds.
818
+ * Sandbox is suspended after this period of inactivity.
819
+ * @default 900 (15 minutes)
820
+ */
821
+ idleTimeoutSeconds?: number;
822
+ /**
823
+ * Enable SSH access to the sandbox.
824
+ * Use `sandbox.ssh()` to get connection credentials.
825
+ * @default false
826
+ */
827
+ sshEnabled?: boolean;
828
+ /** Custom SSH public key for access (optional) */
829
+ sshPublicKey?: string;
830
+ /**
831
+ * Enable web terminal access.
832
+ * Provides a browser-based terminal via websocket.
833
+ * @default false
834
+ */
835
+ webTerminalEnabled?: boolean;
836
+ /**
837
+ * Customer-provided S3-compatible storage for snapshots (BYOS3).
838
+ *
839
+ * When configured, snapshots are stored in your own bucket
840
+ * instead of Tangle's managed storage.
841
+ */
842
+ storage?: StorageConfig;
843
+ /** Snapshot ID to restore from when creating the sandbox */
844
+ fromSnapshot?: string;
845
+ /** Source sandbox ID that owns the snapshot (required when fromSnapshot is set) */
846
+ fromSandboxId?: string;
847
+ /**
848
+ * Apply a saved template at create time. Templates seed the
849
+ * sandbox with a snapshot, default environment, and config defaults
850
+ * so a team can publish a golden-path starting point once and have
851
+ * every member spin up the same baseline.
852
+ *
853
+ * The template must either be personal (owned by the caller) or
854
+ * belong to a team the caller is an active member of. Explicit
855
+ * fields on this call win over template defaults — so you can layer
856
+ * a one-off override on top of the golden path without forking the
857
+ * template itself.
858
+ *
859
+ * @example
860
+ * ```typescript
861
+ * const box = await client.create({
862
+ * templateId: "tpl_abc123",
863
+ * teamId: "team_...", // optional; sandbox is shared with the team
864
+ * });
865
+ * ```
866
+ */
867
+ templateId?: string;
868
+ /**
869
+ * Create from a published public template by id or slug.
870
+ * The API resolves the latest published version unless
871
+ * `publicTemplateVersionId` is also provided.
872
+ */
873
+ publicTemplateId?: string;
874
+ /** Pin sandbox creation to a specific published public-template version. */
875
+ publicTemplateVersionId?: string;
876
+ /**
877
+ * Names of secrets to inject as environment variables.
878
+ *
879
+ * Secrets must be created via `client.secrets.create()` before use.
880
+ * They are injected as environment variables with the same name.
881
+ *
882
+ * @example
883
+ * ```typescript
884
+ * // First, create the secrets
885
+ * await client.secrets.create("HF_TOKEN", "hf_xxx");
886
+ * await client.secrets.create("AWS_ACCESS_KEY", "AKIA...");
887
+ *
888
+ * // Then use them in a sandbox
889
+ * const box = await client.create({
890
+ * secrets: ["HF_TOKEN", "AWS_ACCESS_KEY"],
891
+ * });
892
+ *
893
+ * // Secrets are available as env vars
894
+ * const result = await box.exec("echo $HF_TOKEN");
895
+ * ```
896
+ */
897
+ secrets?: string[];
898
+ /** Custom metadata to store with the sandbox */
899
+ metadata?: Record<string, unknown>;
900
+ /**
901
+ * Share this sandbox with a team. The caller must be an active
902
+ * member of the team — the API rejects requests from non-members
903
+ * before provisioning. When omitted the sandbox is personal
904
+ * (accessible only to the creator).
905
+ */
906
+ teamId?: string;
907
+ /**
908
+ * Sidecar capabilities to enable at boot. Each capability boots an
909
+ * additional subsystem inside the sandbox; absent capabilities incur
910
+ * zero startup cost.
911
+ *
912
+ * Currently supported:
913
+ * - `"computer_use"` — boots Xvfb, dbus, AT-SPI, and an MCP server
914
+ * exposing mouse/keyboard/screenshot via the Anthropic + OpenAI
915
+ * Responses computer-use surface. Required if you plan to call
916
+ * {@link SandboxInstance.getMcpAccessToken | `getMcpAccessToken`}
917
+ * with `capabilities: ["computer_use"]`.
918
+ *
919
+ * The capability is enforced at two layers:
920
+ * 1. The sidecar refuses to start if a capability's binaries are
921
+ * missing (computer_use needs the universal Nix profile, which
922
+ * Docker / host-agent / Firecracker drivers ship via the host
923
+ * bind-mount or the universal sidecar image variant; Firecracker
924
+ * host profiles built without the universal flake do not).
925
+ * 2. The MCP token endpoint refuses to mint a `cap: ["computer_use"]`
926
+ * JWT for a sandbox that wasn't created with that capability.
927
+ *
928
+ * **Sizing note:** `computer_use` boots an always-on Xvfb + dbus
929
+ * stack costing roughly **~100 MB resident memory** inside the
930
+ * container. Billing is by reserved capacity (not measured RSS), so
931
+ * this comes out of your sandbox's RAM envelope rather than adding
932
+ * a separate line item. On a 1 GB sandbox that is ~10% of your
933
+ * workload's headroom; bump `resources.memoryMb` to 1.5–2 GB if
934
+ * the agent will run anything memory-hungry alongside it.
935
+ *
936
+ * @example
937
+ * ```typescript
938
+ * const box = await client.create({
939
+ * environment: "universal",
940
+ * capabilities: ["computer_use"],
941
+ * });
942
+ * const { token } = await box.getMcpAccessToken({
943
+ * capabilities: ["computer_use"],
944
+ * });
945
+ * ```
946
+ */
947
+ capabilities?: ReadonlyArray<"computer_use">;
948
+ /**
949
+ * Privacy controls for the sandbox. Two independent layers:
950
+ *
951
+ * - **`egress`** — what happens when the sandbox sends a request to a
952
+ * model vendor (Anthropic, OpenAI, your own router, etc.):
953
+ * - `"redact"` — PII spans are masked before the request leaves
954
+ * the sandbox. Emails, JWTs, API keys, credit cards (Luhn-
955
+ * validated), SSNs, phone numbers, IPv4 addresses are caught
956
+ * today; names / postal addresses / DOBs land when the OPF
957
+ * model service is enabled. The agent receives normal
958
+ * responses; the vendor sees masked input.
959
+ * - `"block"` — PII presence fails the egress request closed.
960
+ * For high-compliance flows that prefer fail-closed to leak.
961
+ * - `"off"` — no egress filtering. Default for free tier; opt-in
962
+ * for tasks that genuinely need raw PII (form-filling,
963
+ * customer-support agents reading customer details).
964
+ *
965
+ * - **`logs`** — whether infrastructure logs / telemetry / Sentry
966
+ * redact PII before recording. This is OUR side, not the model
967
+ * vendor's, and there's basically never a reason to leak PII into
968
+ * our own logs. Default `"on"`.
969
+ *
970
+ * Note: privacy controls operate at the boundary between the
971
+ * sandbox and external systems. They do NOT redact contents inside
972
+ * the sandbox workspace itself — files / code / database fixtures
973
+ * the customer puts there are the customer's data and stay
974
+ * unmodified. Snapshots preserve those contents verbatim.
975
+ *
976
+ * @example
977
+ * ```typescript
978
+ * const box = await client.create({
979
+ * privacy: { egress: "redact", logs: "on" },
980
+ * });
981
+ * ```
982
+ */
983
+ privacy?: {
984
+ egress?: "redact" | "block" | "off";
985
+ logs?: "on" | "off";
986
+ };
987
+ }
988
+ /**
989
+ * SSH connection credentials.
990
+ */
991
+ interface SSHCredentials {
992
+ /** Username for SSH authentication */
993
+ username: string;
994
+ /** SSH server port */
995
+ port: number;
996
+ /** ProxyCommand for sandbox API tunnel-based SSH. */
997
+ proxyCommand: string;
998
+ }
999
+ interface SSHCommandDescriptor {
1000
+ command: string;
1001
+ env: Record<string, string>;
1002
+ }
1003
+ /**
1004
+ * Connection information for a sandbox.
1005
+ *
1006
+ * Most code should use `SandboxInstance` methods (`exec`, `prompt`, etc.).
1007
+ * The raw `runtimeUrl` and `authToken` are surfaced only for advanced
1008
+ * lower-level use cases such as custom protocol clients.
1009
+ */
1010
+ interface SandboxConnection {
1011
+ /** Sandbox runtime API URL for programmatic access */
1012
+ runtimeUrl?: string;
1013
+ /** Access token for authenticating directly with the runtime (Bearer token) */
1014
+ authToken?: string;
1015
+ /** Token expiration timestamp (ISO 8601). Refresh before this time. */
1016
+ authTokenExpiresAt?: string;
1017
+ /** SSH connection info if `sshEnabled` was true during creation */
1018
+ ssh?: SSHCredentials;
1019
+ /** Web terminal URL if `webTerminalEnabled` was true during creation */
1020
+ webTerminalUrl?: string;
1021
+ }
1022
+ /**
1023
+ * Full sandbox information returned from the API.
1024
+ */
1025
+ interface SandboxInfo {
1026
+ /** Unique sandbox identifier */
1027
+ id: string;
1028
+ /** Human-readable name */
1029
+ name?: string;
1030
+ /** Current status */
1031
+ status: SandboxStatus;
1032
+ /** Connection information */
1033
+ connection?: SandboxConnection;
1034
+ /** Custom metadata */
1035
+ metadata?: Record<string, unknown>;
1036
+ /** When the sandbox was created */
1037
+ createdAt: Date;
1038
+ /** When the sandbox started running */
1039
+ startedAt?: Date;
1040
+ /** Last activity timestamp */
1041
+ lastActivityAt?: Date;
1042
+ /** When the sandbox will expire */
1043
+ expiresAt?: Date;
1044
+ /** Error message if status is 'failed' */
1045
+ error?: string;
1046
+ }
1047
+ /**
1048
+ * Raw TEE attestation evidence returned by the sandbox runtime.
1049
+ *
1050
+ * Pass this object to `@tangle-network/tcloud-attestation` for caller-side
1051
+ * policy checks and hardware verification.
1052
+ */
1053
+ interface TeeAttestationReport {
1054
+ /** TEE backend that produced the report, e.g. `Tdx`, `Sev`, or `Nitro`. */
1055
+ tee_type: string;
1056
+ /** Raw vendor evidence bytes. */
1057
+ evidence: number[];
1058
+ /** Runtime measurement bytes. */
1059
+ measurement: number[];
1060
+ /** Unix timestamp when the report was generated. */
1061
+ timestamp: number;
1062
+ }
1063
+ /**
1064
+ * Response from a sandbox TEE attestation request.
1065
+ */
1066
+ interface TeeAttestationResponse {
1067
+ /** Sandbox identifier the attestation belongs to. */
1068
+ sandbox_id: string;
1069
+ /** Raw TEE attestation report. */
1070
+ attestation: TeeAttestationReport;
1071
+ /** Caller nonce used for this report, when supplied. */
1072
+ attestationNonce?: string;
1073
+ }
1074
+ /**
1075
+ * TEE-bound public key used for sealed-secret encryption.
1076
+ */
1077
+ interface TeePublicKey {
1078
+ /** Key agreement/encryption algorithm, e.g. `x25519-hkdf-sha256`. */
1079
+ algorithm: string;
1080
+ /** Raw public key bytes. */
1081
+ public_key_bytes: number[];
1082
+ /** Attestation report binding this key to the enclave. */
1083
+ attestation: TeeAttestationReport;
1084
+ }
1085
+ /**
1086
+ * Response from a sandbox TEE public-key request.
1087
+ */
1088
+ interface TeePublicKeyResponse {
1089
+ /** Sandbox identifier the public key belongs to. */
1090
+ sandbox_id: string;
1091
+ /** TEE-bound public key and its attestation proof. */
1092
+ public_key: TeePublicKey;
1093
+ }
1094
+ /**
1095
+ * Options for requesting fresh TEE attestation evidence.
1096
+ */
1097
+ interface TeeAttestationOptions {
1098
+ /**
1099
+ * Hex-encoded 32-64 byte caller nonce. When supported by the selected TEE
1100
+ * backend, the runtime binds this to report data so the caller can reject
1101
+ * replayed quotes.
1102
+ */
1103
+ attestationNonce?: string;
1104
+ }
1105
+ /**
1106
+ * Options for listing sandboxes.
1107
+ */
1108
+ interface ListSandboxOptions {
1109
+ /** Filter by status */
1110
+ status?: SandboxStatus | SandboxStatus[];
1111
+ /** Filter personal/team visibility scope */
1112
+ scope?: "personal" | "team" | "all" | `team:${string}`;
1113
+ /** Maximum number of results */
1114
+ limit?: number;
1115
+ /** Offset for pagination */
1116
+ offset?: number;
1117
+ }
1118
+ /**
1119
+ * Result of executing a command.
1120
+ */
1121
+ interface ExecResult {
1122
+ /** Exit code (0 = success) */
1123
+ exitCode: number;
1124
+ /** Standard output */
1125
+ stdout: string;
1126
+ /** Standard error */
1127
+ stderr: string;
1128
+ }
1129
+ /**
1130
+ * Options for executing a command.
1131
+ */
1132
+ interface ExecOptions {
1133
+ /** Working directory for the command. When `sessionId` is set the
1134
+ * runtime remaps well-known absolute sandbox paths to the task's
1135
+ * real workspace; without `sessionId`, absolute paths pass through
1136
+ * verbatim and may not resolve to the task's actual filesystem. */
1137
+ cwd?: string;
1138
+ /** Environment variables */
1139
+ env?: Record<string, string>;
1140
+ /** Timeout in milliseconds */
1141
+ timeoutMs?: number;
1142
+ /** Task session id (e.g. `task-abc123`). When set, the runtime
1143
+ * resolves `cwd` against the session's isolated workspace and
1144
+ * applies a virtual-root remap so a well-known absolute sandbox
1145
+ * path lands in the directory the task actually writes to rather
1146
+ * than the host's literal filesystem. Essential for drivers that
1147
+ * give each task its own workspace subdirectory; no-op for drivers
1148
+ * where the workspace is already the container root. */
1149
+ sessionId?: string;
1150
+ }
1151
+ /**
1152
+ * Options for code search.
1153
+ *
1154
+ * @example Search TypeScript files
1155
+ * ```typescript
1156
+ * const matches = await box.search("TODO", {
1157
+ * glob: "**\/*.ts",
1158
+ * maxResults: 100,
1159
+ * });
1160
+ * ```
1161
+ */
1162
+ interface SearchOptions {
1163
+ /** Glob pattern to filter files (e.g., "**\/*.ts") */
1164
+ glob?: string;
1165
+ /** Directory to search in (default: workspace root) */
1166
+ cwd?: string;
1167
+ /** Maximum number of results */
1168
+ maxResults?: number;
1169
+ /** Case-insensitive search */
1170
+ ignoreCase?: boolean;
1171
+ /** Include line context (lines before/after match) */
1172
+ context?: number;
1173
+ }
1174
+ /**
1175
+ * A single search match from ripgrep.
1176
+ */
1177
+ interface SearchMatch {
1178
+ /** File path relative to search root */
1179
+ path: string;
1180
+ /** Line number (1-indexed) */
1181
+ line: number;
1182
+ /** Column number (1-indexed) */
1183
+ column: number;
1184
+ /** The matching line text */
1185
+ text: string;
1186
+ /** Context lines before the match */
1187
+ before?: string[];
1188
+ /** Context lines after the match */
1189
+ after?: string[];
1190
+ }
1191
+ /**
1192
+ * Git repository status.
1193
+ */
1194
+ interface GitStatus {
1195
+ /** Current branch name */
1196
+ branch: string;
1197
+ /** Commit SHA of HEAD */
1198
+ head: string;
1199
+ /** Whether there are uncommitted changes */
1200
+ isDirty: boolean;
1201
+ /** Number of commits ahead of upstream */
1202
+ ahead: number;
1203
+ /** Number of commits behind upstream */
1204
+ behind: number;
1205
+ /** Staged files */
1206
+ staged: string[];
1207
+ /** Modified but unstaged files */
1208
+ modified: string[];
1209
+ /** Untracked files */
1210
+ untracked: string[];
1211
+ }
1212
+ /**
1213
+ * Git commit information.
1214
+ */
1215
+ interface GitCommit {
1216
+ /** Commit SHA */
1217
+ sha: string;
1218
+ /** Short SHA (7 chars) */
1219
+ shortSha: string;
1220
+ /** Commit message */
1221
+ message: string;
1222
+ /** Author name */
1223
+ author: string;
1224
+ /** Author email */
1225
+ email: string;
1226
+ /** Commit date */
1227
+ date: Date;
1228
+ }
1229
+ /**
1230
+ * Git branch information.
1231
+ */
1232
+ interface GitBranch {
1233
+ /** Branch name */
1234
+ name: string;
1235
+ /** Whether this is the current branch */
1236
+ current: boolean;
1237
+ /** Upstream branch (if tracking) */
1238
+ upstream?: string;
1239
+ /** Latest commit SHA */
1240
+ commit: string;
1241
+ }
1242
+ /**
1243
+ * Git diff information.
1244
+ */
1245
+ interface GitDiff {
1246
+ /** Files changed */
1247
+ files: Array<{
1248
+ path: string;
1249
+ status: "added" | "modified" | "deleted" | "renamed";
1250
+ additions: number;
1251
+ deletions: number;
1252
+ }>;
1253
+ /** Total additions */
1254
+ additions: number;
1255
+ /** Total deletions */
1256
+ deletions: number;
1257
+ /** Raw diff output */
1258
+ raw: string;
1259
+ }
1260
+ /**
1261
+ * Information about an installed tool.
1262
+ */
1263
+ interface InstalledTool {
1264
+ /** Tool name (e.g., "node", "python") */
1265
+ name: string;
1266
+ /** Installed version */
1267
+ version: string;
1268
+ /** Path to the tool binary */
1269
+ path: string;
1270
+ /** Whether this is the active/default version */
1271
+ active: boolean;
1272
+ }
1273
+ /**
1274
+ * Result of an agent prompt.
1275
+ */
1276
+ interface PromptResult {
1277
+ /** Whether the prompt completed successfully */
1278
+ success: boolean;
1279
+ /** Agent's response text */
1280
+ response?: string;
1281
+ /** Error message if failed */
1282
+ error?: string;
1283
+ /** Trace ID for debugging */
1284
+ traceId?: string;
1285
+ /** Duration in milliseconds */
1286
+ durationMs: number;
1287
+ /** Token usage */
1288
+ usage?: {
1289
+ inputTokens: number;
1290
+ outputTokens: number;
1291
+ };
1292
+ }
1293
+ type PromptInputPart = {
1294
+ type: "text";
1295
+ text: string;
1296
+ } | {
1297
+ type: "image";
1298
+ filename?: string;
1299
+ mediaType?: string;
1300
+ url?: string;
1301
+ path?: string;
1302
+ } | {
1303
+ type: "file";
1304
+ filename?: string;
1305
+ mediaType?: string;
1306
+ url?: string;
1307
+ path?: string;
1308
+ content?: string;
1309
+ };
1310
+ /**
1311
+ * Options for sending a prompt.
1312
+ */
1313
+ interface PromptOptions {
1314
+ /** Session ID for conversation continuity */
1315
+ sessionId?: string;
1316
+ /** Model to use (format: provider/model, e.g., anthropic/claude-sonnet-4-20250514) */
1317
+ model?: string;
1318
+ /**
1319
+ * Per-run backend override.
1320
+ *
1321
+ * Use `backend.profile` with a string for a named profile or a provider-neutral
1322
+ * `AgentProfile` object for inline profile configuration.
1323
+ */
1324
+ backend?: Partial<BackendConfig>;
1325
+ /** Timeout in milliseconds */
1326
+ timeoutMs?: number;
1327
+ /** Additional context */
1328
+ context?: Record<string, unknown>;
1329
+ /** AbortSignal for cancellation */
1330
+ signal?: AbortSignal;
1331
+ }
1332
+ /**
1333
+ * SSE event from sandbox streaming.
1334
+ */
1335
+ interface SandboxEvent {
1336
+ /** Event type */
1337
+ type: string;
1338
+ /** Event data */
1339
+ data: Record<string, unknown>;
1340
+ /** Event ID */
1341
+ id?: string;
1342
+ }
1343
+ interface SandboxTraceEvent {
1344
+ type: "sandbox.lifecycle.snapshot" | "sandbox.runtime.snapshot" | "sandbox.usage.snapshot" | "sandbox.insight.summary";
1345
+ timestamp: string;
1346
+ sandboxId: string;
1347
+ durationMs?: number;
1348
+ attributes: Record<string, unknown>;
1349
+ }
1350
+ interface SandboxTraceExport {
1351
+ schemaVersion: "sandbox.trace.v1";
1352
+ traceId: string;
1353
+ sandboxId: string;
1354
+ exportedAt: string;
1355
+ timings: {
1356
+ observedLifecycleMs: number;
1357
+ observedRuntimeMs: number;
1358
+ idleObservedMs: number;
1359
+ };
1360
+ criticalPath: {
1361
+ durationMs: number;
1362
+ phases: Array<{
1363
+ name: string;
1364
+ durationMs: number;
1365
+ }>;
1366
+ };
1367
+ events: SandboxTraceEvent[];
1368
+ }
1369
+ interface SandboxIntelligenceEnvelope {
1370
+ schemaVersion: "sandbox.intelligence.v1";
1371
+ source: "sandbox-api";
1372
+ subject: {
1373
+ type: "sandbox";
1374
+ sandboxId: string;
1375
+ };
1376
+ billing: {
1377
+ billable: false;
1378
+ billedTo: "platform";
1379
+ costUsd: 0;
1380
+ reason: "deterministic_platform_insight";
1381
+ };
1382
+ metrics: Record<string, number>;
1383
+ signals: Array<{
1384
+ name: string;
1385
+ value: string | number | boolean;
1386
+ severity: "info" | "warn" | "critical";
1387
+ rationale: string;
1388
+ }>;
1389
+ recommendedActions: string[];
1390
+ }
1391
+ interface SandboxTraceBundle {
1392
+ trace: SandboxTraceExport;
1393
+ intelligence?: SandboxIntelligenceEnvelope;
1394
+ }
1395
+ interface SandboxTraceOptions {
1396
+ /**
1397
+ * Include the platform-generated intelligence envelope. Defaults to false.
1398
+ * Set true when a customer wants generated insight with the raw trace export.
1399
+ */
1400
+ includeIntelligence?: boolean;
1401
+ }
1402
+ type IntelligenceReportSubjectType = "sandbox" | "fleet" | "dispatch" | "trace_set";
1403
+ interface IntelligenceReport {
1404
+ jobId: string;
1405
+ subject: {
1406
+ type: IntelligenceReportSubjectType;
1407
+ id: string;
1408
+ };
1409
+ mode: "deterministic" | "agentic";
1410
+ status: "queued" | "running" | "completed" | "failed";
1411
+ billing: {
1412
+ billable: boolean;
1413
+ billedTo: "platform" | "customer";
1414
+ costUsd: number;
1415
+ reason: string;
1416
+ budgetMaxUsd?: number;
1417
+ };
1418
+ result: Record<string, unknown> | null;
1419
+ error?: string;
1420
+ createdAt: string;
1421
+ updatedAt: string;
1422
+ completedAt?: string;
1423
+ }
1424
+ interface IntelligenceReportBudget {
1425
+ maxUsd?: number;
1426
+ billTo?: "customer" | "platform";
1427
+ }
1428
+ interface CreateIntelligenceReportOptions {
1429
+ subject: {
1430
+ type: IntelligenceReportSubjectType;
1431
+ id: string;
1432
+ };
1433
+ mode?: "deterministic" | "agentic";
1434
+ acknowledgeCost?: boolean;
1435
+ budget?: IntelligenceReportBudget;
1436
+ metadata?: Record<string, unknown>;
1437
+ }
1438
+ /**
1439
+ * Options for event streaming.
1440
+ */
1441
+ interface EventStreamOptions {
1442
+ /** AbortSignal for cancellation */
1443
+ signal?: AbortSignal;
1444
+ /** Filter to specific event types */
1445
+ eventTypes?: string[];
1446
+ }
1447
+ /**
1448
+ * Provisioning step identifier for progress reporting.
1449
+ */
1450
+ type ProvisionStep = "match" | "networking" | "git" | "host-select" | "storage" | "image-check" | "image-pull" | "image-build" | "container-create" | "container-start" | "health-check" | "runtime-ready" | "workspace";
1451
+ /**
1452
+ * Status of a provisioning step.
1453
+ */
1454
+ type ProvisionStatus = "started" | "progress" | "completed" | "skipped" | "error";
1455
+ /**
1456
+ * Provisioning progress event emitted during sandbox creation.
1457
+ *
1458
+ * Subscribe via `box.watchProvisioning()` or pass `onProgress` to `box.waitFor()`.
1459
+ *
1460
+ * @example
1461
+ * ```typescript
1462
+ * for await (const event of box.watchProvisioning()) {
1463
+ * console.log(`[${event.step}] ${event.status} — ${event.message}`);
1464
+ * if (event.percent !== undefined) {
1465
+ * updateProgressBar(event.percent);
1466
+ * }
1467
+ * }
1468
+ * ```
1469
+ */
1470
+ interface ProvisionEvent {
1471
+ /** The provisioning step (e.g., "image-pull", "container-start") */
1472
+ step: ProvisionStep;
1473
+ /** Status of this step */
1474
+ status: ProvisionStatus;
1475
+ /** Human-readable progress message */
1476
+ message?: string;
1477
+ /** Overall progress percentage (0-100) */
1478
+ percent?: number;
1479
+ /** Additional detail for the step */
1480
+ detail?: Record<string, unknown>;
1481
+ /** ISO timestamp */
1482
+ timestamp: string;
1483
+ }
1484
+ /**
1485
+ * Terminal provisioning event indicating success or failure.
1486
+ */
1487
+ type ProvisionResult = {
1488
+ type: "complete";
1489
+ containerId: string;
1490
+ timestamp: string;
1491
+ } | {
1492
+ type: "failed";
1493
+ error: string;
1494
+ timestamp: string;
1495
+ };
1496
+ /**
1497
+ * Options for `waitFor()`.
1498
+ */
1499
+ interface WaitForOptions {
1500
+ /** Timeout in milliseconds (default: 120000) */
1501
+ timeoutMs?: number;
1502
+ /** Poll interval in milliseconds when SSE is unavailable (default: 2000) */
1503
+ pollIntervalMs?: number;
1504
+ /** AbortSignal for cancellation */
1505
+ signal?: AbortSignal;
1506
+ /**
1507
+ * Callback invoked with real-time provisioning progress events.
1508
+ * When provided and the sandbox is provisioning, `waitFor()` uses SSE
1509
+ * instead of polling for faster, more granular updates.
1510
+ */
1511
+ onProgress?: (event: ProvisionEvent) => void;
1512
+ }
1513
+ /**
1514
+ * Usage information for the account.
1515
+ */
1516
+ interface UsageInfo {
1517
+ /** Total compute minutes used today */
1518
+ computeMinutes: number;
1519
+ /** Number of currently active sandboxes */
1520
+ activeSandboxes: number;
1521
+ /** Total sandboxes created (lifetime) */
1522
+ totalSandboxes: number;
1523
+ /** Period start date (current day UTC) */
1524
+ periodStart: Date;
1525
+ /** Period end date (next day UTC) */
1526
+ periodEnd: Date;
1527
+ }
1528
+ /**
1529
+ * Subscription and billing information for the account.
1530
+ */
1531
+ interface SubscriptionInfo {
1532
+ /** Current plan tier */
1533
+ plan: "free" | "pro" | "enterprise";
1534
+ /** Subscription status */
1535
+ status: "active" | "canceled" | "past_due";
1536
+ /**
1537
+ * Available credit balance in USD.
1538
+ *
1539
+ * **May be negative** for overage-enabled plans (pro/enterprise):
1540
+ * overage charges can push the stored balance below zero. Free-tier
1541
+ * plans floor at 0 at the charge path — free users top up their
1542
+ * prepaid balance via Stripe Checkout (`POST /v1/billing/topup`,
1543
+ * issue #874) when they hit zero rather than going into the red.
1544
+ *
1545
+ * Freshness semantics differ by deployment backend: the
1546
+ * Cloudflare/D1 backend includes real-time projected cost of
1547
+ * currently-running sandboxes; the Node/Redis backend returns the
1548
+ * last-deducted stored balance and reflects running sandboxes only
1549
+ * once their usage is recorded. Consumers should not assume this
1550
+ * value is non-negative — use `>= 0` checks rather than truthiness.
1551
+ */
1552
+ creditsAvailableUsd: number;
1553
+ /** Credits used in USD */
1554
+ creditsUsedUsd: number;
1555
+ /** Monthly included balance in USD */
1556
+ monthlyBalanceUsd: number;
1557
+ /** Max concurrent sandboxes (0 = unlimited) */
1558
+ maxConcurrentSandboxes: number;
1559
+ /** Whether overage billing is allowed */
1560
+ overageAllowed: boolean;
1561
+ /** Resource limits */
1562
+ limits: {
1563
+ maxCpuCores: number;
1564
+ maxRamGB: number;
1565
+ maxStorageGB: number;
1566
+ };
1567
+ /** Current billing period end (epoch ms) */
1568
+ currentPeriodEnd: number;
1569
+ }
1570
+ /**
1571
+ * S3-compatible storage provider configuration (BYOS3 - Bring Your Own S3).
1572
+ *
1573
+ * Allows customers to store snapshots in their own S3-compatible storage.
1574
+ * Supports AWS S3, Google Cloud Storage (GCS), and Cloudflare R2.
1575
+ *
1576
+ * @example AWS S3
1577
+ * ```typescript
1578
+ * const storage: StorageConfig = {
1579
+ * type: "s3",
1580
+ * bucket: "my-snapshots",
1581
+ * region: "us-east-1",
1582
+ * credentials: {
1583
+ * accessKeyId: "AKIA...",
1584
+ * secretAccessKey: "...",
1585
+ * },
1586
+ * };
1587
+ * ```
1588
+ *
1589
+ * @example Cloudflare R2
1590
+ * ```typescript
1591
+ * const storage: StorageConfig = {
1592
+ * type: "r2",
1593
+ * bucket: "my-snapshots",
1594
+ * endpoint: "https://<account>.r2.cloudflarestorage.com",
1595
+ * credentials: {
1596
+ * accessKeyId: "...",
1597
+ * secretAccessKey: "...",
1598
+ * },
1599
+ * };
1600
+ * ```
1601
+ *
1602
+ * @example Google Cloud Storage
1603
+ * ```typescript
1604
+ * const storage: StorageConfig = {
1605
+ * type: "gcs",
1606
+ * bucket: "my-snapshots",
1607
+ * credentials: {
1608
+ * accessKeyId: "...", // HMAC key
1609
+ * secretAccessKey: "...",
1610
+ * },
1611
+ * };
1612
+ * ```
1613
+ */
1614
+ interface StorageConfig {
1615
+ /** Storage provider type */
1616
+ type: "s3" | "gcs" | "r2";
1617
+ /** Bucket name */
1618
+ bucket: string;
1619
+ /** Custom endpoint URL (required for R2, optional for S3/GCS) */
1620
+ endpoint?: string;
1621
+ /** Region (e.g., us-east-1) */
1622
+ region?: string;
1623
+ /** Access credentials */
1624
+ credentials: {
1625
+ accessKeyId: string;
1626
+ secretAccessKey: string;
1627
+ };
1628
+ /** Path prefix within bucket (default: sandbox-snapshots/) */
1629
+ prefix?: string;
1630
+ }
1631
+ /**
1632
+ * Options for running a multi-turn task.
1633
+ */
1634
+ interface TaskOptions extends PromptOptions {
1635
+ /** Maximum number of agent turns (default: 10, 0 = unlimited) */
1636
+ maxTurns?: number;
1637
+ }
1638
+ /**
1639
+ * Result of a multi-turn task execution.
1640
+ */
1641
+ interface TaskResult extends PromptResult {
1642
+ /** Number of agent turns used */
1643
+ turnsUsed: number;
1644
+ /** Session ID for the task (can be used to continue) */
1645
+ sessionId: string;
1646
+ }
1647
+ /**
1648
+ * Lifecycle state of an agent session inside a sandbox.
1649
+ */
1650
+ type SessionStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
1651
+ /**
1652
+ * Snapshot of a session's state at the moment it was queried. Returned
1653
+ * by `box.session(id).status()` and `box.sessions()`.
1654
+ */
1655
+ interface SessionInfo {
1656
+ /** Stable session id assigned by the sandbox runtime. */
1657
+ id: string;
1658
+ /** Current lifecycle state. */
1659
+ status: SessionStatus;
1660
+ /** Backend identifier (e.g. provider name). */
1661
+ backend?: string;
1662
+ /** Model id the session was created with. */
1663
+ model?: string;
1664
+ /** Number of prompts the session has processed. */
1665
+ promptCount?: number;
1666
+ /** When the session was created in the sandbox. */
1667
+ createdAt?: Date;
1668
+ /** When the session began executing. */
1669
+ startedAt?: Date;
1670
+ /** When the session reached a terminal state. */
1671
+ endedAt?: Date;
1672
+ /** Raw payload from the sidecar — stable subset above; this carries
1673
+ * everything else for forward-compatibility. */
1674
+ raw?: Record<string, unknown>;
1675
+ }
1676
+ /**
1677
+ * Options for `box.sessions()` listing.
1678
+ */
1679
+ interface SessionListOptions {
1680
+ /** Filter by status. */
1681
+ status?: SessionStatus;
1682
+ /** Filter by backend identifier. */
1683
+ backend?: string;
1684
+ }
1685
+ /**
1686
+ * Options for `SandboxSession.events()` streaming.
1687
+ */
1688
+ interface SessionEventStreamOptions {
1689
+ /** Replay starting from this event id (inclusive). Omit to start at
1690
+ * the live tail. Useful for reconnect-after-disconnect flows. */
1691
+ since?: string;
1692
+ /** Cancel the stream by aborting this signal. */
1693
+ signal?: AbortSignal;
1694
+ }
1695
+ /**
1696
+ * Options for `box.dispatchPrompt()` — fire-and-detach prompt semantics.
1697
+ */
1698
+ interface DispatchPromptOptions extends PromptOptions {
1699
+ /** Client-supplied session id for idempotency. Re-dispatching with
1700
+ * the same id while the session is running is a lookup, not a
1701
+ * re-create. Lets queue retries and reconnect-after-restart be safe
1702
+ * by construction. */
1703
+ sessionId?: string;
1704
+ }
1705
+ /**
1706
+ * Returned by `box.dispatchPrompt()` — minimum the caller needs to track
1707
+ * the session afterward. The sandbox keeps running the prompt; use
1708
+ * `box.session(sessionId)` to follow it.
1709
+ */
1710
+ interface DispatchedSession {
1711
+ /** Session id (either the one the caller supplied or one the sandbox
1712
+ * minted). */
1713
+ sessionId: string;
1714
+ /** Lifecycle state at the moment dispatch returned. */
1715
+ status: SessionStatus;
1716
+ /** True when an existing session with the supplied id was found and
1717
+ * dispatch was a no-op (idempotency). */
1718
+ alreadyExisted: boolean;
1719
+ }
1720
+ /**
1721
+ * Scope of a `box.mintScopedToken()` request. Each value narrows the
1722
+ * token's authority compared to the full sandbox bearer.
1723
+ */
1724
+ type ScopedTokenScope = "session" | "project" | "read-only";
1725
+ /**
1726
+ * Options for `box.mintScopedToken()`.
1727
+ */
1728
+ interface MintScopedTokenOptions {
1729
+ /** Scope to mint. `session` narrows to a single session id; `project`
1730
+ * grants read access to the whole sandbox; `read-only` is a project
1731
+ * scope without prompt-dispatch capabilities. */
1732
+ scope: ScopedTokenScope;
1733
+ /** Required when `scope === "session"`. */
1734
+ sessionId?: string;
1735
+ /** TTL in minutes. Default 5; clamped to [1, 15]. Browser-side
1736
+ * bearers must be short-lived; pair with `client.onTokenRefresh()`
1737
+ * for long-running consumers. */
1738
+ ttlMinutes?: number;
1739
+ }
1740
+ /**
1741
+ * Returned by `box.mintScopedToken()`. The token verifies against the
1742
+ * same sidecar middleware that already gates ProductTokenIssuer-issued
1743
+ * JWTs — no new sidecar surface.
1744
+ */
1745
+ interface ScopedToken {
1746
+ /** Bearer token (JWT). Send as `Authorization: Bearer <token>` or
1747
+ * via the `EventSource` URL with token query param. */
1748
+ token: string;
1749
+ /** When the token expires. */
1750
+ expiresAt: Date;
1751
+ /** Echo of the requested scope. */
1752
+ scope: ScopedTokenScope;
1753
+ }
1754
+ /**
1755
+ * Callback invoked when the SDK refreshes a sandbox bearer transparently
1756
+ * (e.g. after a 401 retry against the runtime endpoint). Lets long-
1757
+ * running consumers propagate the new token to dependents (live
1758
+ * `EventSource` connections, browser-side caches, etc.).
1759
+ */
1760
+ type TokenRefreshHandler = (sandboxId: string, newToken: string) => void;
1761
+ /**
1762
+ * Options for creating a snapshot.
1763
+ */
1764
+ interface SnapshotOptions {
1765
+ /** Tags to apply to the snapshot */
1766
+ tags?: string[];
1767
+ /** Specific paths to include (default: entire workspace) */
1768
+ paths?: string[];
1769
+ /** Customer-provided storage for BYOS3 (calls the runtime directly) */
1770
+ storage?: StorageConfig;
1771
+ }
1772
+ /**
1773
+ * Result of a snapshot operation.
1774
+ */
1775
+ interface SnapshotResult {
1776
+ /** Unique snapshot identifier */
1777
+ snapshotId: string;
1778
+ /** When the snapshot was created */
1779
+ createdAt: Date;
1780
+ /** Size in bytes */
1781
+ sizeBytes?: number;
1782
+ /** Tags applied to the snapshot */
1783
+ tags: string[];
1784
+ }
1785
+ interface RestoreSnapshotOptions {
1786
+ destinationPath?: string;
1787
+ snapshotId?: string;
1788
+ }
1789
+ /**
1790
+ * Metadata about an existing snapshot.
1791
+ */
1792
+ interface SnapshotInfo {
1793
+ /** Unique snapshot identifier */
1794
+ snapshotId: string;
1795
+ /** Sandbox this snapshot belongs to */
1796
+ sandboxId: string;
1797
+ /** When the snapshot was created */
1798
+ createdAt: Date;
1799
+ /** Tags applied to the snapshot */
1800
+ tags: string[];
1801
+ /** Paths included in the snapshot */
1802
+ paths: string[];
1803
+ /** Size in bytes */
1804
+ sizeBytes?: number;
1805
+ }
1806
+ /**
1807
+ * A single task in a batch execution.
1808
+ */
1809
+ interface BatchTask {
1810
+ /** Unique task identifier */
1811
+ id: string;
1812
+ /** Task prompt/message */
1813
+ message: string;
1814
+ /** Additional context for this task */
1815
+ context?: Record<string, unknown>;
1816
+ /** Per-task timeout in milliseconds */
1817
+ timeoutMs?: number;
1818
+ }
1819
+ /**
1820
+ * Options for batch execution.
1821
+ */
1822
+ interface BatchOptions {
1823
+ /** Timeout for entire batch in milliseconds (default: 300000 = 5 min) */
1824
+ timeoutMs?: number;
1825
+ /** Scaling mode: fastest, balanced, or cheapest (default: balanced) */
1826
+ scalingMode?: "fastest" | "balanced" | "cheapest";
1827
+ /**
1828
+ * Shared backend override for the batch.
1829
+ *
1830
+ * Use `backend.profile` with a string for a named profile or a provider-neutral
1831
+ * `AgentProfile` object for inline profile configuration.
1832
+ */
1833
+ backend?: Partial<BackendConfig>;
1834
+ /** Keep sandboxes alive after completion (default: false) */
1835
+ persistent?: boolean;
1836
+ /** Milliseconds to keep non-persistent batch sandboxes alive after completion. */
1837
+ graceMs?: number;
1838
+ /**
1839
+ * AbortSignal to cancel the batch mid-stream. When aborted, the HTTP
1840
+ * request to `/batch/run` is torn down; the SSE generator stops
1841
+ * yielding and `runBatch`/`streamBatch` reject with an `AbortError`.
1842
+ *
1843
+ * Note: the server-side batch may continue running to completion —
1844
+ * the signal is strictly for disconnecting the client from the
1845
+ * stream, not for halting server work.
1846
+ */
1847
+ signal?: AbortSignal;
1848
+ }
1849
+ /**
1850
+ * Result of a single task in a batch.
1851
+ */
1852
+ interface BatchTaskResult {
1853
+ /** Task identifier */
1854
+ taskId: string;
1855
+ /** Whether the task succeeded */
1856
+ success: boolean;
1857
+ /** Task response if successful */
1858
+ response?: string;
1859
+ /** Error message if failed */
1860
+ error?: string;
1861
+ /** Duration in milliseconds */
1862
+ durationMs: number;
1863
+ /** Number of retries */
1864
+ retries: number;
1865
+ /** Token usage if available */
1866
+ tokensUsed?: number;
1867
+ }
1868
+ /**
1869
+ * Summary of batch execution.
1870
+ */
1871
+ interface BatchResult {
1872
+ /** Total tasks executed */
1873
+ totalTasks: number;
1874
+ /** Number of successful tasks */
1875
+ succeeded: number;
1876
+ /** Number of failed tasks */
1877
+ failed: number;
1878
+ /** Total retries across all tasks */
1879
+ totalRetries: number;
1880
+ /** Success rate (0-100) */
1881
+ successRate: number;
1882
+ /** Individual task results */
1883
+ results: BatchTaskResult[];
1884
+ }
1885
+ /**
1886
+ * SSE event from batch streaming.
1887
+ */
1888
+ interface BatchEvent {
1889
+ /** Event type (batch.started, task.completed, etc.) */
1890
+ type: string;
1891
+ /** Event data */
1892
+ data: Record<string, unknown>;
1893
+ /**
1894
+ * Optional `id:` from the SSE frame. Present at runtime whenever
1895
+ * the server emits an `id:` line (used by EventSource-style
1896
+ * reconnection). Declared optional because the batch protocol
1897
+ * doesn't currently emit it — downstream consumers that want to
1898
+ * implement resume should feature-detect.
1899
+ */
1900
+ id?: string;
1901
+ }
1902
+ /**
1903
+ * Stable worker identifier inside a sandbox fleet.
1904
+ *
1905
+ * Machine IDs are intentionally narrower than sandbox names so agents
1906
+ * can route work without smuggling shell metacharacters or path-like
1907
+ * values through tool calls.
1908
+ */
1909
+ type FleetMachineId = string;
1910
+ type SandboxFleetMachineRole = "coordinator" | "worker";
1911
+ /**
1912
+ * Resource policy for a single fleet create call.
1913
+ *
1914
+ * These caps are enforced client-side before any sandbox is created.
1915
+ * Server-side plan quotas still apply and remain the source of truth.
1916
+ */
1917
+ interface SandboxFleetPolicy {
1918
+ /** Maximum number of machines in this create call. Defaults to machines.length. */
1919
+ maxMachines?: number;
1920
+ /** Maximum sandbox create fanout allowed for this fleet request. */
1921
+ maxConcurrentCreates?: number;
1922
+ /** Maximum total requested CPU cores across machines with explicit resources. */
1923
+ maxTotalCpu?: number;
1924
+ /** Maximum total requested memory across machines with explicit resources. */
1925
+ maxTotalMemoryMb?: number;
1926
+ /** Maximum total requested storage across machines with explicit resources. */
1927
+ maxTotalStorageMb?: number;
1928
+ /** Maximum total requested accelerator devices across machines. */
1929
+ maxTotalAccelerators?: number;
1930
+ /** Maximum lifetime in seconds for any machine in this fleet. */
1931
+ maxLifetimeSeconds?: number;
1932
+ /** Maximum estimated USD spend for the fleet's configured lifetime. */
1933
+ maxSpendUsd?: number;
1934
+ /** Allowed infrastructure drivers for fleet machines. */
1935
+ allowedDrivers?: DriverType[];
1936
+ /** Allowed images/environments for fleet machines. */
1937
+ allowedImages?: string[];
1938
+ /** Allowed personal or public template identifiers for fleet machines. */
1939
+ allowedTemplateIds?: string[];
1940
+ /** Whether machines may request accelerator devices. Defaults to allowed. */
1941
+ allowAccelerators?: boolean;
1942
+ }
1943
+ interface SandboxFleetWorkspace {
1944
+ mode: "isolated" | "shared";
1945
+ id?: string;
1946
+ quotaMb?: number;
1947
+ mountPath?: string;
1948
+ snapshotId?: string;
1949
+ }
1950
+ /**
1951
+ * Per-machine create spec for a sandbox fleet.
1952
+ */
1953
+ interface SandboxFleetMachineSpec extends Omit<CreateSandboxOptions, "metadata" | "name"> {
1954
+ /** Stable agent-facing machine id, e.g. "coordinator" or "worker-1". */
1955
+ machineId: FleetMachineId;
1956
+ /** Optional display name. Defaults to `${fleetId}-${machineId}`. */
1957
+ name?: string;
1958
+ /** Machine-specific metadata. Fleet tags are added automatically. */
1959
+ metadata?: Record<string, unknown>;
1960
+ /** Optional orchestration role. Defaults to worker. */
1961
+ role?: SandboxFleetMachineRole;
1962
+ }
1963
+ /**
1964
+ * Create a named set of sandboxes for one workload.
1965
+ */
1966
+ interface CreateSandboxFleetOptions {
1967
+ /** Stable fleet id. Generated when omitted. */
1968
+ fleetId?: string;
1969
+ /** Shared defaults applied to every machine before per-machine overrides. */
1970
+ defaults?: Omit<CreateSandboxOptions, "metadata" | "name">;
1971
+ /** Machines to create. */
1972
+ machines: SandboxFleetMachineSpec[];
1973
+ /** Fleet-level metadata copied to each sandbox under stable tags. */
1974
+ metadata?: Record<string, unknown>;
1975
+ /** Workspace policy for isolated or driver-supported shared mounts. */
1976
+ workspace?: SandboxFleetWorkspace;
1977
+ /**
1978
+ * Client-side safety caps for this create call. These do not replace
1979
+ * server-side quota enforcement.
1980
+ */
1981
+ policy?: SandboxFleetPolicy;
1982
+ /**
1983
+ * Delete already-created machines if a later machine fails to create.
1984
+ * Defaults to true so partial fleets do not silently burn quota.
1985
+ */
1986
+ cleanupOnFailure?: boolean;
1987
+ /**
1988
+ * Maximum concurrent sandbox creates for this fleet request.
1989
+ * Defaults to 4 to avoid accidental control-plane stampedes while still
1990
+ * provisioning worker fleets faster than serial creation.
1991
+ */
1992
+ maxConcurrentCreates?: number;
1993
+ /**
1994
+ * Idempotency key for the server-backed fleet record. Defaults to fleetId.
1995
+ */
1996
+ idempotencyKey?: string;
1997
+ }
1998
+ interface CreateSandboxFleetWithCoordinatorOptions extends Omit<CreateSandboxFleetOptions, "machines"> {
1999
+ /** Coordinator machine. Defaults to machineId "coordinator". */
2000
+ coordinator?: Omit<SandboxFleetMachineSpec, "machineId" | "role"> & {
2001
+ machineId?: FleetMachineId;
2002
+ };
2003
+ /** Worker machines attached to the same fleet. */
2004
+ workers: SandboxFleetMachineSpec[];
2005
+ }
2006
+ /**
2007
+ * A sandbox with its fleet-local machine id.
2008
+ */
2009
+ interface SandboxFleetMachine {
2010
+ machineId: FleetMachineId;
2011
+ sandbox: SandboxInfo;
2012
+ role?: SandboxFleetMachineRole;
2013
+ }
2014
+ /**
2015
+ * Fleet create/list result.
2016
+ */
2017
+ interface SandboxFleetInfo {
2018
+ fleetId: string;
2019
+ machines: SandboxFleetMachine[];
2020
+ }
2021
+ interface FleetExecDispatchOptions extends Pick<ExecOptions, "cwd" | "env" | "timeoutMs"> {
2022
+ machines?: FleetMachineId[];
2023
+ maxConcurrent?: number;
2024
+ retry?: {
2025
+ attempts?: number;
2026
+ };
2027
+ /** Caller-supplied dispatch id for idempotency/result lookup when supported by the API. */
2028
+ dispatchId?: string;
2029
+ /** Ask the API to retain branch results for later `dispatchResults` calls. */
2030
+ bufferResults?: boolean;
2031
+ }
2032
+ interface FleetExecDispatchResult {
2033
+ machineId: FleetMachineId;
2034
+ sandboxId: string;
2035
+ ok: boolean;
2036
+ durationMs: number;
2037
+ attempts?: number;
2038
+ result?: ExecResult;
2039
+ error?: {
2040
+ message: string;
2041
+ status?: number;
2042
+ failureClass?: SandboxFleetDispatchFailureClass;
2043
+ };
2044
+ }
2045
+ interface FleetPromptDispatchOptions extends Pick<PromptOptions, "sessionId" | "model" | "backend" | "timeoutMs" | "context"> {
2046
+ machines?: FleetMachineId[];
2047
+ maxConcurrent?: number;
2048
+ retry?: {
2049
+ attempts?: number;
2050
+ };
2051
+ /** Caller-supplied dispatch id for idempotency/result lookup when supported by the API. */
2052
+ dispatchId?: string;
2053
+ /** Ask the API to retain branch results for later `dispatchResults` calls. */
2054
+ bufferResults?: boolean;
2055
+ }
2056
+ interface FleetPromptDispatchResult {
2057
+ machineId: FleetMachineId;
2058
+ sandboxId: string;
2059
+ ok: boolean;
2060
+ durationMs: number;
2061
+ attempts?: number;
2062
+ prompt?: PromptResult & {
2063
+ metadata?: Record<string, unknown>;
2064
+ };
2065
+ error?: {
2066
+ message: string;
2067
+ status?: number;
2068
+ failureClass?: SandboxFleetDispatchFailureClass;
2069
+ };
2070
+ }
2071
+ type SandboxFleetDispatchFailureClass = "oom" | "timeout" | "dependency" | "infra" | "model" | "user_code";
2072
+ interface FleetDispatchStreamOptions {
2073
+ signal?: AbortSignal;
2074
+ }
2075
+ interface FleetDispatchResultBufferOptions {
2076
+ cursor?: string;
2077
+ limit?: number;
2078
+ machines?: FleetMachineId[];
2079
+ }
2080
+ interface FleetDispatchResultBuffer<T = FleetExecDispatchResult | FleetPromptDispatchResult> {
2081
+ fleetId: string;
2082
+ dispatchId: string;
2083
+ results: T[];
2084
+ cursor?: string;
2085
+ nextCursor?: string;
2086
+ done?: boolean;
2087
+ truncated?: boolean;
2088
+ trace?: SandboxFleetTraceExport;
2089
+ intelligence?: SandboxFleetIntelligenceEnvelope;
2090
+ }
2091
+ interface FleetDispatchCancelResult {
2092
+ fleetId: string;
2093
+ dispatchId: string;
2094
+ cancelled: boolean;
2095
+ status?: string;
2096
+ }
2097
+ interface SandboxFleetArtifactSpec {
2098
+ machineId: FleetMachineId;
2099
+ /**
2100
+ * Absolute path under /workspace. Fleet artifact collection intentionally
2101
+ * rejects host/system paths so caller-provided manifests cannot turn artifact
2102
+ * collection into arbitrary sandbox file reads.
2103
+ */
2104
+ path: string;
2105
+ label?: string;
2106
+ /** Maximum allowed artifact content size in bytes. Defaults to 5 MiB. */
2107
+ maxBytes?: number;
2108
+ }
2109
+ interface SandboxFleetArtifact extends SandboxFleetArtifactSpec {
2110
+ sandboxId: string;
2111
+ content: string;
2112
+ }
2113
+ interface SandboxFleetDriverTimings {
2114
+ queueMs?: number;
2115
+ placementMs?: number;
2116
+ provisionMs?: number;
2117
+ startupMs?: number;
2118
+ cleanupMs?: number;
2119
+ }
2120
+ interface SandboxFleetMachineMeteredUsage {
2121
+ runtimeMs: number;
2122
+ updatedAt: string;
2123
+ }
2124
+ interface AttachSandboxFleetMachineOptions {
2125
+ machineId: FleetMachineId;
2126
+ sandboxId: string;
2127
+ status?: string;
2128
+ role?: SandboxFleetMachineRole;
2129
+ driverType?: DriverType;
2130
+ image?: string;
2131
+ environment?: string;
2132
+ templateId?: string;
2133
+ publicTemplateId?: string;
2134
+ acceleratorCount?: number;
2135
+ driverTimings?: SandboxFleetDriverTimings;
2136
+ }
2137
+ interface SandboxFleetMachineRecord extends AttachSandboxFleetMachineOptions {
2138
+ workspaceMountPath?: string;
2139
+ meteredUsage?: SandboxFleetMachineMeteredUsage;
2140
+ createdAt?: string;
2141
+ updatedAt?: string;
2142
+ }
2143
+ interface SandboxFleetManifestMachine {
2144
+ machineId: FleetMachineId;
2145
+ sandboxId: string;
2146
+ role?: SandboxFleetMachineRole;
2147
+ status?: string;
2148
+ driverType?: DriverType;
2149
+ image?: string;
2150
+ environment?: string;
2151
+ templateId?: string;
2152
+ publicTemplateId?: string;
2153
+ acceleratorCount?: number;
2154
+ workspaceMountPath?: string;
2155
+ driverTimings?: SandboxFleetDriverTimings;
2156
+ meteredUsage?: SandboxFleetMachineMeteredUsage;
2157
+ createdAt?: string;
2158
+ updatedAt?: string;
2159
+ }
2160
+ interface SandboxFleetManifest {
2161
+ fleetId?: string;
2162
+ id?: string;
2163
+ metadata?: Record<string, unknown>;
2164
+ policy?: SandboxFleetPolicy;
2165
+ resources?: Record<string, unknown>;
2166
+ workspace?: SandboxFleetWorkspace & {
2167
+ status?: string;
2168
+ createdAt?: string;
2169
+ updatedAt?: string;
2170
+ deletedAt?: string;
2171
+ };
2172
+ machines: SandboxFleetManifestMachine[];
2173
+ createdAt?: string;
2174
+ updatedAt?: string;
2175
+ }
2176
+ interface SandboxFleetDispatchResponse<T = FleetExecDispatchResult | FleetPromptDispatchResult> {
2177
+ fleetId: string;
2178
+ dispatchId: string;
2179
+ type: "exec" | "prompt";
2180
+ results: T[];
2181
+ durationMs: number;
2182
+ trace?: SandboxFleetTraceExport;
2183
+ intelligence?: SandboxFleetIntelligenceEnvelope;
2184
+ }
2185
+ interface SandboxFleetWorkspaceSnapshotResult {
2186
+ snapshotId?: string;
2187
+ id?: string;
2188
+ status?: string;
2189
+ createdAt?: string;
2190
+ [key: string]: JsonValue | undefined;
2191
+ }
2192
+ interface SandboxFleetWorkspaceRestoreResult {
2193
+ restored?: boolean;
2194
+ snapshotId?: string;
2195
+ status?: string;
2196
+ [key: string]: JsonValue | undefined;
2197
+ }
2198
+ interface SandboxFleetWorkspaceReconcileResult {
2199
+ fleetId: string;
2200
+ workspaceId?: string;
2201
+ checked: number;
2202
+ orphanedMounts: number;
2203
+ machines: Array<{
2204
+ machineId: string;
2205
+ sandboxId: string;
2206
+ mounted: boolean;
2207
+ }>;
2208
+ }
2209
+ interface SandboxFleetDriverCapability {
2210
+ driverType: DriverType;
2211
+ sharedWorkspace: boolean;
2212
+ accelerators: boolean;
2213
+ queueTimings: boolean;
2214
+ }
2215
+ interface SandboxFleetOperationsSummary {
2216
+ capacity: {
2217
+ fleets: number;
2218
+ machines: number;
2219
+ runningMachines: number;
2220
+ failedMachines: number;
2221
+ requestedCpu: number;
2222
+ requestedMemoryMb: number;
2223
+ requestedStorageMb: number;
2224
+ requestedAccelerators: number;
2225
+ };
2226
+ alerts: Array<{
2227
+ name: string;
2228
+ severity: "info" | "warn" | "critical";
2229
+ fleetId?: string;
2230
+ machineId?: string;
2231
+ message: string;
2232
+ runbook: string[];
2233
+ }>;
2234
+ }
2235
+ interface ReconcileSandboxFleetsOptions {
2236
+ dryRun?: boolean;
2237
+ }
2238
+ interface ReconcileSandboxFleetsResult {
2239
+ dryRun: boolean;
2240
+ checked: number;
2241
+ orphaned: number;
2242
+ removed: number;
2243
+ machines: Array<{
2244
+ fleetId: string;
2245
+ machineId: string;
2246
+ sandboxId: string;
2247
+ removed: boolean;
2248
+ status?: number;
2249
+ error?: string;
2250
+ }>;
2251
+ }
2252
+ interface SandboxFleetUsage {
2253
+ usage: {
2254
+ fleetId: string;
2255
+ status: string;
2256
+ machineCount: number;
2257
+ coordinatorCount: number;
2258
+ workerCount: number;
2259
+ runningMachines: number;
2260
+ failedMachines: number;
2261
+ resources?: {
2262
+ machines: number;
2263
+ totalCpu: number;
2264
+ totalMemoryMb: number;
2265
+ totalStorageMb: number;
2266
+ totalAccelerators: number;
2267
+ maxLifetimeSeconds?: number;
2268
+ };
2269
+ meteredUsage?: {
2270
+ runtimeMs: number;
2271
+ machineRuntimeMs: Record<string, number>;
2272
+ updatedAt: string;
2273
+ };
2274
+ createdAt: string;
2275
+ updatedAt: string;
2276
+ };
2277
+ insights: {
2278
+ reliabilityScore: number;
2279
+ parallelismEfficiencyScore: number;
2280
+ failureRate: number;
2281
+ recommendedActions: string[];
2282
+ };
2283
+ trace: SandboxFleetTraceExport;
2284
+ intelligence: SandboxFleetIntelligenceEnvelope;
2285
+ }
2286
+ interface SandboxFleetTraceEvent {
2287
+ type: "fleet.lifecycle.snapshot" | "fleet.machine.lifecycle.snapshot" | "fleet.workspace.lifecycle.snapshot" | "fleet.usage.snapshot" | "fleet.dispatch.result" | "fleet.insight.summary";
2288
+ timestamp: string;
2289
+ fleetId: string;
2290
+ machineId?: string;
2291
+ durationMs?: number;
2292
+ attributes: Record<string, unknown>;
2293
+ }
2294
+ interface SandboxFleetTraceExport {
2295
+ schemaVersion: "fleet.trace.v1";
2296
+ traceId: string;
2297
+ fleetId: string;
2298
+ exportedAt: string;
2299
+ timings: {
2300
+ observedLifecycleMs: number;
2301
+ machineObservedLifecycleMs: number;
2302
+ dispatchFanoutMs: number;
2303
+ dispatchRuntimeMs: number;
2304
+ cleanupObservedMs: number;
2305
+ driverQueueMs: number;
2306
+ driverPlacementMs: number;
2307
+ driverProvisionMs: number;
2308
+ driverStartupMs: number;
2309
+ driverCleanupMs: number;
2310
+ };
2311
+ criticalPath: {
2312
+ durationMs: number;
2313
+ phases: Array<{
2314
+ name: string;
2315
+ durationMs: number;
2316
+ machineId?: string;
2317
+ }>;
2318
+ };
2319
+ events: SandboxFleetTraceEvent[];
2320
+ }
2321
+ interface SandboxFleetIntelligenceEnvelope {
2322
+ schemaVersion: "fleet.intelligence.v1";
2323
+ source: "sandbox-api";
2324
+ subject: {
2325
+ type: "sandbox_fleet";
2326
+ fleetId: string;
2327
+ };
2328
+ billing: {
2329
+ billable: false;
2330
+ billedTo: "platform";
2331
+ costUsd: 0;
2332
+ reason: "deterministic_platform_insight";
2333
+ };
2334
+ metrics: Record<string, number>;
2335
+ signals: Array<{
2336
+ name: string;
2337
+ value: string | number | boolean;
2338
+ severity: "info" | "warn" | "critical";
2339
+ rationale: string;
2340
+ }>;
2341
+ recommendedActions: string[];
2342
+ }
2343
+ interface SandboxFleetTraceBundle {
2344
+ trace: SandboxFleetTraceExport;
2345
+ intelligence?: SandboxFleetIntelligenceEnvelope;
2346
+ }
2347
+ interface SandboxFleetTraceOptions {
2348
+ /**
2349
+ * Include the platform-generated intelligence envelope. Defaults to false.
2350
+ * Set true when a customer wants generated insight with the raw trace export.
2351
+ */
2352
+ includeIntelligence?: boolean;
2353
+ }
2354
+ interface SandboxFleetCostEstimate {
2355
+ plan: "free" | "pro" | "enterprise";
2356
+ currency: "USD";
2357
+ hourlyUsd: number;
2358
+ maxLifetimeSeconds: number;
2359
+ estimatedMaxLifetimeUsd: number;
2360
+ requestedResources: {
2361
+ machines: number;
2362
+ totalCpu: number;
2363
+ totalMemoryMb: number;
2364
+ totalStorageMb: number;
2365
+ totalAccelerators: number;
2366
+ maxLifetimeSeconds?: number;
2367
+ };
2368
+ rates: {
2369
+ cpuPerHr: number;
2370
+ ramPerGbHr: number;
2371
+ diskPerGbHr: number;
2372
+ acceleratorPerDeviceHr: number;
2373
+ minChargePerHr: number;
2374
+ entDiscount: number;
2375
+ };
2376
+ }
2377
+ type SandboxFleetTokenAction = "list" | "create" | "delete" | "exec" | "prompt" | "read" | "write";
2378
+ interface CreateSandboxFleetTokenOptions {
2379
+ /** Allowed fleet actions. Defaults to read/list/exec. */
2380
+ actions?: SandboxFleetTokenAction[];
2381
+ /** Optional token-side policy caps enforced by the Sandbox API. */
2382
+ policy?: SandboxFleetPolicy;
2383
+ /** Token lifetime in minutes. API clamps to its server-side maximum. */
2384
+ ttlMinutes?: number;
2385
+ }
2386
+ interface SandboxFleetToken {
2387
+ token: string;
2388
+ expiresAt: number;
2389
+ fleetId: string;
2390
+ actions: SandboxFleetTokenAction[];
2391
+ policy?: SandboxFleetPolicy;
2392
+ }
2393
+ interface ReapExpiredSandboxFleetsOptions {
2394
+ dryRun?: boolean;
2395
+ }
2396
+ interface ReapExpiredSandboxFleetsResult {
2397
+ dryRun: boolean;
2398
+ expired: number;
2399
+ deleted: number;
2400
+ fleets: Array<{
2401
+ fleetId: string;
2402
+ expiredAt: string;
2403
+ deleted: boolean;
2404
+ machines: Array<{
2405
+ machineId: string;
2406
+ sandboxId: string;
2407
+ ok: boolean;
2408
+ status?: number;
2409
+ error?: string;
2410
+ }>;
2411
+ }>;
2412
+ }
2413
+ /**
2414
+ * Options for listing fleet machines.
2415
+ */
2416
+ interface ListSandboxFleetOptions extends ListSandboxOptions {
2417
+ /** Fleet id to filter by. */
2418
+ fleetId: string;
2419
+ }
2420
+ /**
2421
+ * Options for creating a checkpoint.
2422
+ */
2423
+ interface CheckpointOptions {
2424
+ /** Tags to apply to the checkpoint */
2425
+ tags?: string[];
2426
+ /** Keep sandbox running after checkpoint (default: false - sandbox stops) */
2427
+ leaveRunning?: boolean;
2428
+ /** Also create a filesystem snapshot for data consistency */
2429
+ includeSnapshot?: boolean;
2430
+ }
2431
+ /**
2432
+ * Result of a checkpoint operation.
2433
+ */
2434
+ interface CheckpointResult {
2435
+ /** Unique checkpoint identifier */
2436
+ checkpointId: string;
2437
+ /** When the checkpoint was created */
2438
+ createdAt: Date;
2439
+ /** Size of checkpoint in bytes (memory state) */
2440
+ sizeBytes?: number;
2441
+ /** Tags applied to the checkpoint */
2442
+ tags: string[];
2443
+ }
2444
+ /**
2445
+ * Information about an existing checkpoint.
2446
+ */
2447
+ interface CheckpointInfo {
2448
+ /** Unique checkpoint identifier */
2449
+ checkpointId: string;
2450
+ /** Sandbox this checkpoint belongs to */
2451
+ sandboxId: string;
2452
+ /** When the checkpoint was created */
2453
+ createdAt: Date;
2454
+ /** Tags applied to the checkpoint */
2455
+ tags: string[];
2456
+ /** Size of checkpoint in bytes */
2457
+ sizeBytes?: number;
2458
+ /** Whether checkpoint includes memory state */
2459
+ hasMemoryState: boolean;
2460
+ /** Whether checkpoint includes filesystem snapshot */
2461
+ hasFilesystemSnapshot: boolean;
2462
+ }
2463
+ /**
2464
+ * Options for forking a sandbox from a checkpoint.
2465
+ */
2466
+ interface ForkOptions {
2467
+ /** Name for the forked sandbox */
2468
+ name?: string;
2469
+ /** Override environment variables in the fork */
2470
+ env?: Record<string, string>;
2471
+ /** Override resource limits in the fork */
2472
+ resources?: SandboxResources;
2473
+ /** Custom metadata for the fork */
2474
+ metadata?: Record<string, unknown>;
2475
+ }
2476
+ /**
2477
+ * Result of a fork operation.
2478
+ */
2479
+ interface ForkResult {
2480
+ /** The newly created sandbox instance */
2481
+ sandbox: SandboxInfo;
2482
+ /** The checkpoint that was forked from */
2483
+ sourceCheckpoint: CheckpointInfo;
2484
+ /** ID of the source sandbox */
2485
+ sourceId: string;
2486
+ /** Time taken to fork in milliseconds */
2487
+ forkTimeMs: number;
2488
+ }
2489
+ /**
2490
+ * Infrastructure driver identifier.
2491
+ *
2492
+ * Most callers should omit `driver` and let the platform select automatically.
2493
+ */
2494
+ type DriverType = "docker" | "firecracker" | "host-agent" | "tangle";
2495
+ /**
2496
+ * Accelerator class for GPU-class workloads.
2497
+ *
2498
+ * Examples: `nvidia-h100`, `nvidia-l4`, `nvidia-rtx-4090`, `amd-mi300x`.
2499
+ * Providers can introduce new SKU labels without requiring an SDK release.
2500
+ */
2501
+ type AcceleratorKind = string;
2502
+ /**
2503
+ * Compute accelerator request.
2504
+ *
2505
+ * Accelerators are requested as resources because they are part of workload
2506
+ * shape and billing, not a driver option.
2507
+ */
2508
+ interface SandboxAccelerator {
2509
+ /** Accelerator class required by the workload. */
2510
+ kind: AcceleratorKind;
2511
+ /**
2512
+ * Number of accelerator devices required.
2513
+ * @default 1
2514
+ */
2515
+ count?: number;
2516
+ /** Minimum device memory in megabytes when the exact GPU class is flexible. */
2517
+ memoryMB?: number;
2518
+ }
2519
+ /**
2520
+ * Infrastructure driver configuration.
2521
+ *
2522
+ * @example Default
2523
+ * ```typescript
2524
+ * driver: { type: "docker" }
2525
+ * ```
2526
+ *
2527
+ * @example With pause/resume support
2528
+ * ```typescript
2529
+ * driver: { type: "firecracker", enableCriu: true }
2530
+ * ```
2531
+ *
2532
+ * @example Accelerator-backed sandbox
2533
+ * ```typescript
2534
+ * resources: {
2535
+ * accelerator: { kind: "nvidia-a100", count: 1 },
2536
+ * }
2537
+ * ```
2538
+ */
2539
+ interface DriverConfig {
2540
+ /**
2541
+ * Driver type identifier.
2542
+ * @default "docker"
2543
+ */
2544
+ type: DriverType;
2545
+ /**
2546
+ * Enable checkpointing for pause/resume and fork operations.
2547
+ * Support depends on the selected driver.
2548
+ */
2549
+ enableCriu?: boolean;
2550
+ /**
2551
+ * Preferred placement region.
2552
+ * e.g., "us-east-1", "eu-west-1".
2553
+ */
2554
+ preferredRegion?: string;
2555
+ /**
2556
+ * @deprecated Use `resources.accelerator` on sandbox or fleet machine specs.
2557
+ */
2558
+ gpuRequired?: boolean;
2559
+ /**
2560
+ * @deprecated Use `resources.accelerator.kind`.
2561
+ */
2562
+ gpuType?: GpuType;
2563
+ /**
2564
+ * @deprecated Use `resources.accelerator.count`.
2565
+ */
2566
+ gpuCount?: number;
2567
+ }
2568
+ /**
2569
+ * Driver capabilities and status.
2570
+ */
2571
+ interface DriverInfo {
2572
+ /** Driver type */
2573
+ type: DriverType;
2574
+ /** Whether driver is available */
2575
+ available: boolean;
2576
+ /** Driver version string */
2577
+ version: string;
2578
+ /** Driver capabilities */
2579
+ capabilities: {
2580
+ /** Checkpoint/restore support */criu: boolean; /** GPU support */
2581
+ gpu: boolean; /** Filesystem snapshots */
2582
+ snapshots: boolean; /** Multi-user management */
2583
+ userManagement: boolean; /** Network isolation */
2584
+ networkIsolation: boolean;
2585
+ };
2586
+ /** Current capacity */
2587
+ capacity?: {
2588
+ available: number;
2589
+ total: number;
2590
+ };
2591
+ acceleratorCapacity?: {
2592
+ available: number;
2593
+ total: number;
2594
+ kinds: AcceleratorKind[];
2595
+ };
2596
+ }
2597
+ /**
2598
+ * Backend type identifier. Controls which AI agent runtime runs inside the sandbox.
2599
+ *
2600
+ * The public-SDK source of truth. Kept in lock-step with the private
2601
+ * `@tangle-network/cli-agent-registry` spec list via the parity check in
2602
+ * `packages/cli-agent-registry/tests/specs.test.ts` (adding a new CLI spec
2603
+ * without updating this union surfaces as a test failure at PR review
2604
+ * time). Inlined here so the published SDK doesn't carry an unpublished
2605
+ * internal package as a runtime dep.
2606
+ *
2607
+ * - `"opencode"` — Default. Multi-provider, profile system, MCP support.
2608
+ * - `"claude-code"` — Anthropic Claude Code CLI. Requires an Anthropic API key.
2609
+ * - `"kimi-code"` — Moonshot Kimi Code CLI. Uses the operator's Kimi Code
2610
+ * subscription OAuth (shipped via authFiles) by default; falls back to
2611
+ * `MOONSHOT_API_KEY` when an apiKey is supplied.
2612
+ * - `"codex"` — OpenAI Codex CLI. Requires an OpenAI API key.
2613
+ * - `"amp"` — Sourcegraph AMP agent.
2614
+ * - `"factory-droids"` — Factory Droid agent.
2615
+ * - `"pi"` — Pi coding-agent CLI.
2616
+ * - `"hermes"` — Hermes inference-router agent.
2617
+ * - `"forge"` — Forge (forgecode.dev, tailcallhq) multi-provider coding agent.
2618
+ * - `"openclaw"` — OpenClaw dispatcher that routes to claude-cli/codex-cli/gemini-cli.
2619
+ * - `"acp"` — Agent Client Protocol bridge — fronts any ACP-compliant
2620
+ * agent binary (claude-agent-acp, codex-acp, gemini, openclaw acp).
2621
+ * Pick the backing agent via config.subAgent.
2622
+ * - `"cursor"` — Cursor Agent SDK local/cloud backend.
2623
+ * - `"cli-base"` — Minimal CLI-only (no AI agent).
2624
+ */
2625
+ type BackendType = "opencode" | "claude-code" | "kimi-code" | "codex" | "amp" | "factory-droids" | "pi" | "hermes" | "forge" | "openclaw" | "acp" | "cursor" | "cli-base";
2626
+ /**
2627
+ * MCP (Model Context Protocol) server configuration.
2628
+ */
2629
+ interface McpServerConfig {
2630
+ /** Command to run (e.g., "npx", "node") */
2631
+ command: string;
2632
+ /** Command arguments */
2633
+ args?: string[];
2634
+ /** Environment variables */
2635
+ env?: Record<string, string>;
2636
+ /** Working directory */
2637
+ cwd?: string;
2638
+ /** Remote URL (for remote MCP servers via SSE) */
2639
+ url?: string;
2640
+ /** Headers for remote connections */
2641
+ headers?: Record<string, string>;
2642
+ }
2643
+ /**
2644
+ * AI coding agent backend configuration.
2645
+ *
2646
+ * @example OpenCode with default settings
2647
+ * ```typescript
2648
+ * backend: { type: "opencode" }
2649
+ * ```
2650
+ *
2651
+ * @example OpenCode with named profile
2652
+ * ```typescript
2653
+ * backend: {
2654
+ * type: "opencode",
2655
+ * profile: "with-web-search",
2656
+ * }
2657
+ * ```
2658
+ *
2659
+ * @example Claude Code with BYOK
2660
+ * ```typescript
2661
+ * backend: {
2662
+ * type: "claude-code",
2663
+ * model: {
2664
+ * provider: "anthropic",
2665
+ * model: "claude-sonnet-4-20250514",
2666
+ * apiKey: process.env.ANTHROPIC_API_KEY,
2667
+ * }
2668
+ * }
2669
+ * ```
2670
+ */
2671
+ interface BackendConfig {
2672
+ /**
2673
+ * Backend type identifier.
2674
+ * @default "opencode"
2675
+ */
2676
+ type: BackendType;
2677
+ /**
2678
+ * Backend profile selection.
2679
+ *
2680
+ * Use a string for a named provider/backend profile, or an `AgentProfile`
2681
+ * object for an inline provider-neutral profile definition.
2682
+ */
2683
+ profile?: string | AgentProfile;
2684
+ /**
2685
+ * Model configuration override.
2686
+ */
2687
+ model?: {
2688
+ /** Provider name (e.g., "anthropic", "openai", "google") */provider?: string; /** Model identifier (e.g., "claude-sonnet-4-20250514") */
2689
+ model?: string; /** BYOK (Bring Your Own Key) API key */
2690
+ apiKey?: string; /** Custom API base URL (for proxies or on-prem) */
2691
+ baseUrl?: string; /** Maximum thinking tokens for extended reasoning */
2692
+ maxThinkingTokens?: number; /** API mode: "api" for direct calls, "cli" for CLI wrapper */
2693
+ mode?: "api" | "cli"; /** Authentication mode for CLI-native backends */
2694
+ authMode?: "api-key" | "oauth"; /** Auth files to write into the sandbox home directory before CLI startup */
2695
+ authFiles?: Array<{
2696
+ path: string;
2697
+ content: string;
2698
+ mode?: number;
2699
+ }>;
2700
+ };
2701
+ /**
2702
+ * Backend server configuration.
2703
+ */
2704
+ server?: {
2705
+ /** Server port (auto-assigned if not specified) */port?: number; /** Server hostname */
2706
+ hostname?: string;
2707
+ };
2708
+ }
2709
+ /**
2710
+ * Backend capabilities.
2711
+ */
2712
+ interface BackendCapabilities {
2713
+ /** Supports streaming responses */
2714
+ streaming: boolean;
2715
+ /** Supports tool/function use */
2716
+ toolUse: boolean;
2717
+ /** Supports extended thinking/reasoning */
2718
+ reasoning: boolean;
2719
+ /** Supports multimodal (images, etc) */
2720
+ multimodal: boolean;
2721
+ /** Context window size in tokens */
2722
+ contextWindow: number;
2723
+ /** Support details for provider-neutral `AgentProfile` values */
2724
+ profile?: AgentProfileCapabilities;
2725
+ }
2726
+ /**
2727
+ * Backend status information.
2728
+ */
2729
+ interface BackendStatus {
2730
+ /** Backend type */
2731
+ type: BackendType;
2732
+ /** Current status */
2733
+ status: "running" | "stopped" | "starting" | "stopping" | "unknown";
2734
+ /** Backend version */
2735
+ version?: string;
2736
+ /** Error message if failed */
2737
+ error?: string;
2738
+ /** Additional metadata */
2739
+ metadata?: Record<string, unknown>;
2740
+ }
2741
+ /**
2742
+ * Backend information.
2743
+ */
2744
+ interface BackendInfo {
2745
+ /** Backend type */
2746
+ type: BackendType;
2747
+ /** Whether backend is available */
2748
+ available: boolean;
2749
+ /** Backend capabilities */
2750
+ capabilities: BackendCapabilities;
2751
+ /** Available profiles (for opencode) */
2752
+ profiles?: Array<{
2753
+ name: string;
2754
+ description?: string;
2755
+ tags?: string[];
2756
+ }>;
2757
+ }
2758
+ interface BackendListOptions {
2759
+ limit?: number;
2760
+ cursor?: string;
2761
+ }
2762
+ interface BackendListResult<TItem> {
2763
+ items: TItem[];
2764
+ nextCursor?: string;
2765
+ }
2766
+ interface BackendAccount {
2767
+ apiKeyName?: string;
2768
+ userId?: number;
2769
+ userEmail?: string;
2770
+ userFirstName?: string;
2771
+ userLastName?: string;
2772
+ createdAt?: string;
2773
+ metadata?: Record<string, unknown>;
2774
+ }
2775
+ interface BackendModel {
2776
+ id: string;
2777
+ displayName?: string;
2778
+ description?: string;
2779
+ parameters?: Array<Record<string, unknown>>;
2780
+ variants?: Array<Record<string, unknown>>;
2781
+ }
2782
+ interface BackendRepository {
2783
+ url: string;
2784
+ }
2785
+ interface BackendAgent {
2786
+ agentId: string;
2787
+ name?: string;
2788
+ summary?: string;
2789
+ lastModified?: number;
2790
+ status?: "running" | "finished" | "error";
2791
+ createdAt?: number;
2792
+ archived?: boolean;
2793
+ runtime?: "local" | "cloud";
2794
+ cwd?: string;
2795
+ env?: Record<string, unknown>;
2796
+ repos?: string[];
2797
+ }
2798
+ interface BackendRun {
2799
+ id: string;
2800
+ agentId?: string;
2801
+ status?: "running" | "finished" | "cancelled" | "error";
2802
+ result?: string;
2803
+ durationMs?: number;
2804
+ model?: Record<string, unknown>;
2805
+ git?: Record<string, unknown>;
2806
+ }
2807
+ interface BackendArtifact {
2808
+ path: string;
2809
+ sizeBytes?: number;
2810
+ updatedAt?: string;
2811
+ }
2812
+ /**
2813
+ * Network configuration for sandbox network isolation.
2814
+ *
2815
+ * Supports two modes:
2816
+ * - `blockOutbound: true` - Block all egress traffic (ports still work for inbound)
2817
+ * - `allowList: ["cidr", ...]` - Allow only specific destinations
2818
+ *
2819
+ * These modes are mutually exclusive.
2820
+ *
2821
+ * @example Block all outbound traffic
2822
+ * ```typescript
2823
+ * const box = await client.create({
2824
+ * network: { blockOutbound: true }
2825
+ * });
2826
+ * ```
2827
+ *
2828
+ * @example Allow only specific destinations
2829
+ * ```typescript
2830
+ * const box = await client.create({
2831
+ * network: {
2832
+ * allowList: [
2833
+ * "8.8.8.8/32", // Google DNS
2834
+ * "10.0.0.0/8", // Private network
2835
+ * ]
2836
+ * }
2837
+ * });
2838
+ * ```
2839
+ *
2840
+ * @example Pre-expose ports at creation
2841
+ * ```typescript
2842
+ * const box = await client.create({
2843
+ * network: {
2844
+ * blockOutbound: true,
2845
+ * ports: [8000, 8080], // Pre-expose these ports
2846
+ * }
2847
+ * });
2848
+ * ```
2849
+ */
2850
+ interface NetworkConfig {
2851
+ /**
2852
+ * Block all outbound network traffic.
2853
+ * Exposed ports still work for inbound connections.
2854
+ * Mutually exclusive with `allowList`.
2855
+ */
2856
+ blockOutbound?: boolean;
2857
+ /**
2858
+ * CIDR allowlist for outbound traffic.
2859
+ * Only traffic to these destinations is allowed.
2860
+ * Maximum 10 entries. Mutually exclusive with `blockOutbound`.
2861
+ *
2862
+ * Supports both IPv4 and IPv6 CIDR notation:
2863
+ * - "8.8.8.8/32" - Single IPv4 address
2864
+ * - "10.0.0.0/8" - IPv4 subnet
2865
+ * - "2001:db8::/32" - IPv6 subnet
2866
+ */
2867
+ allowList?: string[];
2868
+ /**
2869
+ * Ports to expose at creation time.
2870
+ * These ports will be accessible regardless of network restrictions.
2871
+ */
2872
+ ports?: number[];
2873
+ }
2874
+ /**
2875
+ * Network manager for runtime network configuration.
2876
+ * Access via `sandbox.network`.
2877
+ *
2878
+ * @example Update network restrictions
2879
+ * ```typescript
2880
+ * // Block all outbound traffic
2881
+ * await box.network.update({ blockOutbound: true });
2882
+ *
2883
+ * // Or switch to allowlist mode
2884
+ * await box.network.update({
2885
+ * allowList: ["192.168.1.0/24", "8.8.8.8/32"]
2886
+ * });
2887
+ *
2888
+ * // Remove restrictions
2889
+ * await box.network.update({ blockOutbound: false });
2890
+ * ```
2891
+ *
2892
+ * @example Expose ports dynamically
2893
+ * ```typescript
2894
+ * const url = await box.network.exposePort(8000);
2895
+ * console.log(`Service available at: ${url}`);
2896
+ *
2897
+ * const allUrls = await box.network.listUrls();
2898
+ * ```
2899
+ */
2900
+ interface NetworkManager {
2901
+ /**
2902
+ * Update network permissions at runtime.
2903
+ * Changes apply immediately without container restart.
2904
+ *
2905
+ * @param config - Partial network configuration to apply
2906
+ * @throws Error if blockOutbound and allowList are both specified
2907
+ * @throws Error if allowList exceeds 10 entries
2908
+ * @throws Error if CIDR format is invalid
2909
+ */
2910
+ update(config: Partial<NetworkConfig>): Promise<void>;
2911
+ /**
2912
+ * Expose a port dynamically.
2913
+ * Returns a publicly accessible URL for the port.
2914
+ * Works regardless of network restrictions.
2915
+ *
2916
+ * @param port - Port number to expose (1-65535)
2917
+ * @returns Public URL for accessing the exposed port
2918
+ */
2919
+ exposePort(port: number): Promise<string>;
2920
+ /**
2921
+ * List all exposed port URLs.
2922
+ *
2923
+ * @returns Map of port numbers to their public URLs
2924
+ */
2925
+ listUrls(): Promise<Record<number, string>>;
2926
+ /**
2927
+ * Get current network configuration.
2928
+ *
2929
+ * @returns Current network config including any runtime changes
2930
+ */
2931
+ getConfig(): Promise<NetworkConfig>;
2932
+ }
2933
+ interface PreviewLinkInfo {
2934
+ previewId: string;
2935
+ sandboxId: string;
2936
+ port: number;
2937
+ protocol: "tcp" | "udp";
2938
+ hostname: string;
2939
+ url: string;
2940
+ status: "provisioning" | "ready" | "error" | "disabled";
2941
+ lastSyncAt: string;
2942
+ createdAt: string;
2943
+ updatedAt: string;
2944
+ metadata?: Record<string, unknown>;
2945
+ }
2946
+ /**
2947
+ * Preview link management.
2948
+ *
2949
+ * Create publicly accessible HTTPS URLs for TCP ports inside the sandbox.
2950
+ *
2951
+ * @example
2952
+ * ```typescript
2953
+ * // Expose a dev server
2954
+ * const link = await box.previewLinks.create(3000);
2955
+ * console.log(link.url);
2956
+ *
2957
+ * // List all preview links
2958
+ * const links = await box.previewLinks.list();
2959
+ *
2960
+ * // Remove a preview link
2961
+ * await box.previewLinks.remove(link.previewId);
2962
+ * ```
2963
+ */
2964
+ interface PreviewLinkManager {
2965
+ /**
2966
+ * Create a preview link for a port.
2967
+ * Returns the preview link with its public URL.
2968
+ * If a link already exists for this port, returns the existing one.
2969
+ *
2970
+ * @param port - Port number to expose (1-65535)
2971
+ * @param options - Optional protocol and metadata
2972
+ */
2973
+ create(port: number, options?: {
2974
+ protocol?: "tcp" | "udp";
2975
+ metadata?: Record<string, unknown>;
2976
+ }): Promise<PreviewLinkInfo>;
2977
+ /**
2978
+ * List all preview links for this sandbox.
2979
+ */
2980
+ list(): Promise<PreviewLinkInfo[]>;
2981
+ /**
2982
+ * Remove a preview link by ID.
2983
+ *
2984
+ * @param previewId - The preview link ID to remove
2985
+ */
2986
+ remove(previewId: string): Promise<void>;
2987
+ }
2988
+ /**
2989
+ * Permission level for sandbox users.
2990
+ *
2991
+ * - `owner` — Full access, can manage users.
2992
+ * - `admin` — Read/write workspace, can manage users.
2993
+ * - `developer` — Read/write workspace.
2994
+ * - `viewer` — Read-only workspace.
2995
+ */
2996
+ type PermissionLevel = "owner" | "admin" | "developer" | "viewer";
2997
+ /**
2998
+ * Directory-level permission override.
2999
+ */
3000
+ interface DirectoryPermission {
3001
+ /** Directory path (absolute, e.g. "/workspace/shared") */
3002
+ path: string;
3003
+ /** Read access */
3004
+ read: boolean;
3005
+ /** Write access */
3006
+ write: boolean;
3007
+ /** Execute/traverse access */
3008
+ execute: boolean;
3009
+ }
3010
+ /**
3011
+ * Glob-based access policy rule.
3012
+ *
3013
+ * @example Block all .env files
3014
+ * ```typescript
3015
+ * { pattern: "*.env", permission: "none" }
3016
+ * ```
3017
+ *
3018
+ * @example Read-only secrets directory
3019
+ * ```typescript
3020
+ * { pattern: "/secrets/**", permission: "read" }
3021
+ * ```
3022
+ */
3023
+ interface AccessPolicyRule {
3024
+ /** Glob pattern for matching (e.g., "*.env", "/secrets/**") */
3025
+ pattern: string;
3026
+ /** Access level for matching paths */
3027
+ permission: "read" | "write" | "none";
3028
+ /** Priority when patterns overlap (higher wins) */
3029
+ priority?: number;
3030
+ }
3031
+ /**
3032
+ * User in a sandbox.
3033
+ */
3034
+ interface SandboxUser {
3035
+ /** Unique user ID (from auth system) */
3036
+ userId: string;
3037
+ /** Username inside sandbox (Unix username) */
3038
+ username: string;
3039
+ /** Home directory path */
3040
+ homeDir: string;
3041
+ /** Permission level */
3042
+ role: PermissionLevel;
3043
+ /** SSH public keys */
3044
+ sshKeys: string[];
3045
+ /** Directory permission overrides */
3046
+ directoryPermissions?: DirectoryPermission[];
3047
+ /** Access policy rules */
3048
+ accessPolicies?: AccessPolicyRule[];
3049
+ /** When user was added */
3050
+ createdAt: Date;
3051
+ }
3052
+ /**
3053
+ * Options for adding a user to a sandbox.
3054
+ */
3055
+ interface AddUserOptions {
3056
+ /** Unique user ID (from your auth system) */
3057
+ userId: string;
3058
+ /** Preferred username (will be sanitized for Unix) */
3059
+ username?: string;
3060
+ /** Permission level (default: developer) */
3061
+ role?: PermissionLevel;
3062
+ /** SSH public keys for remote access */
3063
+ sshKeys?: string[];
3064
+ /** Custom directory permissions */
3065
+ directoryPermissions?: DirectoryPermission[];
3066
+ }
3067
+ /**
3068
+ * Options for updating a user.
3069
+ */
3070
+ interface UpdateUserOptions {
3071
+ /** New permission level */
3072
+ role?: PermissionLevel;
3073
+ /** SSH keys to add */
3074
+ addSshKeys?: string[];
3075
+ /** SSH keys to remove */
3076
+ removeSshKeys?: string[];
3077
+ /** Directory permissions to add/update */
3078
+ directoryPermissions?: DirectoryPermission[];
3079
+ }
3080
+ /**
3081
+ * Initial permissions configuration for sandbox creation.
3082
+ */
3083
+ interface SandboxPermissionsConfig {
3084
+ /**
3085
+ * Default role for invited users.
3086
+ * @default "developer"
3087
+ */
3088
+ defaultRole?: PermissionLevel;
3089
+ /**
3090
+ * Users to invite at creation time.
3091
+ * Owner is automatically added from the API key.
3092
+ */
3093
+ initialUsers?: Array<{
3094
+ userId: string;
3095
+ role?: PermissionLevel;
3096
+ sshKeys?: string[];
3097
+ }>;
3098
+ /**
3099
+ * Default access policies for all users.
3100
+ */
3101
+ defaultPolicies?: AccessPolicyRule[];
3102
+ /**
3103
+ * Enable multi-user mode.
3104
+ * @default true when initialUsers is provided
3105
+ */
3106
+ multiUser?: boolean;
3107
+ }
3108
+ /**
3109
+ * Permissions manager interface.
3110
+ * Access via `sandbox.permissions`.
3111
+ */
3112
+ interface PermissionsManager {
3113
+ /** List all users in the sandbox */
3114
+ list(): Promise<SandboxUser[]>;
3115
+ /** Get a specific user */
3116
+ get(userId: string): Promise<SandboxUser | null>;
3117
+ /** Add a user to the sandbox */
3118
+ add(options: AddUserOptions): Promise<SandboxUser>;
3119
+ /** Update a user's permissions */
3120
+ update(userId: string, options: UpdateUserOptions): Promise<SandboxUser>;
3121
+ /** Remove a user from the sandbox */
3122
+ remove(userId: string, options?: {
3123
+ preserveHomeDir?: boolean;
3124
+ }): Promise<void>;
3125
+ /** Set access policies for a user */
3126
+ setAccessPolicies(userId: string, rules: AccessPolicyRule[]): Promise<void>;
3127
+ /** Get access policies for a user */
3128
+ getAccessPolicies(userId: string): Promise<AccessPolicyRule[]>;
3129
+ /** Check if a user can perform an action on a path */
3130
+ checkAccess(userId: string, path: string, action: "read" | "write" | "execute"): Promise<boolean>;
3131
+ }
3132
+ /**
3133
+ * Backend manager for runtime agent configuration.
3134
+ * Access via `sandbox.backend`.
3135
+ */
3136
+ interface BackendManager {
3137
+ /** Get current backend status */
3138
+ status(): Promise<BackendStatus>;
3139
+ /** Get backend capabilities */
3140
+ capabilities(): Promise<BackendCapabilities>;
3141
+ /** Add MCP server at runtime (opencode only) */
3142
+ addMcp(name: string, config: McpServerConfig): Promise<void>;
3143
+ /** Get MCP server status */
3144
+ getMcpStatus(): Promise<Record<string, {
3145
+ status: "running" | "stopped" | "error";
3146
+ error?: string;
3147
+ }>>;
3148
+ /** Update backend configuration */
3149
+ updateConfig(config: Partial<BackendConfig>): Promise<void>;
3150
+ /** Provider account metadata, when exposed by the backend SDK */
3151
+ account(): Promise<BackendAccount>;
3152
+ /** Provider model catalog, when exposed by the backend SDK */
3153
+ models(): Promise<BackendModel[]>;
3154
+ /** Provider repository catalog, when exposed by the backend SDK */
3155
+ repositories(): Promise<BackendRepository[]>;
3156
+ /** Provider-native agent list */
3157
+ agents(options?: BackendListOptions): Promise<BackendListResult<BackendAgent>>;
3158
+ /** Provider-native agent lookup */
3159
+ agent(agentId: string): Promise<BackendAgent>;
3160
+ /** Archive provider-native agent */
3161
+ archiveAgent(agentId: string): Promise<void>;
3162
+ /** Unarchive provider-native agent */
3163
+ unarchiveAgent(agentId: string): Promise<void>;
3164
+ /** Delete provider-native agent */
3165
+ deleteAgent(agentId: string): Promise<void>;
3166
+ /** Provider-native runs for an agent */
3167
+ runs(agentId: string, options?: BackendListOptions): Promise<BackendListResult<BackendRun>>;
3168
+ /** Provider-native run lookup */
3169
+ run(runId: string, options?: {
3170
+ agentId?: string;
3171
+ }): Promise<BackendRun>;
3172
+ /** Provider-native agent messages */
3173
+ agentMessages(agentId: string, options?: BackendListOptions): Promise<unknown>;
3174
+ /** Artifacts for an active backend session */
3175
+ artifacts(sessionId: string): Promise<BackendArtifact[]>;
3176
+ /** Download an artifact from an active backend session */
3177
+ downloadArtifact(sessionId: string, path: string): Promise<Uint8Array>;
3178
+ /**
3179
+ * Validate a provider-neutral profile against the active backend.
3180
+ *
3181
+ * Optional while backends adopt the public `AgentProfile` contract.
3182
+ */
3183
+ validateProfile?(profile: AgentProfile): Promise<AgentProfileValidationResult>;
3184
+ /** Restart the backend agent */
3185
+ restart(): Promise<void>;
3186
+ }
3187
+ /**
3188
+ * Options for spawning a process.
3189
+ *
3190
+ * @example Basic spawn
3191
+ * ```typescript
3192
+ * const proc = await box.process.spawn("python train.py");
3193
+ * ```
3194
+ *
3195
+ * @example With options
3196
+ * ```typescript
3197
+ * const proc = await box.process.spawn("python train.py", {
3198
+ * cwd: "/workspace/ml",
3199
+ * env: { "CUDA_VISIBLE_DEVICES": "0" },
3200
+ * timeoutMs: 3600000, // 1 hour
3201
+ * });
3202
+ * ```
3203
+ */
3204
+ interface ProcessSpawnOptions {
3205
+ /** Working directory for the process */
3206
+ cwd?: string;
3207
+ /** Environment variables to set */
3208
+ env?: Record<string, string>;
3209
+ /** Timeout in milliseconds (0 = no timeout) */
3210
+ timeoutMs?: number;
3211
+ }
3212
+ /**
3213
+ * Options for running Python code.
3214
+ *
3215
+ * @example Simple code execution
3216
+ * ```typescript
3217
+ * const result = await box.process.runCode(`
3218
+ * import numpy as np
3219
+ * print(np.random.rand(10))
3220
+ * `);
3221
+ * ```
3222
+ */
3223
+ interface RunCodeOptions {
3224
+ /** Working directory */
3225
+ cwd?: string;
3226
+ /** Environment variables */
3227
+ env?: Record<string, string>;
3228
+ /** Timeout in milliseconds */
3229
+ timeoutMs?: number;
3230
+ }
3231
+ /**
3232
+ * Status of a spawned process.
3233
+ */
3234
+ interface ProcessStatus {
3235
+ /** Process ID */
3236
+ pid: number;
3237
+ /** Command that was executed */
3238
+ command: string;
3239
+ /** Working directory */
3240
+ cwd?: string;
3241
+ /** Whether the process is still running */
3242
+ running: boolean;
3243
+ /** Exit code (-1 if still running) */
3244
+ exitCode: number;
3245
+ /** Signal that killed the process (if any) */
3246
+ exitSignal?: string;
3247
+ /** When the process started */
3248
+ startedAt: Date;
3249
+ /** When the process exited (if exited) */
3250
+ exitedAt?: Date;
3251
+ }
3252
+ /**
3253
+ * Full process information including environment.
3254
+ */
3255
+ interface ProcessInfo extends ProcessStatus {
3256
+ /** Environment variables used */
3257
+ env?: Record<string, string>;
3258
+ }
3259
+ /**
3260
+ * A log entry from process stdout/stderr.
3261
+ */
3262
+ interface ProcessLogEntry {
3263
+ /** Log source: stdout or stderr */
3264
+ type: "stdout" | "stderr";
3265
+ /** Log content */
3266
+ data: string;
3267
+ /** Timestamp in milliseconds */
3268
+ timestamp: number;
3269
+ }
3270
+ /**
3271
+ * Result of running code or a blocking process.
3272
+ */
3273
+ interface CodeResult {
3274
+ /** Process ID */
3275
+ pid: number;
3276
+ /** Exit code */
3277
+ exitCode: number;
3278
+ /** Standard output */
3279
+ stdout: string;
3280
+ /** Standard error */
3281
+ stderr: string;
3282
+ /** Execution duration in milliseconds */
3283
+ durationMs: number;
3284
+ }
3285
+ /**
3286
+ * Signal types for killing processes.
3287
+ */
3288
+ type ProcessSignal = "SIGTERM" | "SIGKILL" | "SIGINT" | "SIGHUP" | "SIGQUIT" | "SIGUSR1" | "SIGUSR2";
3289
+ /**
3290
+ * A handle to a spawned process with control methods.
3291
+ *
3292
+ * @example Non-blocking process with log streaming
3293
+ * ```typescript
3294
+ * const proc = await box.process.spawn("python train.py", {
3295
+ * cwd: "/workspace",
3296
+ * env: { "CUDA_VISIBLE_DEVICES": "0" }
3297
+ * });
3298
+ *
3299
+ * console.log(`Started PID: ${proc.pid}`);
3300
+ *
3301
+ * // Stream logs in real-time
3302
+ * for await (const line of proc.logs()) {
3303
+ * console.log(line);
3304
+ * }
3305
+ *
3306
+ * // Or wait for completion
3307
+ * const exitCode = await proc.wait();
3308
+ * ```
3309
+ *
3310
+ * @example Check status and kill
3311
+ * ```typescript
3312
+ * const status = await proc.status();
3313
+ * if (status.running) {
3314
+ * await proc.kill("SIGKILL");
3315
+ * }
3316
+ * ```
3317
+ */
3318
+ interface Process {
3319
+ /** Process ID */
3320
+ readonly pid: number;
3321
+ /** Command that was executed */
3322
+ readonly command: string;
3323
+ /**
3324
+ * Get current process status.
3325
+ */
3326
+ status(): Promise<ProcessStatus>;
3327
+ /**
3328
+ * Wait for the process to exit.
3329
+ * @returns Exit code
3330
+ */
3331
+ wait(): Promise<number>;
3332
+ /**
3333
+ * Kill the process.
3334
+ * @param signal - Signal to send (default: SIGTERM)
3335
+ */
3336
+ kill(signal?: ProcessSignal): Promise<void>;
3337
+ /**
3338
+ * Stream stdout/stderr logs in real-time.
3339
+ * Includes buffered logs from process start.
3340
+ */
3341
+ logs(): AsyncIterable<ProcessLogEntry>;
3342
+ /**
3343
+ * Stream only stdout.
3344
+ */
3345
+ stdout(): AsyncIterable<string>;
3346
+ /**
3347
+ * Stream only stderr.
3348
+ */
3349
+ stderr(): AsyncIterable<string>;
3350
+ }
3351
+ /**
3352
+ * Process manager for spawning and controlling processes.
3353
+ * Access via `sandbox.process`.
3354
+ *
3355
+ * Provides non-blocking process execution with real-time log streaming,
3356
+ * ideal for long-running tasks like ML training or dev servers.
3357
+ *
3358
+ * @example Non-blocking process
3359
+ * ```typescript
3360
+ * const proc = await box.process.spawn("python train.py", {
3361
+ * cwd: "/workspace",
3362
+ * env: { "CUDA_VISIBLE_DEVICES": "0" }
3363
+ * });
3364
+ *
3365
+ * // Stream logs
3366
+ * for await (const entry of proc.logs()) {
3367
+ * console.log(`[${entry.type}] ${entry.data}`);
3368
+ * }
3369
+ *
3370
+ * // Check status
3371
+ * const status = await proc.status();
3372
+ * console.log(`Running: ${status.running}`);
3373
+ *
3374
+ * // Kill if needed
3375
+ * await proc.kill();
3376
+ * ```
3377
+ *
3378
+ * @example Run Python code directly
3379
+ * ```typescript
3380
+ * const result = await box.process.runCode(`
3381
+ * import numpy as np
3382
+ * print(np.random.rand(10).mean())
3383
+ * `);
3384
+ * console.log(result.stdout); // Prints the mean
3385
+ * ```
3386
+ *
3387
+ * @example List and manage processes
3388
+ * ```typescript
3389
+ * const procs = await box.process.list();
3390
+ * for (const p of procs) {
3391
+ * console.log(`PID ${p.pid}: ${p.command} (${p.running ? 'running' : 'exited'})`);
3392
+ * }
3393
+ *
3394
+ * // Get specific process
3395
+ * const proc = await box.process.get(1234);
3396
+ * if (proc) {
3397
+ * await proc.kill();
3398
+ * }
3399
+ * ```
3400
+ */
3401
+ interface ProcessManager {
3402
+ /**
3403
+ * Spawn a process without blocking.
3404
+ * Returns immediately with a Process handle.
3405
+ *
3406
+ * @param command - Shell command to execute
3407
+ * @param options - Spawn options (cwd, env, timeout)
3408
+ * @returns Process handle for control and monitoring
3409
+ */
3410
+ spawn(command: string, options?: ProcessSpawnOptions): Promise<Process>;
3411
+ /**
3412
+ * Run Python code directly.
3413
+ * Blocks until completion and returns result.
3414
+ *
3415
+ * @param code - Python code to execute
3416
+ * @param options - Execution options
3417
+ * @returns Execution result with stdout/stderr
3418
+ */
3419
+ runCode(code: string, options?: RunCodeOptions): Promise<CodeResult>;
3420
+ /**
3421
+ * List all tracked processes.
3422
+ *
3423
+ * @returns Array of process status objects
3424
+ */
3425
+ list(): Promise<ProcessStatus[]>;
3426
+ /**
3427
+ * Get a process by PID.
3428
+ *
3429
+ * @param pid - Process ID
3430
+ * @returns Process handle or null if not found
3431
+ */
3432
+ get(pid: number): Promise<Process | null>;
3433
+ }
3434
+ /**
3435
+ * Information about a stored secret (without the value).
3436
+ */
3437
+ interface SecretInfo {
3438
+ /** Secret name (e.g., HF_TOKEN, AWS_ACCESS_KEY) */
3439
+ name: string;
3440
+ /** When the secret was created */
3441
+ createdAt: Date;
3442
+ /** When the secret was last updated */
3443
+ updatedAt: Date;
3444
+ }
3445
+ /**
3446
+ * Secrets manager for storing and retrieving encrypted secrets.
3447
+ * Access via `client.secrets`.
3448
+ *
3449
+ * Secrets are encrypted at rest and can be injected into sandboxes
3450
+ * as environment variables.
3451
+ *
3452
+ * @example Create and manage secrets
3453
+ * ```typescript
3454
+ * // Create a secret
3455
+ * await client.secrets.create("HF_TOKEN", "hf_xxx");
3456
+ *
3457
+ * // List all secrets (names only, not values)
3458
+ * const secrets = await client.secrets.list();
3459
+ * console.log(secrets.map(s => s.name)); // ["HF_TOKEN"]
3460
+ *
3461
+ * // Get a secret value (audited operation)
3462
+ * const value = await client.secrets.get("HF_TOKEN");
3463
+ *
3464
+ * // Update a secret
3465
+ * await client.secrets.update("HF_TOKEN", "hf_new_value");
3466
+ *
3467
+ * // Delete a secret
3468
+ * await client.secrets.delete("HF_TOKEN");
3469
+ * ```
3470
+ *
3471
+ * @example Use secrets in a sandbox
3472
+ * ```typescript
3473
+ * // Create sandbox with secrets injected as env vars
3474
+ * const box = await client.create({
3475
+ * secrets: ["HF_TOKEN", "AWS_ACCESS_KEY"],
3476
+ * });
3477
+ *
3478
+ * // Secrets are available as environment variables
3479
+ * const result = await box.exec("echo $HF_TOKEN");
3480
+ * ```
3481
+ */
3482
+ interface SecretsManager {
3483
+ /**
3484
+ * Create a new secret.
3485
+ *
3486
+ * @param name - Secret name (uppercase, alphanumeric + underscore, max 63 chars)
3487
+ * @param value - Secret value (max 64KB)
3488
+ * @returns Created secret info
3489
+ * @throws If secret already exists or name is invalid
3490
+ *
3491
+ * @example
3492
+ * ```typescript
3493
+ * await client.secrets.create("HF_TOKEN", "hf_xxx");
3494
+ * await client.secrets.create("AWS_ACCESS_KEY", "AKIA...");
3495
+ * ```
3496
+ */
3497
+ create(name: string, value: string): Promise<SecretInfo>;
3498
+ /**
3499
+ * List all secrets (names and metadata only, not values).
3500
+ *
3501
+ * @returns Array of secret info objects
3502
+ *
3503
+ * @example
3504
+ * ```typescript
3505
+ * const secrets = await client.secrets.list();
3506
+ * for (const s of secrets) {
3507
+ * console.log(`${s.name} - created ${s.createdAt}`);
3508
+ * }
3509
+ * ```
3510
+ */
3511
+ list(): Promise<SecretInfo[]>;
3512
+ /**
3513
+ * Get a secret's decrypted value.
3514
+ *
3515
+ * This is an audited operation - access is logged.
3516
+ *
3517
+ * @param name - Secret name
3518
+ * @returns Secret value
3519
+ * @throws If secret not found
3520
+ *
3521
+ * @example
3522
+ * ```typescript
3523
+ * const token = await client.secrets.get("HF_TOKEN");
3524
+ * ```
3525
+ */
3526
+ get(name: string): Promise<string>;
3527
+ /**
3528
+ * Update an existing secret's value.
3529
+ *
3530
+ * @param name - Secret name
3531
+ * @param value - New secret value
3532
+ * @returns Updated secret info
3533
+ * @throws If secret not found
3534
+ *
3535
+ * @example
3536
+ * ```typescript
3537
+ * await client.secrets.update("HF_TOKEN", "hf_new_value");
3538
+ * ```
3539
+ */
3540
+ update(name: string, value: string): Promise<SecretInfo>;
3541
+ /**
3542
+ * Delete a secret.
3543
+ *
3544
+ * @param name - Secret name
3545
+ * @throws If secret not found
3546
+ *
3547
+ * @example
3548
+ * ```typescript
3549
+ * await client.secrets.delete("HF_TOKEN");
3550
+ * ```
3551
+ */
3552
+ delete(name: string): Promise<void>;
3553
+ }
3554
+ /**
3555
+ * Detailed file/directory information.
3556
+ */
3557
+ interface FileInfo {
3558
+ /** File/directory name */
3559
+ name: string;
3560
+ /** Full path relative to workspace */
3561
+ path: string;
3562
+ /** Size in bytes */
3563
+ size: number;
3564
+ /** Whether this is a directory */
3565
+ isDir: boolean;
3566
+ /** Whether this is a regular file */
3567
+ isFile: boolean;
3568
+ /** Whether this is a symbolic link */
3569
+ isSymlink: boolean;
3570
+ /** Unix permissions (e.g., 0o755) */
3571
+ permissions: number;
3572
+ /** Owner user ID/name */
3573
+ owner: string;
3574
+ /** Group ID/name */
3575
+ group: string;
3576
+ /** Last modification time */
3577
+ modTime: Date;
3578
+ /** Last access time */
3579
+ accessTime: Date;
3580
+ }
3581
+ /**
3582
+ * Options for uploading files.
3583
+ */
3584
+ interface UploadOptions {
3585
+ /** Overwrite if file exists (default: true) */
3586
+ overwrite?: boolean;
3587
+ /** Set file permissions (Unix mode, e.g., 0o644) */
3588
+ permissions?: number;
3589
+ /** Progress callback for large files */
3590
+ onProgress?: (progress: UploadProgress) => void;
3591
+ }
3592
+ /**
3593
+ * Upload progress information.
3594
+ */
3595
+ interface UploadProgress {
3596
+ /** Bytes uploaded so far */
3597
+ bytesUploaded: number;
3598
+ /** Total bytes to upload */
3599
+ totalBytes: number;
3600
+ /** Percentage complete (0-100) */
3601
+ percentage: number;
3602
+ }
3603
+ /**
3604
+ * Options for downloading files.
3605
+ */
3606
+ interface DownloadOptions {
3607
+ /** Overwrite local file if exists (default: true) */
3608
+ overwrite?: boolean;
3609
+ /** Progress callback for large files */
3610
+ onProgress?: (progress: DownloadProgress) => void;
3611
+ }
3612
+ /**
3613
+ * Download progress information.
3614
+ */
3615
+ interface DownloadProgress {
3616
+ /** Bytes downloaded so far */
3617
+ bytesDownloaded: number;
3618
+ /** Total bytes to download */
3619
+ totalBytes: number;
3620
+ /** Percentage complete (0-100) */
3621
+ percentage: number;
3622
+ }
3623
+ /**
3624
+ * Options for listing directories.
3625
+ */
3626
+ interface ListOptions {
3627
+ /** Include hidden files (starting with .) */
3628
+ all?: boolean;
3629
+ /** Include full metadata (like ls -l) */
3630
+ long?: boolean;
3631
+ }
3632
+ /**
3633
+ * Options for creating directories.
3634
+ */
3635
+ interface MkdirOptions {
3636
+ /** Create parent directories as needed (like mkdir -p) */
3637
+ recursive?: boolean;
3638
+ /** Set directory permissions (Unix mode, e.g., 0o755) */
3639
+ mode?: number;
3640
+ }
3641
+ /**
3642
+ * Options for deleting files/directories.
3643
+ */
3644
+ interface DeleteOptions {
3645
+ /** Recursively delete directories (like rm -rf) */
3646
+ recursive?: boolean;
3647
+ }
3648
+ /**
3649
+ * File system operations for sandboxes. Access via `sandbox.fs`.
3650
+ *
3651
+ * Beyond basic read/write: binary upload/download, directory operations,
3652
+ * progress reporting for large files.
3653
+ *
3654
+ * @example Upload and download files
3655
+ * ```typescript
3656
+ * // Upload a local file
3657
+ * await box.fs.upload("./model.bin", "/workspace/models/model.bin");
3658
+ *
3659
+ * // Download a file
3660
+ * await box.fs.download("/workspace/results.zip", "./local/results.zip");
3661
+ *
3662
+ * // With progress reporting
3663
+ * await box.fs.upload("./large-file.bin", "/workspace/data.bin", {
3664
+ * onProgress: (p) => console.log(`${p.percentage}%`),
3665
+ * });
3666
+ * ```
3667
+ *
3668
+ * @example Directory operations
3669
+ * ```typescript
3670
+ * // Upload entire directory
3671
+ * await box.fs.uploadDir("./local/project", "/workspace/project");
3672
+ *
3673
+ * // Download entire directory
3674
+ * await box.fs.downloadDir("/workspace/output", "./local/output");
3675
+ *
3676
+ * // List directory contents
3677
+ * const files = await box.fs.list("/workspace");
3678
+ * for (const f of files) {
3679
+ * console.log(`${f.name} - ${f.size} bytes`);
3680
+ * }
3681
+ * ```
3682
+ *
3683
+ * @example File management
3684
+ * ```typescript
3685
+ * // Check if file exists
3686
+ * if (await box.fs.exists("/workspace/config.json")) {
3687
+ * const info = await box.fs.stat("/workspace/config.json");
3688
+ * console.log(`Size: ${info.size}, Modified: ${info.modTime}`);
3689
+ * }
3690
+ *
3691
+ * // Create directory
3692
+ * await box.fs.mkdir("/workspace/output/images", { recursive: true });
3693
+ *
3694
+ * // Delete file or directory
3695
+ * await box.fs.delete("/workspace/temp", { recursive: true });
3696
+ * ```
3697
+ */
3698
+ interface FileSystem {
3699
+ /**
3700
+ * Read a file's contents as a string.
3701
+ * For binary files, use download() instead.
3702
+ *
3703
+ * @param path - Path to file (relative to workspace)
3704
+ * @returns File contents as UTF-8 string
3705
+ * @throws NotFoundError if file doesn't exist
3706
+ */
3707
+ read(path: string): Promise<string>;
3708
+ /**
3709
+ * Write string content to a file.
3710
+ * For binary files, use upload() instead.
3711
+ * Creates parent directories as needed.
3712
+ *
3713
+ * @param path - Path to file (relative to workspace)
3714
+ * @param content - Content to write
3715
+ */
3716
+ write(path: string, content: string): Promise<void>;
3717
+ /**
3718
+ * Search for text patterns in files using ripgrep.
3719
+ * @see SearchOptions for available options
3720
+ */
3721
+ search(query: string, options?: SearchOptions): AsyncIterable<SearchMatch>;
3722
+ /**
3723
+ * Upload a local file to the sandbox.
3724
+ * Handles binary files correctly using multipart upload.
3725
+ * Creates parent directories as needed.
3726
+ *
3727
+ * @param localPath - Path to local file
3728
+ * @param remotePath - Destination path in sandbox
3729
+ * @param options - Upload options (overwrite, permissions, progress)
3730
+ * @throws Error if local file doesn't exist
3731
+ *
3732
+ * @example
3733
+ * ```typescript
3734
+ * await box.fs.upload("./model.bin", "/workspace/models/model.bin");
3735
+ *
3736
+ * // With progress
3737
+ * await box.fs.upload("./large-file.bin", "/data/file.bin", {
3738
+ * onProgress: (p) => console.log(`${p.percentage.toFixed(1)}%`),
3739
+ * });
3740
+ * ```
3741
+ */
3742
+ upload(localPath: string, remotePath: string, options?: UploadOptions): Promise<void>;
3743
+ /**
3744
+ * Download a file from the sandbox.
3745
+ * Handles binary files correctly.
3746
+ * Creates local parent directories as needed.
3747
+ *
3748
+ * @param remotePath - Path to file in sandbox
3749
+ * @param localPath - Local destination path
3750
+ * @param options - Download options (overwrite, progress)
3751
+ * @throws NotFoundError if remote file doesn't exist
3752
+ *
3753
+ * @example
3754
+ * ```typescript
3755
+ * await box.fs.download("/workspace/output.zip", "./results.zip");
3756
+ * ```
3757
+ */
3758
+ download(remotePath: string, localPath: string, options?: DownloadOptions): Promise<void>;
3759
+ /**
3760
+ * Upload a local directory to the sandbox.
3761
+ * Uses tar for efficient transfer.
3762
+ * Preserves directory structure and file permissions.
3763
+ *
3764
+ * @param localDir - Path to local directory
3765
+ * @param remoteDir - Destination directory in sandbox
3766
+ * @throws Error if local directory doesn't exist
3767
+ *
3768
+ * @example
3769
+ * ```typescript
3770
+ * await box.fs.uploadDir("./project", "/workspace/project");
3771
+ * ```
3772
+ */
3773
+ uploadDir(localDir: string, remoteDir: string): Promise<void>;
3774
+ /**
3775
+ * Download a directory from the sandbox.
3776
+ * Uses tar for efficient transfer.
3777
+ * Preserves directory structure and file permissions.
3778
+ *
3779
+ * @param remoteDir - Directory path in sandbox
3780
+ * @param localDir - Local destination directory
3781
+ * @throws NotFoundError if remote directory doesn't exist
3782
+ *
3783
+ * @example
3784
+ * ```typescript
3785
+ * await box.fs.downloadDir("/workspace/output", "./local-output");
3786
+ * ```
3787
+ */
3788
+ downloadDir(remoteDir: string, localDir: string): Promise<void>;
3789
+ /**
3790
+ * List directory contents with metadata.
3791
+ *
3792
+ * @param path - Directory path (relative to workspace)
3793
+ * @param options - List options (all, long)
3794
+ * @returns Array of file/directory info
3795
+ * @throws NotFoundError if directory doesn't exist
3796
+ *
3797
+ * @example
3798
+ * ```typescript
3799
+ * const entries = await box.fs.list("/workspace", { all: true });
3800
+ * for (const e of entries) {
3801
+ * const type = e.isDir ? "DIR" : "FILE";
3802
+ * console.log(`[${type}] ${e.name} (${e.size} bytes)`);
3803
+ * }
3804
+ * ```
3805
+ */
3806
+ list(path: string, options?: ListOptions): Promise<FileInfo[]>;
3807
+ /**
3808
+ * Get detailed information about a file or directory.
3809
+ *
3810
+ * @param path - Path to file/directory
3811
+ * @returns File/directory metadata
3812
+ * @throws NotFoundError if path doesn't exist
3813
+ *
3814
+ * @example
3815
+ * ```typescript
3816
+ * const info = await box.fs.stat("/workspace/model.bin");
3817
+ * console.log(`Size: ${info.size}, Modified: ${info.modTime}`);
3818
+ * ```
3819
+ */
3820
+ stat(path: string): Promise<FileInfo>;
3821
+ /**
3822
+ * Delete a file or directory.
3823
+ *
3824
+ * @param path - Path to delete
3825
+ * @param options - Delete options (recursive for directories)
3826
+ * @throws NotFoundError if path doesn't exist
3827
+ * @throws Error if deleting non-empty directory without recursive
3828
+ *
3829
+ * @example
3830
+ * ```typescript
3831
+ * // Delete file
3832
+ * await box.fs.delete("/workspace/temp.txt");
3833
+ *
3834
+ * // Delete directory recursively
3835
+ * await box.fs.delete("/workspace/cache", { recursive: true });
3836
+ * ```
3837
+ */
3838
+ delete(path: string, options?: DeleteOptions): Promise<void>;
3839
+ /**
3840
+ * Create a directory.
3841
+ *
3842
+ * @param path - Directory path to create
3843
+ * @param options - Options (recursive to create parents)
3844
+ *
3845
+ * @example
3846
+ * ```typescript
3847
+ * // Create with parents
3848
+ * await box.fs.mkdir("/workspace/output/images", { recursive: true });
3849
+ * ```
3850
+ */
3851
+ mkdir(path: string, options?: MkdirOptions): Promise<void>;
3852
+ /**
3853
+ * Check if a path exists.
3854
+ *
3855
+ * @param path - Path to check
3856
+ * @returns true if path exists, false otherwise
3857
+ *
3858
+ * @example
3859
+ * ```typescript
3860
+ * if (await box.fs.exists("/workspace/config.json")) {
3861
+ * // File exists
3862
+ * }
3863
+ * ```
3864
+ */
3865
+ exists(path: string): Promise<boolean>;
3866
+ }
3867
+ //#endregion
3868
+ //#region src/session.d.ts
3869
+ /**
3870
+ * A single agent session inside a sandbox. Created via
3871
+ * `box.session(id)` — does not hit the network until a method is called.
3872
+ */
3873
+ declare class SandboxSession {
3874
+ private readonly box;
3875
+ /** Stable session id assigned by the sandbox runtime. */
3876
+ readonly id: string;
3877
+ /**
3878
+ * @internal SDK-internal constructor — apps should call `box.session(id)`.
3879
+ */
3880
+ constructor(box: SandboxInstance, /** Stable session id assigned by the sandbox runtime. */
3881
+
3882
+ id: string);
3883
+ /**
3884
+ * Fetch the current session state from the sandbox. Includes status,
3885
+ * model, prompt count, token usage if known, and timing metadata.
3886
+ *
3887
+ * Throws on transport error; returns `null` if the session id is not
3888
+ * known to the sandbox (e.g. it ended and was reaped, or the id is
3889
+ * invalid).
3890
+ */
3891
+ status(): Promise<SessionInfo | null>;
3892
+ /**
3893
+ * Stream events from this session as they arrive. With no `since`,
3894
+ * starts at the live tail; with `since`, replays from that event id
3895
+ * forward — useful for reconnect-after-disconnect flows.
3896
+ *
3897
+ * The async iterator terminates when the session reaches a terminal
3898
+ * state (`completed`, `failed`, `cancelled`) and the corresponding
3899
+ * terminal event has been yielded, OR when the caller's signal aborts.
3900
+ */
3901
+ events(opts?: SessionEventStreamOptions): AsyncGenerator<SandboxEvent>;
3902
+ /**
3903
+ * Await the session's terminal result. Polls status + drains events
3904
+ * until the session reaches a terminal state, then returns the
3905
+ * aggregated `PromptResult`.
3906
+ *
3907
+ * Use this to wait for a session that was started by another caller
3908
+ * (e.g. `dispatchPrompt`).
3909
+ */
3910
+ result(): Promise<PromptResult>;
3911
+ /**
3912
+ * Continue this session with an additional prompt. Equivalent to
3913
+ * `box.prompt(message, { ...opts, sessionId: this.id })` but reads
3914
+ * naturally on a Session reference.
3915
+ */
3916
+ prompt(message: string | PromptInputPart[], opts?: PromptOptions): Promise<PromptResult>;
3917
+ /**
3918
+ * Cancel the session. Best-effort: an in-flight LLM call may still
3919
+ * complete one more token before the abort takes effect. Idempotent —
3920
+ * cancelling a completed session is a no-op.
3921
+ */
3922
+ cancel(): Promise<void>;
3923
+ }
3924
+ //#endregion
3925
+ //#region src/trace-exporter.d.ts
3926
+ type JsonObject = {
3927
+ [key: string]: JsonValue;
3928
+ };
3929
+ type TraceExportFormat = "tangle" | "otel-json";
3930
+ type TraceExportBundle = SandboxTraceBundle | SandboxFleetTraceBundle;
3931
+ interface TraceExportSink {
3932
+ url: string;
3933
+ headers?: Record<string, string>;
3934
+ format?: TraceExportFormat;
3935
+ serviceName?: string;
3936
+ timeoutMs?: number;
3937
+ fetch?: typeof fetch;
3938
+ }
3939
+ interface TraceExportResult {
3940
+ status: number;
3941
+ ok: boolean;
3942
+ body: string;
3943
+ }
3944
+ declare function buildTraceExportPayload(bundle: TraceExportBundle, format?: TraceExportFormat, serviceName?: string): TraceExportBundle | JsonObject;
3945
+ declare function exportTraceBundle(bundle: TraceExportBundle, sink: TraceExportSink): Promise<TraceExportResult>;
3946
+ declare function toOtelJson(bundle: TraceExportBundle, serviceName?: string): JsonObject;
3947
+ declare function otelTraceIdForTangleTrace(traceId: string): string;
3948
+ //#endregion
3949
+ //#region src/sandbox.d.ts
3950
+ /**
3951
+ * HTTP client interface for making requests.
3952
+ */
3953
+ interface HttpClient {
3954
+ fetch(path: string, options?: RequestInit): Promise<Response>;
3955
+ getApiKey?(): string | undefined;
3956
+ }
3957
+ /**
3958
+ * Git capability for repository operations.
3959
+ */
3960
+ interface GitCapability {
3961
+ /** Get repository status */
3962
+ status(): Promise<GitStatus>;
3963
+ /** Get commit log */
3964
+ log(limit?: number): Promise<GitCommit[]>;
3965
+ /** Get diff (optionally against a ref) */
3966
+ diff(ref?: string): Promise<GitDiff>;
3967
+ /** Stage files */
3968
+ add(paths: string[]): Promise<void>;
3969
+ /** Create a commit */
3970
+ commit(message: string, options?: {
3971
+ amend?: boolean;
3972
+ }): Promise<GitCommit>;
3973
+ /** Push to remote */
3974
+ push(options?: {
3975
+ force?: boolean;
3976
+ }): Promise<void>;
3977
+ /** Pull from remote */
3978
+ pull(options?: {
3979
+ rebase?: boolean;
3980
+ }): Promise<void>;
3981
+ /** List branches */
3982
+ branches(): Promise<GitBranch[]>;
3983
+ /** Checkout a branch or ref */
3984
+ checkout(ref: string, options?: {
3985
+ create?: boolean;
3986
+ }): Promise<void>;
3987
+ }
3988
+ /**
3989
+ * Tools capability for managing language runtimes via mise.
3990
+ */
3991
+ interface ToolsCapability {
3992
+ /** Install a tool version */
3993
+ install(tool: string, version: string): Promise<void>;
3994
+ /** Activate a tool version for the session */
3995
+ use(tool: string, version: string): Promise<void>;
3996
+ /** List installed tools */
3997
+ list(): Promise<InstalledTool[]>;
3998
+ /** Run a command with a specific tool */
3999
+ run(tool: string, args: string[]): Promise<ExecResult>;
4000
+ }
4001
+ /**
4002
+ * A sandbox instance with methods for interaction.
4003
+ */
4004
+ declare class SandboxInstance {
4005
+ private readonly client;
4006
+ private info;
4007
+ private readonly defaultRuntimeBackend?;
4008
+ constructor(client: HttpClient, info: SandboxInfo, defaultRuntimeBackend?: BackendConfig);
4009
+ /** Unique sandbox identifier */
4010
+ get id(): string;
4011
+ /** Human-readable name */
4012
+ get name(): string | undefined;
4013
+ /** Current status */
4014
+ get status(): SandboxStatus;
4015
+ /** Connection information */
4016
+ get connection(): SandboxConnection | undefined;
4017
+ /** Custom metadata */
4018
+ get metadata(): Record<string, unknown> | undefined;
4019
+ /** When the sandbox was created */
4020
+ get createdAt(): Date;
4021
+ /** When the sandbox started running */
4022
+ get startedAt(): Date | undefined;
4023
+ /** Last activity timestamp */
4024
+ get lastActivityAt(): Date | undefined;
4025
+ /** When the sandbox will expire */
4026
+ get expiresAt(): Date | undefined;
4027
+ /** Error message if status is 'failed' */
4028
+ get error(): string | undefined;
4029
+ /** Web terminal URL for browser-based access */
4030
+ get url(): string | undefined;
4031
+ /**
4032
+ * Serialize to the public sandbox shape for logs and structured
4033
+ * output. Secrets in `connection` (currently `authToken`) are
4034
+ * redacted so that `JSON.stringify(box)` is safe to ship to log
4035
+ * sinks. Use {@link toDebugJSON} when the bearer is required (e.g.
4036
+ * one-off CLI commands that print credentials to the user).
4037
+ */
4038
+ toJSON(): SandboxInfo;
4039
+ /**
4040
+ * Serialize the sandbox **including secrets** when `includeSecrets`
4041
+ * is true. The default behavior matches {@link toJSON} and redacts
4042
+ * `connection.authToken`.
4043
+ *
4044
+ * Use only when the caller has an explicit need for the bearer
4045
+ * (e.g. presenting it once to the human operator). Never wire the
4046
+ * result of `toDebugJSON({ includeSecrets: true })` into a structured
4047
+ * logger — the bearer will land in any log sink consuming that output.
4048
+ */
4049
+ toDebugJSON(options?: {
4050
+ includeSecrets?: boolean;
4051
+ }): SandboxInfo;
4052
+ /**
4053
+ * Create an advanced direct-runtime view of this sandbox.
4054
+ *
4055
+ * Runtime methods on the returned instance talk to the sandbox runtime
4056
+ * directly using `connection.runtimeUrl` and `connection.authToken`.
4057
+ * Lifecycle methods still go through the parent SDK client.
4058
+ */
4059
+ direct(): SandboxInstance;
4060
+ /**
4061
+ * Get an MCP endpoint for this sandbox. Returns a paste-able config
4062
+ * for any MCP-capable host (Claude Desktop, Cursor, claude-code,
4063
+ * codex, opencode, …) plus a freshly-minted, capability-scoped JWT.
4064
+ *
4065
+ * The token is short-lived and limited to the requested capabilities
4066
+ * — it cannot be used against admin endpoints (`/exec`, `/files`,
4067
+ * etc.) on the sandbox. Call `getMcpEndpoint()` again to rotate.
4068
+ *
4069
+ * Requires the sandbox to have been created with `capabilities`
4070
+ * including the requested capability (default: `computer_use`).
4071
+ *
4072
+ * @example
4073
+ * ```typescript
4074
+ * const ep = await box.getMcpEndpoint();
4075
+ * // Save ep.config to your IDE's mcp.json — that's it.
4076
+ * fs.writeFileSync("mcp.json", JSON.stringify(ep.config, null, 2));
4077
+ * ```
4078
+ */
4079
+ getMcpEndpoint(options?: {
4080
+ capabilities?: ReadonlyArray<"computer_use">; /** Override server entry name (default: "tangle-sandbox"). */
4081
+ serverName?: string; /** Token TTL in minutes (server clamps to its policy). */
4082
+ ttlMinutes?: number;
4083
+ }): Promise<SandboxMcpEndpoint>;
4084
+ /**
4085
+ * Refresh sandbox information from the server.
4086
+ */
4087
+ refresh(): Promise<void>;
4088
+ /**
4089
+ * Fetch fresh TEE attestation evidence for this sandbox.
4090
+ *
4091
+ * When `attestationNonce` is supplied, the runtime must return evidence bound
4092
+ * to that challenge or fail closed if the selected TEE backend cannot support
4093
+ * nonce-bound report data.
4094
+ */
4095
+ getTeeAttestation(options?: TeeAttestationOptions): Promise<TeeAttestationResponse>;
4096
+ /**
4097
+ * Fetch the TEE-bound public key used for sealed-secret encryption.
4098
+ *
4099
+ * The returned key includes an attestation report. Verify that report before
4100
+ * encrypting secrets to the key.
4101
+ */
4102
+ getTeePublicKey(): Promise<TeePublicKeyResponse>;
4103
+ /**
4104
+ * Bootstrap a real-time collaboration session for a file.
4105
+ * Returns the WebSocket URL and auth token needed to connect a
4106
+ * Hocuspocus/Yjs provider for live multi-user editing.
4107
+ *
4108
+ * @example
4109
+ * ```typescript
4110
+ * const collab = await box.collaborate("src/index.ts")
4111
+ * // Use collab.transport.websocketUrl + collab.transport.token
4112
+ * // with @hocuspocus/provider to connect
4113
+ * ```
4114
+ */
4115
+ collaborate(path: string, options?: {
4116
+ access?: "read" | "write";
4117
+ }): Promise<{
4118
+ documentId: string;
4119
+ transport: {
4120
+ websocketUrl: string;
4121
+ token: string;
4122
+ expiresAt: number;
4123
+ };
4124
+ permissions: {
4125
+ access: "read" | "write";
4126
+ canSnapshot: boolean;
4127
+ };
4128
+ }>;
4129
+ /**
4130
+ * Refresh a collaboration token for an existing document session.
4131
+ */
4132
+ /**
4133
+ * Refresh a collaboration token. Access level is preserved from the original
4134
+ * token — cannot be escalated (read stays read, write stays write).
4135
+ */
4136
+ refreshCollaborationToken(documentId: string, currentToken: string): Promise<{
4137
+ token: string;
4138
+ expiresAt: number;
4139
+ access: "read" | "write";
4140
+ }>;
4141
+ /**
4142
+ * Get SSH credentials for connecting to the sandbox.
4143
+ * Throws if SSH is not enabled or sandbox is not running.
4144
+ */
4145
+ ssh(): Promise<SSHCredentials>;
4146
+ sshCommand(): Promise<SSHCommandDescriptor>;
4147
+ /**
4148
+ * Execute a command in the sandbox.
4149
+ */
4150
+ exec(command: string, options?: ExecOptions): Promise<ExecResult>;
4151
+ /**
4152
+ * Read a file from the sandbox.
4153
+ *
4154
+ * @param path - Path to the file. Relative paths resolve from the workspace root.
4155
+ * Absolute paths (e.g., `/tmp/output.json`) access the container filesystem directly.
4156
+ * @returns File content as string
4157
+ *
4158
+ * @example
4159
+ * ```typescript
4160
+ * const content = await box.read("src/index.ts");
4161
+ * const report = await box.read("/output/report.json");
4162
+ * ```
4163
+ */
4164
+ read(path: string, options?: {
4165
+ sessionId?: string;
4166
+ }): Promise<string>;
4167
+ /**
4168
+ * Write content to a file in the sandbox.
4169
+ *
4170
+ * @param path - Path to the file. Relative paths resolve from the workspace root.
4171
+ * Absolute paths (e.g., `/tmp/cases.json`) write to the container filesystem directly.
4172
+ * @param content - Content to write
4173
+ *
4174
+ * @example
4175
+ * ```typescript
4176
+ * await box.write("src/fix.ts", "export const fix = () => {}");
4177
+ * await box.write("/tmp/config.json", JSON.stringify(config));
4178
+ * ```
4179
+ */
4180
+ write(path: string, content: string): Promise<void>;
4181
+ /**
4182
+ * Send a prompt to the agent running in the sandbox.
4183
+ * Returns the complete response after the agent finishes.
4184
+ */
4185
+ prompt(message: string | PromptInputPart[], options?: PromptOptions): Promise<PromptResult>;
4186
+ /**
4187
+ * Stream events from an agent prompt.
4188
+ * Use this for real-time updates during agent execution.
4189
+ *
4190
+ * Automatically reconnects via the runtime event replay endpoint if the
4191
+ * SSE stream drops before a terminal event (`result` or `done`) is received.
4192
+ * Reconnection is transparent — replayed events that were already yielded
4193
+ * (based on event ID tracking) are deduplicated.
4194
+ */
4195
+ streamPrompt(message: string | PromptInputPart[], options?: PromptOptions): AsyncGenerator<SandboxEvent>;
4196
+ /**
4197
+ * Stream sandbox lifecycle and activity events.
4198
+ */
4199
+ events(options?: EventStreamOptions): AsyncGenerator<SandboxEvent>;
4200
+ trace(options?: SandboxTraceOptions): Promise<SandboxTraceBundle>;
4201
+ intelligence(): Promise<NonNullable<SandboxTraceBundle["intelligence"]>>;
4202
+ createIntelligenceReport(options?: {
4203
+ mode?: "deterministic" | "agentic";
4204
+ acknowledgeCost?: boolean;
4205
+ budget?: IntelligenceReportBudget;
4206
+ metadata?: Record<string, unknown>;
4207
+ }): Promise<IntelligenceReport>;
4208
+ createAgenticIntelligenceReport(options: {
4209
+ maxUsd: number;
4210
+ metadata?: Record<string, unknown>;
4211
+ }): Promise<IntelligenceReport>;
4212
+ exportTrace(sink: TraceExportSink): Promise<TraceExportResult>;
4213
+ /**
4214
+ * Stream real-time provisioning progress events.
4215
+ *
4216
+ * Connects to the SSE events stream and yields typed `ProvisionEvent` objects
4217
+ * for each provisioning step. The generator completes when provisioning
4218
+ * finishes (success or failure) and returns the terminal result.
4219
+ *
4220
+ * @returns AsyncGenerator of ProvisionEvent, with a ProvisionResult return value
4221
+ *
4222
+ * @example
4223
+ * ```typescript
4224
+ * const box = await client.create({ image: "ethereum" });
4225
+ *
4226
+ * const stream = box.watchProvisioning();
4227
+ * for await (const event of stream) {
4228
+ * console.log(`[${event.step}] ${event.status} — ${event.message}`);
4229
+ * }
4230
+ * // stream.return value contains the terminal result
4231
+ * ```
4232
+ */
4233
+ watchProvisioning(options?: {
4234
+ signal?: AbortSignal;
4235
+ }): AsyncGenerator<ProvisionEvent, ProvisionResult | undefined>;
4236
+ /**
4237
+ * Run an agentic task until completion.
4238
+ *
4239
+ * Unlike prompt(), task() is designed for autonomous agent work:
4240
+ * - The agent works until it completes the task or hits an error
4241
+ * - Session state is maintained for context continuity
4242
+ * - Token usage is aggregated across the execution
4243
+ *
4244
+ * Note: The agent (OpenCode/Claude) handles multi-turn execution internally.
4245
+ * Most tasks complete in a single call. The maxTurns option is for edge cases
4246
+ * where the agent explicitly signals it needs additional input.
4247
+ *
4248
+ * @param prompt - Task description for the agent
4249
+ * @param options - Task options
4250
+ * @returns Task result with response and execution metadata
4251
+ */
4252
+ task(prompt: string, options?: TaskOptions): Promise<TaskResult>;
4253
+ /**
4254
+ * Stream events from a task execution.
4255
+ *
4256
+ * Use this for real-time updates as the agent works:
4257
+ * - Tool calls and results
4258
+ * - Thinking/reasoning steps
4259
+ * - File operations
4260
+ * - Final response
4261
+ *
4262
+ * @param prompt - Task description for the agent
4263
+ * @param options - Task options
4264
+ */
4265
+ streamTask(prompt: string, options?: TaskOptions): AsyncGenerator<SandboxEvent>;
4266
+ /**
4267
+ * Search for text patterns in files using ripgrep.
4268
+ *
4269
+ * This is a first-class code search capability, not a shell wrapper.
4270
+ * Ripgrep is pre-installed in all managed sandboxes.
4271
+ *
4272
+ * @param pattern - Regular expression pattern to search for
4273
+ * @param options - Search options
4274
+ * @returns Async iterator of search matches
4275
+ *
4276
+ * @example Search for task-marker comments
4277
+ * ```typescript
4278
+ * for await (const match of box.search("TASK:", { glob: "**\/*.ts" })) {
4279
+ * console.log(`${match.path}:${match.line}: ${match.text}`);
4280
+ * }
4281
+ * ```
4282
+ *
4283
+ * @example Collect all matches
4284
+ * ```typescript
4285
+ * const matches = [];
4286
+ * for await (const match of box.search("function.*async")) {
4287
+ * matches.push(match);
4288
+ * }
4289
+ * ```
4290
+ */
4291
+ search(pattern: string, options?: SearchOptions): AsyncGenerator<SearchMatch>;
4292
+ /**
4293
+ * Git capability object for repository operations.
4294
+ *
4295
+ * All git operations are executed in the sandbox workspace.
4296
+ *
4297
+ * @example Check status and commit
4298
+ * ```typescript
4299
+ * const status = await box.git.status();
4300
+ * if (status.isDirty) {
4301
+ * await box.git.add(["."]);
4302
+ * await box.git.commit("Update files");
4303
+ * await box.git.push();
4304
+ * }
4305
+ * ```
4306
+ */
4307
+ get git(): GitCapability;
4308
+ private gitStatus;
4309
+ private gitLog;
4310
+ private gitDiff;
4311
+ private gitAdd;
4312
+ private gitCommit;
4313
+ private gitPush;
4314
+ private gitPull;
4315
+ private gitBranches;
4316
+ private gitCheckout;
4317
+ /**
4318
+ * Tools capability object for managing language runtimes.
4319
+ *
4320
+ * Uses mise (polyglot version manager) to install and manage tools.
4321
+ *
4322
+ * @example Install and use Node.js
4323
+ * ```typescript
4324
+ * await box.tools.install("node", "22");
4325
+ * await box.tools.use("node", "22");
4326
+ * const list = await box.tools.list();
4327
+ * ```
4328
+ */
4329
+ get tools(): ToolsCapability;
4330
+ /**
4331
+ * File system operations beyond basic read/write:
4332
+ * - Binary upload/download
4333
+ * - Directory ops (uploadDir, downloadDir, list, mkdir)
4334
+ * - Metadata (stat, exists)
4335
+ * - Progress reporting for large files
4336
+ *
4337
+ * @example Upload and download
4338
+ * ```typescript
4339
+ * await box.fs.upload("./model.bin", "/workspace/models/model.bin");
4340
+ * await box.fs.download("/workspace/results.zip", "./results.zip");
4341
+ * ```
4342
+ *
4343
+ * @example Directory operations
4344
+ * ```typescript
4345
+ * await box.fs.uploadDir("./project", "/workspace/project");
4346
+ * const files = await box.fs.list("/workspace");
4347
+ * ```
4348
+ *
4349
+ * @example File management
4350
+ * ```typescript
4351
+ * if (await box.fs.exists("/workspace/config.json")) {
4352
+ * const info = await box.fs.stat("/workspace/config.json");
4353
+ * console.log(`Size: ${info.size}`);
4354
+ * }
4355
+ * await box.fs.mkdir("/workspace/output", { recursive: true });
4356
+ * await box.fs.delete("/workspace/temp", { recursive: true });
4357
+ * ```
4358
+ */
4359
+ get fs(): FileSystem;
4360
+ private fsUpload;
4361
+ private fsDownload;
4362
+ private fsUploadDir;
4363
+ private fsDownloadDir;
4364
+ private fsList;
4365
+ private fsStat;
4366
+ private fsDelete;
4367
+ private fsMkdir;
4368
+ private fsExists;
4369
+ /**
4370
+ * Permissions manager for multi-user access control.
4371
+ *
4372
+ * @example List users
4373
+ * ```typescript
4374
+ * const users = await box.permissions.list();
4375
+ * for (const user of users) {
4376
+ * console.log(`${user.username}: ${user.role}`);
4377
+ * }
4378
+ * ```
4379
+ *
4380
+ * @example Add a developer
4381
+ * ```typescript
4382
+ * await box.permissions.add({
4383
+ * userId: "user_abc",
4384
+ * role: "developer",
4385
+ * sshKeys: ["ssh-ed25519 AAAA..."],
4386
+ * });
4387
+ * ```
4388
+ */
4389
+ get permissions(): PermissionsManager;
4390
+ private permissionsList;
4391
+ private permissionsGet;
4392
+ private permissionsAdd;
4393
+ private permissionsUpdate;
4394
+ private permissionsRemove;
4395
+ private permissionsSetAccessPolicies;
4396
+ private permissionsGetAccessPolicies;
4397
+ private permissionsCheckAccess;
4398
+ /**
4399
+ * Backend manager for runtime agent configuration.
4400
+ *
4401
+ * @example Check backend status
4402
+ * ```typescript
4403
+ * const status = await box.backend.status();
4404
+ * console.log(`Backend: ${status.type}, Status: ${status.status}`);
4405
+ * ```
4406
+ *
4407
+ * @example Add MCP server at runtime
4408
+ * ```typescript
4409
+ * await box.backend.addMcp("web-search", {
4410
+ * command: "npx",
4411
+ * args: ["-y", "@anthropic/web-search"],
4412
+ * });
4413
+ * ```
4414
+ *
4415
+ * @example Read provider-native Cursor metadata
4416
+ * ```typescript
4417
+ * const models = await box.backend.models();
4418
+ * const agents = await box.backend.agents({ limit: 20 });
4419
+ * const runs = await box.backend.runs(agents.items[0].agentId);
4420
+ * ```
4421
+ */
4422
+ get backend(): BackendManager;
4423
+ private backendStatus;
4424
+ private backendCapabilities;
4425
+ private backendAddMcp;
4426
+ private backendGetMcpStatus;
4427
+ private backendUpdateConfig;
4428
+ private backendControlData;
4429
+ private backendControlAction;
4430
+ private backendListSearch;
4431
+ private backendAccount;
4432
+ private backendModels;
4433
+ private backendRepositories;
4434
+ private backendAgents;
4435
+ private backendAgent;
4436
+ private backendArchiveAgent;
4437
+ private backendUnarchiveAgent;
4438
+ private backendDeleteAgent;
4439
+ private backendRuns;
4440
+ private backendRun;
4441
+ private backendAgentMessages;
4442
+ private backendArtifacts;
4443
+ private backendDownloadArtifact;
4444
+ private backendRestart;
4445
+ /**
4446
+ * Process manager for spawning and controlling processes.
4447
+ *
4448
+ * Provides non-blocking process execution with real-time log streaming,
4449
+ * ideal for long-running tasks like ML training or dev servers.
4450
+ *
4451
+ * @example Non-blocking process
4452
+ * ```typescript
4453
+ * const proc = await box.process.spawn("python train.py", {
4454
+ * cwd: "/workspace",
4455
+ * env: { "CUDA_VISIBLE_DEVICES": "0" }
4456
+ * });
4457
+ *
4458
+ * // Stream logs
4459
+ * for await (const entry of proc.logs()) {
4460
+ * console.log(`[${entry.type}] ${entry.data}`);
4461
+ * }
4462
+ *
4463
+ * // Check status
4464
+ * const status = await proc.status();
4465
+ * console.log(`Running: ${status.running}`);
4466
+ *
4467
+ * // Kill if needed
4468
+ * await proc.kill();
4469
+ * ```
4470
+ *
4471
+ * @example Run Python code directly
4472
+ * ```typescript
4473
+ * const result = await box.process.runCode(`
4474
+ * import numpy as np
4475
+ * print(np.random.rand(10).mean())
4476
+ * `);
4477
+ * console.log(result.stdout);
4478
+ * ```
4479
+ */
4480
+ get process(): ProcessManager;
4481
+ private processSpawn;
4482
+ private processRunCode;
4483
+ private processList;
4484
+ private processGet;
4485
+ private createProcessHandle;
4486
+ private parseProcessLogStream;
4487
+ /**
4488
+ * Network manager for runtime network configuration.
4489
+ *
4490
+ * @example Update network restrictions
4491
+ * ```typescript
4492
+ * // Block all outbound traffic
4493
+ * await box.network.update({ blockOutbound: true });
4494
+ *
4495
+ * // Or switch to allowlist mode
4496
+ * await box.network.update({
4497
+ * allowList: ["192.168.1.0/24", "8.8.8.8/32"]
4498
+ * });
4499
+ * ```
4500
+ *
4501
+ * @example Expose ports dynamically
4502
+ * ```typescript
4503
+ * const url = await box.network.exposePort(8000);
4504
+ * console.log(`Service available at: ${url}`);
4505
+ * ```
4506
+ */
4507
+ get network(): NetworkManager;
4508
+ private networkUpdate;
4509
+ private networkExposePort;
4510
+ private networkListUrls;
4511
+ private networkGetConfig;
4512
+ /**
4513
+ * Validate CIDR notation (IPv4 and IPv6)
4514
+ */
4515
+ private isValidCidr;
4516
+ /**
4517
+ * Preview link management.
4518
+ *
4519
+ * Create publicly accessible HTTPS URLs for TCP ports inside the sandbox.
4520
+ *
4521
+ * @example
4522
+ * ```typescript
4523
+ * const link = await box.previewLinks.create(3000);
4524
+ * console.log(link.url);
4525
+ *
4526
+ * const links = await box.previewLinks.list();
4527
+ * await box.previewLinks.remove(link.previewId);
4528
+ * ```
4529
+ */
4530
+ get previewLinks(): PreviewLinkManager;
4531
+ private previewLinkCreate;
4532
+ private previewLinkList;
4533
+ private previewLinkRemove;
4534
+ /**
4535
+ * Get information about the infrastructure driver for this sandbox.
4536
+ *
4537
+ * @example
4538
+ * ```typescript
4539
+ * const info = await box.getDriverInfo();
4540
+ * console.log(`Driver: ${info.type}, CRIU: ${info.capabilities.criu}`);
4541
+ * ```
4542
+ */
4543
+ getDriverInfo(): Promise<DriverInfo>;
4544
+ private toolsInstall;
4545
+ private toolsUse;
4546
+ private toolsList;
4547
+ private toolsRun;
4548
+ /**
4549
+ * Create a snapshot of the sandbox state.
4550
+ * Snapshots can be used to save workspace state for later restoration.
4551
+ *
4552
+ * If `storage` is provided (BYOS3), the snapshot is created directly
4553
+ * directly on the sandbox and uploaded to customer-provided S3 storage.
4554
+ *
4555
+ * @param options - Snapshot options (tags, paths, storage)
4556
+ * @returns Snapshot result with ID and metadata
4557
+ *
4558
+ * @example Standard snapshot (our storage)
4559
+ * ```typescript
4560
+ * const snap = await box.snapshot({
4561
+ * tags: ["v1.0", "stable"],
4562
+ * });
4563
+ * console.log(`Snapshot: ${snap.snapshotId}`);
4564
+ * ```
4565
+ *
4566
+ * @example BYOS3 snapshot (customer storage)
4567
+ * ```typescript
4568
+ * const snap = await box.snapshot({
4569
+ * tags: ["production"],
4570
+ * storage: {
4571
+ * type: "s3",
4572
+ * bucket: "my-snapshots",
4573
+ * credentials: { accessKeyId: "...", secretAccessKey: "..." },
4574
+ * },
4575
+ * });
4576
+ * ```
4577
+ */
4578
+ snapshot(options?: SnapshotOptions): Promise<SnapshotResult>;
4579
+ /**
4580
+ * List all snapshots for this sandbox.
4581
+ *
4582
+ * If `storage` is provided (BYOS3), lists snapshots from customer-provided
4583
+ * S3 storage.
4584
+ *
4585
+ * @param storage - Optional customer storage config for BYOS3
4586
+ * @returns Array of snapshot metadata
4587
+ *
4588
+ * @example List from our storage
4589
+ * ```typescript
4590
+ * const snapshots = await box.listSnapshots();
4591
+ * for (const snap of snapshots) {
4592
+ * console.log(`${snap.snapshotId}: ${snap.createdAt}`);
4593
+ * }
4594
+ * ```
4595
+ *
4596
+ * @example List from customer S3 (BYOS3)
4597
+ * ```typescript
4598
+ * const snapshots = await box.listSnapshots({
4599
+ * type: "s3",
4600
+ * bucket: "my-snapshots",
4601
+ * credentials: { accessKeyId: "...", secretAccessKey: "..." },
4602
+ * });
4603
+ * ```
4604
+ */
4605
+ listSnapshots(storage?: SnapshotOptions["storage"]): Promise<SnapshotInfo[]>;
4606
+ revertToSnapshot(snapshotId: string): Promise<SnapshotResult>;
4607
+ private waitForSnapshotRestore;
4608
+ private waitForSnapshotVisible;
4609
+ deleteSnapshot(snapshotId: string): Promise<void>;
4610
+ /**
4611
+ * Restore from the latest snapshot in customer-provided storage.
4612
+ * Only available when using BYOS3 (calls the runtime directly).
4613
+ *
4614
+ * @param storage - Customer storage config (required)
4615
+ * @param destinationPath - Optional path to restore to
4616
+ * @returns Snapshot info if restored, null if no snapshot found
4617
+ *
4618
+ * @example Restore from customer S3
4619
+ * ```typescript
4620
+ * const result = await box.restoreFromStorage({
4621
+ * type: "s3",
4622
+ * bucket: "my-snapshots",
4623
+ * credentials: { accessKeyId: "...", secretAccessKey: "..." },
4624
+ * });
4625
+ *
4626
+ * if (result) {
4627
+ * console.log(`Restored from ${result.snapshotId}`);
4628
+ * } else {
4629
+ * console.log("No snapshot found");
4630
+ * }
4631
+ * ```
4632
+ */
4633
+ restoreFromStorage(storage: SnapshotOptions["storage"], options?: RestoreSnapshotOptions): Promise<SnapshotResult | null>;
4634
+ /**
4635
+ * Create a CRIU checkpoint of the sandbox's memory state.
4636
+ *
4637
+ * Checkpoints capture the complete memory state of the running sandbox,
4638
+ * enabling true pause/resume and fork operations. Unlike snapshots which
4639
+ * only preserve filesystem state, checkpoints preserve process memory,
4640
+ * open file descriptors, and execution state.
4641
+ *
4642
+ * **Requirements:** CRIU must be available on the host. Check availability
4643
+ * with `client.criuStatus()` before calling.
4644
+ *
4645
+ * **Note:** By default, checkpoint stops the sandbox. Use `leaveRunning: true`
4646
+ * to keep it running (creates a copy-on-write checkpoint).
4647
+ *
4648
+ * @param options - Checkpoint options
4649
+ * @returns Checkpoint result with ID and metadata
4650
+ *
4651
+ * @example Basic checkpoint (stops sandbox)
4652
+ * ```typescript
4653
+ * const checkpoint = await box.checkpoint();
4654
+ * console.log(`Checkpoint: ${checkpoint.checkpointId}`);
4655
+ * // Sandbox is now stopped, resume with box.resume()
4656
+ * ```
4657
+ *
4658
+ * @example Checkpoint without stopping
4659
+ * ```typescript
4660
+ * const checkpoint = await box.checkpoint({
4661
+ * tags: ["before-deploy"],
4662
+ * leaveRunning: true,
4663
+ * });
4664
+ * // Sandbox continues running
4665
+ * ```
4666
+ */
4667
+ checkpoint(options?: CheckpointOptions): Promise<CheckpointResult>;
4668
+ /**
4669
+ * List all checkpoints for this sandbox.
4670
+ *
4671
+ * @returns Array of checkpoint metadata
4672
+ *
4673
+ * @example
4674
+ * ```typescript
4675
+ * const checkpoints = await box.listCheckpoints();
4676
+ * for (const cp of checkpoints) {
4677
+ * console.log(`${cp.checkpointId}: ${cp.createdAt}`);
4678
+ * }
4679
+ * ```
4680
+ */
4681
+ listCheckpoints(): Promise<CheckpointInfo[]>;
4682
+ /**
4683
+ * Delete a checkpoint.
4684
+ *
4685
+ * @param checkpointId - ID of the checkpoint to delete
4686
+ */
4687
+ deleteCheckpoint(checkpointId: string): Promise<void>;
4688
+ /**
4689
+ * Fork a new sandbox from a checkpoint.
4690
+ *
4691
+ * Creates a new sandbox with the same memory state as this sandbox
4692
+ * at the time of the checkpoint. The fork has a new identity but
4693
+ * preserves the execution state.
4694
+ *
4695
+ * **Use cases:**
4696
+ * - Branch workflows: Create parallel execution paths
4697
+ * - A/B testing: Run same state with different configurations
4698
+ * - Debugging: Fork at a specific point to investigate
4699
+ *
4700
+ * @param checkpointId - ID of the checkpoint to fork from
4701
+ * @param options - Fork configuration
4702
+ * @returns The new sandbox instance
4703
+ *
4704
+ * @example Basic fork
4705
+ * ```typescript
4706
+ * const checkpoint = await box.checkpoint({ leaveRunning: true });
4707
+ * const forked = await box.fork(checkpoint.checkpointId);
4708
+ * // forked has same memory state as box at checkpoint time
4709
+ * ```
4710
+ *
4711
+ * @example Fork with custom config
4712
+ * ```typescript
4713
+ * const forked = await box.fork(checkpointId, {
4714
+ * name: "experiment-branch",
4715
+ * env: { EXPERIMENT: "true" },
4716
+ * });
4717
+ * ```
4718
+ */
4719
+ fork(checkpointId: string, options?: ForkOptions): Promise<SandboxInstance>;
4720
+ /**
4721
+ * Stop the sandbox (keeps state for resume).
4722
+ */
4723
+ stop(): Promise<void>;
4724
+ /**
4725
+ * Resume a stopped sandbox.
4726
+ */
4727
+ resume(): Promise<void>;
4728
+ /**
4729
+ * Delete the sandbox permanently.
4730
+ */
4731
+ delete(): Promise<void>;
4732
+ /**
4733
+ * keepAlive is intentionally unavailable until the API exposes timeout updates.
4734
+ * @param seconds - Reserved for future support
4735
+ */
4736
+ keepAlive(_seconds?: number): Promise<void>;
4737
+ /**
4738
+ * Upload a local directory to the sandbox via tar.
4739
+ * @param localPath - Local directory path to upload
4740
+ * @param remotePath - Destination path in the sandbox (default: /home/user)
4741
+ */
4742
+ uploadDirectory(localPath: string, remotePath?: string): Promise<void>;
4743
+ /**
4744
+ * Wait for the sandbox to reach a specific status.
4745
+ *
4746
+ * When `onProgress` is provided and the sandbox is still provisioning,
4747
+ * uses SSE events for real-time progress instead of polling. Falls back
4748
+ * to polling if the SSE connection fails or is unavailable.
4749
+ *
4750
+ * @example Basic wait
4751
+ * ```typescript
4752
+ * await box.waitFor("running");
4753
+ * ```
4754
+ *
4755
+ * @example Wait with progress tracking
4756
+ * ```typescript
4757
+ * await box.waitFor("running", {
4758
+ * onProgress: (event) => {
4759
+ * console.log(`[${event.step}] ${event.status} — ${event.message}`);
4760
+ * if (event.percent !== undefined) {
4761
+ * updateProgressBar(event.percent);
4762
+ * }
4763
+ * },
4764
+ * });
4765
+ * ```
4766
+ */
4767
+ waitFor(status: SandboxStatus | SandboxStatus[], options?: WaitForOptions): Promise<void>;
4768
+ /**
4769
+ * SSE-based wait implementation. Subscribes to provisioning events and
4770
+ * delivers progress callbacks while waiting for a target status.
4771
+ */
4772
+ private waitForWithSSE;
4773
+ private parseCheckpointInfo;
4774
+ private ensureRunning;
4775
+ private runtimeFetch;
4776
+ /**
4777
+ * Delegates to the shared `parseSSEStream` in `lib/sse-parser.ts`
4778
+ * — one canonical SSE implementation for the whole SDK. The
4779
+ * shared parser throws `AbortError` on cancellation (so consumers
4780
+ * can distinguish cancel from clean EOF), but agent/task streaming
4781
+ * callers of this method historically relied on a silent-return
4782
+ * abort: they check `options?.signal?.aborted` AFTER the loop and
4783
+ * decide whether to reconnect. The try/catch below preserves that
4784
+ * legacy contract by swallowing AbortError at the delegate layer.
4785
+ */
4786
+ private parseSSEStream;
4787
+ /**
4788
+ * Associate a session ID with a user ID so the Sandbox API can route
4789
+ * subsequent WebSocket connections to this sandbox.
4790
+ *
4791
+ * @param opts - Session and user identifiers
4792
+ *
4793
+ * @example
4794
+ * ```typescript
4795
+ * await box.registerSessionMapping({
4796
+ * sessionId: "sess_abc",
4797
+ * userId: "user_123",
4798
+ * });
4799
+ * ```
4800
+ */
4801
+ registerSessionMapping(opts: {
4802
+ sessionId: string;
4803
+ userId: string;
4804
+ }): Promise<void>;
4805
+ private parseInfo;
4806
+ private sleep;
4807
+ /**
4808
+ * Get a session reference bound to this sandbox. Lazy: does not hit the
4809
+ * network until you call a method on the returned `SandboxSession`.
4810
+ * Use {@link sessions} to discover existing session ids.
4811
+ */
4812
+ session(id: string): SandboxSession;
4813
+ /**
4814
+ * List sessions on this sandbox, optionally filtering by status. Returns
4815
+ * `SandboxSession` instances paired with their last-known
4816
+ * {@link SessionInfo} so callers can avoid an extra round-trip per
4817
+ * session for status.
4818
+ */
4819
+ sessions(opts?: SessionListOptions): Promise<Array<{
4820
+ session: SandboxSession;
4821
+ info: SessionInfo;
4822
+ }>>;
4823
+ /**
4824
+ * Dispatch a prompt and return immediately with the session id (Issue
4825
+ * #913 Gap 2). The sandbox keeps running the prompt after this call
4826
+ * returns; reconnect via `box.session(id).events()` or wait for
4827
+ * completion with `box.session(id).result()`.
4828
+ *
4829
+ * Idempotent on `opts.sessionId`: re-dispatching with the same id when
4830
+ * the session is already running is a lookup, not a re-create. This
4831
+ * lets queue retries and reconnect-after-Worker-restart be safe by
4832
+ * construction.
4833
+ */
4834
+ dispatchPrompt(message: string | PromptInputPart[], opts?: DispatchPromptOptions): Promise<DispatchedSession>;
4835
+ /**
4836
+ * Mint a scoped, time-bounded JWT for direct browser access to this
4837
+ * sandbox (Issue #913 Gap 1). Authority is the caller's
4838
+ * `TANGLE_API_KEY` (sk-tan-*) — the Sandbox API mints the token;
4839
+ * signing secrets stay server-side.
4840
+ *
4841
+ * Use this to give a browser direct read access to the sandbox without
4842
+ * leaking the full bearer (`box.connection.authToken`). The returned
4843
+ * token verifies against the same sidecar middleware that already
4844
+ * gates ProductTokenIssuer-issued JWTs — no new sidecar surface.
4845
+ */
4846
+ mintScopedToken(opts: MintScopedTokenOptions): Promise<ScopedToken>;
4847
+ /** @internal — invoked by SandboxSession.status(). */
4848
+ _sessionStatus(id: string): Promise<SessionInfo | null>;
4849
+ /** @internal — invoked by SandboxSession.events(). */
4850
+ _sessionEvents(id: string, opts?: SessionEventStreamOptions): AsyncGenerator<SandboxEvent>;
4851
+ /** @internal — invoked by SandboxSession.result(). */
4852
+ _sessionResult(id: string): Promise<PromptResult>;
4853
+ /** @internal — invoked by SandboxSession.cancel(). */
4854
+ _sessionCancel(id: string): Promise<void>;
4855
+ }
4856
+ //#endregion
4857
+ export { FleetExecDispatchOptions as $, StorageConfig as $n, SandboxClientConfig as $t, CreateIntelligenceReportOptions as A, SandboxInfo as An, defineInlineResource as Ar, ProcessLogEntry as At, DownloadProgress as B, ScopedToken as Bn, ProvisionStatus as Bt, BatchResult as C, SandboxFleetTraceExport as Cn, AgentProfileResourceRef as Cr, NetworkManager as Ct, CheckpointOptions as D, SandboxFleetWorkspaceReconcileResult as Dn, AgentSubagentProfile as Dr, PreviewLinkManager as Dt, CheckpointInfo as E, SandboxFleetWorkspace as En, AgentProfileValidationResult as Er, PreviewLinkInfo as Et, DeleteOptions as F, SandboxTraceBundle as Fn, SandboxMcpEndpoint as Fr, PromptInputPart as Ft, ExecOptions as G, SecretsManager as Gn, PublishPublicTemplateVersionOptions as Gt, DriverInfo as H, SearchMatch as Hn, PublicTemplateInfo as Ht, DirectoryPermission as I, SandboxTraceEvent as In, SandboxMcpServerEntry as Ir, PromptOptions as It, FileSystem as J, SessionListOptions as Jn, ReconcileSandboxFleetsOptions as Jt, ExecResult as K, SessionEventStreamOptions as Kn, ReapExpiredSandboxFleetsOptions as Kt, DispatchPromptOptions as L, SandboxTraceExport as Ln, buildSandboxMcpConfig as Lr, PromptResult as Lt, CreateSandboxFleetTokenOptions as M, SandboxPermissionsConfig as Mn, BuildSandboxMcpConfigOptions as Mr, ProcessSignal as Mt, CreateSandboxFleetWithCoordinatorOptions as N, SandboxResources as Nn, SANDBOX_MCP_SERVER_NAME as Nr, ProcessSpawnOptions as Nt, CheckpointResult as O, SandboxFleetWorkspaceRestoreResult as On, defineAgentProfile as Or, Process as Ot, CreateSandboxOptions as P, SandboxStatus as Pn, SandboxMcpConfig as Pr, ProcessStatus as Pt, FleetDispatchStreamOptions as Q, SnapshotResult as Qn, SSHCredentials as Qt, DispatchedSession as R, SandboxTraceOptions as Rn, ProvisionEvent as Rt, BatchOptions as S, SandboxFleetTraceEvent as Sn, AgentProfilePrompt as Sr, NetworkConfig as St, BatchTaskResult as T, SandboxFleetUsage as Tn, AgentProfileValidationIssue as Tr, PermissionsManager as Tt, DriverType as U, SearchOptions as Un, PublicTemplateVersionInfo as Ut, DriverConfig as V, ScopedTokenScope as Vn, ProvisionStep as Vt, EventStreamOptions as W, SecretInfo as Wn, PublishPublicTemplateOptions as Wt, FleetDispatchResultBuffer as X, SnapshotInfo as Xn, RunCodeOptions as Xt, FleetDispatchCancelResult as Y, SessionStatus as Yn, ReconcileSandboxFleetsResult as Yt, FleetDispatchResultBufferOptions as Z, SnapshotOptions as Zn, SSHCommandDescriptor as Zt, BackendInfo as _, SandboxFleetManifestMachine as _n, AgentProfileConfidential as _r, ListSandboxFleetOptions as _t, TraceExportSink as a, SandboxFleetCostEstimate as an, TeeAttestationResponse as ar, ForkResult as at, BackendType as b, SandboxFleetToken as bn, AgentProfileModelHints as br, MintScopedTokenOptions as bt, otelTraceIdForTangleTrace as c, SandboxFleetDriverCapability as cn, TokenRefreshHandler as cr, GitCommit as ct, AcceleratorKind as d, SandboxFleetIntelligenceEnvelope as dn, UploadOptions as dr, GitStatus as dt, SandboxConnection as en, SubscriptionInfo as er, FleetExecDispatchResult as et, AccessPolicyRule as f, SandboxFleetMachine as fn, UploadProgress as fr, GpuType as ft, BackendConfig as g, SandboxFleetManifest as gn, AgentProfileCapabilities as gr, ListOptions as gt, BackendCapabilities as h, SandboxFleetMachineSpec as hn, AgentProfile as hr, IntelligenceReportBudget as ht, TraceExportResult as i, SandboxFleetArtifactSpec as in, TeeAttestationReport as ir, ForkOptions as it, CreateSandboxFleetOptions as j, SandboxIntelligenceEnvelope as jn, mergeAgentProfiles as jr, ProcessManager as jt, CodeResult as k, SandboxFleetWorkspaceSnapshotResult as kn, defineGitHubResource as kr, ProcessInfo as kt, toOtelJson as l, SandboxFleetDriverTimings as ln, ToolsConfig as lr, GitConfig as lt, AttachSandboxFleetMachineOptions as m, SandboxFleetMachineRecord as mn, WaitForOptions as mr, IntelligenceReport as mt, SandboxInstance as n, SandboxEvent as nn, TaskResult as nr, FleetPromptDispatchOptions as nt, buildTraceExportPayload as o, SandboxFleetDispatchFailureClass as on, TeePublicKey as or, GitAuth as ot, AddUserOptions as p, SandboxFleetMachineMeteredUsage as pn, UsageInfo as pr, InstalledTool as pt, FileInfo as q, SessionInfo as qn, ReapExpiredSandboxFleetsResult as qt, TraceExportFormat as r, SandboxFleetArtifact as rn, TeeAttestationOptions as rr, FleetPromptDispatchResult as rt, exportTraceBundle as s, SandboxFleetDispatchResponse as sn, TeePublicKeyResponse as sr, GitBranch as st, HttpClient as t, SandboxEnvironment as tn, TaskOptions as tr, FleetMachineId as tt, SandboxSession as u, SandboxFleetInfo as un, UpdateUserOptions as ur, GitDiff as ut, BackendManager as v, SandboxFleetOperationsSummary as vn, AgentProfileFileMount as vr, ListSandboxOptions as vt, BatchTask as w, SandboxFleetTraceOptions as wn, AgentProfileResources as wr, PermissionLevel as wt, BatchEvent as x, SandboxFleetTraceBundle as xn, AgentProfilePermissionValue as xr, MkdirOptions as xt, BackendStatus as y, SandboxFleetPolicy as yn, AgentProfileMcpServer as yr, McpServerConfig as yt, DownloadOptions as z, SandboxUser as zn, ProvisionResult as zt };