@cloudflare/sandbox 0.0.0-7bccc85 → 0.0.0-7edbfa9

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 (56) hide show
  1. package/CHANGELOG.md +308 -0
  2. package/Dockerfile +142 -9
  3. package/README.md +147 -49
  4. package/dist/index.d.ts +1907 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +3159 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +16 -10
  9. package/src/clients/base-client.ts +295 -0
  10. package/src/clients/command-client.ts +115 -0
  11. package/src/clients/file-client.ts +300 -0
  12. package/src/clients/git-client.ts +91 -0
  13. package/src/clients/index.ts +60 -0
  14. package/src/clients/interpreter-client.ts +333 -0
  15. package/src/clients/port-client.ts +105 -0
  16. package/src/clients/process-client.ts +180 -0
  17. package/src/clients/sandbox-client.ts +39 -0
  18. package/src/clients/types.ts +88 -0
  19. package/src/clients/utility-client.ts +123 -0
  20. package/src/errors/adapter.ts +238 -0
  21. package/src/errors/classes.ts +594 -0
  22. package/src/errors/index.ts +109 -0
  23. package/src/file-stream.ts +169 -0
  24. package/src/index.ts +91 -120
  25. package/src/interpreter.ts +168 -0
  26. package/src/request-handler.ts +183 -0
  27. package/src/sandbox.ts +1247 -0
  28. package/src/security.ts +119 -0
  29. package/src/sse-parser.ts +144 -0
  30. package/src/version.ts +6 -0
  31. package/startup.sh +3 -0
  32. package/tests/base-client.test.ts +364 -0
  33. package/tests/command-client.test.ts +444 -0
  34. package/tests/file-client.test.ts +831 -0
  35. package/tests/file-stream.test.ts +310 -0
  36. package/tests/get-sandbox.test.ts +149 -0
  37. package/tests/git-client.test.ts +415 -0
  38. package/tests/port-client.test.ts +293 -0
  39. package/tests/process-client.test.ts +683 -0
  40. package/tests/request-handler.test.ts +292 -0
  41. package/tests/sandbox.test.ts +702 -0
  42. package/tests/sse-parser.test.ts +291 -0
  43. package/tests/utility-client.test.ts +339 -0
  44. package/tests/version.test.ts +16 -0
  45. package/tests/wrangler.jsonc +35 -0
  46. package/tsconfig.json +9 -1
  47. package/tsdown.config.ts +12 -0
  48. package/vitest.config.ts +31 -0
  49. package/container_src/index.ts +0 -2900
  50. package/container_src/package.json +0 -9
  51. package/src/client.ts +0 -1929
  52. package/tests/client.example.ts +0 -308
  53. package/tests/connection-test.ts +0 -81
  54. package/tests/simple-test.ts +0 -81
  55. package/tests/test1.ts +0 -281
  56. package/tests/test2.ts +0 -929
@@ -0,0 +1,1907 @@
1
+ import { Container } from "@cloudflare/containers";
2
+ import { DurableObject } from "cloudflare:workers";
3
+
4
+ //#region ../shared/dist/interpreter-types.d.ts
5
+ interface CreateContextOptions {
6
+ /**
7
+ * Programming language for the context
8
+ * @default 'python'
9
+ */
10
+ language?: 'python' | 'javascript' | 'typescript';
11
+ /**
12
+ * Working directory for the context
13
+ * @default '/workspace'
14
+ */
15
+ cwd?: string;
16
+ /**
17
+ * Environment variables for the context
18
+ */
19
+ envVars?: Record<string, string>;
20
+ /**
21
+ * Request timeout in milliseconds
22
+ * @default 30000
23
+ */
24
+ timeout?: number;
25
+ }
26
+ interface CodeContext {
27
+ /**
28
+ * Unique identifier for the context
29
+ */
30
+ readonly id: string;
31
+ /**
32
+ * Programming language of the context
33
+ */
34
+ readonly language: string;
35
+ /**
36
+ * Current working directory
37
+ */
38
+ readonly cwd: string;
39
+ /**
40
+ * When the context was created
41
+ */
42
+ readonly createdAt: Date;
43
+ /**
44
+ * When the context was last used
45
+ */
46
+ readonly lastUsed: Date;
47
+ }
48
+ interface RunCodeOptions {
49
+ /**
50
+ * Context to run the code in. If not provided, uses default context for the language
51
+ */
52
+ context?: CodeContext;
53
+ /**
54
+ * Language to use if context is not provided
55
+ * @default 'python'
56
+ */
57
+ language?: 'python' | 'javascript' | 'typescript';
58
+ /**
59
+ * Environment variables for this execution
60
+ */
61
+ envVars?: Record<string, string>;
62
+ /**
63
+ * Execution timeout in milliseconds
64
+ * @default 60000
65
+ */
66
+ timeout?: number;
67
+ /**
68
+ * AbortSignal for cancelling execution
69
+ */
70
+ signal?: AbortSignal;
71
+ /**
72
+ * Callback for stdout output
73
+ */
74
+ onStdout?: (output: OutputMessage) => void | Promise<void>;
75
+ /**
76
+ * Callback for stderr output
77
+ */
78
+ onStderr?: (output: OutputMessage) => void | Promise<void>;
79
+ /**
80
+ * Callback for execution results (charts, tables, etc)
81
+ */
82
+ onResult?: (result: Result) => void | Promise<void>;
83
+ /**
84
+ * Callback for execution errors
85
+ */
86
+ onError?: (error: ExecutionError) => void | Promise<void>;
87
+ }
88
+ interface OutputMessage {
89
+ /**
90
+ * The output text
91
+ */
92
+ text: string;
93
+ /**
94
+ * Timestamp of the output
95
+ */
96
+ timestamp: number;
97
+ }
98
+ interface Result {
99
+ /**
100
+ * Plain text representation
101
+ */
102
+ text?: string;
103
+ /**
104
+ * HTML representation (tables, formatted output)
105
+ */
106
+ html?: string;
107
+ /**
108
+ * PNG image data (base64 encoded)
109
+ */
110
+ png?: string;
111
+ /**
112
+ * JPEG image data (base64 encoded)
113
+ */
114
+ jpeg?: string;
115
+ /**
116
+ * SVG image data
117
+ */
118
+ svg?: string;
119
+ /**
120
+ * LaTeX representation
121
+ */
122
+ latex?: string;
123
+ /**
124
+ * Markdown representation
125
+ */
126
+ markdown?: string;
127
+ /**
128
+ * JavaScript code to execute
129
+ */
130
+ javascript?: string;
131
+ /**
132
+ * JSON data
133
+ */
134
+ json?: any;
135
+ /**
136
+ * Chart data if the result is a visualization
137
+ */
138
+ chart?: ChartData;
139
+ /**
140
+ * Raw data object
141
+ */
142
+ data?: any;
143
+ /**
144
+ * Available output formats
145
+ */
146
+ formats(): string[];
147
+ }
148
+ interface ChartData {
149
+ /**
150
+ * Type of chart
151
+ */
152
+ type: 'line' | 'bar' | 'scatter' | 'pie' | 'histogram' | 'heatmap' | 'unknown';
153
+ /**
154
+ * Chart title
155
+ */
156
+ title?: string;
157
+ /**
158
+ * Chart data (format depends on library)
159
+ */
160
+ data: any;
161
+ /**
162
+ * Chart layout/configuration
163
+ */
164
+ layout?: any;
165
+ /**
166
+ * Additional configuration
167
+ */
168
+ config?: any;
169
+ /**
170
+ * Library that generated the chart
171
+ */
172
+ library?: 'matplotlib' | 'plotly' | 'altair' | 'seaborn' | 'unknown';
173
+ /**
174
+ * Base64 encoded image if available
175
+ */
176
+ image?: string;
177
+ }
178
+ interface ExecutionError {
179
+ /**
180
+ * Error name/type (e.g., 'NameError', 'SyntaxError')
181
+ */
182
+ name: string;
183
+ /**
184
+ * Error message
185
+ */
186
+ message: string;
187
+ /**
188
+ * Stack trace
189
+ */
190
+ traceback: string[];
191
+ /**
192
+ * Line number where error occurred
193
+ */
194
+ lineNumber?: number;
195
+ }
196
+ interface ExecutionResult {
197
+ code: string;
198
+ logs: {
199
+ stdout: string[];
200
+ stderr: string[];
201
+ };
202
+ error?: ExecutionError;
203
+ executionCount?: number;
204
+ results: Array<{
205
+ text?: string;
206
+ html?: string;
207
+ png?: string;
208
+ jpeg?: string;
209
+ svg?: string;
210
+ latex?: string;
211
+ markdown?: string;
212
+ javascript?: string;
213
+ json?: any;
214
+ chart?: ChartData;
215
+ data?: any;
216
+ }>;
217
+ }
218
+ declare class Execution {
219
+ readonly code: string;
220
+ readonly context: CodeContext;
221
+ /**
222
+ * All results from the execution
223
+ */
224
+ results: Result[];
225
+ /**
226
+ * Accumulated stdout and stderr
227
+ */
228
+ logs: {
229
+ stdout: string[];
230
+ stderr: string[];
231
+ };
232
+ /**
233
+ * Execution error if any
234
+ */
235
+ error?: ExecutionError;
236
+ /**
237
+ * Execution count (for interpreter)
238
+ */
239
+ executionCount?: number;
240
+ constructor(code: string, context: CodeContext);
241
+ /**
242
+ * Convert to a plain object for serialization
243
+ */
244
+ toJSON(): ExecutionResult;
245
+ }
246
+ declare class ResultImpl implements Result {
247
+ private raw;
248
+ constructor(raw: any);
249
+ get text(): string | undefined;
250
+ get html(): string | undefined;
251
+ get png(): string | undefined;
252
+ get jpeg(): string | undefined;
253
+ get svg(): string | undefined;
254
+ get latex(): string | undefined;
255
+ get markdown(): string | undefined;
256
+ get javascript(): string | undefined;
257
+ get json(): any;
258
+ get chart(): ChartData | undefined;
259
+ get data(): any;
260
+ formats(): string[];
261
+ }
262
+ //#endregion
263
+ //#region ../shared/dist/logger/types.d.ts
264
+ /**
265
+ * Logger types for Cloudflare Sandbox SDK
266
+ *
267
+ * Provides structured, trace-aware logging across Worker, Durable Object, and Container.
268
+ */
269
+ /**
270
+ * Log levels (from most to least verbose)
271
+ */
272
+ declare enum LogLevel {
273
+ DEBUG = 0,
274
+ INFO = 1,
275
+ WARN = 2,
276
+ ERROR = 3,
277
+ }
278
+ type LogComponent = 'container' | 'sandbox-do' | 'executor';
279
+ /**
280
+ * Context metadata included in every log entry
281
+ */
282
+ interface LogContext {
283
+ /**
284
+ * Unique trace ID for request correlation across distributed components
285
+ * Format: "tr_" + 16 hex chars (e.g., "tr_7f3a9b2c4e5d6f1a")
286
+ */
287
+ traceId: string;
288
+ /**
289
+ * Component that generated the log
290
+ */
291
+ component: LogComponent;
292
+ /**
293
+ * Sandbox identifier (which sandbox instance)
294
+ */
295
+ sandboxId?: string;
296
+ /**
297
+ * Session identifier (which session within sandbox)
298
+ */
299
+ sessionId?: string;
300
+ /**
301
+ * Process identifier (which background process)
302
+ */
303
+ processId?: string;
304
+ /**
305
+ * Command identifier (which command execution)
306
+ */
307
+ commandId?: string;
308
+ /**
309
+ * Operation name (e.g., 'exec', 'startProcess', 'writeFile')
310
+ */
311
+ operation?: string;
312
+ /**
313
+ * Duration in milliseconds
314
+ */
315
+ duration?: number;
316
+ /**
317
+ * Extensible for additional metadata
318
+ */
319
+ [key: string]: unknown;
320
+ }
321
+ /**
322
+ * Logger interface for structured logging
323
+ *
324
+ * All methods accept optional context that gets merged with the logger's base context.
325
+ */
326
+ interface Logger {
327
+ /**
328
+ * Log debug-level message (most verbose, typically disabled in production)
329
+ *
330
+ * @param message Human-readable message
331
+ * @param context Optional additional context
332
+ */
333
+ debug(message: string, context?: Partial<LogContext>): void;
334
+ /**
335
+ * Log info-level message (normal operational events)
336
+ *
337
+ * @param message Human-readable message
338
+ * @param context Optional additional context
339
+ */
340
+ info(message: string, context?: Partial<LogContext>): void;
341
+ /**
342
+ * Log warning-level message (recoverable issues, degraded state)
343
+ *
344
+ * @param message Human-readable message
345
+ * @param context Optional additional context
346
+ */
347
+ warn(message: string, context?: Partial<LogContext>): void;
348
+ /**
349
+ * Log error-level message (failures, exceptions)
350
+ *
351
+ * @param message Human-readable message
352
+ * @param error Optional Error object to include
353
+ * @param context Optional additional context
354
+ */
355
+ error(message: string, error?: Error, context?: Partial<LogContext>): void;
356
+ /**
357
+ * Create a child logger with additional context
358
+ *
359
+ * The child logger inherits all context from the parent and adds new context.
360
+ * This is useful for adding operation-specific context without passing through parameters.
361
+ *
362
+ * @param context Additional context to merge
363
+ * @returns New logger instance with merged context
364
+ *
365
+ * @example
366
+ * const logger = createLogger({ component: 'sandbox-do', traceId: 'tr_abc123' });
367
+ * const execLogger = logger.child({ operation: 'exec', commandId: 'cmd-456' });
368
+ * execLogger.info('Command started'); // Includes all context: component, traceId, operation, commandId
369
+ */
370
+ child(context: Partial<LogContext>): Logger;
371
+ }
372
+ //#endregion
373
+ //#region ../shared/dist/logger/trace-context.d.ts
374
+ /**
375
+ * Trace context utilities for request correlation
376
+ *
377
+ * Trace IDs enable correlating logs across distributed components:
378
+ * Worker → Durable Object → Container → back
379
+ *
380
+ * The trace ID is propagated via the X-Trace-Id HTTP header.
381
+ */
382
+ /**
383
+ * Utility for managing trace context across distributed components
384
+ */
385
+ declare class TraceContext {
386
+ /**
387
+ * HTTP header name for trace ID propagation
388
+ */
389
+ private static readonly TRACE_HEADER;
390
+ /**
391
+ * Generate a new trace ID
392
+ *
393
+ * Format: "tr_" + 16 random hex characters
394
+ * Example: "tr_7f3a9b2c4e5d6f1a"
395
+ *
396
+ * @returns Newly generated trace ID
397
+ */
398
+ static generate(): string;
399
+ /**
400
+ * Extract trace ID from HTTP request headers
401
+ *
402
+ * @param headers Request headers
403
+ * @returns Trace ID if present, null otherwise
404
+ */
405
+ static fromHeaders(headers: Headers): string | null;
406
+ /**
407
+ * Create headers object with trace ID for outgoing requests
408
+ *
409
+ * @param traceId Trace ID to include
410
+ * @returns Headers object with X-Trace-Id set
411
+ */
412
+ static toHeaders(traceId: string): Record<string, string>;
413
+ /**
414
+ * Get the header name used for trace ID propagation
415
+ *
416
+ * @returns Header name ("X-Trace-Id")
417
+ */
418
+ static getHeaderName(): string;
419
+ }
420
+ //#endregion
421
+ //#region ../shared/dist/logger/index.d.ts
422
+ /**
423
+ * Create a no-op logger for testing
424
+ *
425
+ * Returns a logger that implements the Logger interface but does nothing.
426
+ * Useful for tests that don't need actual logging output.
427
+ *
428
+ * @returns No-op logger instance
429
+ *
430
+ * @example
431
+ * ```typescript
432
+ * // In tests
433
+ * const client = new HttpClient({
434
+ * baseUrl: 'http://test.com',
435
+ * logger: createNoOpLogger() // Optional - tests can enable real logging if needed
436
+ * });
437
+ * ```
438
+ */
439
+ declare function createNoOpLogger(): Logger;
440
+ /**
441
+ * Get the current logger from AsyncLocalStorage
442
+ *
443
+ * @throws Error if no logger is initialized in the current async context
444
+ * @returns Current logger instance
445
+ *
446
+ * @example
447
+ * ```typescript
448
+ * function someHelperFunction() {
449
+ * const logger = getLogger(); // Automatically has all context!
450
+ * logger.info('Helper called');
451
+ * }
452
+ * ```
453
+ */
454
+ declare function getLogger(): Logger;
455
+ /**
456
+ * Run a function with a logger stored in AsyncLocalStorage
457
+ *
458
+ * The logger is available to all code within the function via getLogger().
459
+ * This is typically called at request entry points (fetch handler) and when
460
+ * creating child loggers with additional context.
461
+ *
462
+ * @param logger Logger instance to store in context
463
+ * @param fn Function to execute with logger context
464
+ * @returns Result of the function
465
+ *
466
+ * @example
467
+ * ```typescript
468
+ * // At request entry point
469
+ * async fetch(request: Request): Promise<Response> {
470
+ * const logger = createLogger({ component: 'sandbox-do', traceId: 'tr_abc' });
471
+ * return runWithLogger(logger, async () => {
472
+ * return await this.handleRequest(request);
473
+ * });
474
+ * }
475
+ *
476
+ * // When adding operation context
477
+ * async exec(command: string) {
478
+ * const logger = getLogger().child({ operation: 'exec', commandId: 'cmd-123' });
479
+ * return runWithLogger(logger, async () => {
480
+ * logger.info('Command started');
481
+ * await this.executeCommand(command); // Nested calls get the child logger
482
+ * logger.info('Command completed');
483
+ * });
484
+ * }
485
+ * ```
486
+ */
487
+ declare function runWithLogger<T>(logger: Logger, fn: () => T | Promise<T>): T | Promise<T>;
488
+ /**
489
+ * Create a new logger instance
490
+ *
491
+ * @param context Base context for the logger. Must include 'component'.
492
+ * TraceId will be auto-generated if not provided.
493
+ * @returns New logger instance
494
+ *
495
+ * @example
496
+ * ```typescript
497
+ * // In Durable Object
498
+ * const logger = createLogger({
499
+ * component: 'sandbox-do',
500
+ * traceId: TraceContext.fromHeaders(request.headers) || TraceContext.generate(),
501
+ * sandboxId: this.id
502
+ * });
503
+ *
504
+ * // In Container
505
+ * const logger = createLogger({
506
+ * component: 'container',
507
+ * traceId: TraceContext.fromHeaders(request.headers)!,
508
+ * sessionId: this.id
509
+ * });
510
+ * ```
511
+ */
512
+ declare function createLogger(context: Partial<LogContext> & {
513
+ component: LogComponent;
514
+ }): Logger;
515
+ //#endregion
516
+ //#region ../shared/dist/request-types.d.ts
517
+ /**
518
+ * Request to start a background process
519
+ * Uses flat structure consistent with other endpoints
520
+ */
521
+ interface StartProcessRequest {
522
+ command: string;
523
+ sessionId?: string;
524
+ processId?: string;
525
+ timeoutMs?: number;
526
+ env?: Record<string, string>;
527
+ cwd?: string;
528
+ encoding?: string;
529
+ autoCleanup?: boolean;
530
+ }
531
+ /**
532
+ * Request to delete a file
533
+ */
534
+ interface DeleteFileRequest {
535
+ path: string;
536
+ sessionId?: string;
537
+ }
538
+ /**
539
+ * Request to rename a file
540
+ */
541
+ interface RenameFileRequest {
542
+ oldPath: string;
543
+ newPath: string;
544
+ sessionId?: string;
545
+ }
546
+ /**
547
+ * Request to move a file
548
+ */
549
+ interface MoveFileRequest {
550
+ sourcePath: string;
551
+ destinationPath: string;
552
+ sessionId?: string;
553
+ }
554
+ /**
555
+ * Request to check if a file or directory exists
556
+ */
557
+ interface FileExistsRequest {
558
+ path: string;
559
+ sessionId?: string;
560
+ }
561
+ /**
562
+ * Request to create a session
563
+ */
564
+ interface SessionCreateRequest {
565
+ id?: string;
566
+ name?: string;
567
+ env?: Record<string, string>;
568
+ cwd?: string;
569
+ }
570
+ /**
571
+ * Request to delete a session
572
+ */
573
+ interface SessionDeleteRequest {
574
+ sessionId: string;
575
+ }
576
+ //#endregion
577
+ //#region ../shared/dist/types.d.ts
578
+ interface BaseExecOptions {
579
+ /**
580
+ * Maximum execution time in milliseconds
581
+ */
582
+ timeout?: number;
583
+ /**
584
+ * Environment variables for the command
585
+ */
586
+ env?: Record<string, string>;
587
+ /**
588
+ * Working directory for command execution
589
+ */
590
+ cwd?: string;
591
+ /**
592
+ * Text encoding for output (default: 'utf8')
593
+ */
594
+ encoding?: string;
595
+ }
596
+ interface ExecOptions extends BaseExecOptions {
597
+ /**
598
+ * Enable real-time output streaming via callbacks
599
+ */
600
+ stream?: boolean;
601
+ /**
602
+ * Callback for real-time output data
603
+ */
604
+ onOutput?: (stream: 'stdout' | 'stderr', data: string) => void;
605
+ /**
606
+ * Callback when command completes (only when stream: true)
607
+ */
608
+ onComplete?: (result: ExecResult) => void;
609
+ /**
610
+ * Callback for execution errors
611
+ */
612
+ onError?: (error: Error) => void;
613
+ /**
614
+ * AbortSignal for cancelling execution
615
+ */
616
+ signal?: AbortSignal;
617
+ }
618
+ interface ExecResult {
619
+ /**
620
+ * Whether the command succeeded (exitCode === 0)
621
+ */
622
+ success: boolean;
623
+ /**
624
+ * Process exit code
625
+ */
626
+ exitCode: number;
627
+ /**
628
+ * Standard output content
629
+ */
630
+ stdout: string;
631
+ /**
632
+ * Standard error content
633
+ */
634
+ stderr: string;
635
+ /**
636
+ * Command that was executed
637
+ */
638
+ command: string;
639
+ /**
640
+ * Execution duration in milliseconds
641
+ */
642
+ duration: number;
643
+ /**
644
+ * ISO timestamp when command started
645
+ */
646
+ timestamp: string;
647
+ /**
648
+ * Session ID if provided
649
+ */
650
+ sessionId?: string;
651
+ }
652
+ interface ProcessOptions extends BaseExecOptions {
653
+ /**
654
+ * Custom process ID for later reference
655
+ * If not provided, a UUID will be generated
656
+ */
657
+ processId?: string;
658
+ /**
659
+ * Automatically cleanup process record after exit (default: true)
660
+ */
661
+ autoCleanup?: boolean;
662
+ /**
663
+ * Callback when process exits
664
+ */
665
+ onExit?: (code: number | null) => void;
666
+ /**
667
+ * Callback for real-time output (background processes)
668
+ */
669
+ onOutput?: (stream: 'stdout' | 'stderr', data: string) => void;
670
+ /**
671
+ * Callback when process starts successfully
672
+ */
673
+ onStart?: (process: Process) => void;
674
+ /**
675
+ * Callback for process errors
676
+ */
677
+ onError?: (error: Error) => void;
678
+ }
679
+ type ProcessStatus = 'starting' | 'running' | 'completed' | 'failed' | 'killed' | 'error';
680
+ interface Process {
681
+ /**
682
+ * Unique process identifier
683
+ */
684
+ readonly id: string;
685
+ /**
686
+ * System process ID (if available and running)
687
+ */
688
+ readonly pid?: number;
689
+ /**
690
+ * Command that was executed
691
+ */
692
+ readonly command: string;
693
+ /**
694
+ * Current process status
695
+ */
696
+ readonly status: ProcessStatus;
697
+ /**
698
+ * When the process was started
699
+ */
700
+ readonly startTime: Date;
701
+ /**
702
+ * When the process ended (if completed)
703
+ */
704
+ readonly endTime?: Date;
705
+ /**
706
+ * Process exit code (if completed)
707
+ */
708
+ readonly exitCode?: number;
709
+ /**
710
+ * Session ID if provided
711
+ */
712
+ readonly sessionId?: string;
713
+ /**
714
+ * Kill the process
715
+ */
716
+ kill(signal?: string): Promise<void>;
717
+ /**
718
+ * Get current process status (refreshed)
719
+ */
720
+ getStatus(): Promise<ProcessStatus>;
721
+ /**
722
+ * Get accumulated logs
723
+ */
724
+ getLogs(): Promise<{
725
+ stdout: string;
726
+ stderr: string;
727
+ }>;
728
+ }
729
+ interface ExecEvent {
730
+ type: 'start' | 'stdout' | 'stderr' | 'complete' | 'error';
731
+ timestamp: string;
732
+ data?: string;
733
+ command?: string;
734
+ exitCode?: number;
735
+ result?: ExecResult;
736
+ error?: string;
737
+ sessionId?: string;
738
+ }
739
+ interface LogEvent {
740
+ type: 'stdout' | 'stderr' | 'exit' | 'error';
741
+ timestamp: string;
742
+ data: string;
743
+ processId: string;
744
+ sessionId?: string;
745
+ exitCode?: number;
746
+ }
747
+ interface StreamOptions extends BaseExecOptions {
748
+ /**
749
+ * Buffer size for streaming output
750
+ */
751
+ bufferSize?: number;
752
+ /**
753
+ * AbortSignal for cancelling stream
754
+ */
755
+ signal?: AbortSignal;
756
+ }
757
+ interface SessionOptions {
758
+ /**
759
+ * Optional session ID (auto-generated if not provided)
760
+ */
761
+ id?: string;
762
+ /**
763
+ * Session name for identification
764
+ */
765
+ name?: string;
766
+ /**
767
+ * Environment variables for this session
768
+ */
769
+ env?: Record<string, string>;
770
+ /**
771
+ * Working directory
772
+ */
773
+ cwd?: string;
774
+ /**
775
+ * Enable PID namespace isolation (requires CAP_SYS_ADMIN)
776
+ */
777
+ isolation?: boolean;
778
+ }
779
+ interface SandboxOptions {
780
+ /**
781
+ * Duration after which the sandbox instance will sleep if no requests are received
782
+ * Can be:
783
+ * - A string like "30s", "3m", "5m", "1h" (seconds, minutes, or hours)
784
+ * - A number representing seconds (e.g., 180 for 3 minutes)
785
+ * Default: "10m" (10 minutes)
786
+ *
787
+ * Note: Ignored when keepAlive is true
788
+ */
789
+ sleepAfter?: string | number;
790
+ /**
791
+ * Base URL for the sandbox API
792
+ */
793
+ baseUrl?: string;
794
+ /**
795
+ * Keep the container alive indefinitely by preventing automatic shutdown
796
+ * When true, the container will never auto-timeout and must be explicitly destroyed
797
+ * - Any scenario where activity can't be automatically detected
798
+ *
799
+ * Important: You MUST call sandbox.destroy() when done to avoid resource leaks
800
+ *
801
+ * Default: false
802
+ */
803
+ keepAlive?: boolean;
804
+ }
805
+ /**
806
+ * Execution session - isolated execution context within a sandbox
807
+ * Returned by sandbox.createSession()
808
+ * Provides the same API as ISandbox but bound to a specific session
809
+ */
810
+ interface MkdirResult {
811
+ success: boolean;
812
+ path: string;
813
+ recursive: boolean;
814
+ timestamp: string;
815
+ exitCode?: number;
816
+ }
817
+ interface WriteFileResult {
818
+ success: boolean;
819
+ path: string;
820
+ timestamp: string;
821
+ exitCode?: number;
822
+ }
823
+ interface ReadFileResult {
824
+ success: boolean;
825
+ path: string;
826
+ content: string;
827
+ timestamp: string;
828
+ exitCode?: number;
829
+ /**
830
+ * Encoding used for content (utf-8 for text, base64 for binary)
831
+ */
832
+ encoding?: 'utf-8' | 'base64';
833
+ /**
834
+ * Whether the file is detected as binary
835
+ */
836
+ isBinary?: boolean;
837
+ /**
838
+ * MIME type of the file (e.g., 'image/png', 'text/plain')
839
+ */
840
+ mimeType?: string;
841
+ /**
842
+ * File size in bytes
843
+ */
844
+ size?: number;
845
+ }
846
+ interface DeleteFileResult {
847
+ success: boolean;
848
+ path: string;
849
+ timestamp: string;
850
+ exitCode?: number;
851
+ }
852
+ interface RenameFileResult {
853
+ success: boolean;
854
+ path: string;
855
+ newPath: string;
856
+ timestamp: string;
857
+ exitCode?: number;
858
+ }
859
+ interface MoveFileResult {
860
+ success: boolean;
861
+ path: string;
862
+ newPath: string;
863
+ timestamp: string;
864
+ exitCode?: number;
865
+ }
866
+ interface FileExistsResult {
867
+ success: boolean;
868
+ path: string;
869
+ exists: boolean;
870
+ timestamp: string;
871
+ }
872
+ interface FileInfo {
873
+ name: string;
874
+ absolutePath: string;
875
+ relativePath: string;
876
+ type: 'file' | 'directory' | 'symlink' | 'other';
877
+ size: number;
878
+ modifiedAt: string;
879
+ mode: string;
880
+ permissions: {
881
+ readable: boolean;
882
+ writable: boolean;
883
+ executable: boolean;
884
+ };
885
+ }
886
+ interface ListFilesOptions {
887
+ recursive?: boolean;
888
+ includeHidden?: boolean;
889
+ }
890
+ interface ListFilesResult {
891
+ success: boolean;
892
+ path: string;
893
+ files: FileInfo[];
894
+ count: number;
895
+ timestamp: string;
896
+ exitCode?: number;
897
+ }
898
+ interface GitCheckoutResult {
899
+ success: boolean;
900
+ repoUrl: string;
901
+ branch: string;
902
+ targetDir: string;
903
+ timestamp: string;
904
+ exitCode?: number;
905
+ }
906
+ /**
907
+ * SSE events for file streaming
908
+ */
909
+ type FileStreamEvent = {
910
+ type: 'metadata';
911
+ mimeType: string;
912
+ size: number;
913
+ isBinary: boolean;
914
+ encoding: 'utf-8' | 'base64';
915
+ } | {
916
+ type: 'chunk';
917
+ data: string;
918
+ } | {
919
+ type: 'complete';
920
+ bytesRead: number;
921
+ } | {
922
+ type: 'error';
923
+ error: string;
924
+ };
925
+ /**
926
+ * File metadata from streaming
927
+ */
928
+ interface FileMetadata {
929
+ mimeType: string;
930
+ size: number;
931
+ isBinary: boolean;
932
+ encoding: 'utf-8' | 'base64';
933
+ }
934
+ /**
935
+ * File stream chunk - either string (text) or Uint8Array (binary, auto-decoded)
936
+ */
937
+ type FileChunk = string | Uint8Array;
938
+ interface ProcessStartResult {
939
+ success: boolean;
940
+ processId: string;
941
+ pid?: number;
942
+ command: string;
943
+ timestamp: string;
944
+ }
945
+ interface ProcessListResult {
946
+ success: boolean;
947
+ processes: Array<{
948
+ id: string;
949
+ pid?: number;
950
+ command: string;
951
+ status: ProcessStatus;
952
+ startTime: string;
953
+ endTime?: string;
954
+ exitCode?: number;
955
+ }>;
956
+ timestamp: string;
957
+ }
958
+ interface ProcessInfoResult {
959
+ success: boolean;
960
+ process: {
961
+ id: string;
962
+ pid?: number;
963
+ command: string;
964
+ status: ProcessStatus;
965
+ startTime: string;
966
+ endTime?: string;
967
+ exitCode?: number;
968
+ };
969
+ timestamp: string;
970
+ }
971
+ interface ProcessKillResult {
972
+ success: boolean;
973
+ processId: string;
974
+ signal?: string;
975
+ timestamp: string;
976
+ }
977
+ interface ProcessLogsResult {
978
+ success: boolean;
979
+ processId: string;
980
+ stdout: string;
981
+ stderr: string;
982
+ timestamp: string;
983
+ }
984
+ interface ProcessCleanupResult {
985
+ success: boolean;
986
+ cleanedCount: number;
987
+ timestamp: string;
988
+ }
989
+ interface SessionCreateResult {
990
+ success: boolean;
991
+ sessionId: string;
992
+ name?: string;
993
+ cwd?: string;
994
+ timestamp: string;
995
+ }
996
+ interface SessionDeleteResult {
997
+ success: boolean;
998
+ sessionId: string;
999
+ timestamp: string;
1000
+ }
1001
+ interface EnvSetResult {
1002
+ success: boolean;
1003
+ timestamp: string;
1004
+ }
1005
+ interface PortExposeResult {
1006
+ success: boolean;
1007
+ port: number;
1008
+ url: string;
1009
+ timestamp: string;
1010
+ }
1011
+ interface PortStatusResult {
1012
+ success: boolean;
1013
+ port: number;
1014
+ status: 'active' | 'inactive';
1015
+ url?: string;
1016
+ timestamp: string;
1017
+ }
1018
+ interface PortListResult {
1019
+ success: boolean;
1020
+ ports: Array<{
1021
+ port: number;
1022
+ url: string;
1023
+ status: 'active' | 'inactive';
1024
+ }>;
1025
+ timestamp: string;
1026
+ }
1027
+ interface PortCloseResult {
1028
+ success: boolean;
1029
+ port: number;
1030
+ timestamp: string;
1031
+ }
1032
+ interface InterpreterHealthResult {
1033
+ success: boolean;
1034
+ status: 'healthy' | 'unhealthy';
1035
+ timestamp: string;
1036
+ }
1037
+ interface ContextCreateResult {
1038
+ success: boolean;
1039
+ contextId: string;
1040
+ language: string;
1041
+ cwd?: string;
1042
+ timestamp: string;
1043
+ }
1044
+ interface ContextListResult {
1045
+ success: boolean;
1046
+ contexts: Array<{
1047
+ id: string;
1048
+ language: string;
1049
+ cwd?: string;
1050
+ }>;
1051
+ timestamp: string;
1052
+ }
1053
+ interface ContextDeleteResult {
1054
+ success: boolean;
1055
+ contextId: string;
1056
+ timestamp: string;
1057
+ }
1058
+ interface HealthCheckResult {
1059
+ success: boolean;
1060
+ status: 'healthy' | 'unhealthy';
1061
+ timestamp: string;
1062
+ }
1063
+ interface ShutdownResult {
1064
+ success: boolean;
1065
+ message: string;
1066
+ timestamp: string;
1067
+ }
1068
+ interface ExecutionSession {
1069
+ /** Unique session identifier */
1070
+ readonly id: string;
1071
+ exec(command: string, options?: ExecOptions): Promise<ExecResult>;
1072
+ execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>>;
1073
+ startProcess(command: string, options?: ProcessOptions): Promise<Process>;
1074
+ listProcesses(): Promise<Process[]>;
1075
+ getProcess(id: string): Promise<Process | null>;
1076
+ killProcess(id: string, signal?: string): Promise<void>;
1077
+ killAllProcesses(): Promise<number>;
1078
+ cleanupCompletedProcesses(): Promise<number>;
1079
+ getProcessLogs(id: string): Promise<{
1080
+ stdout: string;
1081
+ stderr: string;
1082
+ processId: string;
1083
+ }>;
1084
+ streamProcessLogs(processId: string, options?: {
1085
+ signal?: AbortSignal;
1086
+ }): Promise<ReadableStream<Uint8Array>>;
1087
+ writeFile(path: string, content: string, options?: {
1088
+ encoding?: string;
1089
+ }): Promise<WriteFileResult>;
1090
+ readFile(path: string, options?: {
1091
+ encoding?: string;
1092
+ }): Promise<ReadFileResult>;
1093
+ readFileStream(path: string): Promise<ReadableStream<Uint8Array>>;
1094
+ mkdir(path: string, options?: {
1095
+ recursive?: boolean;
1096
+ }): Promise<MkdirResult>;
1097
+ deleteFile(path: string): Promise<DeleteFileResult>;
1098
+ renameFile(oldPath: string, newPath: string): Promise<RenameFileResult>;
1099
+ moveFile(sourcePath: string, destinationPath: string): Promise<MoveFileResult>;
1100
+ listFiles(path: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1101
+ exists(path: string): Promise<FileExistsResult>;
1102
+ gitCheckout(repoUrl: string, options?: {
1103
+ branch?: string;
1104
+ targetDir?: string;
1105
+ }): Promise<GitCheckoutResult>;
1106
+ setEnvVars(envVars: Record<string, string>): Promise<void>;
1107
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1108
+ runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
1109
+ runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream<Uint8Array>>;
1110
+ listCodeContexts(): Promise<CodeContext[]>;
1111
+ deleteCodeContext(contextId: string): Promise<void>;
1112
+ }
1113
+ interface ISandbox {
1114
+ exec(command: string, options?: ExecOptions): Promise<ExecResult>;
1115
+ startProcess(command: string, options?: ProcessOptions): Promise<Process>;
1116
+ listProcesses(): Promise<Process[]>;
1117
+ getProcess(id: string): Promise<Process | null>;
1118
+ killProcess(id: string, signal?: string): Promise<void>;
1119
+ killAllProcesses(): Promise<number>;
1120
+ execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>>;
1121
+ streamProcessLogs(processId: string, options?: {
1122
+ signal?: AbortSignal;
1123
+ }): Promise<ReadableStream<Uint8Array>>;
1124
+ cleanupCompletedProcesses(): Promise<number>;
1125
+ getProcessLogs(id: string): Promise<{
1126
+ stdout: string;
1127
+ stderr: string;
1128
+ processId: string;
1129
+ }>;
1130
+ writeFile(path: string, content: string, options?: {
1131
+ encoding?: string;
1132
+ }): Promise<WriteFileResult>;
1133
+ readFile(path: string, options?: {
1134
+ encoding?: string;
1135
+ }): Promise<ReadFileResult>;
1136
+ readFileStream(path: string): Promise<ReadableStream<Uint8Array>>;
1137
+ mkdir(path: string, options?: {
1138
+ recursive?: boolean;
1139
+ }): Promise<MkdirResult>;
1140
+ deleteFile(path: string): Promise<DeleteFileResult>;
1141
+ renameFile(oldPath: string, newPath: string): Promise<RenameFileResult>;
1142
+ moveFile(sourcePath: string, destinationPath: string): Promise<MoveFileResult>;
1143
+ listFiles(path: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1144
+ exists(path: string, sessionId?: string): Promise<FileExistsResult>;
1145
+ gitCheckout(repoUrl: string, options?: {
1146
+ branch?: string;
1147
+ targetDir?: string;
1148
+ }): Promise<GitCheckoutResult>;
1149
+ createSession(options?: SessionOptions): Promise<ExecutionSession>;
1150
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1151
+ runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
1152
+ runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
1153
+ listCodeContexts(): Promise<CodeContext[]>;
1154
+ deleteCodeContext(contextId: string): Promise<void>;
1155
+ }
1156
+ declare function isExecResult(value: any): value is ExecResult;
1157
+ declare function isProcess(value: any): value is Process;
1158
+ declare function isProcessStatus(value: string): value is ProcessStatus;
1159
+ //#endregion
1160
+ //#region src/clients/types.d.ts
1161
+ /**
1162
+ * Minimal interface for container fetch functionality
1163
+ */
1164
+ interface ContainerStub {
1165
+ containerFetch(url: string, options: RequestInit, port?: number): Promise<Response>;
1166
+ }
1167
+ /**
1168
+ * Shared HTTP client configuration options
1169
+ */
1170
+ interface HttpClientOptions {
1171
+ logger?: Logger;
1172
+ baseUrl?: string;
1173
+ port?: number;
1174
+ stub?: ContainerStub;
1175
+ onCommandComplete?: (success: boolean, exitCode: number, stdout: string, stderr: string, command: string) => void;
1176
+ onError?: (error: string, command?: string) => void;
1177
+ }
1178
+ /**
1179
+ * Base response interface for all API responses
1180
+ */
1181
+ interface BaseApiResponse {
1182
+ success: boolean;
1183
+ timestamp: string;
1184
+ }
1185
+ /**
1186
+ * Legacy error response interface - deprecated, use ApiErrorResponse
1187
+ */
1188
+ interface ErrorResponse {
1189
+ error: string;
1190
+ details?: string;
1191
+ code?: string;
1192
+ }
1193
+ /**
1194
+ * HTTP request configuration
1195
+ */
1196
+ interface RequestConfig extends RequestInit {
1197
+ endpoint: string;
1198
+ data?: Record<string, any>;
1199
+ }
1200
+ /**
1201
+ * Typed response handler
1202
+ */
1203
+ type ResponseHandler<T> = (response: Response) => Promise<T>;
1204
+ /**
1205
+ * Common session-aware request interface
1206
+ */
1207
+ interface SessionRequest {
1208
+ sessionId?: string;
1209
+ }
1210
+ //#endregion
1211
+ //#region src/clients/base-client.d.ts
1212
+ /**
1213
+ * Abstract base class providing common HTTP functionality for all domain clients
1214
+ */
1215
+ declare abstract class BaseHttpClient {
1216
+ protected baseUrl: string;
1217
+ protected options: HttpClientOptions;
1218
+ protected logger: Logger;
1219
+ constructor(options?: HttpClientOptions);
1220
+ /**
1221
+ * Core HTTP request method with automatic retry for container provisioning delays
1222
+ */
1223
+ protected doFetch(path: string, options?: RequestInit): Promise<Response>;
1224
+ /**
1225
+ * Make a POST request with JSON body
1226
+ */
1227
+ protected post<T>(endpoint: string, data: Record<string, any>, responseHandler?: ResponseHandler<T>): Promise<T>;
1228
+ /**
1229
+ * Make a GET request
1230
+ */
1231
+ protected get<T>(endpoint: string, responseHandler?: ResponseHandler<T>): Promise<T>;
1232
+ /**
1233
+ * Make a DELETE request
1234
+ */
1235
+ protected delete<T>(endpoint: string, responseHandler?: ResponseHandler<T>): Promise<T>;
1236
+ /**
1237
+ * Handle HTTP response with error checking and parsing
1238
+ */
1239
+ protected handleResponse<T>(response: Response, customHandler?: ResponseHandler<T>): Promise<T>;
1240
+ /**
1241
+ * Handle error responses with consistent error throwing
1242
+ */
1243
+ protected handleErrorResponse(response: Response): Promise<never>;
1244
+ /**
1245
+ * Create a streaming response handler for Server-Sent Events
1246
+ */
1247
+ protected handleStreamResponse(response: Response): Promise<ReadableStream<Uint8Array>>;
1248
+ /**
1249
+ * Utility method to log successful operations
1250
+ */
1251
+ protected logSuccess(operation: string, details?: string): void;
1252
+ /**
1253
+ * Utility method to log errors intelligently
1254
+ * Only logs unexpected errors (5xx), not expected errors (4xx)
1255
+ *
1256
+ * - 4xx errors (validation, not found, conflicts): Don't log (expected client errors)
1257
+ * - 5xx errors (server failures, internal errors): DO log (unexpected server errors)
1258
+ */
1259
+ protected logError(operation: string, error: unknown): void;
1260
+ /**
1261
+ * Check if 503 response is from container provisioning (retryable)
1262
+ * vs user application (not retryable)
1263
+ */
1264
+ private isContainerProvisioningError;
1265
+ private executeFetch;
1266
+ }
1267
+ //#endregion
1268
+ //#region src/clients/command-client.d.ts
1269
+ /**
1270
+ * Request interface for command execution
1271
+ */
1272
+ interface ExecuteRequest extends SessionRequest {
1273
+ command: string;
1274
+ timeoutMs?: number;
1275
+ }
1276
+ /**
1277
+ * Response interface for command execution
1278
+ */
1279
+ interface ExecuteResponse extends BaseApiResponse {
1280
+ stdout: string;
1281
+ stderr: string;
1282
+ exitCode: number;
1283
+ command: string;
1284
+ }
1285
+ /**
1286
+ * Client for command execution operations
1287
+ */
1288
+ declare class CommandClient extends BaseHttpClient {
1289
+ /**
1290
+ * Execute a command and return the complete result
1291
+ * @param command - The command to execute
1292
+ * @param sessionId - The session ID for this command execution
1293
+ * @param timeoutMs - Optional timeout in milliseconds (unlimited by default)
1294
+ */
1295
+ execute(command: string, sessionId: string, timeoutMs?: number): Promise<ExecuteResponse>;
1296
+ /**
1297
+ * Execute a command and return a stream of events
1298
+ * @param command - The command to execute
1299
+ * @param sessionId - The session ID for this command execution
1300
+ */
1301
+ executeStream(command: string, sessionId: string): Promise<ReadableStream<Uint8Array>>;
1302
+ }
1303
+ //#endregion
1304
+ //#region src/clients/file-client.d.ts
1305
+ /**
1306
+ * Request interface for creating directories
1307
+ */
1308
+ interface MkdirRequest extends SessionRequest {
1309
+ path: string;
1310
+ recursive?: boolean;
1311
+ }
1312
+ /**
1313
+ * Request interface for writing files
1314
+ */
1315
+ interface WriteFileRequest extends SessionRequest {
1316
+ path: string;
1317
+ content: string;
1318
+ encoding?: string;
1319
+ }
1320
+ /**
1321
+ * Request interface for reading files
1322
+ */
1323
+ interface ReadFileRequest extends SessionRequest {
1324
+ path: string;
1325
+ encoding?: string;
1326
+ }
1327
+ /**
1328
+ * Request interface for file operations (delete, rename, move)
1329
+ */
1330
+ interface FileOperationRequest extends SessionRequest {
1331
+ path: string;
1332
+ newPath?: string;
1333
+ }
1334
+ /**
1335
+ * Client for file system operations
1336
+ */
1337
+ declare class FileClient extends BaseHttpClient {
1338
+ /**
1339
+ * Create a directory
1340
+ * @param path - Directory path to create
1341
+ * @param sessionId - The session ID for this operation
1342
+ * @param options - Optional settings (recursive)
1343
+ */
1344
+ mkdir(path: string, sessionId: string, options?: {
1345
+ recursive?: boolean;
1346
+ }): Promise<MkdirResult>;
1347
+ /**
1348
+ * Write content to a file
1349
+ * @param path - File path to write to
1350
+ * @param content - Content to write
1351
+ * @param sessionId - The session ID for this operation
1352
+ * @param options - Optional settings (encoding)
1353
+ */
1354
+ writeFile(path: string, content: string, sessionId: string, options?: {
1355
+ encoding?: string;
1356
+ }): Promise<WriteFileResult>;
1357
+ /**
1358
+ * Read content from a file
1359
+ * @param path - File path to read from
1360
+ * @param sessionId - The session ID for this operation
1361
+ * @param options - Optional settings (encoding)
1362
+ */
1363
+ readFile(path: string, sessionId: string, options?: {
1364
+ encoding?: string;
1365
+ }): Promise<ReadFileResult>;
1366
+ /**
1367
+ * Stream a file using Server-Sent Events
1368
+ * Returns a ReadableStream of SSE events containing metadata, chunks, and completion
1369
+ * @param path - File path to stream
1370
+ * @param sessionId - The session ID for this operation
1371
+ */
1372
+ readFileStream(path: string, sessionId: string): Promise<ReadableStream<Uint8Array>>;
1373
+ /**
1374
+ * Delete a file
1375
+ * @param path - File path to delete
1376
+ * @param sessionId - The session ID for this operation
1377
+ */
1378
+ deleteFile(path: string, sessionId: string): Promise<DeleteFileResult>;
1379
+ /**
1380
+ * Rename a file
1381
+ * @param path - Current file path
1382
+ * @param newPath - New file path
1383
+ * @param sessionId - The session ID for this operation
1384
+ */
1385
+ renameFile(path: string, newPath: string, sessionId: string): Promise<RenameFileResult>;
1386
+ /**
1387
+ * Move a file
1388
+ * @param path - Current file path
1389
+ * @param newPath - Destination file path
1390
+ * @param sessionId - The session ID for this operation
1391
+ */
1392
+ moveFile(path: string, newPath: string, sessionId: string): Promise<MoveFileResult>;
1393
+ /**
1394
+ * List files in a directory
1395
+ * @param path - Directory path to list
1396
+ * @param sessionId - The session ID for this operation
1397
+ * @param options - Optional settings (recursive, includeHidden)
1398
+ */
1399
+ listFiles(path: string, sessionId: string, options?: ListFilesOptions): Promise<ListFilesResult>;
1400
+ /**
1401
+ * Check if a file or directory exists
1402
+ * @param path - Path to check
1403
+ * @param sessionId - The session ID for this operation
1404
+ */
1405
+ exists(path: string, sessionId: string): Promise<FileExistsResult>;
1406
+ }
1407
+ //#endregion
1408
+ //#region src/clients/git-client.d.ts
1409
+ /**
1410
+ * Request interface for Git checkout operations
1411
+ */
1412
+ interface GitCheckoutRequest extends SessionRequest {
1413
+ repoUrl: string;
1414
+ branch?: string;
1415
+ targetDir?: string;
1416
+ }
1417
+ /**
1418
+ * Client for Git repository operations
1419
+ */
1420
+ declare class GitClient extends BaseHttpClient {
1421
+ /**
1422
+ * Clone a Git repository
1423
+ * @param repoUrl - URL of the Git repository to clone
1424
+ * @param sessionId - The session ID for this operation
1425
+ * @param options - Optional settings (branch, targetDir)
1426
+ */
1427
+ checkout(repoUrl: string, sessionId: string, options?: {
1428
+ branch?: string;
1429
+ targetDir?: string;
1430
+ }): Promise<GitCheckoutResult>;
1431
+ /**
1432
+ * Extract repository name from URL for default directory name
1433
+ */
1434
+ private extractRepoName;
1435
+ }
1436
+ //#endregion
1437
+ //#region src/clients/interpreter-client.d.ts
1438
+ interface ExecutionCallbacks {
1439
+ onStdout?: (output: OutputMessage) => void | Promise<void>;
1440
+ onStderr?: (output: OutputMessage) => void | Promise<void>;
1441
+ onResult?: (result: Result) => void | Promise<void>;
1442
+ onError?: (error: ExecutionError) => void | Promise<void>;
1443
+ }
1444
+ declare class InterpreterClient extends BaseHttpClient {
1445
+ private readonly maxRetries;
1446
+ private readonly retryDelayMs;
1447
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1448
+ runCodeStream(contextId: string | undefined, code: string, language: string | undefined, callbacks: ExecutionCallbacks, timeoutMs?: number): Promise<void>;
1449
+ listCodeContexts(): Promise<CodeContext[]>;
1450
+ deleteCodeContext(contextId: string): Promise<void>;
1451
+ /**
1452
+ * Execute an operation with automatic retry for transient errors
1453
+ */
1454
+ private executeWithRetry;
1455
+ private isRetryableError;
1456
+ private parseErrorResponse;
1457
+ private readLines;
1458
+ private parseExecutionResult;
1459
+ }
1460
+ //#endregion
1461
+ //#region src/clients/port-client.d.ts
1462
+ /**
1463
+ * Request interface for exposing ports
1464
+ */
1465
+ interface ExposePortRequest {
1466
+ port: number;
1467
+ name?: string;
1468
+ }
1469
+ /**
1470
+ * Request interface for unexposing ports
1471
+ */
1472
+ interface UnexposePortRequest {
1473
+ port: number;
1474
+ }
1475
+ /**
1476
+ * Client for port management and preview URL operations
1477
+ */
1478
+ declare class PortClient extends BaseHttpClient {
1479
+ /**
1480
+ * Expose a port and get a preview URL
1481
+ * @param port - Port number to expose
1482
+ * @param sessionId - The session ID for this operation
1483
+ * @param name - Optional name for the port
1484
+ */
1485
+ exposePort(port: number, sessionId: string, name?: string): Promise<PortExposeResult>;
1486
+ /**
1487
+ * Unexpose a port and remove its preview URL
1488
+ * @param port - Port number to unexpose
1489
+ * @param sessionId - The session ID for this operation
1490
+ */
1491
+ unexposePort(port: number, sessionId: string): Promise<PortCloseResult>;
1492
+ /**
1493
+ * Get all currently exposed ports
1494
+ * @param sessionId - The session ID for this operation
1495
+ */
1496
+ getExposedPorts(sessionId: string): Promise<PortListResult>;
1497
+ }
1498
+ //#endregion
1499
+ //#region src/clients/process-client.d.ts
1500
+ /**
1501
+ * Client for background process management
1502
+ */
1503
+ declare class ProcessClient extends BaseHttpClient {
1504
+ /**
1505
+ * Start a background process
1506
+ * @param command - Command to execute as a background process
1507
+ * @param sessionId - The session ID for this operation
1508
+ * @param options - Optional settings (processId)
1509
+ */
1510
+ startProcess(command: string, sessionId: string, options?: {
1511
+ processId?: string;
1512
+ }): Promise<ProcessStartResult>;
1513
+ /**
1514
+ * List all processes (sandbox-scoped, not session-scoped)
1515
+ */
1516
+ listProcesses(): Promise<ProcessListResult>;
1517
+ /**
1518
+ * Get information about a specific process (sandbox-scoped, not session-scoped)
1519
+ * @param processId - ID of the process to retrieve
1520
+ */
1521
+ getProcess(processId: string): Promise<ProcessInfoResult>;
1522
+ /**
1523
+ * Kill a specific process (sandbox-scoped, not session-scoped)
1524
+ * @param processId - ID of the process to kill
1525
+ */
1526
+ killProcess(processId: string): Promise<ProcessKillResult>;
1527
+ /**
1528
+ * Kill all running processes (sandbox-scoped, not session-scoped)
1529
+ */
1530
+ killAllProcesses(): Promise<ProcessCleanupResult>;
1531
+ /**
1532
+ * Get logs from a specific process (sandbox-scoped, not session-scoped)
1533
+ * @param processId - ID of the process to get logs from
1534
+ */
1535
+ getProcessLogs(processId: string): Promise<ProcessLogsResult>;
1536
+ /**
1537
+ * Stream logs from a specific process (sandbox-scoped, not session-scoped)
1538
+ * @param processId - ID of the process to stream logs from
1539
+ */
1540
+ streamProcessLogs(processId: string): Promise<ReadableStream<Uint8Array>>;
1541
+ }
1542
+ //#endregion
1543
+ //#region src/clients/utility-client.d.ts
1544
+ /**
1545
+ * Response interface for ping operations
1546
+ */
1547
+ interface PingResponse extends BaseApiResponse {
1548
+ message: string;
1549
+ uptime?: number;
1550
+ }
1551
+ /**
1552
+ * Response interface for getting available commands
1553
+ */
1554
+ interface CommandsResponse extends BaseApiResponse {
1555
+ availableCommands: string[];
1556
+ count: number;
1557
+ }
1558
+ /**
1559
+ * Request interface for creating sessions
1560
+ */
1561
+ interface CreateSessionRequest {
1562
+ id: string;
1563
+ env?: Record<string, string>;
1564
+ cwd?: string;
1565
+ }
1566
+ /**
1567
+ * Response interface for creating sessions
1568
+ */
1569
+ interface CreateSessionResponse extends BaseApiResponse {
1570
+ id: string;
1571
+ message: string;
1572
+ }
1573
+ /**
1574
+ * Client for health checks and utility operations
1575
+ */
1576
+ declare class UtilityClient extends BaseHttpClient {
1577
+ /**
1578
+ * Ping the sandbox to check if it's responsive
1579
+ */
1580
+ ping(): Promise<string>;
1581
+ /**
1582
+ * Get list of available commands in the sandbox environment
1583
+ */
1584
+ getCommands(): Promise<string[]>;
1585
+ /**
1586
+ * Create a new execution session
1587
+ * @param options - Session configuration (id, env, cwd)
1588
+ */
1589
+ createSession(options: CreateSessionRequest): Promise<CreateSessionResponse>;
1590
+ /**
1591
+ * Get the container version
1592
+ * Returns the version embedded in the Docker image during build
1593
+ */
1594
+ getVersion(): Promise<string>;
1595
+ }
1596
+ //#endregion
1597
+ //#region src/clients/sandbox-client.d.ts
1598
+ /**
1599
+ * Main sandbox client that composes all domain-specific clients
1600
+ * Provides organized access to all sandbox functionality
1601
+ */
1602
+ declare class SandboxClient {
1603
+ readonly commands: CommandClient;
1604
+ readonly files: FileClient;
1605
+ readonly processes: ProcessClient;
1606
+ readonly ports: PortClient;
1607
+ readonly git: GitClient;
1608
+ readonly interpreter: InterpreterClient;
1609
+ readonly utils: UtilityClient;
1610
+ constructor(options: HttpClientOptions);
1611
+ }
1612
+ //#endregion
1613
+ //#region src/sandbox.d.ts
1614
+ declare function getSandbox(ns: DurableObjectNamespace<Sandbox>, id: string, options?: SandboxOptions): Sandbox;
1615
+ /**
1616
+ * Connect an incoming WebSocket request to a specific port inside the container.
1617
+ *
1618
+ * Note: This is a standalone function (not a Sandbox method) because WebSocket
1619
+ * connections cannot be serialized over Durable Object RPC.
1620
+ *
1621
+ * @param sandbox - The Sandbox instance to route the request through
1622
+ * @param request - The incoming WebSocket upgrade request
1623
+ * @param port - The port number to connect to (1024-65535)
1624
+ * @returns The WebSocket upgrade response
1625
+ * @throws {SecurityError} - If port is invalid or in restricted range
1626
+ *
1627
+ * @example
1628
+ * const sandbox = getSandbox(env.Sandbox, 'sandbox-id');
1629
+ * if (request.headers.get('Upgrade')?.toLowerCase() === 'websocket') {
1630
+ * return await connect(sandbox, request, 8080);
1631
+ * }
1632
+ */
1633
+ declare function connect(sandbox: Sandbox, request: Request, port: number): Promise<Response>;
1634
+ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
1635
+ defaultPort: number;
1636
+ sleepAfter: string | number;
1637
+ client: SandboxClient;
1638
+ private codeInterpreter;
1639
+ private sandboxName;
1640
+ private baseUrl;
1641
+ private portTokens;
1642
+ private defaultSession;
1643
+ envVars: Record<string, string>;
1644
+ private logger;
1645
+ private keepAliveEnabled;
1646
+ constructor(ctx: DurableObject['ctx'], env: Env);
1647
+ setSandboxName(name: string): Promise<void>;
1648
+ setBaseUrl(baseUrl: string): Promise<void>;
1649
+ setSleepAfter(sleepAfter: string | number): Promise<void>;
1650
+ setKeepAlive(keepAlive: boolean): Promise<void>;
1651
+ setEnvVars(envVars: Record<string, string>): Promise<void>;
1652
+ /**
1653
+ * Cleanup and destroy the sandbox container
1654
+ */
1655
+ destroy(): Promise<void>;
1656
+ onStart(): void;
1657
+ /**
1658
+ * Check if the container version matches the SDK version
1659
+ * Logs a warning if there's a mismatch
1660
+ */
1661
+ private checkVersionCompatibility;
1662
+ onStop(): void;
1663
+ onError(error: unknown): void;
1664
+ /**
1665
+ * Override onActivityExpired to prevent automatic shutdown when keepAlive is enabled
1666
+ * When keepAlive is disabled, calls parent implementation which stops the container
1667
+ */
1668
+ onActivityExpired(): Promise<void>;
1669
+ fetch(request: Request): Promise<Response>;
1670
+ private determinePort;
1671
+ /**
1672
+ * Ensure default session exists - lazy initialization
1673
+ * This is called automatically by all public methods that need a session
1674
+ *
1675
+ * The session is persisted to Durable Object storage to survive hot reloads
1676
+ * during development. If a session already exists in the container after reload,
1677
+ * we reuse it instead of trying to create a new one.
1678
+ */
1679
+ private ensureDefaultSession;
1680
+ exec(command: string, options?: ExecOptions): Promise<ExecResult>;
1681
+ /**
1682
+ * Internal session-aware exec implementation
1683
+ * Used by both public exec() and session wrappers
1684
+ */
1685
+ private execWithSession;
1686
+ private executeWithStreaming;
1687
+ private mapExecuteResponseToExecResult;
1688
+ /**
1689
+ * Create a Process domain object from HTTP client DTO
1690
+ * Centralizes process object creation with bound methods
1691
+ * This eliminates duplication across startProcess, listProcesses, getProcess, and session wrappers
1692
+ */
1693
+ private createProcessFromDTO;
1694
+ startProcess(command: string, options?: ProcessOptions, sessionId?: string): Promise<Process>;
1695
+ listProcesses(sessionId?: string): Promise<Process[]>;
1696
+ getProcess(id: string, sessionId?: string): Promise<Process | null>;
1697
+ killProcess(id: string, signal?: string, sessionId?: string): Promise<void>;
1698
+ killAllProcesses(sessionId?: string): Promise<number>;
1699
+ cleanupCompletedProcesses(sessionId?: string): Promise<number>;
1700
+ getProcessLogs(id: string, sessionId?: string): Promise<{
1701
+ stdout: string;
1702
+ stderr: string;
1703
+ processId: string;
1704
+ }>;
1705
+ execStream(command: string, options?: StreamOptions): Promise<ReadableStream<Uint8Array>>;
1706
+ /**
1707
+ * Internal session-aware execStream implementation
1708
+ */
1709
+ private execStreamWithSession;
1710
+ /**
1711
+ * Stream logs from a background process as a ReadableStream.
1712
+ */
1713
+ streamProcessLogs(processId: string, options?: {
1714
+ signal?: AbortSignal;
1715
+ }): Promise<ReadableStream<Uint8Array>>;
1716
+ gitCheckout(repoUrl: string, options: {
1717
+ branch?: string;
1718
+ targetDir?: string;
1719
+ sessionId?: string;
1720
+ }): Promise<GitCheckoutResult>;
1721
+ mkdir(path: string, options?: {
1722
+ recursive?: boolean;
1723
+ sessionId?: string;
1724
+ }): Promise<MkdirResult>;
1725
+ writeFile(path: string, content: string, options?: {
1726
+ encoding?: string;
1727
+ sessionId?: string;
1728
+ }): Promise<WriteFileResult>;
1729
+ deleteFile(path: string, sessionId?: string): Promise<DeleteFileResult>;
1730
+ renameFile(oldPath: string, newPath: string, sessionId?: string): Promise<RenameFileResult>;
1731
+ moveFile(sourcePath: string, destinationPath: string, sessionId?: string): Promise<MoveFileResult>;
1732
+ readFile(path: string, options?: {
1733
+ encoding?: string;
1734
+ sessionId?: string;
1735
+ }): Promise<ReadFileResult>;
1736
+ /**
1737
+ * Stream a file from the sandbox using Server-Sent Events
1738
+ * Returns a ReadableStream that can be consumed with streamFile() or collectFile() utilities
1739
+ * @param path - Path to the file to stream
1740
+ * @param options - Optional session ID
1741
+ */
1742
+ readFileStream(path: string, options?: {
1743
+ sessionId?: string;
1744
+ }): Promise<ReadableStream<Uint8Array>>;
1745
+ listFiles(path: string, options?: {
1746
+ recursive?: boolean;
1747
+ includeHidden?: boolean;
1748
+ }): Promise<ListFilesResult>;
1749
+ exists(path: string, sessionId?: string): Promise<FileExistsResult>;
1750
+ exposePort(port: number, options: {
1751
+ name?: string;
1752
+ hostname: string;
1753
+ }): Promise<{
1754
+ url: string;
1755
+ port: number;
1756
+ name: string | undefined;
1757
+ }>;
1758
+ unexposePort(port: number): Promise<void>;
1759
+ getExposedPorts(hostname: string): Promise<{
1760
+ url: string;
1761
+ port: number;
1762
+ status: "active" | "inactive";
1763
+ }[]>;
1764
+ isPortExposed(port: number): Promise<boolean>;
1765
+ validatePortToken(port: number, token: string): Promise<boolean>;
1766
+ private generatePortToken;
1767
+ private persistPortTokens;
1768
+ private constructPreviewUrl;
1769
+ /**
1770
+ * Create isolated execution session for advanced use cases
1771
+ * Returns ExecutionSession with full sandbox API bound to specific session
1772
+ */
1773
+ createSession(options?: SessionOptions): Promise<ExecutionSession>;
1774
+ /**
1775
+ * Get an existing session by ID
1776
+ * Returns ExecutionSession wrapper bound to the specified session
1777
+ *
1778
+ * This is useful for retrieving sessions across different requests/contexts
1779
+ * without storing the ExecutionSession object (which has RPC lifecycle limitations)
1780
+ *
1781
+ * @param sessionId - The ID of an existing session
1782
+ * @returns ExecutionSession wrapper bound to the session
1783
+ */
1784
+ getSession(sessionId: string): Promise<ExecutionSession>;
1785
+ /**
1786
+ * Internal helper to create ExecutionSession wrapper for a given sessionId
1787
+ * Used by both createSession and getSession
1788
+ */
1789
+ private getSessionWrapper;
1790
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1791
+ runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
1792
+ runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
1793
+ listCodeContexts(): Promise<CodeContext[]>;
1794
+ deleteCodeContext(contextId: string): Promise<void>;
1795
+ }
1796
+ //#endregion
1797
+ //#region src/file-stream.d.ts
1798
+ /**
1799
+ * Stream a file from the sandbox with automatic base64 decoding for binary files
1800
+ *
1801
+ * @param stream - The ReadableStream from readFileStream()
1802
+ * @returns AsyncGenerator that yields FileChunk (string for text, Uint8Array for binary)
1803
+ *
1804
+ * @example
1805
+ * ```ts
1806
+ * const stream = await sandbox.readFileStream('/path/to/file.png');
1807
+ * for await (const chunk of streamFile(stream)) {
1808
+ * if (chunk instanceof Uint8Array) {
1809
+ * // Binary chunk
1810
+ * console.log('Binary chunk:', chunk.length, 'bytes');
1811
+ * } else {
1812
+ * // Text chunk
1813
+ * console.log('Text chunk:', chunk);
1814
+ * }
1815
+ * }
1816
+ * ```
1817
+ */
1818
+ declare function streamFile(stream: ReadableStream<Uint8Array>): AsyncGenerator<FileChunk, FileMetadata>;
1819
+ /**
1820
+ * Collect an entire file into memory from a stream
1821
+ *
1822
+ * @param stream - The ReadableStream from readFileStream()
1823
+ * @returns Object containing the file content and metadata
1824
+ *
1825
+ * @example
1826
+ * ```ts
1827
+ * const stream = await sandbox.readFileStream('/path/to/file.txt');
1828
+ * const { content, metadata } = await collectFile(stream);
1829
+ * console.log('Content:', content);
1830
+ * console.log('MIME type:', metadata.mimeType);
1831
+ * ```
1832
+ */
1833
+ declare function collectFile(stream: ReadableStream<Uint8Array>): Promise<{
1834
+ content: string | Uint8Array;
1835
+ metadata: FileMetadata;
1836
+ }>;
1837
+ //#endregion
1838
+ //#region src/interpreter.d.ts
1839
+ declare class CodeInterpreter {
1840
+ private interpreterClient;
1841
+ private contexts;
1842
+ constructor(sandbox: Sandbox);
1843
+ /**
1844
+ * Create a new code execution context
1845
+ */
1846
+ createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
1847
+ /**
1848
+ * Run code with optional context
1849
+ */
1850
+ runCode(code: string, options?: RunCodeOptions): Promise<Execution>;
1851
+ /**
1852
+ * Run code and return a streaming response
1853
+ */
1854
+ runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
1855
+ /**
1856
+ * List all code contexts
1857
+ */
1858
+ listCodeContexts(): Promise<CodeContext[]>;
1859
+ /**
1860
+ * Delete a code context
1861
+ */
1862
+ deleteCodeContext(contextId: string): Promise<void>;
1863
+ private getOrCreateDefaultContext;
1864
+ }
1865
+ //#endregion
1866
+ //#region src/request-handler.d.ts
1867
+ interface SandboxEnv {
1868
+ Sandbox: DurableObjectNamespace<Sandbox>;
1869
+ }
1870
+ interface RouteInfo {
1871
+ port: number;
1872
+ sandboxId: string;
1873
+ path: string;
1874
+ token: string;
1875
+ }
1876
+ declare function proxyToSandbox<E extends SandboxEnv>(request: Request, env: E): Promise<Response | null>;
1877
+ //#endregion
1878
+ //#region src/sse-parser.d.ts
1879
+ /**
1880
+ * Server-Sent Events (SSE) parser for streaming responses
1881
+ * Converts ReadableStream<Uint8Array> to typed AsyncIterable<T>
1882
+ */
1883
+ /**
1884
+ * Parse a ReadableStream of SSE events into typed AsyncIterable
1885
+ * @param stream - The ReadableStream from fetch response
1886
+ * @param signal - Optional AbortSignal for cancellation
1887
+ */
1888
+ declare function parseSSEStream<T>(stream: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncIterable<T>;
1889
+ /**
1890
+ * Helper to convert a Response with SSE stream directly to AsyncIterable
1891
+ * @param response - Response object with SSE stream
1892
+ * @param signal - Optional AbortSignal for cancellation
1893
+ */
1894
+ declare function responseToAsyncIterable<T>(response: Response, signal?: AbortSignal): AsyncIterable<T>;
1895
+ /**
1896
+ * Create an SSE-formatted ReadableStream from an AsyncIterable
1897
+ * (Useful for Worker endpoints that need to forward AsyncIterable as SSE)
1898
+ * @param events - AsyncIterable of events
1899
+ * @param options - Stream options
1900
+ */
1901
+ declare function asyncIterableToSSEStream<T>(events: AsyncIterable<T>, options?: {
1902
+ signal?: AbortSignal;
1903
+ serialize?: (event: T) => string;
1904
+ }): ReadableStream<Uint8Array>;
1905
+ //#endregion
1906
+ export { type BaseApiResponse, type BaseExecOptions, type ChartData, type CodeContext, CodeInterpreter, CommandClient, type ExecuteResponse as CommandExecuteResponse, type CommandsResponse, type ContainerStub, ContextCreateResult, ContextDeleteResult, ContextListResult, type CreateContextOptions, DeleteFileRequest, DeleteFileResult, EnvSetResult, type ErrorResponse, type ExecEvent, type ExecOptions, type ExecResult, type ExecuteRequest, Execution, type ExecutionCallbacks, type ExecutionError, type ExecutionResult, ExecutionSession, type ExposePortRequest, type FileChunk, FileClient, FileExistsRequest, FileExistsResult, FileInfo, type FileMetadata, type FileOperationRequest, type FileStreamEvent, type GitCheckoutRequest, type GitCheckoutResult, GitClient, HealthCheckResult, type ISandbox, type InterpreterClient, InterpreterHealthResult, ListFilesOptions, ListFilesResult, type LogContext, type LogEvent, type LogLevel, LogLevel as LogLevelEnum, type Logger, type MkdirRequest, MkdirResult, MoveFileRequest, MoveFileResult, type OutputMessage, type PingResponse, PortClient, type PortCloseResult, type PortExposeResult, type PortListResult, PortStatusResult, type Process, type ProcessCleanupResult, ProcessClient, type ProcessInfoResult, type ProcessKillResult, type ProcessListResult, type ProcessLogsResult, type ProcessOptions, type ProcessStartResult, type ProcessStatus, type ReadFileRequest, ReadFileResult, RenameFileRequest, RenameFileResult, type RequestConfig, type ResponseHandler, type Result, ResultImpl, type RouteInfo, type RunCodeOptions, Sandbox, SandboxClient, type HttpClientOptions as SandboxClientOptions, type SandboxEnv, SandboxOptions, SessionCreateRequest, SessionCreateResult, SessionDeleteRequest, SessionDeleteResult, SessionOptions, type SessionRequest, ShutdownResult, type StartProcessRequest, type StreamOptions, TraceContext, type UnexposePortRequest, UtilityClient, type WriteFileRequest, WriteFileResult, asyncIterableToSSEStream, collectFile, connect, createLogger, createNoOpLogger, getLogger, getSandbox, isExecResult, isProcess, isProcessStatus, parseSSEStream, proxyToSandbox, responseToAsyncIterable, runWithLogger, streamFile };
1907
+ //# sourceMappingURL=index.d.ts.map