@computesdk/e2b 1.1.0 → 1.2.0

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/README.md CHANGED
@@ -1,15 +1,6 @@
1
1
  # @computesdk/e2b
2
2
 
3
- E2B provider for ComputeSDK - Execute Python code with full filesystem and terminal support in secure, isolated E2B sandboxes.
4
-
5
- ## Features
6
-
7
- - 🐍 **Python Code Execution** - Run Python scripts with data science libraries
8
- - 📁 **Full Filesystem Access** - Read, write, create directories, and manage files
9
- - 🖥️ **Interactive Terminals** - PTY terminal sessions with real-time I/O
10
- - ⚡ **Command Execution** - Run shell commands directly
11
- - 🔒 **Secure Isolation** - Each sandbox runs in its own isolated environment
12
- - 📊 **Data Science Ready** - Pre-installed pandas, numpy, matplotlib, scikit-learn
3
+ E2B provider for ComputeSDK - Execute code in secure, isolated E2B sandboxes with full filesystem and terminal support.
13
4
 
14
5
  ## Installation
15
6
 
@@ -26,17 +17,24 @@ npm install @computesdk/e2b
26
17
  export E2B_API_KEY=e2b_your_api_key_here
27
18
  ```
28
19
 
29
- ## Quick Start
20
+ ## Usage
30
21
 
31
- ### Basic Code Execution
22
+ ### With ComputeSDK
32
23
 
33
24
  ```typescript
25
+ import { compute } from 'computesdk';
34
26
  import { e2b } from '@computesdk/e2b';
35
27
 
36
- const sandbox = e2b();
28
+ // Set as default provider
29
+ compute.setConfig({
30
+ provider: e2b({ apiKey: process.env.E2B_API_KEY })
31
+ });
32
+
33
+ // Create sandbox
34
+ const sandbox = await compute.sandbox.create({});
37
35
 
38
36
  // Execute Python code
39
- const result = await sandbox.execute(`
37
+ const result = await sandbox.runCode(`
40
38
  import pandas as pd
41
39
  import numpy as np
42
40
 
@@ -54,73 +52,213 @@ console.log(result.stdout);
54
52
  // 2 3 6
55
53
  // Sum: 21
56
54
 
57
- await sandbox.kill();
55
+ // Clean up
56
+ await compute.sandbox.destroy(sandbox.sandboxId);
58
57
  ```
59
58
 
60
- ### With ComputeSDK Auto-Detection
59
+ ### Direct Usage
61
60
 
62
61
  ```typescript
63
- import { ComputeSDK } from 'computesdk';
62
+ import { e2b } from '@computesdk/e2b';
64
63
 
65
- // Automatically uses E2B if E2B_API_KEY is set
66
- const sandbox = ComputeSDK.createSandbox();
64
+ // Create provider
65
+ const provider = e2b({
66
+ apiKey: 'e2b_your_api_key',
67
+ timeout: 600000 // 10 minutes
68
+ });
67
69
 
68
- const result = await sandbox.execute('print("Hello from E2B!")');
69
- console.log(result.stdout); // "Hello from E2B!"
70
+ // Use with compute singleton
71
+ const sandbox = await compute.sandbox.create({ provider });
70
72
  ```
71
73
 
72
- ## Filesystem Operations
74
+ ## Configuration
73
75
 
74
- E2B provides full filesystem access through the `sandbox.filesystem` interface:
76
+ ### Environment Variables
75
77
 
76
- ### File Operations
78
+ ```bash
79
+ export E2B_API_KEY=e2b_your_api_key_here
80
+ ```
81
+
82
+ ### Configuration Options
77
83
 
78
84
  ```typescript
79
- import { e2b } from '@computesdk/e2b';
85
+ interface E2BConfig {
86
+ /** E2B API key - if not provided, will use E2B_API_KEY env var */
87
+ apiKey?: string;
88
+ /** Default runtime environment */
89
+ runtime?: 'python' | 'node';
90
+ /** Execution timeout in milliseconds */
91
+ timeout?: number;
92
+ }
93
+ ```
80
94
 
81
- const sandbox = e2b();
95
+ ## Features
82
96
 
83
- // Write a file
84
- await sandbox.filesystem.writeFile('/tmp/data.json', JSON.stringify({
85
- name: 'ComputeSDK',
86
- version: '1.0.0'
87
- }));
97
+ - **Code Execution** - Python and Node.js runtime support
98
+ - ✅ **Command Execution** - Run shell commands in sandbox
99
+ - ✅ **Filesystem Operations** - Full file system access via E2B API
100
+ - ✅ **Terminal Support** - Interactive PTY terminals
101
+ - ✅ **Auto Runtime Detection** - Automatically detects Python vs Node.js
102
+ - ✅ **Data Science Ready** - Pre-installed pandas, numpy, matplotlib, etc.
88
103
 
89
- // Read the file
90
- const content = await sandbox.filesystem.readFile('/tmp/data.json');
91
- console.log(JSON.parse(content)); // { name: 'ComputeSDK', version: '1.0.0' }
104
+ ## API Reference
92
105
 
93
- // Check if file exists
94
- const exists = await sandbox.filesystem.exists('/tmp/data.json');
95
- console.log(exists); // true
106
+ ### Code Execution
107
+
108
+ ```typescript
109
+ // Execute Python code
110
+ const result = await sandbox.runCode(`
111
+ import json
112
+ data = {"message": "Hello from Python"}
113
+ print(json.dumps(data))
114
+ `, 'python');
115
+
116
+ // Execute Node.js code
117
+ const result = await sandbox.runCode(`
118
+ const data = { message: "Hello from Node.js" };
119
+ console.log(JSON.stringify(data));
120
+ `, 'node');
121
+
122
+ // Auto-detection (based on code patterns)
123
+ const result = await sandbox.runCode('print("Auto-detected as Python")');
124
+ ```
125
+
126
+ ### Command Execution
127
+
128
+ ```typescript
129
+ // List files
130
+ const result = await sandbox.runCommand('ls', ['-la']);
131
+
132
+ // Install packages
133
+ const result = await sandbox.runCommand('pip', ['install', 'requests']);
96
134
 
97
- // Remove the file
98
- await sandbox.filesystem.remove('/tmp/data.json');
135
+ // Run scripts
136
+ const result = await sandbox.runCommand('python', ['script.py']);
99
137
  ```
100
138
 
101
- ### Directory Operations
139
+ ### Filesystem Operations
102
140
 
103
141
  ```typescript
104
- // Create directories
105
- await sandbox.filesystem.mkdir('/project/data');
106
- await sandbox.filesystem.mkdir('/project/output');
142
+ // Write file
143
+ await sandbox.filesystem.writeFile('/tmp/hello.py', 'print("Hello World")');
144
+
145
+ // Read file
146
+ const content = await sandbox.filesystem.readFile('/tmp/hello.py');
147
+
148
+ // Create directory
149
+ await sandbox.filesystem.mkdir('/tmp/data');
107
150
 
108
151
  // List directory contents
109
- const entries = await sandbox.filesystem.readdir('/project');
110
- entries.forEach(entry => {
111
- console.log(`${entry.name} (${entry.isDirectory ? 'dir' : 'file'}) - ${entry.size} bytes`);
152
+ const files = await sandbox.filesystem.readdir('/tmp');
153
+
154
+ // Check if file exists
155
+ const exists = await sandbox.filesystem.exists('/tmp/hello.py');
156
+
157
+ // Remove file or directory
158
+ await sandbox.filesystem.remove('/tmp/hello.py');
159
+ ```
160
+
161
+ ### Terminal Operations
162
+
163
+ ```typescript
164
+ // Create terminal
165
+ const terminal = await sandbox.terminal.create({
166
+ command: 'bash',
167
+ cols: 80,
168
+ rows: 24,
169
+ onData: (data: Uint8Array) => {
170
+ const output = new TextDecoder().decode(data);
171
+ console.log('Terminal output:', output);
172
+ }
112
173
  });
113
174
 
114
- // Remove directory
115
- await sandbox.filesystem.remove('/project/data');
175
+ // Write to terminal
176
+ await terminal.write('echo "Hello Terminal!"\n');
177
+
178
+ // Resize terminal
179
+ await terminal.resize(120, 30);
180
+
181
+ // Kill terminal
182
+ await terminal.kill();
183
+
184
+ // List all terminals
185
+ const terminals = await sandbox.terminal.list();
186
+
187
+ // Get terminal by ID
188
+ const existingTerminal = await sandbox.terminal.getById('terminal-id');
116
189
  ```
117
190
 
118
- ### Data Science Workflow
191
+ ### Sandbox Management
119
192
 
120
193
  ```typescript
194
+ // Get sandbox info
195
+ const info = await sandbox.getInfo();
196
+ console.log(info.id, info.provider, info.status);
197
+
198
+ // Get existing sandbox (reconnect)
199
+ const existing = await compute.sandbox.getById(provider, 'sandbox-id');
200
+
201
+ // Destroy sandbox
202
+ await compute.sandbox.destroy(provider, 'sandbox-id');
203
+
204
+ // Note: E2B doesn't support listing all sandboxes
205
+ // Each sandbox is managed individually
206
+ ```
207
+
208
+ ## Runtime Detection
209
+
210
+ The provider automatically detects the runtime based on code patterns:
211
+
212
+ **Python indicators:**
213
+ - `print(` statements
214
+ - `import` statements
215
+ - `def` function definitions
216
+ - Python-specific syntax (`f"`, `__`, etc.)
217
+
218
+ **Default:** Node.js for all other cases
219
+
220
+ ## Error Handling
221
+
222
+ ```typescript
223
+ try {
224
+ const result = await sandbox.runCode('invalid code');
225
+ } catch (error) {
226
+ if (error.message.includes('Missing E2B API key')) {
227
+ console.error('Set E2B_API_KEY environment variable');
228
+ } else if (error.message.includes('Invalid E2B API key format')) {
229
+ console.error('E2B API keys should start with "e2b_"');
230
+ } else if (error.message.includes('authentication failed')) {
231
+ console.error('Check your E2B API key');
232
+ } else if (error.message.includes('quota exceeded')) {
233
+ console.error('E2B usage limits reached');
234
+ } else if (error.message.includes('Syntax error')) {
235
+ console.error('Code has syntax errors');
236
+ }
237
+ }
238
+ ```
239
+
240
+ ## Web Framework Integration
241
+
242
+ Use with web frameworks via the request handler:
243
+
244
+ ```typescript
245
+ import { handleComputeRequest } from 'computesdk';
121
246
  import { e2b } from '@computesdk/e2b';
122
247
 
123
- const sandbox = e2b();
248
+ export async function POST(request: Request) {
249
+ return handleComputeRequest({
250
+ request,
251
+ provider: e2b({ apiKey: process.env.E2B_API_KEY })
252
+ });
253
+ }
254
+ ```
255
+
256
+ ## Examples
257
+
258
+ ### Data Science Workflow
259
+
260
+ ```typescript
261
+ const sandbox = await compute.sandbox.create({});
124
262
 
125
263
  // Create project structure
126
264
  await sandbox.filesystem.mkdir('/analysis');
@@ -136,7 +274,7 @@ Charlie,35,Chicago`;
136
274
  await sandbox.filesystem.writeFile('/analysis/data/people.csv', csvData);
137
275
 
138
276
  // Process data with Python
139
- const result = await sandbox.execute(`
277
+ const result = await sandbox.runCode(`
140
278
  import pandas as pd
141
279
  import matplotlib.pyplot as plt
142
280
 
@@ -183,251 +321,50 @@ const chartExists = await sandbox.filesystem.exists('/analysis/output/age_chart.
183
321
  console.log('Chart created:', chartExists);
184
322
  ```
185
323
 
186
- ## Terminal Operations
187
-
188
- E2B supports interactive PTY terminals for real-time command execution:
189
-
190
- ### Basic Terminal Usage
324
+ ### Interactive Terminal Session
191
325
 
192
326
  ```typescript
193
- import { e2b } from '@computesdk/e2b';
194
-
195
- const sandbox = e2b();
327
+ const sandbox = await compute.sandbox.create({});
196
328
 
197
- // Create a new terminal session
329
+ // Create interactive Python terminal
198
330
  const terminal = await sandbox.terminal.create({
199
- command: 'bash',
200
- cols: 80,
201
- rows: 24
202
- });
203
-
204
- console.log(`Terminal created with PID: ${terminal.pid}`);
205
-
206
- // Write commands to terminal
207
- await terminal.write('echo "Hello from terminal!"\n');
208
- await terminal.write('ls -la\n');
209
- await terminal.write('python --version\n');
210
-
211
- // Set up data handler for terminal output
212
- terminal.onData = (data: Uint8Array) => {
213
- const output = new TextDecoder().decode(data);
214
- console.log('Terminal output:', output);
215
- };
216
-
217
- // Resize terminal
218
- await terminal.resize(120, 30);
219
-
220
- // List all active terminals
221
- const terminals = await sandbox.terminal.list();
222
- console.log(`Active terminals: ${terminals.length}`);
223
-
224
- // Clean up
225
- await terminal.kill();
226
- ```
227
-
228
- ### Interactive Python Session
229
-
230
- ```typescript
231
- const sandbox = e2b();
232
-
233
- // Start Python interpreter in terminal
234
- const pythonTerminal = await sandbox.terminal.create({
235
331
  command: 'python3',
236
332
  cols: 80,
237
- rows: 24
333
+ rows: 24,
334
+ onData: (data: Uint8Array) => {
335
+ const output = new TextDecoder().decode(data);
336
+ process.stdout.write(output); // Forward to console
337
+ }
238
338
  });
239
339
 
240
- // Set up output handler
241
- pythonTerminal.onData = (data: Uint8Array) => {
242
- const output = new TextDecoder().decode(data);
243
- process.stdout.write(output); // Forward to console
244
- };
245
-
246
340
  // Send Python commands
247
- await pythonTerminal.write('import numpy as np\n');
248
- await pythonTerminal.write('import pandas as pd\n');
249
- await pythonTerminal.write('print("Libraries loaded!")\n');
250
- await pythonTerminal.write('data = np.array([1, 2, 3, 4, 5])\n');
251
- await pythonTerminal.write('print(f"Mean: {data.mean()}")\n');
252
- await pythonTerminal.write('exit()\n');
253
-
254
- // Wait a moment for commands to execute
341
+ await terminal.write('import numpy as np\n');
342
+ await terminal.write('import pandas as pd\n');
343
+ await terminal.write('print("Libraries loaded!")\n');
344
+ await terminal.write('data = np.array([1, 2, 3, 4, 5])\n');
345
+ await terminal.write('print(f"Mean: {data.mean()}")\n');
346
+ await terminal.write('exit()\n');
347
+
348
+ // Wait for commands to execute
255
349
  await new Promise(resolve => setTimeout(resolve, 2000));
256
350
 
257
- await pythonTerminal.kill();
258
- ```
259
-
260
- ## Command Execution
261
-
262
- Execute shell commands directly with full output capture:
263
-
264
- ```typescript
265
- import { e2b } from '@computesdk/e2b';
266
-
267
- const sandbox = e2b();
268
-
269
- // Run shell commands
270
- const lsResult = await sandbox.runCommand('ls', ['-la', '/tmp']);
271
- console.log('Directory listing:', lsResult.stdout);
272
-
273
- // Install packages
274
- const pipResult = await sandbox.runCommand('pip', ['install', 'requests']);
275
- console.log('Package installation:', pipResult.stdout);
276
-
277
- // Run complex commands
278
- const gitResult = await sandbox.runCommand('git', ['--version']);
279
- console.log('Git version:', gitResult.stdout);
280
-
281
- // Check system info
282
- const systemResult = await sandbox.runCommand('uname', ['-a']);
283
- console.log('System info:', systemResult.stdout);
284
- ```
285
-
286
- ## Configuration
287
-
288
- ```typescript
289
- import { e2b } from '@computesdk/e2b';
290
-
291
- const sandbox = e2b({
292
- timeout: 600000, // 10 minutes (default: 5 minutes)
293
- runtime: 'python' // Only Python is supported
294
- });
295
- ```
296
-
297
- ## API Reference
298
-
299
- ### Core Methods
300
-
301
- #### `sandbox.execute(code: string, runtime?: Runtime): Promise<ExecutionResult>`
302
-
303
- Execute Python code in the sandbox.
304
-
305
- ```typescript
306
- const result = await sandbox.execute(`
307
- x = 1 + 1
308
- print(f"Result: {x}")
309
- `);
310
- // Returns: { stdout: "Result: 2", stderr: "", exitCode: 0, executionTime: 45 }
311
- ```
312
-
313
- #### `sandbox.runCommand(command: string, args?: string[]): Promise<ExecutionResult>`
314
-
315
- Execute shell commands.
316
-
317
- ```typescript
318
- const result = await sandbox.runCommand('python', ['--version']);
319
- // Returns: { stdout: "Python 3.11.0", stderr: "", exitCode: 0, executionTime: 12 }
320
- ```
321
-
322
- #### `sandbox.getInfo(): Promise<SandboxInfo>`
323
-
324
- Get sandbox information.
325
-
326
- ```typescript
327
- const info = await sandbox.getInfo();
328
- // Returns: { provider: "e2b", runtime: "python", status: "running", ... }
329
- ```
330
-
331
- #### `sandbox.kill(): Promise<void>`
332
-
333
- Terminate the sandbox and clean up resources.
334
-
335
- ```typescript
336
- await sandbox.kill();
337
- ```
338
-
339
- ### Filesystem API
340
-
341
- #### `sandbox.filesystem.readFile(path: string): Promise<string>`
342
-
343
- Read file contents as text.
344
-
345
- #### `sandbox.filesystem.writeFile(path: string, content: string): Promise<void>`
346
-
347
- Write content to a file (creates file if it doesn't exist).
348
-
349
- #### `sandbox.filesystem.mkdir(path: string): Promise<void>`
350
-
351
- Create directory and parent directories if needed.
352
-
353
- #### `sandbox.filesystem.readdir(path: string): Promise<FileEntry[]>`
354
-
355
- List directory contents with metadata.
356
-
357
- #### `sandbox.filesystem.exists(path: string): Promise<boolean>`
358
-
359
- Check if file or directory exists.
360
-
361
- #### `sandbox.filesystem.remove(path: string): Promise<void>`
362
-
363
- Remove file or directory.
364
-
365
- ### Terminal API
366
-
367
- #### `sandbox.terminal.create(options?: TerminalCreateOptions): Promise<InteractiveTerminalSession>`
368
-
369
- Create a new PTY terminal session.
370
-
371
- ```typescript
372
- const terminal = await sandbox.terminal.create({
373
- command: 'bash', // Command to run (default: 'bash')
374
- cols: 80, // Terminal width (default: 80)
375
- rows: 24 // Terminal height (default: 24)
376
- });
377
- ```
378
-
379
- #### `sandbox.terminal.list(): Promise<InteractiveTerminalSession[]>`
380
-
381
- List all active terminal sessions.
382
-
383
- #### Terminal Session Methods
384
-
385
- - `terminal.write(data: string | Uint8Array): Promise<void>` - Send input to terminal
386
- - `terminal.resize(cols: number, rows: number): Promise<void>` - Resize terminal
387
- - `terminal.kill(): Promise<void>` - Terminate terminal session
388
- - `terminal.onData: (data: Uint8Array) => void` - Output data handler
389
-
390
- ## Error Handling
391
-
392
- ```typescript
393
- import { e2b } from '@computesdk/e2b';
394
-
395
- try {
396
- const sandbox = e2b();
397
- const result = await sandbox.execute('invalid python code');
398
- } catch (error) {
399
- if (error.message.includes('Missing E2B API key')) {
400
- console.error('Set E2B_API_KEY environment variable');
401
- } else if (error.message.includes('Invalid E2B API key format')) {
402
- console.error('E2B API keys should start with "e2b_"');
403
- } else if (error.message.includes('authentication failed')) {
404
- console.error('Check your E2B API key');
405
- } else if (error.message.includes('quota exceeded')) {
406
- console.error('E2B usage quota exceeded');
407
- } else if (error.message.includes('timeout')) {
408
- console.error('Execution timed out - consider increasing timeout');
409
- } else if (error.message.includes('memory limits')) {
410
- console.error('Memory limit exceeded - optimize your code');
411
- }
412
- }
351
+ await terminal.kill();
413
352
  ```
414
353
 
415
- ## Examples
416
-
417
354
  ### Machine Learning Pipeline
418
355
 
419
356
  ```typescript
420
- import { e2b } from '@computesdk/e2b';
421
-
422
- const sandbox = e2b({ timeout: 600000 }); // 10 minutes for ML tasks
357
+ const sandbox = await compute.sandbox.create({
358
+ options: { timeout: 600000 } // 10 minutes for ML tasks
359
+ });
423
360
 
424
361
  // Create ML project structure
425
362
  await sandbox.filesystem.mkdir('/ml-project');
426
363
  await sandbox.filesystem.mkdir('/ml-project/data');
427
364
  await sandbox.filesystem.mkdir('/ml-project/models');
428
365
 
429
- // Generate sample data
430
- const result = await sandbox.execute(`
366
+ // Generate and process data
367
+ const result = await sandbox.runCode(`
431
368
  import numpy as np
432
369
  import pandas as pd
433
370
  from sklearn.model_selection import train_test_split
@@ -501,99 +438,24 @@ console.log('ML Results:', JSON.parse(results));
501
438
  // Verify model file exists
502
439
  const modelExists = await sandbox.filesystem.exists('/ml-project/models/linear_model.pkl');
503
440
  console.log('Model saved:', modelExists);
504
-
505
- await sandbox.kill();
506
- ```
507
-
508
- ### Web Scraping and Analysis
509
-
510
- ```typescript
511
- import { e2b } from '@computesdk/e2b';
512
-
513
- const sandbox = e2b();
514
-
515
- // Install required packages and scrape data
516
- const result = await sandbox.execute(`
517
- import subprocess
518
- import sys
519
-
520
- # Install required packages
521
- subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'requests', 'beautifulsoup4'])
522
-
523
- import requests
524
- from bs4 import BeautifulSoup
525
- import json
526
- import pandas as pd
527
-
528
- # Example: Scrape Python.org news (respecting robots.txt)
529
- url = 'https://www.python.org/jobs/'
530
- headers = {'User-Agent': 'Mozilla/5.0 (compatible; ComputeSDK/1.0)'}
531
-
532
- try:
533
- response = requests.get(url, headers=headers, timeout=10)
534
- response.raise_for_status()
535
-
536
- soup = BeautifulSoup(response.content, 'html.parser')
537
-
538
- # Extract job listings (example structure)
539
- jobs = []
540
- job_elements = soup.find_all('h2', class_='listing-company-name')[:5] # Limit to 5
541
-
542
- for job_elem in job_elements:
543
- job_title = job_elem.get_text(strip=True)
544
- jobs.append({'title': job_title, 'source': 'python.org'})
545
-
546
- print(f"Found {len(jobs)} job listings:")
547
- for i, job in enumerate(jobs, 1):
548
- print(f"{i}. {job['title']}")
549
-
550
- # Save data
551
- with open('/tmp/jobs.json', 'w') as f:
552
- json.dump(jobs, f, indent=2)
553
-
554
- print("\\nData saved to /tmp/jobs.json")
555
-
556
- except Exception as e:
557
- print(f"Error scraping data: {e}")
558
- # Create sample data instead
559
- jobs = [
560
- {'title': 'Senior Python Developer', 'source': 'example.com'},
561
- {'title': 'Data Scientist', 'source': 'example.com'},
562
- {'title': 'Backend Engineer', 'source': 'example.com'}
563
- ]
564
-
565
- with open('/tmp/jobs.json', 'w') as f:
566
- json.dump(jobs, f, indent=2)
567
-
568
- print("Created sample data instead")
569
- `);
570
-
571
- console.log(result.stdout);
572
-
573
- // Read the scraped data
574
- const jobsData = await sandbox.filesystem.readFile('/tmp/jobs.json');
575
- console.log('Scraped jobs:', JSON.parse(jobsData));
576
-
577
- await sandbox.kill();
578
441
  ```
579
442
 
580
443
  ## Best Practices
581
444
 
582
- 1. **Resource Management**: Always call `sandbox.kill()` when done to free resources
445
+ 1. **Resource Management**: Always destroy sandboxes when done to free resources
583
446
  2. **Error Handling**: Use try-catch blocks for robust error handling
584
447
  3. **Timeouts**: Set appropriate timeouts for long-running tasks
585
- 4. **File Organization**: Use the filesystem API to organize your project files
448
+ 4. **File Organization**: Use the filesystem API to organize project files
586
449
  5. **Terminal Sessions**: Clean up terminal sessions with `terminal.kill()`
587
- 6. **Memory Usage**: Monitor memory usage for large datasets
588
- 7. **API Quotas**: Keep track of your E2B usage and quotas
450
+ 6. **API Key Security**: Never commit API keys to version control
589
451
 
590
452
  ## Limitations
591
453
 
592
- - **Python Only**: Currently only supports Python runtime
454
+ - **Sandbox Listing**: E2B doesn't support listing all sandboxes (each is managed individually)
593
455
  - **Memory Limits**: Subject to E2B sandbox memory constraints
594
456
  - **Network Access**: Limited outbound network access
595
- - **Execution Time**: Default 5-minute timeout (configurable up to E2B limits)
596
457
  - **File Persistence**: Files are not persisted between sandbox sessions
458
+ - **Execution Time**: Subject to E2B timeout limits
597
459
 
598
460
  ## Support
599
461
 
package/dist/index.js CHANGED
@@ -48,14 +48,24 @@ var e2b = (0, import_computesdk.createProvider)({
48
48
  let sandboxId;
49
49
  if (options?.sandboxId) {
50
50
  sandbox = await import_code_interpreter.Sandbox.connect(options.sandboxId, {
51
- apiKey
51
+ apiKey,
52
+ domain: options.domain
52
53
  });
53
54
  sandboxId = options.sandboxId;
54
55
  } else {
55
- sandbox = await import_code_interpreter.Sandbox.create({
56
- apiKey,
57
- timeoutMs: timeout
58
- });
56
+ if (options?.templateId) {
57
+ sandbox = await import_code_interpreter.Sandbox.create(options.templateId, {
58
+ apiKey,
59
+ timeoutMs: timeout,
60
+ domain: options.domain
61
+ });
62
+ } else {
63
+ sandbox = await import_code_interpreter.Sandbox.create({
64
+ apiKey,
65
+ timeoutMs: timeout,
66
+ domain: options?.domain
67
+ });
68
+ }
59
69
  sandboxId = sandbox.sandboxId || `e2b-${Date.now()}`;
60
70
  }
61
71
  return {
@@ -200,6 +210,17 @@ var e2b = (0, import_computesdk.createProvider)({
200
210
  }
201
211
  };
202
212
  },
213
+ getUrl: async (sandbox, options) => {
214
+ try {
215
+ const host = sandbox.getHost(options.port);
216
+ const protocol = options.protocol || "https";
217
+ return `${protocol}://${host}`;
218
+ } catch (error) {
219
+ throw new Error(
220
+ `Failed to get E2B host for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`
221
+ );
222
+ }
223
+ },
203
224
  // Optional filesystem methods - E2B has full filesystem support
204
225
  filesystem: {
205
226
  readFile: async (sandbox, path) => {
@@ -227,85 +248,6 @@ var e2b = (0, import_computesdk.createProvider)({
227
248
  remove: async (sandbox, path) => {
228
249
  await sandbox.files.remove(path);
229
250
  }
230
- },
231
- // Optional terminal methods - E2B has PTY terminal support
232
- terminal: {
233
- create: async (sandbox, options = {}) => {
234
- const cols = options.cols || 80;
235
- const rows = options.rows || 24;
236
- const ptyHandle = await sandbox.pty.create({
237
- cols,
238
- rows,
239
- onData: options.onData || (() => {
240
- })
241
- });
242
- const terminalWrapper = {
243
- ...ptyHandle,
244
- onData: options.onData,
245
- onExit: options.onExit
246
- };
247
- return {
248
- terminal: terminalWrapper,
249
- terminalId: ptyHandle.pid.toString()
250
- };
251
- },
252
- getById: async (sandbox, terminalId) => {
253
- try {
254
- const pid = parseInt(terminalId);
255
- if (isNaN(pid)) return null;
256
- const processes = await sandbox.commands.list();
257
- const ptyProcess = processes.find((p) => p.pid === pid);
258
- if (!ptyProcess) return null;
259
- return {
260
- terminal: { pid: ptyProcess.pid, cmd: ptyProcess.cmd },
261
- terminalId
262
- };
263
- } catch (error) {
264
- return null;
265
- }
266
- },
267
- list: async (sandbox) => {
268
- try {
269
- const processes = await sandbox.commands.list();
270
- return processes.filter((p) => ["bash", "sh", "zsh", "fish", "pty"].some((term) => p.cmd.includes(term))).map((p) => ({
271
- terminal: { pid: p.pid, cmd: p.cmd },
272
- terminalId: p.pid.toString()
273
- }));
274
- } catch (error) {
275
- return [];
276
- }
277
- },
278
- destroy: async (sandbox, terminalId) => {
279
- const pid = parseInt(terminalId);
280
- if (isNaN(pid)) {
281
- throw new Error(`Invalid terminal ID: ${terminalId}. Expected numeric PID.`);
282
- }
283
- try {
284
- await sandbox.pty.kill(pid);
285
- } catch (error) {
286
- }
287
- },
288
- // Terminal instance methods
289
- write: async (sandbox, terminal, data) => {
290
- const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
291
- if (terminal.pid) {
292
- await sandbox.pty.sendInput(terminal.pid, bytes);
293
- } else {
294
- await sandbox.pty.sendInput(terminal.pid || terminal.id, bytes);
295
- }
296
- },
297
- resize: async (sandbox, terminal, cols, rows) => {
298
- const pid = terminal.pid || terminal.id;
299
- await sandbox.pty.resize(pid, { cols, rows });
300
- },
301
- kill: async (sandbox, terminal) => {
302
- const pid = terminal.pid || terminal.id;
303
- if (terminal.kill) {
304
- await terminal.kill();
305
- } else {
306
- await sandbox.pty.kill(pid);
307
- }
308
- }
309
251
  }
310
252
  }
311
253
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * E2B Provider - Factory-based Implementation\n * \n * Full-featured provider with filesystem and terminal support using the factory pattern.\n * Reduces ~400 lines of boilerplate to ~100 lines of core logic.\n */\n\nimport { Sandbox as E2BSandbox } from '@e2b/code-interpreter';\nimport { createProvider } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n TerminalCreateOptions,\n CreateSandboxOptions,\n FileEntry\n} from 'computesdk';\n\n/**\n * E2B-specific configuration options\n */\nexport interface E2BConfig {\n /** E2B API key - if not provided, will fallback to E2B_API_KEY environment variable */\n apiKey?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n\n\n/**\n * Create an E2B provider instance using the factory pattern\n */\nexport const e2b = createProvider<E2BSandbox, E2BConfig>({\n name: 'e2b',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: E2BConfig, options?: CreateSandboxOptions) => {\n // Validate API key\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.E2B_API_KEY) || '';\n\n if (!apiKey) {\n throw new Error(\n `Missing E2B API key. Provide 'apiKey' in config or set E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n\n // Validate API key format\n if (!apiKey.startsWith('e2b_')) {\n throw new Error(\n `Invalid E2B API key format. E2B API keys should start with 'e2b_'. Check your E2B_API_KEY environment variable.`\n );\n }\n\n\n const timeout = config.timeout || 300000;\n\n try {\n let sandbox: E2BSandbox;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing E2B session\n sandbox = await E2BSandbox.connect(options.sandboxId, {\n apiKey: apiKey,\n });\n sandboxId = options.sandboxId;\n } else {\n // Create new E2B session\n sandbox = await E2BSandbox.create({\n apiKey: apiKey,\n timeoutMs: timeout,\n });\n sandboxId = sandbox.sandboxId || `e2b-${Date.now()}`;\n }\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('API key')) {\n throw new Error(\n `E2B authentication failed. Please check your E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `E2B quota exceeded. Please check your usage at https://e2b.dev/`\n );\n }\n }\n throw new Error(\n `Failed to create E2B sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: E2BConfig) => {\n throw new Error(\n `E2B provider does not support listing sandboxes. E2B sandboxes are managed individually and don't have a native list API. Consider using a provider with persistent sandbox management or implement your own tracking system.`\n );\n },\n\n destroy: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n await sandbox.kill();\n } catch (error) {\n // Sandbox might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (sandbox: E2BSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n \n // Auto-detect runtime if not specified\n const effectiveRuntime = runtime || (\n // Strong Python indicators\n code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\")\n ? 'python'\n // Default to Node.js for all other cases (including ambiguous)\n : 'node'\n );\n \n // Use runCommand for consistent execution across all providers\n let result;\n \n // Use base64 encoding for both runtimes for reliability and consistency\n const encoded = Buffer.from(code).toString('base64');\n \n if (effectiveRuntime === 'python') {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | python3`);\n } else {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | node`);\n }\n\n // Check for syntax errors and throw them (similar to Vercel behavior)\n if (result.exitCode !== 0 && result.stderr) {\n // Check for common syntax error patterns\n if (result.stderr.includes('SyntaxError') || \n result.stderr.includes('invalid syntax') ||\n result.stderr.includes('Unexpected token') ||\n result.stderr.includes('Unexpected identifier')) {\n throw new Error(`Syntax error: ${result.stderr.trim()}`);\n }\n }\n\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // Handle E2B's CommandExitError - check if it contains actual error details\n if (error instanceof Error && error.message === 'exit status 1') {\n const actualStderr = (error as any)?.result?.stderr || '';\n const isSyntaxError = actualStderr.includes('SyntaxError');\n \n if (isSyntaxError) {\n // For syntax errors, throw\n const syntaxErrorLine = actualStderr.split('\\n').find((line: string) => line.includes('SyntaxError')) || 'SyntaxError: Invalid syntax in code';\n throw new Error(`Syntax error: ${syntaxErrorLine}`);\n } else {\n // For runtime errors, return a result instead of throwing\n return {\n stdout: '',\n stderr: actualStderr || 'Error: Runtime error occurred during execution',\n exitCode: 1,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n }\n \n // Re-throw syntax errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error;\n }\n throw new Error(\n `E2B execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (sandbox: E2BSandbox, command: string, args: string[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Construct full command with arguments\n const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command;\n\n // Execute command using E2B's bash execution via Python subprocess\n const execution = await sandbox.commands.run(fullCommand);\n\n return {\n stdout: execution.stdout,\n stderr: execution.stderr,\n exitCode: execution.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n },\n\n getInfo: async (sandbox: E2BSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b',\n runtime: 'python', // E2B default\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n e2bSessionId: sandbox.sandboxId\n }\n };\n },\n\n // Optional filesystem methods - E2B has full filesystem support\n filesystem: {\n readFile: async (sandbox: E2BSandbox, path: string): Promise<string> => {\n return await sandbox.files.read(path);\n },\n\n writeFile: async (sandbox: E2BSandbox, path: string, content: string): Promise<void> => {\n await sandbox.files.write(path, content);\n },\n\n mkdir: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.makeDir(path);\n },\n\n readdir: async (sandbox: E2BSandbox, path: string): Promise<FileEntry[]> => {\n const entries = await sandbox.files.list(path);\n\n return entries.map((entry: any) => ({\n name: entry.name,\n path: entry.path,\n isDirectory: Boolean(entry.isDir || entry.isDirectory),\n size: entry.size || 0,\n lastModified: new Date(entry.lastModified || Date.now())\n }));\n },\n\n exists: async (sandbox: E2BSandbox, path: string): Promise<boolean> => {\n return await sandbox.files.exists(path);\n },\n\n remove: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.remove(path);\n }\n },\n\n // Optional terminal methods - E2B has PTY terminal support\n terminal: {\n create: async (sandbox: E2BSandbox, options: TerminalCreateOptions = {}) => {\n const cols = options.cols || 80;\n const rows = options.rows || 24;\n\n // Create PTY session using E2B's pty.create\n const ptyHandle = await sandbox.pty.create({ \n cols: cols, \n rows: rows,\n onData: options.onData || (() => {\n // Default no-op if no onData provided\n })\n });\n\n // Create a wrapper object that includes the onData callback\n const terminalWrapper = {\n ...ptyHandle,\n onData: options.onData,\n onExit: options.onExit\n };\n\n return {\n terminal: terminalWrapper,\n terminalId: ptyHandle.pid.toString()\n };\n },\n\n getById: async (sandbox: E2BSandbox, terminalId: string) => {\n try {\n const pid = parseInt(terminalId);\n if (isNaN(pid)) return null;\n\n // List all running processes (includes PTY sessions)\n const processes = await sandbox.commands.list();\n \n // Find PTY process by PID\n const ptyProcess = processes.find(p => p.pid === pid);\n if (!ptyProcess) return null;\n\n return {\n terminal: { pid: ptyProcess.pid, cmd: ptyProcess.cmd },\n terminalId: terminalId\n };\n } catch (error) {\n return null;\n }\n },\n\n list: async (sandbox: E2BSandbox) => {\n try {\n // List all running processes\n const processes = await sandbox.commands.list();\n \n // Filter for PTY sessions and return raw terminal data\n return processes\n .filter(p => ['bash', 'sh', 'zsh', 'fish', 'pty'].some(term => p.cmd.includes(term)))\n .map(p => ({\n terminal: { pid: p.pid, cmd: p.cmd },\n terminalId: p.pid.toString()\n }));\n } catch (error) {\n // If listing fails, return empty array\n return [];\n }\n },\n\n destroy: async (sandbox: E2BSandbox, terminalId: string): Promise<void> => {\n const pid = parseInt(terminalId);\n if (isNaN(pid)) {\n throw new Error(`Invalid terminal ID: ${terminalId}. Expected numeric PID.`);\n }\n\n try {\n await sandbox.pty.kill(pid);\n } catch (error) {\n // Terminal might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Terminal instance methods\n write: async (sandbox: E2BSandbox, terminal: any, data: Uint8Array | string): Promise<void> => {\n const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;\n if (terminal.pid) {\n // For existing terminals, use PID\n await sandbox.pty.sendInput(terminal.pid, bytes);\n } else {\n // For new terminals, use the ptyHandle directly\n await sandbox.pty.sendInput(terminal.pid || terminal.id, bytes);\n }\n },\n\n resize: async (sandbox: E2BSandbox, terminal: any, cols: number, rows: number): Promise<void> => {\n const pid = terminal.pid || terminal.id;\n await sandbox.pty.resize(pid, { cols, rows });\n },\n\n kill: async (sandbox: E2BSandbox, terminal: any): Promise<void> => {\n const pid = terminal.pid || terminal.id;\n if (terminal.kill) {\n // For ptyHandle objects\n await terminal.kill();\n } else {\n // For process objects\n await sandbox.pty.kill(pid);\n }\n }\n }\n }\n }\n});\n"],"mappings":"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","names":["E2BSandbox"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * E2B Provider - Factory-based Implementation\n * \n * Full-featured provider with filesystem support using the factory pattern.\n * Reduces ~400 lines of boilerplate to ~100 lines of core logic.\n */\n\nimport { Sandbox as E2BSandbox } from '@e2b/code-interpreter';\nimport { createProvider } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry\n} from 'computesdk';\n\n/**\n * E2B-specific configuration options\n */\nexport interface E2BConfig {\n /** E2B API key - if not provided, will fallback to E2B_API_KEY environment variable */\n apiKey?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n\n\n/**\n * Create an E2B provider instance using the factory pattern\n */\nexport const e2b = createProvider<E2BSandbox, E2BConfig>({\n name: 'e2b',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: E2BConfig, options?: CreateSandboxOptions) => {\n // Validate API key\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.E2B_API_KEY) || '';\n\n if (!apiKey) {\n throw new Error(\n `Missing E2B API key. Provide 'apiKey' in config or set E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n\n // Validate API key format\n if (!apiKey.startsWith('e2b_')) {\n throw new Error(\n `Invalid E2B API key format. E2B API keys should start with 'e2b_'. Check your E2B_API_KEY environment variable.`\n );\n }\n\n\n const timeout = config.timeout || 300000;\n\n try {\n let sandbox: E2BSandbox;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing E2B session\n sandbox = await E2BSandbox.connect(options.sandboxId, {\n apiKey: apiKey,\n domain: options.domain,\n });\n sandboxId = options.sandboxId;\n } else {\n // Create new E2B session\n if (options?.templateId) {\n sandbox = await E2BSandbox.create(options.templateId, {\n apiKey: apiKey,\n timeoutMs: timeout,\n domain: options.domain,\n });\n } else {\n sandbox = await E2BSandbox.create({\n apiKey: apiKey,\n timeoutMs: timeout,\n domain: options?.domain,\n });\n }\n sandboxId = sandbox.sandboxId || `e2b-${Date.now()}`;\n }\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('API key')) {\n throw new Error(\n `E2B authentication failed. Please check your E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `E2B quota exceeded. Please check your usage at https://e2b.dev/`\n );\n }\n }\n throw new Error(\n `Failed to create E2B sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: E2BConfig) => {\n throw new Error(\n `E2B provider does not support listing sandboxes. E2B sandboxes are managed individually and don't have a native list API. Consider using a provider with persistent sandbox management or implement your own tracking system.`\n );\n },\n\n destroy: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n await sandbox.kill();\n } catch (error) {\n // Sandbox might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (sandbox: E2BSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n \n // Auto-detect runtime if not specified\n const effectiveRuntime = runtime || (\n // Strong Python indicators\n code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\")\n ? 'python'\n // Default to Node.js for all other cases (including ambiguous)\n : 'node'\n );\n \n // Use runCommand for consistent execution across all providers\n let result;\n \n // Use base64 encoding for both runtimes for reliability and consistency\n const encoded = Buffer.from(code).toString('base64');\n \n if (effectiveRuntime === 'python') {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | python3`);\n } else {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | node`);\n }\n\n // Check for syntax errors and throw them (similar to Vercel behavior)\n if (result.exitCode !== 0 && result.stderr) {\n // Check for common syntax error patterns\n if (result.stderr.includes('SyntaxError') || \n result.stderr.includes('invalid syntax') ||\n result.stderr.includes('Unexpected token') ||\n result.stderr.includes('Unexpected identifier')) {\n throw new Error(`Syntax error: ${result.stderr.trim()}`);\n }\n }\n\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // Handle E2B's CommandExitError - check if it contains actual error details\n if (error instanceof Error && error.message === 'exit status 1') {\n const actualStderr = (error as any)?.result?.stderr || '';\n const isSyntaxError = actualStderr.includes('SyntaxError');\n \n if (isSyntaxError) {\n // For syntax errors, throw\n const syntaxErrorLine = actualStderr.split('\\n').find((line: string) => line.includes('SyntaxError')) || 'SyntaxError: Invalid syntax in code';\n throw new Error(`Syntax error: ${syntaxErrorLine}`);\n } else {\n // For runtime errors, return a result instead of throwing\n return {\n stdout: '',\n stderr: actualStderr || 'Error: Runtime error occurred during execution',\n exitCode: 1,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n }\n \n // Re-throw syntax errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error;\n }\n throw new Error(\n `E2B execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (sandbox: E2BSandbox, command: string, args: string[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Construct full command with arguments\n const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command;\n\n // Execute command using E2B's bash execution via Python subprocess\n const execution = await sandbox.commands.run(fullCommand);\n\n return {\n stdout: execution.stdout,\n stderr: execution.stderr,\n exitCode: execution.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n },\n\n getInfo: async (sandbox: E2BSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b',\n runtime: 'python', // E2B default\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n e2bSessionId: sandbox.sandboxId\n }\n };\n },\n\n getUrl: async (sandbox: E2BSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n // Use E2B's built-in getHost method for accurate host information\n const host = sandbox.getHost(options.port);\n const protocol = options.protocol || 'https';\n return `${protocol}://${host}`;\n } catch (error) {\n throw new Error(\n `Failed to get E2B host for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Optional filesystem methods - E2B has full filesystem support\n filesystem: {\n readFile: async (sandbox: E2BSandbox, path: string): Promise<string> => {\n return await sandbox.files.read(path);\n },\n\n writeFile: async (sandbox: E2BSandbox, path: string, content: string): Promise<void> => {\n await sandbox.files.write(path, content);\n },\n\n mkdir: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.makeDir(path);\n },\n\n readdir: async (sandbox: E2BSandbox, path: string): Promise<FileEntry[]> => {\n const entries = await sandbox.files.list(path);\n\n return entries.map((entry: any) => ({\n name: entry.name,\n path: entry.path,\n isDirectory: Boolean(entry.isDir || entry.isDirectory),\n size: entry.size || 0,\n lastModified: new Date(entry.lastModified || Date.now())\n }));\n },\n\n exists: async (sandbox: E2BSandbox, path: string): Promise<boolean> => {\n return await sandbox.files.exists(path);\n },\n\n remove: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.remove(path);\n }\n },\n\n\n }\n }\n});\n"],"mappings":"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","names":["E2BSandbox"]}
package/dist/index.mjs CHANGED
@@ -24,14 +24,24 @@ var e2b = createProvider({
24
24
  let sandboxId;
25
25
  if (options?.sandboxId) {
26
26
  sandbox = await E2BSandbox.connect(options.sandboxId, {
27
- apiKey
27
+ apiKey,
28
+ domain: options.domain
28
29
  });
29
30
  sandboxId = options.sandboxId;
30
31
  } else {
31
- sandbox = await E2BSandbox.create({
32
- apiKey,
33
- timeoutMs: timeout
34
- });
32
+ if (options?.templateId) {
33
+ sandbox = await E2BSandbox.create(options.templateId, {
34
+ apiKey,
35
+ timeoutMs: timeout,
36
+ domain: options.domain
37
+ });
38
+ } else {
39
+ sandbox = await E2BSandbox.create({
40
+ apiKey,
41
+ timeoutMs: timeout,
42
+ domain: options?.domain
43
+ });
44
+ }
35
45
  sandboxId = sandbox.sandboxId || `e2b-${Date.now()}`;
36
46
  }
37
47
  return {
@@ -176,6 +186,17 @@ var e2b = createProvider({
176
186
  }
177
187
  };
178
188
  },
189
+ getUrl: async (sandbox, options) => {
190
+ try {
191
+ const host = sandbox.getHost(options.port);
192
+ const protocol = options.protocol || "https";
193
+ return `${protocol}://${host}`;
194
+ } catch (error) {
195
+ throw new Error(
196
+ `Failed to get E2B host for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`
197
+ );
198
+ }
199
+ },
179
200
  // Optional filesystem methods - E2B has full filesystem support
180
201
  filesystem: {
181
202
  readFile: async (sandbox, path) => {
@@ -203,85 +224,6 @@ var e2b = createProvider({
203
224
  remove: async (sandbox, path) => {
204
225
  await sandbox.files.remove(path);
205
226
  }
206
- },
207
- // Optional terminal methods - E2B has PTY terminal support
208
- terminal: {
209
- create: async (sandbox, options = {}) => {
210
- const cols = options.cols || 80;
211
- const rows = options.rows || 24;
212
- const ptyHandle = await sandbox.pty.create({
213
- cols,
214
- rows,
215
- onData: options.onData || (() => {
216
- })
217
- });
218
- const terminalWrapper = {
219
- ...ptyHandle,
220
- onData: options.onData,
221
- onExit: options.onExit
222
- };
223
- return {
224
- terminal: terminalWrapper,
225
- terminalId: ptyHandle.pid.toString()
226
- };
227
- },
228
- getById: async (sandbox, terminalId) => {
229
- try {
230
- const pid = parseInt(terminalId);
231
- if (isNaN(pid)) return null;
232
- const processes = await sandbox.commands.list();
233
- const ptyProcess = processes.find((p) => p.pid === pid);
234
- if (!ptyProcess) return null;
235
- return {
236
- terminal: { pid: ptyProcess.pid, cmd: ptyProcess.cmd },
237
- terminalId
238
- };
239
- } catch (error) {
240
- return null;
241
- }
242
- },
243
- list: async (sandbox) => {
244
- try {
245
- const processes = await sandbox.commands.list();
246
- return processes.filter((p) => ["bash", "sh", "zsh", "fish", "pty"].some((term) => p.cmd.includes(term))).map((p) => ({
247
- terminal: { pid: p.pid, cmd: p.cmd },
248
- terminalId: p.pid.toString()
249
- }));
250
- } catch (error) {
251
- return [];
252
- }
253
- },
254
- destroy: async (sandbox, terminalId) => {
255
- const pid = parseInt(terminalId);
256
- if (isNaN(pid)) {
257
- throw new Error(`Invalid terminal ID: ${terminalId}. Expected numeric PID.`);
258
- }
259
- try {
260
- await sandbox.pty.kill(pid);
261
- } catch (error) {
262
- }
263
- },
264
- // Terminal instance methods
265
- write: async (sandbox, terminal, data) => {
266
- const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
267
- if (terminal.pid) {
268
- await sandbox.pty.sendInput(terminal.pid, bytes);
269
- } else {
270
- await sandbox.pty.sendInput(terminal.pid || terminal.id, bytes);
271
- }
272
- },
273
- resize: async (sandbox, terminal, cols, rows) => {
274
- const pid = terminal.pid || terminal.id;
275
- await sandbox.pty.resize(pid, { cols, rows });
276
- },
277
- kill: async (sandbox, terminal) => {
278
- const pid = terminal.pid || terminal.id;
279
- if (terminal.kill) {
280
- await terminal.kill();
281
- } else {
282
- await sandbox.pty.kill(pid);
283
- }
284
- }
285
227
  }
286
228
  }
287
229
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * E2B Provider - Factory-based Implementation\n * \n * Full-featured provider with filesystem and terminal support using the factory pattern.\n * Reduces ~400 lines of boilerplate to ~100 lines of core logic.\n */\n\nimport { Sandbox as E2BSandbox } from '@e2b/code-interpreter';\nimport { createProvider } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n TerminalCreateOptions,\n CreateSandboxOptions,\n FileEntry\n} from 'computesdk';\n\n/**\n * E2B-specific configuration options\n */\nexport interface E2BConfig {\n /** E2B API key - if not provided, will fallback to E2B_API_KEY environment variable */\n apiKey?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n\n\n/**\n * Create an E2B provider instance using the factory pattern\n */\nexport const e2b = createProvider<E2BSandbox, E2BConfig>({\n name: 'e2b',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: E2BConfig, options?: CreateSandboxOptions) => {\n // Validate API key\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.E2B_API_KEY) || '';\n\n if (!apiKey) {\n throw new Error(\n `Missing E2B API key. Provide 'apiKey' in config or set E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n\n // Validate API key format\n if (!apiKey.startsWith('e2b_')) {\n throw new Error(\n `Invalid E2B API key format. E2B API keys should start with 'e2b_'. Check your E2B_API_KEY environment variable.`\n );\n }\n\n\n const timeout = config.timeout || 300000;\n\n try {\n let sandbox: E2BSandbox;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing E2B session\n sandbox = await E2BSandbox.connect(options.sandboxId, {\n apiKey: apiKey,\n });\n sandboxId = options.sandboxId;\n } else {\n // Create new E2B session\n sandbox = await E2BSandbox.create({\n apiKey: apiKey,\n timeoutMs: timeout,\n });\n sandboxId = sandbox.sandboxId || `e2b-${Date.now()}`;\n }\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('API key')) {\n throw new Error(\n `E2B authentication failed. Please check your E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `E2B quota exceeded. Please check your usage at https://e2b.dev/`\n );\n }\n }\n throw new Error(\n `Failed to create E2B sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: E2BConfig) => {\n throw new Error(\n `E2B provider does not support listing sandboxes. E2B sandboxes are managed individually and don't have a native list API. Consider using a provider with persistent sandbox management or implement your own tracking system.`\n );\n },\n\n destroy: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n await sandbox.kill();\n } catch (error) {\n // Sandbox might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (sandbox: E2BSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n \n // Auto-detect runtime if not specified\n const effectiveRuntime = runtime || (\n // Strong Python indicators\n code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\")\n ? 'python'\n // Default to Node.js for all other cases (including ambiguous)\n : 'node'\n );\n \n // Use runCommand for consistent execution across all providers\n let result;\n \n // Use base64 encoding for both runtimes for reliability and consistency\n const encoded = Buffer.from(code).toString('base64');\n \n if (effectiveRuntime === 'python') {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | python3`);\n } else {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | node`);\n }\n\n // Check for syntax errors and throw them (similar to Vercel behavior)\n if (result.exitCode !== 0 && result.stderr) {\n // Check for common syntax error patterns\n if (result.stderr.includes('SyntaxError') || \n result.stderr.includes('invalid syntax') ||\n result.stderr.includes('Unexpected token') ||\n result.stderr.includes('Unexpected identifier')) {\n throw new Error(`Syntax error: ${result.stderr.trim()}`);\n }\n }\n\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // Handle E2B's CommandExitError - check if it contains actual error details\n if (error instanceof Error && error.message === 'exit status 1') {\n const actualStderr = (error as any)?.result?.stderr || '';\n const isSyntaxError = actualStderr.includes('SyntaxError');\n \n if (isSyntaxError) {\n // For syntax errors, throw\n const syntaxErrorLine = actualStderr.split('\\n').find((line: string) => line.includes('SyntaxError')) || 'SyntaxError: Invalid syntax in code';\n throw new Error(`Syntax error: ${syntaxErrorLine}`);\n } else {\n // For runtime errors, return a result instead of throwing\n return {\n stdout: '',\n stderr: actualStderr || 'Error: Runtime error occurred during execution',\n exitCode: 1,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n }\n \n // Re-throw syntax errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error;\n }\n throw new Error(\n `E2B execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (sandbox: E2BSandbox, command: string, args: string[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Construct full command with arguments\n const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command;\n\n // Execute command using E2B's bash execution via Python subprocess\n const execution = await sandbox.commands.run(fullCommand);\n\n return {\n stdout: execution.stdout,\n stderr: execution.stderr,\n exitCode: execution.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n },\n\n getInfo: async (sandbox: E2BSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b',\n runtime: 'python', // E2B default\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n e2bSessionId: sandbox.sandboxId\n }\n };\n },\n\n // Optional filesystem methods - E2B has full filesystem support\n filesystem: {\n readFile: async (sandbox: E2BSandbox, path: string): Promise<string> => {\n return await sandbox.files.read(path);\n },\n\n writeFile: async (sandbox: E2BSandbox, path: string, content: string): Promise<void> => {\n await sandbox.files.write(path, content);\n },\n\n mkdir: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.makeDir(path);\n },\n\n readdir: async (sandbox: E2BSandbox, path: string): Promise<FileEntry[]> => {\n const entries = await sandbox.files.list(path);\n\n return entries.map((entry: any) => ({\n name: entry.name,\n path: entry.path,\n isDirectory: Boolean(entry.isDir || entry.isDirectory),\n size: entry.size || 0,\n lastModified: new Date(entry.lastModified || Date.now())\n }));\n },\n\n exists: async (sandbox: E2BSandbox, path: string): Promise<boolean> => {\n return await sandbox.files.exists(path);\n },\n\n remove: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.remove(path);\n }\n },\n\n // Optional terminal methods - E2B has PTY terminal support\n terminal: {\n create: async (sandbox: E2BSandbox, options: TerminalCreateOptions = {}) => {\n const cols = options.cols || 80;\n const rows = options.rows || 24;\n\n // Create PTY session using E2B's pty.create\n const ptyHandle = await sandbox.pty.create({ \n cols: cols, \n rows: rows,\n onData: options.onData || (() => {\n // Default no-op if no onData provided\n })\n });\n\n // Create a wrapper object that includes the onData callback\n const terminalWrapper = {\n ...ptyHandle,\n onData: options.onData,\n onExit: options.onExit\n };\n\n return {\n terminal: terminalWrapper,\n terminalId: ptyHandle.pid.toString()\n };\n },\n\n getById: async (sandbox: E2BSandbox, terminalId: string) => {\n try {\n const pid = parseInt(terminalId);\n if (isNaN(pid)) return null;\n\n // List all running processes (includes PTY sessions)\n const processes = await sandbox.commands.list();\n \n // Find PTY process by PID\n const ptyProcess = processes.find(p => p.pid === pid);\n if (!ptyProcess) return null;\n\n return {\n terminal: { pid: ptyProcess.pid, cmd: ptyProcess.cmd },\n terminalId: terminalId\n };\n } catch (error) {\n return null;\n }\n },\n\n list: async (sandbox: E2BSandbox) => {\n try {\n // List all running processes\n const processes = await sandbox.commands.list();\n \n // Filter for PTY sessions and return raw terminal data\n return processes\n .filter(p => ['bash', 'sh', 'zsh', 'fish', 'pty'].some(term => p.cmd.includes(term)))\n .map(p => ({\n terminal: { pid: p.pid, cmd: p.cmd },\n terminalId: p.pid.toString()\n }));\n } catch (error) {\n // If listing fails, return empty array\n return [];\n }\n },\n\n destroy: async (sandbox: E2BSandbox, terminalId: string): Promise<void> => {\n const pid = parseInt(terminalId);\n if (isNaN(pid)) {\n throw new Error(`Invalid terminal ID: ${terminalId}. Expected numeric PID.`);\n }\n\n try {\n await sandbox.pty.kill(pid);\n } catch (error) {\n // Terminal might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Terminal instance methods\n write: async (sandbox: E2BSandbox, terminal: any, data: Uint8Array | string): Promise<void> => {\n const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;\n if (terminal.pid) {\n // For existing terminals, use PID\n await sandbox.pty.sendInput(terminal.pid, bytes);\n } else {\n // For new terminals, use the ptyHandle directly\n await sandbox.pty.sendInput(terminal.pid || terminal.id, bytes);\n }\n },\n\n resize: async (sandbox: E2BSandbox, terminal: any, cols: number, rows: number): Promise<void> => {\n const pid = terminal.pid || terminal.id;\n await sandbox.pty.resize(pid, { cols, rows });\n },\n\n kill: async (sandbox: E2BSandbox, terminal: any): Promise<void> => {\n const pid = terminal.pid || terminal.id;\n if (terminal.kill) {\n // For ptyHandle objects\n await terminal.kill();\n } else {\n // For process objects\n await sandbox.pty.kill(pid);\n }\n }\n }\n }\n }\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * E2B Provider - Factory-based Implementation\n * \n * Full-featured provider with filesystem support using the factory pattern.\n * Reduces ~400 lines of boilerplate to ~100 lines of core logic.\n */\n\nimport { Sandbox as E2BSandbox } from '@e2b/code-interpreter';\nimport { createProvider } from 'computesdk';\nimport type { \n ExecutionResult, \n SandboxInfo, \n Runtime,\n CreateSandboxOptions,\n FileEntry\n} from 'computesdk';\n\n/**\n * E2B-specific configuration options\n */\nexport interface E2BConfig {\n /** E2B API key - if not provided, will fallback to E2B_API_KEY environment variable */\n apiKey?: string;\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n\n\n/**\n * Create an E2B provider instance using the factory pattern\n */\nexport const e2b = createProvider<E2BSandbox, E2BConfig>({\n name: 'e2b',\n methods: {\n sandbox: {\n // Collection operations (map to compute.sandbox.*)\n create: async (config: E2BConfig, options?: CreateSandboxOptions) => {\n // Validate API key\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.E2B_API_KEY) || '';\n\n if (!apiKey) {\n throw new Error(\n `Missing E2B API key. Provide 'apiKey' in config or set E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n\n // Validate API key format\n if (!apiKey.startsWith('e2b_')) {\n throw new Error(\n `Invalid E2B API key format. E2B API keys should start with 'e2b_'. Check your E2B_API_KEY environment variable.`\n );\n }\n\n\n const timeout = config.timeout || 300000;\n\n try {\n let sandbox: E2BSandbox;\n let sandboxId: string;\n\n if (options?.sandboxId) {\n // Reconnect to existing E2B session\n sandbox = await E2BSandbox.connect(options.sandboxId, {\n apiKey: apiKey,\n domain: options.domain,\n });\n sandboxId = options.sandboxId;\n } else {\n // Create new E2B session\n if (options?.templateId) {\n sandbox = await E2BSandbox.create(options.templateId, {\n apiKey: apiKey,\n timeoutMs: timeout,\n domain: options.domain,\n });\n } else {\n sandbox = await E2BSandbox.create({\n apiKey: apiKey,\n timeoutMs: timeout,\n domain: options?.domain,\n });\n }\n sandboxId = sandbox.sandboxId || `e2b-${Date.now()}`;\n }\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('API key')) {\n throw new Error(\n `E2B authentication failed. Please check your E2B_API_KEY environment variable. Get your API key from https://e2b.dev/`\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(\n `E2B quota exceeded. Please check your usage at https://e2b.dev/`\n );\n }\n }\n throw new Error(\n `Failed to create E2B sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n\n return {\n sandbox,\n sandboxId\n };\n } catch (error) {\n // Sandbox doesn't exist or can't be accessed\n return null;\n }\n },\n\n list: async (_config: E2BConfig) => {\n throw new Error(\n `E2B provider does not support listing sandboxes. E2B sandboxes are managed individually and don't have a native list API. Consider using a provider with persistent sandbox management or implement your own tracking system.`\n );\n },\n\n destroy: async (config: E2BConfig, sandboxId: string) => {\n const apiKey = config.apiKey || process.env.E2B_API_KEY!;\n\n try {\n const sandbox = await E2BSandbox.connect(sandboxId, {\n apiKey: apiKey,\n });\n await sandbox.kill();\n } catch (error) {\n // Sandbox might already be destroyed or doesn't exist\n // This is acceptable for destroy operations\n }\n },\n\n // Instance operations (map to individual Sandbox methods)\n runCode: async (sandbox: E2BSandbox, code: string, runtime?: Runtime): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n \n // Auto-detect runtime if not specified\n const effectiveRuntime = runtime || (\n // Strong Python indicators\n code.includes('print(') || \n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\")\n ? 'python'\n // Default to Node.js for all other cases (including ambiguous)\n : 'node'\n );\n \n // Use runCommand for consistent execution across all providers\n let result;\n \n // Use base64 encoding for both runtimes for reliability and consistency\n const encoded = Buffer.from(code).toString('base64');\n \n if (effectiveRuntime === 'python') {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | python3`);\n } else {\n result = await sandbox.commands.run(`echo \"${encoded}\" | base64 -d | node`);\n }\n\n // Check for syntax errors and throw them (similar to Vercel behavior)\n if (result.exitCode !== 0 && result.stderr) {\n // Check for common syntax error patterns\n if (result.stderr.includes('SyntaxError') || \n result.stderr.includes('invalid syntax') ||\n result.stderr.includes('Unexpected token') ||\n result.stderr.includes('Unexpected identifier')) {\n throw new Error(`Syntax error: ${result.stderr.trim()}`);\n }\n }\n\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // Handle E2B's CommandExitError - check if it contains actual error details\n if (error instanceof Error && error.message === 'exit status 1') {\n const actualStderr = (error as any)?.result?.stderr || '';\n const isSyntaxError = actualStderr.includes('SyntaxError');\n \n if (isSyntaxError) {\n // For syntax errors, throw\n const syntaxErrorLine = actualStderr.split('\\n').find((line: string) => line.includes('SyntaxError')) || 'SyntaxError: Invalid syntax in code';\n throw new Error(`Syntax error: ${syntaxErrorLine}`);\n } else {\n // For runtime errors, return a result instead of throwing\n return {\n stdout: '',\n stderr: actualStderr || 'Error: Runtime error occurred during execution',\n exitCode: 1,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n }\n \n // Re-throw syntax errors\n if (error instanceof Error && error.message.includes('Syntax error')) {\n throw error;\n }\n throw new Error(\n `E2B execution failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n runCommand: async (sandbox: E2BSandbox, command: string, args: string[] = []): Promise<ExecutionResult> => {\n const startTime = Date.now();\n\n try {\n // Construct full command with arguments\n const fullCommand = args.length > 0 ? `${command} ${args.join(' ')}` : command;\n\n // Execute command using E2B's bash execution via Python subprocess\n const execution = await sandbox.commands.run(fullCommand);\n\n return {\n stdout: execution.stdout,\n stderr: execution.stderr,\n exitCode: execution.exitCode,\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n } catch (error) {\n // For command failures, return error info instead of throwing\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127, // Command not found exit code\n executionTime: Date.now() - startTime,\n sandboxId: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b'\n };\n }\n },\n\n getInfo: async (sandbox: E2BSandbox): Promise<SandboxInfo> => {\n return {\n id: sandbox.sandboxId || 'e2b-unknown',\n provider: 'e2b',\n runtime: 'python', // E2B default\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n e2bSessionId: sandbox.sandboxId\n }\n };\n },\n\n getUrl: async (sandbox: E2BSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n // Use E2B's built-in getHost method for accurate host information\n const host = sandbox.getHost(options.port);\n const protocol = options.protocol || 'https';\n return `${protocol}://${host}`;\n } catch (error) {\n throw new Error(\n `Failed to get E2B host for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n // Optional filesystem methods - E2B has full filesystem support\n filesystem: {\n readFile: async (sandbox: E2BSandbox, path: string): Promise<string> => {\n return await sandbox.files.read(path);\n },\n\n writeFile: async (sandbox: E2BSandbox, path: string, content: string): Promise<void> => {\n await sandbox.files.write(path, content);\n },\n\n mkdir: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.makeDir(path);\n },\n\n readdir: async (sandbox: E2BSandbox, path: string): Promise<FileEntry[]> => {\n const entries = await sandbox.files.list(path);\n\n return entries.map((entry: any) => ({\n name: entry.name,\n path: entry.path,\n isDirectory: Boolean(entry.isDir || entry.isDirectory),\n size: entry.size || 0,\n lastModified: new Date(entry.lastModified || Date.now())\n }));\n },\n\n exists: async (sandbox: E2BSandbox, path: string): Promise<boolean> => {\n return await sandbox.files.exists(path);\n },\n\n remove: async (sandbox: E2BSandbox, path: string): Promise<void> => {\n await sandbox.files.remove(path);\n }\n },\n\n\n }\n }\n});\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/e2b",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "E2B provider for ComputeSDK",
5
5
  "author": "Garrison",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "@e2b/code-interpreter": "^1.5.1",
22
- "computesdk": "1.1.0"
22
+ "computesdk": "1.2.0"
23
23
  },
24
24
  "keywords": [
25
25
  "e2b",
@@ -46,7 +46,7 @@
46
46
  "tsup": "^8.0.0",
47
47
  "typescript": "^5.0.0",
48
48
  "vitest": "^1.0.0",
49
- "@computesdk/test-utils": "1.1.0"
49
+ "@computesdk/test-utils": "1.2.0"
50
50
  },
51
51
  "scripts": {
52
52
  "build": "tsup",