@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 +216 -354
- package/dist/index.js +26 -84
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +26 -84
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
# @computesdk/e2b
|
|
2
2
|
|
|
3
|
-
E2B provider for ComputeSDK - Execute
|
|
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
|
-
##
|
|
20
|
+
## Usage
|
|
30
21
|
|
|
31
|
-
###
|
|
22
|
+
### With ComputeSDK
|
|
32
23
|
|
|
33
24
|
```typescript
|
|
25
|
+
import { compute } from 'computesdk';
|
|
34
26
|
import { e2b } from '@computesdk/e2b';
|
|
35
27
|
|
|
36
|
-
|
|
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.
|
|
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
|
-
|
|
55
|
+
// Clean up
|
|
56
|
+
await compute.sandbox.destroy(sandbox.sandboxId);
|
|
58
57
|
```
|
|
59
58
|
|
|
60
|
-
###
|
|
59
|
+
### Direct Usage
|
|
61
60
|
|
|
62
61
|
```typescript
|
|
63
|
-
import {
|
|
62
|
+
import { e2b } from '@computesdk/e2b';
|
|
64
63
|
|
|
65
|
-
//
|
|
66
|
-
const
|
|
64
|
+
// Create provider
|
|
65
|
+
const provider = e2b({
|
|
66
|
+
apiKey: 'e2b_your_api_key',
|
|
67
|
+
timeout: 600000 // 10 minutes
|
|
68
|
+
});
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
// Use with compute singleton
|
|
71
|
+
const sandbox = await compute.sandbox.create({ provider });
|
|
70
72
|
```
|
|
71
73
|
|
|
72
|
-
##
|
|
74
|
+
## Configuration
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
### Environment Variables
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
```bash
|
|
79
|
+
export E2B_API_KEY=e2b_your_api_key_here
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Configuration Options
|
|
77
83
|
|
|
78
84
|
```typescript
|
|
79
|
-
|
|
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
|
-
|
|
95
|
+
## Features
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
//
|
|
98
|
-
await sandbox.
|
|
135
|
+
// Run scripts
|
|
136
|
+
const result = await sandbox.runCommand('python', ['script.py']);
|
|
99
137
|
```
|
|
100
138
|
|
|
101
|
-
###
|
|
139
|
+
### Filesystem Operations
|
|
102
140
|
|
|
103
141
|
```typescript
|
|
104
|
-
//
|
|
105
|
-
await sandbox.filesystem.
|
|
106
|
-
|
|
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
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
//
|
|
115
|
-
await
|
|
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
|
-
###
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
const sandbox = e2b();
|
|
327
|
+
const sandbox = await compute.sandbox.create({});
|
|
196
328
|
|
|
197
|
-
// Create
|
|
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
|
|
248
|
-
await
|
|
249
|
-
await
|
|
250
|
-
await
|
|
251
|
-
await
|
|
252
|
-
await
|
|
253
|
-
|
|
254
|
-
// Wait
|
|
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
|
|
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
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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
|
|
430
|
-
const result = await sandbox.
|
|
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
|
|
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
|
|
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. **
|
|
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
|
-
- **
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
}
|
package/dist/index.mjs.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":[]}
|
|
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.
|
|
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.
|
|
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.
|
|
49
|
+
"@computesdk/test-utils": "1.2.0"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsup",
|