@cloudflare/sandbox 0.13.0-next.651.1 → 0.13.0-next.681.1

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.
Files changed (62) hide show
  1. package/Dockerfile +6 -11
  2. package/README.md +2 -2
  3. package/dist/bridge/index.js +68 -49
  4. package/dist/bridge/index.js.map +1 -1
  5. package/dist/codes-y-U76vnQ.d.ts +79 -0
  6. package/dist/codes-y-U76vnQ.d.ts.map +1 -0
  7. package/dist/contexts-DY1LHU1v.d.ts +327 -0
  8. package/dist/contexts-DY1LHU1v.d.ts.map +1 -0
  9. package/dist/{dist-DF8sudAg.js → dist-BStBkGIC.js} +33 -93
  10. package/dist/dist-BStBkGIC.js.map +1 -0
  11. package/dist/errors/index.d.ts +4 -0
  12. package/dist/errors/index.js +4 -0
  13. package/dist/errors-ewgSNicb.js +741 -0
  14. package/dist/errors-ewgSNicb.js.map +1 -0
  15. package/dist/{errors-BG6NZiPD.js → errors-k3B8orjH.js} +41 -4
  16. package/dist/errors-k3B8orjH.js.map +1 -0
  17. package/dist/extensions/index.d.ts +2 -74
  18. package/dist/extensions/index.js +3 -152
  19. package/dist/extensions-CepYdzro.js +191 -0
  20. package/dist/extensions-CepYdzro.js.map +1 -0
  21. package/dist/git/index.d.ts +74 -0
  22. package/dist/git/index.d.ts.map +1 -0
  23. package/dist/git/index.js +345 -0
  24. package/dist/git/index.js.map +1 -0
  25. package/dist/{rpc-types-PBUY-xXM.d.ts → index-B7QgIs0N.d.ts} +571 -409
  26. package/dist/index-B7QgIs0N.d.ts.map +1 -0
  27. package/dist/index-Dy6u9r60.d.ts +390 -0
  28. package/dist/index-Dy6u9r60.d.ts.map +1 -0
  29. package/dist/index.d.ts +27 -190
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +12 -43
  32. package/dist/index.js.map +1 -1
  33. package/dist/interpreter/index.d.ts +309 -0
  34. package/dist/interpreter/index.d.ts.map +1 -0
  35. package/dist/interpreter/index.js +264 -0
  36. package/dist/interpreter/index.js.map +1 -0
  37. package/dist/openai/index.d.ts +3 -2
  38. package/dist/openai/index.d.ts.map +1 -1
  39. package/dist/openai/index.js +2 -2
  40. package/dist/openai/index.js.map +1 -1
  41. package/dist/opencode/index.d.ts +137 -161
  42. package/dist/opencode/index.d.ts.map +1 -1
  43. package/dist/opencode/index.js +269 -159
  44. package/dist/opencode/index.js.map +1 -1
  45. package/dist/{sandbox-D_MMqExx.d.ts → sandbox-DHNO89IF.d.ts} +145 -394
  46. package/dist/sandbox-DHNO89IF.d.ts.map +1 -0
  47. package/dist/{sandbox-BgwMBQ7S.js → sandbox-boKWPIcd.js} +8212 -7268
  48. package/dist/sandbox-boKWPIcd.js.map +1 -0
  49. package/dist/xterm/index.d.ts +6 -6
  50. package/dist/xterm/index.d.ts.map +1 -1
  51. package/dist/xterm/index.js +6 -6
  52. package/dist/xterm/index.js.map +1 -1
  53. package/package.json +26 -3
  54. package/dist/contexts-BS0Bs6IU.d.ts +0 -238
  55. package/dist/contexts-BS0Bs6IU.d.ts.map +0 -1
  56. package/dist/dist-DF8sudAg.js.map +0 -1
  57. package/dist/errors-BG6NZiPD.js.map +0 -1
  58. package/dist/extensions/index.d.ts.map +0 -1
  59. package/dist/extensions/index.js.map +0 -1
  60. package/dist/rpc-types-PBUY-xXM.d.ts.map +0 -1
  61. package/dist/sandbox-BgwMBQ7S.js.map +0 -1
  62. package/dist/sandbox-D_MMqExx.d.ts.map +0 -1
@@ -1,254 +1,32 @@
1
- //#region ../shared/dist/interpreter-types.d.ts
2
- interface CreateContextOptions {
3
- /**
4
- * Programming language for the context
5
- * @default 'python'
6
- */
7
- language?: 'python' | 'javascript' | 'typescript';
8
- /**
9
- * Working directory for the context
10
- * @default '/workspace'
11
- */
12
- cwd?: string;
13
- /**
14
- * Environment variables for the context.
15
- * Undefined values are skipped (treated as "not configured").
16
- */
17
- envVars?: Record<string, string | undefined>;
18
- /**
19
- * Request timeout in milliseconds
20
- * @default 30000
21
- */
22
- timeout?: number;
23
- }
24
- interface CodeContext {
25
- /**
26
- * Unique identifier for the context
27
- */
28
- readonly id: string;
29
- /**
30
- * Programming language of the context
31
- */
32
- readonly language: string;
33
- /**
34
- * Current working directory
35
- */
36
- readonly cwd: string;
37
- /**
38
- * When the context was created
39
- */
40
- readonly createdAt: Date;
41
- /**
42
- * When the context was last used
43
- */
44
- readonly lastUsed: Date;
45
- }
46
- interface RunCodeOptions {
47
- /**
48
- * Context to run the code in. If not provided, uses default context for the language
49
- */
50
- context?: CodeContext;
51
- /**
52
- * Language to use if context is not provided
53
- * @default 'python'
54
- */
55
- language?: 'python' | 'javascript' | 'typescript';
56
- /**
57
- * Environment variables for this execution.
58
- * Undefined values are skipped (treated as "not configured").
59
- */
60
- envVars?: Record<string, string | undefined>;
61
- /**
62
- * Execution timeout in milliseconds
63
- * @default 60000
64
- */
65
- timeout?: number;
66
- /**
67
- * AbortSignal for cancelling execution
68
- */
69
- signal?: AbortSignal;
70
- /**
71
- * Callback for stdout output
72
- */
73
- onStdout?: (output: OutputMessage) => void | Promise<void>;
74
- /**
75
- * Callback for stderr output
76
- */
77
- onStderr?: (output: OutputMessage) => void | Promise<void>;
78
- /**
79
- * Callback for execution results (charts, tables, etc)
80
- */
81
- onResult?: (result: Result) => void | Promise<void>;
82
- /**
83
- * Callback for execution errors
84
- */
85
- onError?: (error: ExecutionError) => void | Promise<void>;
86
- }
87
- interface OutputMessage {
88
- /**
89
- * The output text
90
- */
91
- text: string;
92
- /**
93
- * Timestamp of the output
94
- */
95
- timestamp: number;
96
- }
97
- interface Result {
98
- /**
99
- * Plain text representation
100
- */
101
- text?: string;
102
- /**
103
- * HTML representation (tables, formatted output)
104
- */
105
- html?: string;
106
- /**
107
- * PNG image data (base64 encoded)
108
- */
109
- png?: string;
110
- /**
111
- * JPEG image data (base64 encoded)
112
- */
113
- jpeg?: string;
114
- /**
115
- * SVG image data
116
- */
117
- svg?: string;
118
- /**
119
- * LaTeX representation
120
- */
121
- latex?: string;
122
- /**
123
- * Markdown representation
124
- */
125
- markdown?: string;
126
- /**
127
- * JavaScript code to execute
128
- */
129
- javascript?: string;
130
- /**
131
- * JSON data
132
- */
133
- json?: any;
134
- /**
135
- * Chart data if the result is a visualization
136
- */
137
- chart?: ChartData;
138
- /**
139
- * Raw data object
140
- */
141
- data?: any;
142
- /**
143
- * Available output formats
144
- */
145
- formats(): string[];
146
- }
147
- interface ChartData {
148
- /**
149
- * Type of chart
150
- */
151
- type: 'line' | 'bar' | 'scatter' | 'pie' | 'histogram' | 'heatmap' | 'unknown';
152
- /**
153
- * Chart title
154
- */
155
- title?: string;
156
- /**
157
- * Chart data (format depends on library)
158
- */
159
- data: any;
160
- /**
161
- * Chart layout/configuration
162
- */
163
- layout?: any;
164
- /**
165
- * Additional configuration
166
- */
167
- config?: any;
168
- /**
169
- * Library that generated the chart
170
- */
171
- library?: 'matplotlib' | 'plotly' | 'altair' | 'seaborn' | 'unknown';
172
- /**
173
- * Base64 encoded image if available
174
- */
175
- image?: string;
176
- }
177
- interface ExecutionError {
178
- /**
179
- * Error name/type (e.g., 'NameError', 'SyntaxError')
180
- */
181
- name: string;
182
- /**
183
- * Error message
184
- */
185
- message: string;
186
- /**
187
- * Stack trace
188
- */
189
- traceback: string[];
190
- /**
191
- * Line number where error occurred
192
- */
193
- lineNumber?: number;
194
- }
195
- interface ExecutionResult {
196
- code: string;
197
- logs: {
198
- stdout: string[];
199
- stderr: string[];
200
- };
201
- error?: ExecutionError;
202
- executionCount?: number;
203
- results: Array<{
204
- text?: string;
205
- html?: string;
206
- png?: string;
207
- jpeg?: string;
208
- svg?: string;
209
- latex?: string;
210
- markdown?: string;
211
- javascript?: string;
212
- json?: any;
213
- chart?: ChartData;
214
- data?: any;
215
- }>;
216
- }
217
- declare class Execution {
218
- readonly code: string;
219
- readonly context: CodeContext;
220
- /**
221
- * All results from the execution
222
- */
223
- results: Result[];
224
- /**
225
- * Accumulated stdout and stderr
226
- */
227
- logs: {
228
- stdout: string[];
229
- stderr: string[];
230
- };
231
- /**
232
- * Execution error if any
233
- */
234
- error?: ExecutionError;
235
- /**
236
- * Execution count (for interpreter)
237
- */
238
- executionCount?: number;
239
- constructor(code: string, context: CodeContext);
240
- /**
241
- * Convert to a plain object for serialization
242
- */
243
- toJSON(): ExecutionResult;
244
- }
245
- //#endregion
1
+ import { RpcTarget } from "cloudflare:workers";
2
+
246
3
  //#region ../shared/dist/pty-types.d.ts
247
4
  interface PtyOptions {
248
5
  cols?: number;
249
6
  rows?: number;
250
7
  shell?: string;
251
8
  }
9
+ interface TerminalOptions {
10
+ id?: string;
11
+ cwd?: string;
12
+ shell?: string;
13
+ }
14
+ interface TerminalCreateOptions {
15
+ id: string;
16
+ cwd?: string;
17
+ shell?: string;
18
+ cols?: number;
19
+ rows?: number;
20
+ }
21
+ interface TerminalConnectOptions {
22
+ cols?: number;
23
+ rows?: number;
24
+ }
25
+ interface SandboxTerminal {
26
+ readonly id: string;
27
+ connect(request: Request, options?: TerminalConnectOptions): Promise<Response>;
28
+ destroy(): Promise<void>;
29
+ }
252
30
  //#endregion
253
31
  //#region ../shared/dist/types.d.ts
254
32
  interface BaseExecOptions {
@@ -272,6 +50,11 @@ interface BaseExecOptions {
272
50
  */
273
51
  encoding?: string;
274
52
  }
53
+ /**
54
+ * @deprecated Use `SandboxExecOptions` instead. Will be removed in a future
55
+ * release once all callers migrate to `sandbox.exec(cmd, options)` returning
56
+ * a `SandboxProcessPromise`. See `docs/EXEC_MIGRATION.md`.
57
+ */
275
58
  interface ExecOptions extends BaseExecOptions {
276
59
  /**
277
60
  * Enable real-time output streaming via callbacks
@@ -300,6 +83,10 @@ interface ExecOptions extends BaseExecOptions {
300
83
  */
301
84
  origin?: 'user' | 'internal';
302
85
  }
86
+ /**
87
+ * @deprecated Use `SandboxExecOutput` (returned by
88
+ * `SandboxProcess.output()`) instead. Will be removed alongside `ExecOptions`.
89
+ */
303
90
  interface ExecResult {
304
91
  /**
305
92
  * Whether the command succeeded (exitCode === 0)
@@ -406,6 +193,17 @@ interface PortWatchRequest extends PortCheckRequest {
406
193
  /** Internal polling interval in ms (default: 500) */
407
194
  interval?: number;
408
195
  }
196
+ interface ProcessQueryOptions {
197
+ /**
198
+ * Optional session ID used to bind returned process handles to an explicit session.
199
+ */
200
+ sessionId?: string;
201
+ }
202
+ /**
203
+ * @deprecated Use `SandboxExecOptions` with `processId` set instead. The
204
+ * unified `sandbox.exec()` returns the same `SandboxProcess` handle whether
205
+ * the caller wants a foreground or background process.
206
+ */
409
207
  interface ProcessOptions extends BaseExecOptions {
410
208
  /**
411
209
  * Optional session ID to run the background process in.
@@ -440,6 +238,12 @@ interface ProcessOptions extends BaseExecOptions {
440
238
  onError?: (error: Error) => void;
441
239
  }
442
240
  type ProcessStatus = 'starting' | 'running' | 'completed' | 'failed' | 'killed' | 'error';
241
+ /**
242
+ * @deprecated Use `SandboxProcess` instead. The unified handle has the same
243
+ * `id`/`pid`/`command`/`status`/`startTime`/`sessionId` fields plus
244
+ * `stdin`/`stdout`/`stderr` streams, an `exitCode` promise, `output()` and
245
+ * `kill()` that mirror the `ctx.container.exec()` contract.
246
+ */
443
247
  interface Process {
444
248
  /**
445
249
  * Unique process identifier
@@ -522,6 +326,11 @@ interface Process {
522
326
  */
523
327
  waitForExit(timeout?: number): Promise<WaitForExitResult>;
524
328
  }
329
+ /**
330
+ * @deprecated Internal SSE frame type. Consumers should read
331
+ * `SandboxProcess.stdout` / `.stderr` (raw byte streams) instead of parsing
332
+ * SSE frames. Retained while the legacy `execStream` HTTP route exists.
333
+ */
525
334
  interface ExecEvent {
526
335
  type: 'start' | 'stdout' | 'stderr' | 'complete' | 'error';
527
336
  timestamp: string;
@@ -533,6 +342,10 @@ interface ExecEvent {
533
342
  sessionId?: string;
534
343
  pid?: number;
535
344
  }
345
+ /**
346
+ * @deprecated Internal SSE frame type for `streamProcessLogs`. Consumers
347
+ * should read `SandboxProcess.stdout` / `.stderr` instead.
348
+ */
536
349
  interface LogEvent {
537
350
  type: 'stdout' | 'stderr' | 'exit' | 'error';
538
351
  timestamp: string;
@@ -541,21 +354,231 @@ interface LogEvent {
541
354
  sessionId?: string;
542
355
  exitCode?: number;
543
356
  }
544
- interface StreamOptions extends BaseExecOptions {
357
+ /**
358
+ * Options for `sandbox.exec(cmd, options)`.
359
+ *
360
+ * Mirrors `ContainerExecOptions` from
361
+ * `@cloudflare/workers-types/experimental` (`cwd`, `env`, `stdin`, `stdout`,
362
+ * `stderr`) with sandbox-specific extensions for sessions, named process
363
+ * ids, timeouts, and cancellation.
364
+ *
365
+ * Notable differences from the runtime contract:
366
+ * - `env` values may be `undefined` (treated as "not configured"). The
367
+ * container API requires `Record<string, string>`; the SDK strips
368
+ * `undefined` entries before forwarding.
369
+ * - `stdin` additionally accepts a plain `string` for convenience.
370
+ * - `user` is not yet supported (no session-backend story).
371
+ */
372
+ interface SandboxExecOptions {
373
+ /** Working directory for command execution. */
374
+ cwd?: string;
545
375
  /**
546
- * Optional session ID to run the streaming command in.
376
+ * Environment variables for this command invocation.
547
377
  *
548
- * When omitted, the sandbox's default execution policy applies.
378
+ * Values temporarily override session-level/container-level env for the
379
+ * duration of the command but do not persist after it completes.
380
+ * Undefined values are skipped (treated as "not configured").
381
+ */
382
+ env?: Record<string, string | undefined>;
383
+ /**
384
+ * Standard input source.
385
+ *
386
+ * - `"pipe"` — `SandboxProcess.stdin` is a `WritableStream<Uint8Array>` the
387
+ * caller can write to.
388
+ * - `ReadableStream<Uint8Array>` — the stream is piped into the command.
389
+ * - `string` — convenience: the string is utf-8 encoded and piped in.
390
+ * - omitted — stdin is closed.
391
+ */
392
+ stdin?: ReadableStream<Uint8Array> | string | 'pipe';
393
+ /**
394
+ * Standard output disposition.
395
+ *
396
+ * - `"pipe"` (default) — `SandboxProcess.stdout` exposes a
397
+ * `ReadableStream<Uint8Array>` of the output.
398
+ * - `"ignore"` — output is discarded; `SandboxProcess.stdout` is `null`.
399
+ */
400
+ stdout?: 'pipe' | 'ignore';
401
+ /**
402
+ * Standard error disposition.
403
+ *
404
+ * - `"pipe"` (default) — `SandboxProcess.stderr` exposes a
405
+ * `ReadableStream<Uint8Array>` of the error output.
406
+ * - `"ignore"` — stderr is discarded; `SandboxProcess.stderr` is `null`.
407
+ * - `"combined"` — stderr is merged into stdout; `SandboxProcess.stderr`
408
+ * is `null`.
409
+ */
410
+ stderr?: 'pipe' | 'ignore' | 'combined';
411
+ /**
412
+ * Session ID providing working-directory and environment scope.
413
+ *
414
+ * When omitted, the sandbox's default execution policy applies (typically
415
+ * the persistent default session).
549
416
  */
550
417
  sessionId?: string;
551
418
  /**
552
- * Buffer size for streaming output
419
+ * Client-chosen process id for later re-attach via
420
+ * `sandbox.getProcess(id)`.
421
+ *
422
+ * When omitted, a UUID is generated.
423
+ */
424
+ processId?: string;
425
+ /**
426
+ * Whether to remove the process record on exit.
427
+ *
428
+ * Currently retained for compatibility with legacy process options. Process
429
+ * records are kept so `output()`, `getLogs()`, and re-attach can read logs;
430
+ * callers can use `cleanupCompletedProcesses()` to remove completed records.
431
+ */
432
+ autoCleanup?: boolean;
433
+ /**
434
+ * Wall-clock timeout in milliseconds. When the timeout fires the
435
+ * implementation sends `SIGTERM`; `exitCode` resolves with the resulting
436
+ * code (typically `143` / `-15`).
553
437
  */
554
- bufferSize?: number;
438
+ timeout?: number;
555
439
  /**
556
- * AbortSignal for cancelling stream
440
+ * External cancellation signal. Aborting triggers `kill()` and propagates
441
+ * to in-flight stream consumers.
557
442
  */
558
443
  signal?: AbortSignal;
444
+ /**
445
+ * Whether this command was initiated by the user or by internal
446
+ * infrastructure (backup, bucket mount, env setup, etc.).
447
+ *
448
+ * Sandbox-only; not part of the containers contract. Defaults to
449
+ * `'user'` when omitted.
450
+ */
451
+ origin?: 'user' | 'internal';
452
+ }
453
+ /**
454
+ * Buffered output returned by `SandboxProcess.output()`.
455
+ *
456
+ * Mirrors `ExecOutput` from the containers contract (`stdout`, `stderr`,
457
+ * `exitCode`) with sandbox-specific telemetry fields preserved from the
458
+ * legacy `ExecResult` so existing callers can migrate without losing
459
+ * information.
460
+ *
461
+ * `stdout` / `stderr` are `string` by default (utf-8) or `ArrayBuffer`
462
+ * when `output({ encoding: 'buffer' })` is requested.
463
+ */
464
+ type SandboxOutputMode = 'pipe' | 'ignore';
465
+ type SandboxStderrMode = 'pipe' | 'ignore' | 'combined';
466
+ type SandboxOutputEncoding = 'utf8' | 'buffer';
467
+ interface SandboxExecOutputBase<T> {
468
+ /** Standard output content. */
469
+ stdout: T;
470
+ /** Standard error content. */
471
+ stderr: T;
472
+ /** Process exit code. */
473
+ exitCode: number;
474
+ /** True iff `exitCode === 0`. */
475
+ success: boolean;
476
+ /** Execution duration in milliseconds, measured by the SDK. */
477
+ duration: number;
478
+ /** Command that was executed (display form). */
479
+ command: string;
480
+ /** ISO timestamp when the command started. */
481
+ timestamp: string;
482
+ /** Session ID, if the command ran in a session. */
483
+ sessionId?: string;
484
+ }
485
+ type SandboxExecStringOutput = SandboxExecOutputBase<string>;
486
+ type SandboxExecBufferOutput = SandboxExecOutputBase<ArrayBuffer>;
487
+ type SandboxExecOutput = SandboxExecStringOutput | SandboxExecBufferOutput;
488
+ /**
489
+ * Unified process handle returned (resolved) by `sandbox.exec()`.
490
+ *
491
+ * The first nine members are a superset of `ExecProcess` from the
492
+ * containers runtime contract (`stdin`, `stdout`, `stderr`, `pid`,
493
+ * `exitCode`, `output()`, `kill()`). The remaining members are
494
+ * sandbox-specific extensions for log replay, named processes, and the
495
+ * existing `waitFor*` helpers.
496
+ *
497
+ * On re-attach (via `sandbox.getProcess(id)`):
498
+ * - `stdin` is `null` (the original writer owns the pipe).
499
+ * - `stdout`/`stderr` are replay-then-tail streams sourced from the
500
+ * per-process log file.
501
+ */
502
+ interface SandboxProcess {
503
+ readonly stdin: WritableStream<Uint8Array> | null;
504
+ readonly stdout: ReadableStream<Uint8Array> | null;
505
+ readonly stderr: ReadableStream<Uint8Array> | null;
506
+ readonly pid: number;
507
+ readonly exitCode: Promise<number>;
508
+ /**
509
+ * Drain stdout/stderr and await exit. Mirrors `ExecProcess.output()`.
510
+ *
511
+ * Default encoding is utf-8 strings; pass `{ encoding: 'buffer' }` to get
512
+ * `ArrayBuffer` instead (matches the containers contract).
513
+ */
514
+ output(options: {
515
+ encoding: 'buffer';
516
+ }): Promise<SandboxExecBufferOutput>;
517
+ output(options?: {
518
+ encoding?: 'utf8';
519
+ }): Promise<SandboxExecStringOutput>;
520
+ output(options?: {
521
+ encoding?: SandboxOutputEncoding;
522
+ }): Promise<SandboxExecOutput>;
523
+ /** Sugar for `(await this.output({ encoding: 'utf8' })).stdout` as a string. */
524
+ text(): Promise<string>;
525
+ /** Sugar for `JSON.parse(await this.text())`. */
526
+ json<T = unknown>(): Promise<T>;
527
+ /**
528
+ * Terminate the process.
529
+ *
530
+ * Defaults to `SIGTERM` (15).
531
+ */
532
+ kill(signal?: number | string): void;
533
+ /** Stable sandbox process id (survives re-attach). */
534
+ readonly id: string;
535
+ /** Command that was executed (display form). */
536
+ readonly command: string;
537
+ /** Session ID, if the command was scoped to a session. */
538
+ readonly sessionId?: string;
539
+ /** When the process started. */
540
+ readonly startTime: Date;
541
+ /** Current status snapshot. Cheap; uses local state where possible. */
542
+ status(): Promise<ProcessStatus>;
543
+ /** Replay buffered logs (post-exit or mid-flight). */
544
+ getLogs(): Promise<{
545
+ stdout: string;
546
+ stderr: string;
547
+ }>;
548
+ /** Wait for a log pattern to appear in stdout/stderr. */
549
+ waitForLog(pattern: string | RegExp, timeoutMs?: number): Promise<WaitForLogResult>;
550
+ /** Wait for a TCP port (or HTTP endpoint) to become ready. */
551
+ waitForPort(port: number, options?: WaitForPortOptions): Promise<void>;
552
+ /** Wait for the process to exit. */
553
+ waitForExit(timeoutMs?: number): Promise<WaitForExitResult>;
554
+ }
555
+ /**
556
+ * The thenable returned by `sandbox.exec(cmd, options)`.
557
+ *
558
+ * Resolves to a `SandboxProcess` (so `await sandbox.exec(cmd)` works as
559
+ * expected) and additionally exposes the convenience members directly so
560
+ * callers can write `await sandbox.exec(cmd).output()` / `.text()` /
561
+ * `.json()` / `.kill()` without an extra `await`.
562
+ *
563
+ * Modeled on `Bun.spawn()` / `Deno.Command`.
564
+ */
565
+ interface SandboxProcessPromise extends Promise<SandboxProcess> {
566
+ /** Equivalent to `(await this).output(options)`. */
567
+ output(options: {
568
+ encoding: 'buffer';
569
+ }): Promise<SandboxExecBufferOutput>;
570
+ output(options?: {
571
+ encoding?: 'utf8';
572
+ }): Promise<SandboxExecStringOutput>;
573
+ output(options?: {
574
+ encoding?: SandboxOutputEncoding;
575
+ }): Promise<SandboxExecOutput>;
576
+ /** Sugar for `(await this.output({ encoding: 'utf8' })).stdout` as a string. */
577
+ text(): Promise<string>;
578
+ /** Sugar for `JSON.parse(await this.text())`. */
579
+ json<T = unknown>(): Promise<T>;
580
+ /** Equivalent to `(await this).kill(signal)`. */
581
+ kill(signal?: number | string): Promise<void>;
559
582
  }
560
583
  interface SessionOptions {
561
584
  /**
@@ -804,14 +827,6 @@ interface ListFilesResult {
804
827
  timestamp: string;
805
828
  exitCode?: number;
806
829
  }
807
- interface GitCheckoutResult {
808
- success: boolean;
809
- repoUrl: string;
810
- branch: string;
811
- targetDir: string;
812
- timestamp: string;
813
- exitCode?: number;
814
- }
815
830
  /**
816
831
  * SSE events for file streaming
817
832
  */
@@ -961,6 +976,8 @@ interface ProcessListResult {
961
976
  startTime: string;
962
977
  endTime?: string;
963
978
  exitCode?: number;
979
+ stdout?: SandboxOutputMode;
980
+ stderr?: SandboxStderrMode;
964
981
  }>;
965
982
  timestamp: string;
966
983
  }
@@ -974,6 +991,8 @@ interface ProcessInfoResult {
974
991
  startTime: string;
975
992
  endTime?: string;
976
993
  exitCode?: number;
994
+ stdout?: SandboxOutputMode;
995
+ stderr?: SandboxStderrMode;
977
996
  };
978
997
  timestamp: string;
979
998
  }
@@ -1005,22 +1024,19 @@ interface SessionDeleteResult {
1005
1024
  interface ExecutionSession {
1006
1025
  /** Unique session identifier */
1007
1026
  readonly id: string;
1008
- exec(command: string, options?: ExecOptions): Promise<ExecResult>;
1009
- execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>>;
1010
- startProcess(command: string, options?: ProcessOptions): Promise<Process>;
1011
- listProcesses(sessionId?: string): Promise<Process[]>;
1012
- getProcess(id: string, sessionId?: string): Promise<Process | null>;
1013
- killProcess(id: string, signal?: string): Promise<void>;
1027
+ /**
1028
+ * Session-scoped exec primitive. See `ISandbox.exec`.
1029
+ *
1030
+ * Caller-provided `options.sessionId` is ignored — this wrapper pins
1031
+ * execution to the session that produced it.
1032
+ */
1033
+ exec(command: string | string[], options?: SandboxExecOptions): SandboxProcessPromise;
1034
+ /** Session-scoped buffered execution helper. See `ISandbox.run`. */
1035
+ run(command: string, options?: ExecOptions): Promise<ExecResult>;
1036
+ getProcess(id: string): Promise<SandboxProcess | null>;
1037
+ listProcesses(): Promise<SandboxProcess[]>;
1014
1038
  killAllProcesses(): Promise<number>;
1015
1039
  cleanupCompletedProcesses(): Promise<number>;
1016
- getProcessLogs(id: string): Promise<{
1017
- stdout: string;
1018
- stderr: string;
1019
- processId: string;
1020
- }>;
1021
- streamProcessLogs(processId: string, options?: {
1022
- signal?: AbortSignal;
1023
- }): Promise<ReadableStream<Uint8Array>>;
1024
1040
  writeFile(path: string, content: string | ReadableStream<Uint8Array>, options?: {
1025
1041
  encoding?: string;
1026
1042
  }): Promise<WriteFileResult>;
@@ -1041,20 +1057,7 @@ interface ExecutionSession {
1041
1057
  moveFile(sourcePath: string, destinationPath: string): Promise<MoveFileResult>;
1042
1058
  listFiles(path: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1043
1059
  exists(path: string): Promise<FileExistsResult>;
1044
- gitCheckout(repoUrl: string, options?: {
1045
- branch?: string;
1046
- targetDir?: string;
1047
- /** Clone depth for shallow clones (e.g., 1 for latest commit only) */
1048
- depth?: number;
1049
- /** Maximum wall-clock time for the git clone subprocess in milliseconds */
1050
- cloneTimeoutMs?: number;
1051
- }): Promise<GitCheckoutResult>;
1052
1060
  setEnvVars(envVars: Record<string, string | undefined>): Promise<void>;
1053
- createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1054
- runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
1055
- runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream<Uint8Array>>;
1056
- listCodeContexts(): Promise<CodeContext[]>;
1057
- deleteCodeContext(contextId: string): Promise<void>;
1058
1061
  mountBucket(bucket: string, mountPath: string, options: MountBucketOptions): Promise<void>;
1059
1062
  unmountBucket(mountPath: string): Promise<void>;
1060
1063
  createBackup(options: BackupOptions): Promise<DirectoryBackup>;
@@ -1260,22 +1263,65 @@ interface R2BindingMountBucketOptions {
1260
1263
  */
1261
1264
  type MountBucketOptions = RemoteMountBucketOptions | LocalMountBucketOptions | R2BindingMountBucketOptions;
1262
1265
  interface ISandbox {
1263
- exec(command: string, options?: ExecOptions): Promise<ExecResult>;
1264
- startProcess(command: string, options?: ProcessOptions): Promise<Process>;
1265
- listProcesses(sessionId?: string): Promise<Process[]>;
1266
- getProcess(id: string, sessionId?: string): Promise<Process | null>;
1267
- killProcess(id: string, signal?: string): Promise<void>;
1266
+ /**
1267
+ * Execute a command in the sandbox.
1268
+ *
1269
+ * Mirrors the `ctx.container.exec()` contract from the Cloudflare
1270
+ * Containers runtime, with sandbox-specific extensions for sessions,
1271
+ * named process ids, and re-attach.
1272
+ *
1273
+ * Returns a `SandboxProcessPromise` — a thenable that resolves to a
1274
+ * `SandboxProcess` (`stdin` / `stdout` / `stderr` / `exitCode` /
1275
+ * `kill()` / `output()` plus sandbox extensions) and exposes
1276
+ * `.output()` / `.text()` / `.json()` / `.kill()` directly for the
1277
+ * common "run a command" case:
1278
+ *
1279
+ * @example
1280
+ * // Buffered result
1281
+ * const { stdout } = await sandbox.exec("npm test").output();
1282
+ *
1283
+ * @example
1284
+ * // Long-running, with re-attach by id
1285
+ * const dev = await sandbox.exec("npm run dev", { processId: "dev" });
1286
+ * await dev.waitForPort(3000);
1287
+ *
1288
+ * @example
1289
+ * // Stream stdout straight to the client
1290
+ * const proc = await sandbox.exec(["python", "train.py"]);
1291
+ * return new Response(proc.stdout);
1292
+ */
1293
+ exec(command: string | string[], options?: SandboxExecOptions): SandboxProcessPromise;
1294
+ /**
1295
+ * Buffered, session-state-preserving execution helper.
1296
+ *
1297
+ * Uses the foreground session execution path, so shell state changes
1298
+ * (`cd`, aliases, functions, exports) persist across calls. Prefer
1299
+ * `exec()` for the containers-compatible process handle; use `run()`
1300
+ * when you explicitly want buffered session-shell semantics.
1301
+ */
1302
+ run(command: string, options?: ExecOptions & {
1303
+ sessionId?: string;
1304
+ }): Promise<ExecResult>;
1305
+ /**
1306
+ * Re-attach to an existing process by id.
1307
+ *
1308
+ * The returned `SandboxProcess`'s `stdin` is `null` and `stdout`/`stderr`
1309
+ * are replay-then-tail streams sourced from the per-process log file.
1310
+ * Mirrors `ExecProcess` ownership semantics where a non-owner has
1311
+ * nullable pipes.
1312
+ *
1313
+ * Returns `null` if no such process exists.
1314
+ */
1315
+ getProcess(id: string, options?: ProcessQueryOptions): Promise<SandboxProcess | null>;
1316
+ /**
1317
+ * Snapshot of all known processes.
1318
+ *
1319
+ * Snapshot entries have `stdin`/`stdout`/`stderr` set to `null`; call
1320
+ * `getProcess(id)` to acquire a re-attached handle with live streams.
1321
+ */
1322
+ listProcesses(options?: ProcessQueryOptions): Promise<SandboxProcess[]>;
1268
1323
  killAllProcesses(): Promise<number>;
1269
- execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>>;
1270
- streamProcessLogs(processId: string, options?: {
1271
- signal?: AbortSignal;
1272
- }): Promise<ReadableStream<Uint8Array>>;
1273
1324
  cleanupCompletedProcesses(): Promise<number>;
1274
- getProcessLogs(id: string): Promise<{
1275
- stdout: string;
1276
- stderr: string;
1277
- processId: string;
1278
- }>;
1279
1325
  writeFile(path: string, content: string | ReadableStream<Uint8Array>, options?: {
1280
1326
  encoding?: string;
1281
1327
  }): Promise<WriteFileResult>;
@@ -1295,16 +1341,9 @@ interface ISandbox {
1295
1341
  renameFile(oldPath: string, newPath: string): Promise<RenameFileResult>;
1296
1342
  moveFile(sourcePath: string, destinationPath: string): Promise<MoveFileResult>;
1297
1343
  listFiles(path: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1298
- exists(path: string, sessionId?: string): Promise<FileExistsResult>;
1299
- gitCheckout(repoUrl: string, options?: {
1300
- branch?: string;
1301
- targetDir?: string;
1344
+ exists(path: string, options?: {
1302
1345
  sessionId?: string;
1303
- /** Clone depth for shallow clones (e.g., 1 for latest commit only) */
1304
- depth?: number;
1305
- /** Maximum wall-clock time for the git clone subprocess in milliseconds */
1306
- cloneTimeoutMs?: number;
1307
- }): Promise<GitCheckoutResult>;
1346
+ }): Promise<FileExistsResult>;
1308
1347
  setEnvVars(envVars: Record<string, string | undefined>): Promise<void>;
1309
1348
  mountBucket(bucket: string, mountPath: string, options: MountBucketOptions): Promise<void>;
1310
1349
  unmountBucket(mountPath: string): Promise<void>;
@@ -1317,11 +1356,6 @@ interface ISandbox {
1317
1356
  * when no handshake has been observed yet on this sandbox.
1318
1357
  */
1319
1358
  getContainerPlacementId(): Promise<string | null | undefined>;
1320
- createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1321
- runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
1322
- runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
1323
- listCodeContexts(): Promise<CodeContext[]>;
1324
- deleteCodeContext(contextId: string): Promise<void>;
1325
1359
  createBackup(options: BackupOptions): Promise<DirectoryBackup>;
1326
1360
  restoreBackup(backup: DirectoryBackup): Promise<RestoreBackupResult>;
1327
1361
  wsConnect(request: Request, port: number): Promise<Response>;
@@ -1370,21 +1404,22 @@ interface SandboxAPI {
1370
1404
  files: SandboxFilesAPI;
1371
1405
  processes: SandboxProcessesAPI;
1372
1406
  ports: SandboxPortsAPI;
1373
- git: SandboxGitAPI;
1374
- interpreter: SandboxInterpreterAPI;
1375
1407
  utils: SandboxUtilsAPI;
1376
1408
  backup: SandboxBackupAPI;
1377
1409
  watch: SandboxWatchAPI;
1378
1410
  tunnels: SandboxTunnelsAPI;
1411
+ terminals: SandboxTerminalsAPI;
1379
1412
  extensions: SandboxExtensionsAPI;
1380
1413
  }
1414
+ interface CommandExecuteOptions {
1415
+ sessionId?: string;
1416
+ timeoutMs?: number;
1417
+ env?: Record<string, string | undefined>;
1418
+ cwd?: string;
1419
+ origin?: 'user' | 'internal';
1420
+ }
1381
1421
  interface SandboxCommandsAPI {
1382
- execute(command: string, sessionId: string, options?: {
1383
- timeoutMs?: number;
1384
- env?: Record<string, string | undefined>;
1385
- cwd?: string;
1386
- origin?: 'user' | 'internal';
1387
- }): Promise<{
1422
+ execute(command: string, options?: CommandExecuteOptions): Promise<{
1388
1423
  success: boolean;
1389
1424
  exitCode: number;
1390
1425
  stdout: string;
@@ -1392,48 +1427,59 @@ interface SandboxCommandsAPI {
1392
1427
  command: string;
1393
1428
  timestamp: string;
1394
1429
  }>;
1395
- executeStream(command: string, sessionId: string, options?: {
1396
- timeoutMs?: number;
1397
- env?: Record<string, string | undefined>;
1398
- cwd?: string;
1399
- origin?: 'user' | 'internal';
1400
- }): Promise<ReadableStream<Uint8Array>>;
1430
+ }
1431
+ interface FileSessionOptions {
1432
+ sessionId?: string;
1433
+ }
1434
+ interface ReadFileStreamOptions extends FileSessionOptions {}
1435
+ interface ReadFileBinaryOptions extends FileSessionOptions {
1436
+ encoding: 'none';
1437
+ }
1438
+ interface ReadFileOptions extends FileSessionOptions {
1439
+ encoding?: Exclude<FileEncoding, 'none'>;
1440
+ }
1441
+ interface WriteFileOptions extends FileSessionOptions {
1442
+ encoding?: string;
1443
+ permissions?: string;
1444
+ }
1445
+ interface MkdirOptions extends FileSessionOptions {
1446
+ recursive?: boolean;
1401
1447
  }
1402
1448
  interface SandboxFilesAPI {
1403
- readFile(path: string, sessionId: string, options: {
1404
- encoding: 'none';
1405
- }): Promise<ReadFileStreamResult>;
1406
- readFile(path: string, sessionId: string, options?: {
1407
- encoding?: Exclude<FileEncoding, 'none'>;
1408
- }): Promise<ReadFileResult>;
1409
- readFileStream(path: string, sessionId: string): Promise<ReadableStream<Uint8Array>>;
1410
- writeFile(path: string, content: string, sessionId: string, options?: {
1411
- encoding?: string;
1412
- permissions?: string;
1413
- }): Promise<WriteFileResult>;
1414
- writeFileStream(path: string, stream: ReadableStream<Uint8Array>, sessionId: string): Promise<{
1449
+ readFile(path: string, options: ReadFileBinaryOptions): Promise<ReadFileStreamResult>;
1450
+ readFile(path: string, options?: ReadFileOptions): Promise<ReadFileResult>;
1451
+ readFileStream(path: string, options?: ReadFileStreamOptions): Promise<ReadableStream<Uint8Array>>;
1452
+ writeFile(path: string, content: string, options?: WriteFileOptions): Promise<WriteFileResult>;
1453
+ writeFileStream(path: string, stream: ReadableStream<Uint8Array>, options?: FileSessionOptions): Promise<{
1415
1454
  success: boolean;
1416
1455
  path: string;
1417
1456
  bytesWritten: number;
1418
1457
  timestamp: string;
1419
1458
  }>;
1420
- deleteFile(path: string, sessionId: string): Promise<DeleteFileResult>;
1421
- renameFile(oldPath: string, newPath: string, sessionId: string): Promise<RenameFileResult>;
1422
- moveFile(sourcePath: string, destinationPath: string, sessionId: string): Promise<MoveFileResult>;
1423
- mkdir(path: string, sessionId: string, options?: {
1424
- recursive?: boolean;
1425
- }): Promise<MkdirResult>;
1426
- listFiles(path: string, sessionId: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1427
- exists(path: string, sessionId: string): Promise<FileExistsResult>;
1459
+ deleteFile(path: string, options?: FileSessionOptions): Promise<DeleteFileResult>;
1460
+ renameFile(oldPath: string, newPath: string, options?: FileSessionOptions): Promise<RenameFileResult>;
1461
+ moveFile(sourcePath: string, destinationPath: string, options?: FileSessionOptions): Promise<MoveFileResult>;
1462
+ mkdir(path: string, options?: MkdirOptions): Promise<MkdirResult>;
1463
+ listFiles(path: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1464
+ exists(path: string, options?: FileSessionOptions): Promise<FileExistsResult>;
1465
+ }
1466
+ interface ProcessStartOptions {
1467
+ sessionId?: string;
1468
+ processId?: string;
1469
+ timeoutMs?: number;
1470
+ env?: Record<string, string | undefined>;
1471
+ cwd?: string;
1472
+ encoding?: string;
1473
+ autoCleanup?: boolean;
1474
+ origin?: 'user' | 'internal';
1475
+ stdout?: 'pipe' | 'ignore';
1476
+ stderr?: 'pipe' | 'ignore' | 'combined';
1428
1477
  }
1429
1478
  interface SandboxProcessesAPI {
1430
- startProcess(command: string, sessionId: string, options?: {
1431
- processId?: string;
1432
- timeoutMs?: number;
1433
- }): Promise<ProcessStartResult>;
1479
+ startProcess(command: string, options?: ProcessStartOptions, stdin?: ReadableStream<Uint8Array>): Promise<ProcessStartResult>;
1434
1480
  listProcesses(): Promise<ProcessListResult>;
1435
1481
  getProcess(id: string): Promise<ProcessInfoResult>;
1436
- killProcess(id: string): Promise<ProcessKillResult>;
1482
+ killProcess(id: string, signal?: number): Promise<ProcessKillResult>;
1437
1483
  killAllProcesses(): Promise<ProcessCleanupResult>;
1438
1484
  getProcessLogs(id: string): Promise<ProcessLogsResult>;
1439
1485
  streamProcessLogs(id: string): Promise<ReadableStream<Uint8Array>>;
@@ -1441,35 +1487,17 @@ interface SandboxProcessesAPI {
1441
1487
  interface SandboxPortsAPI {
1442
1488
  watchPort(request: PortWatchRequest): Promise<ReadableStream<Uint8Array>>;
1443
1489
  }
1444
- interface SandboxGitAPI {
1445
- checkout(repoUrl: string, sessionId: string, options?: {
1446
- branch?: string;
1447
- targetDir?: string;
1448
- depth?: number;
1449
- timeoutMs?: number;
1450
- }): Promise<GitCheckoutResult>;
1451
- }
1452
- interface SandboxInterpreterAPI {
1453
- createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1454
- streamCode(contextId: string, code: string, language?: string): Promise<ReadableStream<Uint8Array>>;
1455
- runCodeStream(contextId: string | undefined, code: string, language: string | undefined, callbacks: {
1456
- onStdout?: (output: OutputMessage) => void | Promise<void>;
1457
- onStderr?: (output: OutputMessage) => void | Promise<void>;
1458
- onResult?: (result: Result) => void | Promise<void>;
1459
- onError?: (error: ExecutionError) => void | Promise<void>;
1460
- }, timeoutMs?: number): Promise<void>;
1461
- listCodeContexts(): Promise<CodeContext[]>;
1462
- deleteCodeContext(contextId: string): Promise<void>;
1490
+ interface SessionCreateOptions {
1491
+ id: string;
1492
+ env?: Record<string, string | undefined>;
1493
+ cwd?: string;
1494
+ commandTimeoutMs?: number;
1463
1495
  }
1464
1496
  interface SandboxUtilsAPI {
1465
1497
  ping(): Promise<string>;
1466
1498
  getVersion(): Promise<string>;
1467
1499
  getCommands(): Promise<string[]>;
1468
- createSession(options: {
1469
- id: string;
1470
- env?: Record<string, string | undefined>;
1471
- cwd?: string;
1472
- }): Promise<{
1500
+ createSession(options: SessionCreateOptions): Promise<{
1473
1501
  success: boolean;
1474
1502
  id: string;
1475
1503
  message: string;
@@ -1485,13 +1513,18 @@ interface SandboxUtilsAPI {
1485
1513
  sessions: string[];
1486
1514
  }>;
1487
1515
  }
1516
+ interface BackupCreateArchiveOptions {
1517
+ sessionId?: string;
1518
+ excludes?: string[];
1519
+ gitignore?: boolean;
1520
+ compression?: BackupCompressionOptions;
1521
+ }
1522
+ interface BackupRestoreArchiveOptions {
1523
+ sessionId?: string;
1524
+ }
1488
1525
  interface SandboxBackupAPI {
1489
- createArchive(dir: string, archivePath: string, sessionId: string, options?: {
1490
- excludes?: string[];
1491
- gitignore?: boolean;
1492
- compression?: BackupCompressionOptions;
1493
- }): Promise<CreateBackupResponse>;
1494
- restoreArchive(dir: string, archivePath: string, sessionId: string): Promise<RestoreBackupResponse>;
1526
+ createArchive(dir: string, archivePath: string, options?: BackupCreateArchiveOptions): Promise<CreateBackupResponse>;
1527
+ restoreArchive(dir: string, archivePath: string, options?: BackupRestoreArchiveOptions): Promise<RestoreBackupResponse>;
1495
1528
  uploadParts(request: {
1496
1529
  archivePath: string;
1497
1530
  parts: Array<{
@@ -1548,28 +1581,67 @@ interface TunnelOptions {
1548
1581
  */
1549
1582
  name?: string;
1550
1583
  }
1551
- interface SandboxTunnelsAPI {
1552
- /** Spawn `cloudflared tunnel --url`. No credentials required. */
1553
- runQuickTunnel(id: string, port: number): Promise<TunnelInfo>;
1554
- /**
1555
- * Spawn `cloudflared tunnel run --token <token> --url http://localhost:<port>`.
1556
- *
1557
- * The SDK is the source of truth for the hostname this tunnel binds to;
1558
- * the container only sees the opaque token and the local port. The
1559
- * returned `TunnelInfo` carries empty `url`/`hostname` fields — the SDK
1560
- * enriches them with the values from the Cloudflare API before handing
1561
- * the record to user code.
1562
- *
1563
- * The token must never be logged, persisted, or echoed back to callers.
1564
- */
1565
- runNamedTunnel(id: string, token: string, port: number): Promise<TunnelInfo>;
1566
- /** Stop the cloudflared process for the given tunnel id. */
1567
- destroyTunnel(id: string): Promise<{
1584
+ type TunnelRunMode = 'quick' | 'named';
1585
+ interface TunnelRunIdentity {
1586
+ tunnelId: string;
1587
+ runId: string;
1588
+ }
1589
+ type TunnelRunRef = TunnelRunIdentity;
1590
+ interface EnsureQuickTunnelRunRequest extends TunnelRunIdentity {
1591
+ mode: 'quick';
1592
+ port: number;
1593
+ readyTimeoutMs?: number;
1594
+ stopGraceMs?: number;
1595
+ }
1596
+ interface EnsureNamedTunnelRunRequest extends TunnelRunIdentity {
1597
+ mode: 'named';
1598
+ port: number;
1599
+ cloudflaredToken: string;
1600
+ readyTimeoutMs?: number;
1601
+ stopGraceMs?: number;
1602
+ }
1603
+ type EnsureTunnelRunRequest = EnsureQuickTunnelRunRequest | EnsureNamedTunnelRunRequest;
1604
+ interface QuickTunnelRunSnapshot extends TunnelRunIdentity {
1605
+ mode: 'quick';
1606
+ port: number;
1607
+ url: string;
1608
+ hostname: string;
1609
+ startedAt: string;
1610
+ }
1611
+ interface NamedTunnelRunSnapshot extends TunnelRunIdentity {
1612
+ mode: 'named';
1613
+ port: number;
1614
+ startedAt: string;
1615
+ }
1616
+ type TunnelRunSnapshot = QuickTunnelRunSnapshot | NamedTunnelRunSnapshot;
1617
+ interface EnsureTunnelRunResult {
1618
+ run: TunnelRunSnapshot;
1619
+ started: boolean;
1620
+ }
1621
+ type StopTunnelRunRequest = TunnelRunRef;
1622
+ interface StopTunnelRunResult {
1623
+ stopped: boolean;
1624
+ }
1625
+ interface TunnelRunExitEvent extends TunnelRunIdentity {
1626
+ mode: TunnelRunMode;
1627
+ port: number;
1628
+ exitCode: number | null;
1629
+ }
1630
+ interface SandboxTerminalsAPI {
1631
+ createTerminal(options: TerminalCreateOptions): Promise<{
1632
+ success: true;
1633
+ id: string;
1634
+ }>;
1635
+ destroyTerminal(id: string): Promise<{
1568
1636
  success: true;
1569
1637
  id: string;
1570
1638
  }>;
1571
- /** List tunnels currently running inside the container. */
1572
- listTunnels(): Promise<TunnelInfo[]>;
1639
+ }
1640
+ interface SandboxTunnelsAPI {
1641
+ /** Ensure a runtime-local cloudflared process for a DO-issued run id. */
1642
+ ensureTunnelRun(request: EnsureTunnelRunRequest): Promise<EnsureTunnelRunResult>;
1643
+ /** Stop the matching runtime-local cloudflared process. */
1644
+ stopTunnelRun(request: StopTunnelRunRequest): Promise<StopTunnelRunResult>;
1573
1645
  }
1574
1646
  /**
1575
1647
  * Author-facing description of a sidecar extension. An extension is an
@@ -1666,14 +1738,104 @@ interface SandboxExtensionsAPI {
1666
1738
  * future container→DO events.
1667
1739
  */
1668
1740
  interface SandboxControlCallback {
1741
+ /** Called by the container when a runtime-local tunnel run exits. */
1742
+ onTunnelRunExit(event: TunnelRunExitEvent): Promise<void>;
1743
+ }
1744
+ //#endregion
1745
+ //#region src/extensions/index.d.ts
1746
+ interface HTTPAuthHostConfig {
1747
+ token: string;
1748
+ username?: string;
1749
+ type?: 'basic' | 'bearer';
1750
+ }
1751
+ interface HTTPAuthInterceptorParams {
1752
+ hosts: Record<string, HTTPAuthHostConfig>;
1753
+ }
1754
+ /**
1755
+ * The slice of the Sandbox an extension captures: its control `client`, unified
1756
+ * `exec()` surface, and sandbox-level environment variables. Narrow on purpose
1757
+ * \u2014 an extension never holds the whole instance.
1758
+ *
1759
+ * `envVars` mirrors what the Sandbox applies to sessionless execution, so an
1760
+ * extension that drives commands through `client` directly can still honour
1761
+ * sandbox-level env (tokens, proxy settings) without an explicit session.
1762
+ */
1763
+ type SandboxLike = {
1764
+ readonly client: SandboxAPI;
1765
+ readonly exec?: (command: string | string[], options?: SandboxExecOptions) => SandboxProcessPromise;
1766
+ readonly envVars?: Record<string, string>;
1767
+ registerGitAuthInterceptor?: (params: HTTPAuthInterceptorParams) => Promise<void>;
1768
+ };
1769
+ /**
1770
+ * The one base class for *every* extension.
1771
+ *
1772
+ * - SDK-only: just drives existing sub-APIs.
1773
+ * - Sidecar: pass an {@link ExtensionPackage} to `super(sandbox, pkg)` and
1774
+ * call `this.sidecar<T>()` to get a typed capnweb stub of the sidecar.
1775
+ *
1776
+ * The sidecar accessor throws a clear error if no package was supplied, so an
1777
+ * extension only "becomes" a sidecar extension when it opts in.
1778
+ *
1779
+ * ```ts
1780
+ * // SDK-only
1781
+ * class Git extends SandboxExtension {
1782
+ * constructor(s: SandboxLike) { super(s); }
1783
+ * async status(sid: string) {
1784
+ * return this.exec('git status', { sessionId: sid }).output();
1785
+ * }
1786
+ * }
1787
+ *
1788
+ * // Sidecar
1789
+ * import sidecarTarballBytes from './sidecar-package.tgz';
1790
+ * import type { MyAPI } from './shared';
1791
+ *
1792
+ * class MyExt extends SandboxExtension {
1793
+ * constructor(s: SandboxLike) { super(s, { tarball: new Uint8Array(sidecarTarballBytes) }); }
1794
+ * async run(input: string): Promise<string> {
1795
+ * const api = await this.sidecar<MyAPI>();
1796
+ * return api.run(input);
1797
+ * }
1798
+ * }
1799
+ * ```
1800
+ *
1801
+ * RPC-safety: the sandbox lives in `#sandbox` and is reached only through the
1802
+ * `protected` `client` getter (a prototype accessor, not an own property),
1803
+ * so it is never serialised across RPC. Only the public methods you add form
1804
+ * the extension's RPC surface.
1805
+ */
1806
+ declare abstract class SandboxExtension extends RpcTarget {
1807
+ #private;
1808
+ protected constructor(sandbox: SandboxLike, pkg?: ExtensionPackage);
1809
+ /** The container control client. Use inside your own methods, lazily. */
1810
+ protected get client(): SandboxAPI;
1811
+ /** Unified process-handle exec surface from the owning Sandbox. */
1812
+ protected exec(command: string | string[], options?: SandboxExecOptions): SandboxProcessPromise;
1813
+ /**
1814
+ * Sandbox-level environment variables. Apply these to sessionless execution
1815
+ * so commands driven straight through `client` still inherit sandbox env
1816
+ * (tokens, proxy settings) the way the Sandbox's own sessionless path does.
1817
+ */
1818
+ protected get envVars(): Record<string, string>;
1819
+ protected get httpAuthInterceptor(): ((params: HTTPAuthInterceptorParams) => Promise<void>) | undefined;
1820
+ /**
1821
+ * Return the sidecar's capnweb remote main, provisioning + spawning on
1822
+ * demand. `T` is the typed interface the sidecar exposes (its
1823
+ * `SandboxSidecar` subclass shape). Each call reconnects through the host
1824
+ * so a crashed sidecar can be restarted transparently on the next use.
1825
+ *
1826
+ * Streaming is just a method that takes a callback parameter: capnweb
1827
+ * stubs the callback and routes invocations back through the SDK\u2192container
1828
+ * \u2192sidecar hops.
1829
+ */
1830
+ protected sidecar<T extends object>(): Promise<T>;
1831
+ /** Health snapshot for this extension's sidecar. */
1832
+ protected sidecarHealth(): Promise<ExtensionHealth>;
1669
1833
  /**
1670
- * Called by the container when a `cloudflared` process exits for any
1671
- * reason — SIGTERM from `destroyTunnel`, container-initiated SIGKILL,
1672
- * network failure, segfault. `exitCode` is `null` if the process was
1673
- * signalled rather than exited cleanly.
1834
+ * Stop this extension's sidecar. The next `sidecar()` call will respawn on
1835
+ * demand.
1674
1836
  */
1675
- onTunnelExit(id: string, port: number, exitCode: number | null): Promise<void>;
1837
+ protected stopSidecar(): Promise<void>;
1676
1838
  }
1677
1839
  //#endregion
1678
- export { RenameFileResult as $, ExecResult as A, ListFilesOptions as B, BucketProvider as C, DirectoryBackup as D, DeleteFileResult as E, FileMetadata as F, MountBucketOptions as G, LocalMountBucketOptions as H, FileStreamEvent as I, ProcessOptions as J, MoveFileResult as K, FileWatchSSEEvent as L, FileChunk as M, FileEncoding as N, ExecEvent as O, FileExistsResult as P, RemoteMountBucketOptions as Q, GitCheckoutResult as R, BucketCredentials as S, CheckChangesResult as T, LogEvent as U, ListFilesResult as V, MkdirResult as W, ReadFileResult as X, ProcessStatus as Y, ReadFileStreamResult as Z, SandboxWatchAPI as _, RunCodeOptions as _t, SandboxAPI as a, WaitForLogResult as at, BackupOptions as b, SandboxControlCallback as c, WriteFileResult as ct, SandboxGitAPI as d, isProcessStatus as dt, RestoreBackupResult as et, SandboxInterpreterAPI as f, PtyOptions as ft, SandboxUtilsAPI as g, ExecutionResult as gt, SandboxTunnelsAPI as h, Execution as ht, QuickTunnelInfo as i, StreamOptions as it, ExecutionSession as j, ExecOptions as k, SandboxExtensionsAPI as l, isExecResult as lt, SandboxProcessesAPI as m, CreateContextOptions as mt, ExtensionPackage as n, SessionDeleteResult as nt, SandboxBackupAPI as o, WaitForPortOptions as ot, SandboxPortsAPI as p, CodeContext as pt, Process as q, NamedTunnelInfo as r, SessionOptions as rt, SandboxCommandsAPI as s, WatchOptions as st, ExtensionHealth as t, SandboxOptions as tt, SandboxFilesAPI as u, isProcess as ut, TunnelInfo as v, CheckChangesOptions as w, BaseExecOptions as x, TunnelOptions as y, ISandbox as z };
1679
- //# sourceMappingURL=rpc-types-PBUY-xXM.d.ts.map
1840
+ export { ReadFileStreamResult as $, ExecEvent as A, ISandbox as B, BaseExecOptions as C, CheckChangesResult as D, CheckChangesOptions as E, FileEncoding as F, MkdirResult as G, ListFilesResult as H, FileExistsResult as I, Process as J, MountBucketOptions as K, FileMetadata as L, ExecResult as M, ExecutionSession as N, DeleteFileResult as O, FileChunk as P, ReadFileResult as Q, FileStreamEvent as R, BackupOptions as S, BucketProvider as T, LocalMountBucketOptions as U, ListFilesOptions as V, LogEvent as W, ProcessQueryOptions as X, ProcessOptions as Y, ProcessStatus as Z, SandboxTunnelsAPI as _, PtyOptions as _t, ExtensionHealth as a, SandboxOptions as at, TunnelInfo as b, TerminalCreateOptions as bt, QuickTunnelInfo as c, SessionDeleteResult as ct, SandboxControlCallback as d, WaitForPortOptions as dt, RemoteMountBucketOptions as et, SandboxExtensionsAPI as f, WatchOptions as ft, SandboxTerminalsAPI as g, isProcessStatus as gt, SandboxProcessesAPI as h, isProcess as ht, SandboxLike as i, SandboxExecOutput as it, ExecOptions as j, DirectoryBackup as k, SandboxBackupAPI as l, SessionOptions as lt, SandboxPortsAPI as m, isExecResult as mt, HTTPAuthInterceptorParams as n, RestoreBackupResult as nt, ExtensionPackage as o, SandboxProcess as ot, SandboxFilesAPI as p, WriteFileResult as pt, MoveFileResult as q, SandboxExtension as r, SandboxExecOptions as rt, NamedTunnelInfo as s, SandboxProcessPromise as st, HTTPAuthHostConfig as t, RenameFileResult as tt, SandboxCommandsAPI as u, WaitForLogResult as ut, SandboxUtilsAPI as v, SandboxTerminal as vt, BucketCredentials as w, TunnelOptions as x, TerminalOptions as xt, SandboxWatchAPI as y, TerminalConnectOptions as yt, FileWatchSSEEvent as z };
1841
+ //# sourceMappingURL=index-B7QgIs0N.d.ts.map