@cloudflare/sandbox 0.0.0-fd5ec7f → 0.0.0-feafd32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,134 @@
1
1
  # @cloudflare/sandbox
2
2
 
3
+ ## 0.3.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#83](https://github.com/cloudflare/sandbox-sdk/pull/83) [`eec5bb6`](https://github.com/cloudflare/sandbox-sdk/commit/eec5bb6203dd5d775b4b54e91c26de25eeb767ce) Thanks [@mikenomitch](https://github.com/mikenomitch)! - Bump containers package version
8
+
9
+ ## 0.3.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#76](https://github.com/cloudflare/sandbox-sdk/pull/76) [`ef9e320`](https://github.com/cloudflare/sandbox-sdk/commit/ef9e320dcef30e57797fef6ebd9a9383fa9720d9) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Replace Jupyter with lightweight interpreters for >90% faster cold starts for `.runCode` calls, while maintaining full code execution capabilities and rich output support.
14
+
15
+ ## 0.3.1
16
+
17
+ ### Patch Changes
18
+
19
+ - [#71](https://github.com/cloudflare/sandbox-sdk/pull/71) [`fb3c9c2`](https://github.com/cloudflare/sandbox-sdk/commit/fb3c9c22242d9d4f157c26f547f1e697ef7875f9) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Bump containers package version
20
+
21
+ - [#70](https://github.com/cloudflare/sandbox-sdk/pull/70) [`e1fa354`](https://github.com/cloudflare/sandbox-sdk/commit/e1fa354ab1bc7b0e89db4901b67028ebf1a93d0a) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Fix escaped quotes in file write operations
22
+
23
+ - [#68](https://github.com/cloudflare/sandbox-sdk/pull/68) [`69b91d1`](https://github.com/cloudflare/sandbox-sdk/commit/69b91d1a8f6afb63262cc381ea93e94a033ed5e8) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Configurable timeouts via environment variables in isolation.ts
24
+
25
+ - [#66](https://github.com/cloudflare/sandbox-sdk/pull/66) [`eca93b9`](https://github.com/cloudflare/sandbox-sdk/commit/eca93b97e40fa0d3bd9dc27af2cc214ec355b696) Thanks [@peterp](https://github.com/peterp)! - Determine if the port is specified in the URL.
26
+
27
+ ## 0.3.0
28
+
29
+ ### Minor Changes
30
+
31
+ - [#59](https://github.com/cloudflare/sandbox-sdk/pull/59) [`b6757f7`](https://github.com/cloudflare/sandbox-sdk/commit/b6757f730c34381d5a70d513944bbf9840f598ab) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Add process isolation for sandbox commands
32
+
33
+ Implements PID namespace isolation to protect control plane processes (Jupyter, Bun) from sandboxed code. Commands executed via `exec()` now run in isolated namespaces that cannot see or interact with system processes.
34
+
35
+ **Key security improvements:**
36
+
37
+ - Control plane processes are hidden from sandboxed commands
38
+ - Platform secrets in `/proc/1/environ` are inaccessible
39
+ - Ports 8888 (Jupyter) and 3000 (Bun) are protected from hijacking
40
+
41
+ **Breaking changes:**
42
+
43
+ 1. **Removed `sessionId` parameter**: The `sessionId` parameter has been removed from all methods (`exec()`, `execStream()`, `startProcess()`, etc.). Each sandbox now maintains its own persistent session automatically.
44
+
45
+ ```javascript
46
+ // Before: manual session management
47
+ await sandbox.exec("cd /app", { sessionId: "my-session" });
48
+
49
+ // After: automatic session per sandbox
50
+ await sandbox.exec("cd /app");
51
+ ```
52
+
53
+ 2. **Commands now maintain state**: Commands within the same sandbox now share state (working directory, environment variables, background processes). Previously each command was stateless.
54
+
55
+ ```javascript
56
+ // Before: each exec was independent
57
+ await sandbox.exec("cd /app");
58
+ await sandbox.exec("pwd"); // Output: /workspace
59
+
60
+ // After: state persists in session
61
+ await sandbox.exec("cd /app");
62
+ await sandbox.exec("pwd"); // Output: /app
63
+ ```
64
+
65
+ **Migration guide:**
66
+
67
+ - Remove `sessionId` from all method calls - each sandbox maintains its own session
68
+ - If you need isolated execution contexts within the same sandbox, use `sandbox.createSession()`:
69
+ ```javascript
70
+ // Create independent sessions with different environments
71
+ const buildSession = await sandbox.createSession({
72
+ name: "build",
73
+ env: { NODE_ENV: "production" },
74
+ cwd: "/build",
75
+ });
76
+ const testSession = await sandbox.createSession({
77
+ name: "test",
78
+ env: { NODE_ENV: "test" },
79
+ cwd: "/test",
80
+ });
81
+ ```
82
+ - Environment variables set in one command persist to the next
83
+ - Background processes remain active until explicitly killed
84
+ - Requires CAP_SYS_ADMIN (available in production, falls back gracefully in dev)
85
+
86
+ ### Patch Changes
87
+
88
+ - [#62](https://github.com/cloudflare/sandbox-sdk/pull/62) [`4bedc3a`](https://github.com/cloudflare/sandbox-sdk/commit/4bedc3aba347f3d4090a6efe2c9778bac00ce74a) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Fix broken build due to bun lockfile not being used
89
+
90
+ ## 0.2.4
91
+
92
+ ### Patch Changes
93
+
94
+ - [#57](https://github.com/cloudflare/sandbox-sdk/pull/57) [`12bbd12`](https://github.com/cloudflare/sandbox-sdk/commit/12bbd1229c07ef8c1c0bf58a4235a27938155b08) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Add listFiles method
95
+
96
+ ## 0.2.3
97
+
98
+ ### Patch Changes
99
+
100
+ - [#53](https://github.com/cloudflare/sandbox-sdk/pull/53) [`c87db11`](https://github.com/cloudflare/sandbox-sdk/commit/c87db117693a86cfb667bf09fb7720d6a6e0524d) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Improve jupyterlab config to speed up startup
101
+
102
+ ## 0.2.2
103
+
104
+ ### Patch Changes
105
+
106
+ - [#51](https://github.com/cloudflare/sandbox-sdk/pull/51) [`4aceb32`](https://github.com/cloudflare/sandbox-sdk/commit/4aceb3215c836f59afcb88b2b325016b3f623f46) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Handle intermittent interpreter failures and decouple jupyter startup
107
+
108
+ ## 0.2.1
109
+
110
+ ### Patch Changes
111
+
112
+ - [#49](https://github.com/cloudflare/sandbox-sdk/pull/49) [`d81d2a5`](https://github.com/cloudflare/sandbox-sdk/commit/d81d2a563c9af8947d5444019ed4d6156db563e3) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Implement code interpreter API
113
+
114
+ ## 0.2.0
115
+
116
+ ### Minor Changes
117
+
118
+ - [#47](https://github.com/cloudflare/sandbox-sdk/pull/47) [`8a93d0c`](https://github.com/cloudflare/sandbox-sdk/commit/8a93d0cae18a25bda6506b8b0a08d9e9eb3bb290) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Change default directory to a clean /workspace
119
+
120
+ ## 0.1.4
121
+
122
+ ### Patch Changes
123
+
124
+ - [#46](https://github.com/cloudflare/sandbox-sdk/pull/46) [`7de28be`](https://github.com/cloudflare/sandbox-sdk/commit/7de28be482d9634551572d548c7c4b5842df812d) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Update README
125
+
126
+ - [#44](https://github.com/cloudflare/sandbox-sdk/pull/44) [`215ab49`](https://github.com/cloudflare/sandbox-sdk/commit/215ab494427d7e2a92bb9a25384cb493a221c200) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Update example to use env & cwd
127
+
128
+ - [#42](https://github.com/cloudflare/sandbox-sdk/pull/42) [`bb72193`](https://github.com/cloudflare/sandbox-sdk/commit/bb72193ad75695979bd1132206f481e91fe37325) Thanks [@jonasnobile](https://github.com/jonasnobile)! - Propagate `cwd` and `env` options in `executeCommand`
129
+
130
+ - [#27](https://github.com/cloudflare/sandbox-sdk/pull/27) [`fd5ec7f`](https://github.com/cloudflare/sandbox-sdk/commit/fd5ec7f34bc12b06320a89356c4af07801f52d64) Thanks [@threepointone](https://github.com/threepointone)! - remove yarn and pnpm from the image
131
+
3
132
  ## 0.1.3
4
133
 
5
134
  ### Patch Changes
package/Dockerfile CHANGED
@@ -31,23 +31,19 @@ RUN apt-get update && apt-get install -y \
31
31
  python3.11 \
32
32
  python3.11-dev \
33
33
  python3-pip \
34
+ python3.11-venv \
34
35
  # Other useful tools
35
- sudo \
36
36
  ca-certificates \
37
37
  gnupg \
38
38
  lsb-release \
39
+ strace \
39
40
  && rm -rf /var/lib/apt/lists/*
40
41
 
41
42
  # Set Python 3.11 as default python3
42
43
  RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
43
44
 
44
- # Install Node.js 22 LTS
45
- # Using the official NodeSource repository setup script
46
- RUN apt-get update && apt-get install -y ca-certificates curl gnupg \
47
- && mkdir -p /etc/apt/keyrings \
48
- && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
49
- && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \
50
- && apt-get update \
45
+ # Install Node.js 20 LTS using official NodeSource setup script
46
+ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
51
47
  && apt-get install -y nodejs \
52
48
  && rm -rf /var/lib/apt/lists/*
53
49
 
@@ -55,22 +51,52 @@ RUN apt-get update && apt-get install -y ca-certificates curl gnupg \
55
51
  COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
56
52
  COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
57
53
 
54
+ # Install essential Python packages for code execution
55
+ RUN pip3 install --no-cache-dir \
56
+ matplotlib \
57
+ numpy \
58
+ pandas \
59
+ ipython
58
60
 
59
- # Set up working directory
60
- WORKDIR /app
61
+ # Set up container server directory
62
+ WORKDIR /container-server
61
63
 
62
64
  # Verify installations
63
65
  RUN python3 --version && \
64
66
  node --version && \
65
67
  npm --version && \
66
68
  bun --version
67
-
68
69
 
69
- # Copy container source files
70
+ # Copy container source files to server directory
71
+ COPY container_src/package.json container_src/bun.lock ./
72
+ RUN bun install --frozen-lockfile
73
+
70
74
  COPY container_src/ ./
71
75
 
72
- # Expose the application port
76
+ # Compile TypeScript files using the locally installed TypeScript
77
+ RUN npx tsc control-process.ts --outDir . --module commonjs --target es2020 --esModuleInterop --skipLibCheck
78
+ RUN cd runtime/executors/javascript && npx tsc node_executor.ts --module commonjs --target es2020 --esModuleInterop --skipLibCheck
79
+ RUN cd runtime/executors/typescript && npx tsc ts_executor.ts --module commonjs --target es2020 --esModuleInterop --skipLibCheck
80
+
81
+ # Configure process pool sizes (can be overridden at runtime)
82
+ ENV PYTHON_POOL_MIN_SIZE=3
83
+ ENV PYTHON_POOL_MAX_SIZE=15
84
+ ENV JAVASCRIPT_POOL_MIN_SIZE=3
85
+ ENV JAVASCRIPT_POOL_MAX_SIZE=10
86
+ ENV TYPESCRIPT_POOL_MIN_SIZE=3
87
+ ENV TYPESCRIPT_POOL_MAX_SIZE=10
88
+
89
+ # Create clean workspace directory for user code
90
+ # Architecture:
91
+ # /container-server/ - SDK infrastructure (server, executors, dependencies)
92
+ # /workspace/ - User's clean workspace for their code
93
+ RUN mkdir -p /workspace
94
+
95
+ # Expose the application port (3000 for control)
73
96
  EXPOSE 3000
74
97
 
75
- # Run the application
76
- CMD ["bun", "index.ts"]
98
+ # Make startup script executable
99
+ RUN chmod +x startup.sh
100
+
101
+ # Use startup script
102
+ CMD ["./startup.sh"]
package/README.md CHANGED
@@ -17,6 +17,10 @@
17
17
  - [Basic Setup](#basic-setup)
18
18
  - [📚 API Reference](#api-reference)
19
19
  - [Core Methods](#core-methods)
20
+ - [🧪 Code Interpreter](#code-interpreter)
21
+ - [Code Execution](#code-execution)
22
+ - [Rich Outputs](#rich-outputs)
23
+ - [Output Formats](#output-formats)
20
24
  - [🌐 Port Forwarding](#port-forwarding)
21
25
  - [Utility Methods](#utility-methods)
22
26
  - [💡 Examples](#examples)
@@ -24,6 +28,7 @@
24
28
  - [Build and Test Code](#build-and-test-code)
25
29
  - [Interactive Development Environment](#interactive-development-environment)
26
30
  - [Expose Services with Preview URLs](#expose-services-with-preview-urls)
31
+ - [Data Analysis with Code Interpreter](#data-analysis-with-code-interpreter)
27
32
  - [🏗️ Architecture](#architecture)
28
33
  - [🛠️ Advanced Usage](#advanced-usage)
29
34
  - [AsyncIterable Streaming Support](#asynciterable-streaming-support)
@@ -50,6 +55,9 @@ The Cloudflare Sandbox SDK enables you to run isolated code environments directl
50
55
  - **🔄 Git Integration**: Clone repositories directly into sandboxes
51
56
  - **🚀 Streaming Support**: Real-time output streaming for long-running commands
52
57
  - **🎮 Session Management**: Maintain state across multiple operations
58
+ - **🧪 Code Interpreter**: Execute Python and JavaScript with rich outputs (charts, tables, formatted data)
59
+ - **📊 Multi-Language Support**: Persistent execution contexts for Python and JavaScript/TypeScript
60
+ - **🎨 Rich MIME Types**: Automatic processing of images, HTML, charts, and structured data
53
61
 
54
62
  <h2 id="quick-start">🚀 Quick Start</h2>
55
63
 
@@ -64,7 +72,7 @@ npm install @cloudflare/sandbox
64
72
  1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
65
73
 
66
74
  ```dockerfile
67
- FROM docker.io/cloudflare/sandbox:0.1.3
75
+ FROM docker.io/cloudflare/sandbox:0.3.3
68
76
 
69
77
  # Expose the ports you want to expose
70
78
  EXPOSE 3000
@@ -81,7 +89,7 @@ EXPOSE 3000
81
89
  {
82
90
  "class_name": "Sandbox",
83
91
  "image": "./Dockerfile",
84
- "max_instances": 1
92
+ "max_instances": 20
85
93
  }
86
94
  ],
87
95
  "durable_objects": {
@@ -176,7 +184,7 @@ for await (const log of parseSSEStream<LogEvent>(logStream)) {
176
184
  Write content to a file.
177
185
 
178
186
  ```typescript
179
- await sandbox.writeFile("/app.js", "console.log('Hello!');");
187
+ await sandbox.writeFile("/workspace/app.js", "console.log('Hello!');");
180
188
  ```
181
189
 
182
190
  #### `readFile(path, options?)`
@@ -246,6 +254,131 @@ console.log(result.stdout); // "production"
246
254
  - `unexposePort(port)` - Remove port exposure
247
255
  - `getExposedPorts()` - List all exposed ports with their URLs
248
256
 
257
+ #### Session Methods
258
+
259
+ - `createSession(options)` - Create an isolated execution session
260
+ - `name`: Session identifier
261
+ - `env`: Environment variables for this session
262
+ - `cwd`: Working directory
263
+ - `isolation`: Enable PID namespace isolation (requires CAP_SYS_ADMIN)
264
+
265
+ <h2 id="code-interpreter">🧪 Code Interpreter</h2>
266
+
267
+ The Sandbox SDK includes powerful code interpreter capabilities, allowing you to execute Python and JavaScript code with rich outputs including charts, tables, and formatted data.
268
+
269
+ ### Code Execution
270
+
271
+ #### `createCodeContext(options?)`
272
+
273
+ Creates a new code execution context with persistent state.
274
+
275
+ ```typescript
276
+ // Create a Python context
277
+ const pythonCtx = await sandbox.createCodeContext({ language: 'python' });
278
+
279
+ // Create a JavaScript context
280
+ const jsCtx = await sandbox.createCodeContext({ language: 'javascript' });
281
+ ```
282
+
283
+ **Options:**
284
+ - `language`: Programming language (`'python'` | `'javascript'` | `'typescript'`)
285
+ - `cwd`: Working directory (default: `/workspace`)
286
+ - `envVars`: Environment variables for the context
287
+
288
+ #### `runCode(code, options?)`
289
+
290
+ Executes code with optional streaming callbacks.
291
+
292
+ ```typescript
293
+ // Simple execution
294
+ const execution = await sandbox.runCode('print("Hello World")', {
295
+ context: pythonCtx
296
+ });
297
+
298
+ // With streaming callbacks
299
+ await sandbox.runCode(`
300
+ for i in range(5):
301
+ print(f"Step {i}")
302
+ time.sleep(1)
303
+ `, {
304
+ context: pythonCtx,
305
+ onStdout: (output) => console.log('Real-time:', output.text),
306
+ onResult: (result) => console.log('Result:', result)
307
+ });
308
+ ```
309
+
310
+ **Options:**
311
+ - `context`: Context to run the code in
312
+ - `language`: Language if no context provided
313
+ - `onStdout`: Callback for stdout output
314
+ - `onStderr`: Callback for stderr output
315
+ - `onResult`: Callback for execution results
316
+ - `onError`: Callback for errors
317
+
318
+ #### `runCodeStream(code, options?)`
319
+
320
+ Returns a streaming response for real-time processing.
321
+
322
+ ```typescript
323
+ const stream = await sandbox.runCodeStream('import time; [print(i) for i in range(10)]');
324
+ // Process the stream as needed
325
+ ```
326
+
327
+ ### Rich Outputs
328
+
329
+ The code interpreter automatically detects and processes various output types:
330
+
331
+ ```typescript
332
+ // Data visualization
333
+ const execution = await sandbox.runCode(`
334
+ import matplotlib.pyplot as plt
335
+ import numpy as np
336
+
337
+ x = np.linspace(0, 10, 100)
338
+ y = np.sin(x)
339
+ plt.plot(x, y)
340
+ plt.title('Sine Wave')
341
+ plt.show()
342
+ `, {
343
+ context: pythonCtx,
344
+ onResult: (result) => {
345
+ if (result.png) {
346
+ // Base64 encoded PNG image
347
+ console.log('Chart generated!');
348
+ }
349
+ }
350
+ });
351
+
352
+ // HTML tables with pandas
353
+ const tableExecution = await sandbox.runCode(`
354
+ import pandas as pd
355
+ df = pd.DataFrame({
356
+ 'name': ['Alice', 'Bob', 'Charlie'],
357
+ 'score': [92, 88, 95]
358
+ })
359
+ df
360
+ `, { context: pythonCtx });
361
+
362
+ // Access HTML table in execution.results[0].html
363
+ ```
364
+
365
+ ### Output Formats
366
+
367
+ Results can include multiple formats:
368
+ - `text`: Plain text representation
369
+ - `html`: HTML (often pandas DataFrames)
370
+ - `png`/`jpeg`: Base64 encoded images
371
+ - `svg`: Vector graphics
372
+ - `json`: Structured data
373
+ - `chart`: Parsed chart information
374
+
375
+ Check available formats with `result.formats()`.
376
+
377
+ #### Additional Code Interpreter Methods
378
+
379
+ - `listCodeContexts()` - List all active code contexts
380
+ - `deleteCodeContext(contextId)` - Delete a specific context
381
+
249
382
  <h2 id="port-forwarding">🌐 Port Forwarding</h2>
250
383
 
251
384
  The SDK automatically handles preview URL routing for exposed ports. Just add one line to your worker:
@@ -314,7 +447,7 @@ const sandbox = getSandbox(env.Sandbox, "node-app");
314
447
 
315
448
  // Write a simple Express server
316
449
  await sandbox.writeFile(
317
- "/app.js",
450
+ "/workspace/app.js",
318
451
  `
319
452
  const express = require('express');
320
453
  const app = express();
@@ -404,14 +537,100 @@ console.log(`Service available at: ${preview.url}`);
404
537
  // See the example in examples/basic/src/index.ts for the routing implementation.
405
538
  ```
406
539
 
540
+ ### Data Analysis with Code Interpreter
541
+
542
+ ```typescript
543
+ const sandbox = getSandbox(env.Sandbox, "analysis");
544
+
545
+ // Create a Python context for data analysis
546
+ const pythonCtx = await sandbox.createCodeContext({ language: 'python' });
547
+
548
+ // Load and analyze data
549
+ const analysis = await sandbox.runCode(`
550
+ import pandas as pd
551
+ import matplotlib.pyplot as plt
552
+
553
+ # Create sample data
554
+ data = {
555
+ 'Month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
556
+ 'Sales': [10000, 12000, 15000, 14000, 18000],
557
+ 'Profit': [2000, 2500, 3200, 2800, 4000]
558
+ }
559
+ df = pd.DataFrame(data)
560
+
561
+ # Display summary statistics
562
+ print("Sales Summary:")
563
+ print(df.describe())
564
+
565
+ # Create visualization
566
+ plt.figure(figsize=(10, 6))
567
+ plt.subplot(1, 2, 1)
568
+ plt.bar(df['Month'], df['Sales'])
569
+ plt.title('Monthly Sales')
570
+ plt.xlabel('Month')
571
+ plt.ylabel('Sales ($)')
572
+
573
+ plt.subplot(1, 2, 2)
574
+ plt.plot(df['Month'], df['Profit'], marker='o', color='green')
575
+ plt.title('Monthly Profit')
576
+ plt.xlabel('Month')
577
+ plt.ylabel('Profit ($)')
578
+
579
+ plt.tight_layout()
580
+ plt.show()
581
+
582
+ # Return the data as JSON
583
+ df.to_dict('records')
584
+ `, {
585
+ context: pythonCtx,
586
+ onResult: (result) => {
587
+ if (result.png) {
588
+ // Handle the chart image
589
+ console.log('Chart generated:', result.png.substring(0, 50) + '...');
590
+ }
591
+ if (result.json) {
592
+ // Handle the structured data
593
+ console.log('Data:', result.json);
594
+ }
595
+ }
596
+ });
597
+
598
+ // Multi-language workflow: Process in Python, analyze in JavaScript
599
+ await sandbox.runCode(`
600
+ # Save processed data
601
+ df.to_json('/tmp/sales_data.json', orient='records')
602
+ `, { context: pythonCtx });
603
+
604
+ const jsCtx = await sandbox.createCodeContext({ language: 'javascript' });
605
+ const jsAnalysis = await sandbox.runCode(`
606
+ const fs = require('fs');
607
+ const data = JSON.parse(fs.readFileSync('/tmp/sales_data.json', 'utf8'));
608
+
609
+ // Calculate growth rate
610
+ const growth = data.map((curr, idx) => {
611
+ if (idx === 0) return { ...curr, growth: 0 };
612
+ const prev = data[idx - 1];
613
+ return {
614
+ ...curr,
615
+ growth: ((curr.Sales - prev.Sales) / prev.Sales * 100).toFixed(2) + '%'
616
+ };
617
+ });
618
+
619
+ console.log('Growth Analysis:', growth);
620
+ growth;
621
+ `, { context: jsCtx });
622
+ ```
623
+
407
624
  <h2 id="architecture">🏗️ Architecture</h2>
408
625
 
409
626
  The SDK leverages Cloudflare's infrastructure:
410
627
 
411
628
  - **Durable Objects**: Manages sandbox lifecycle and state
412
- - **Containers**: Provides isolated execution environments
629
+ - **Containers**: Provides isolated execution environments with Jupyter kernels
413
630
  - **Workers**: Handles HTTP routing and API interface
414
631
  - **Edge Network**: Enables global distribution and low latency
632
+ - **Jupyter Integration**: Python (IPython) and JavaScript (TSLab) kernels for code execution
633
+ - **MIME Processing**: Automatic detection and handling of rich output formats
415
634
 
416
635
  <h2 id="advanced-usage">🛠️ Advanced Usage</h2>
417
636
 
@@ -492,17 +711,71 @@ for await (const log of parseSSEStream<LogEvent>(logStream)) {
492
711
 
493
712
  ### Session Management
494
713
 
495
- Maintain context across commands:
714
+ The SDK provides two approaches for managing execution context:
715
+
716
+ #### Implicit Sessions (Recommended)
717
+
718
+ Each sandbox maintains its own persistent session automatically:
496
719
 
497
720
  ```typescript
498
- const sessionId = crypto.randomUUID();
721
+ const sandbox = getSandbox(env.Sandbox, "my-app");
499
722
 
500
- // Commands in the same session share working directory
501
- await sandbox.exec("cd /app", { sessionId });
502
- await sandbox.exec("npm install", { sessionId });
503
- const app = await sandbox.startProcess("npm start", { sessionId });
723
+ // These commands share state (pwd, env vars, etc.)
724
+ await sandbox.exec("cd /app");
725
+ await sandbox.exec("pwd"); // Output: /app
726
+ await sandbox.exec("export MY_VAR=hello");
727
+ await sandbox.exec("echo $MY_VAR"); // Output: hello
504
728
  ```
505
729
 
730
+ #### Explicit Sessions for Advanced Use Cases
731
+
732
+ Create isolated execution contexts within the same sandbox:
733
+
734
+ ```typescript
735
+ const sandbox = getSandbox(env.Sandbox, "multi-env");
736
+
737
+ // Create independent sessions with different environments
738
+ const buildSession = await sandbox.createSession({
739
+ name: "build",
740
+ env: { NODE_ENV: "production" },
741
+ cwd: "/build"
742
+ });
743
+
744
+ const testSession = await sandbox.createSession({
745
+ name: "test",
746
+ env: { NODE_ENV: "test" },
747
+ cwd: "/test"
748
+ });
749
+
750
+ // Run commands in parallel with different contexts
751
+ await Promise.all([
752
+ buildSession.exec("npm run build"),
753
+ testSession.exec("npm test")
754
+ ]);
755
+ ```
756
+
757
+ #### Security with AI Agents
758
+
759
+ When using AI coding agents, separate development from execution:
760
+
761
+ ```typescript
762
+ // Phase 1: AI agent writes code (with API keys)
763
+ const devSession = await sandbox.createSession({
764
+ name: "ai-development",
765
+ env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY }
766
+ });
767
+ await devSession.exec('opencode "build a web server"');
768
+
769
+ // Phase 2: Run the generated code (without API keys)
770
+ const appSession = await sandbox.createSession({
771
+ name: "app-runtime",
772
+ env: { PORT: "3000" } // Only app-specific vars
773
+ });
774
+ await appSession.exec("node server.js");
775
+ ```
776
+
777
+ > **Best Practice**: Keep AI agent credentials separate from your application runtime to prevent accidental exposure of API keys.
778
+
506
779
  <h2 id="debugging">🔍 Debugging</h2>
507
780
 
508
781
  Enable verbose logging:
@@ -521,6 +794,9 @@ sandbox.client.onCommandComplete = (success, code) =>
521
794
  - Maximum container runtime is limited by Durable Object constraints
522
795
  - WebSocket support for preview URLs coming soon
523
796
  - Some system calls may be restricted in the container environment
797
+ - Code interpreter has no internet access (sandbox restriction)
798
+ - Some Python/JavaScript packages may not be pre-installed
799
+ - Resource limits apply to code execution (CPU, memory)
524
800
 
525
801
  <h2 id="contributing">🤝 Contributing</h2>
526
802
 
@@ -534,11 +810,21 @@ cd sandbox-sdk
534
810
  # Install dependencies
535
811
  npm install
536
812
 
813
+ # Install Bun (if not already installed)
814
+ # Visit https://bun.sh for installation instructions
815
+ curl -fsSL https://bun.sh/install | bash
816
+
817
+ # Install container dependencies (required for TypeScript checking)
818
+ cd packages/sandbox/container_src && bun install && cd -
819
+
537
820
  # Run tests
538
821
  npm test
539
822
 
540
823
  # Build the project
541
824
  npm run build
825
+
826
+ # Run type checking and linting
827
+ npm run check
542
828
  ```
543
829
 
544
830
  <h2 id="license">📄 License</h2>