computesdk 1.0.1 → 1.1.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/LICENSE +21 -0
- package/README.md +746 -0
- package/dist/index.d.mts +416 -340
- package/dist/index.d.ts +416 -340
- package/dist/index.js +910 -450
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +906 -436
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -34
package/README.md
ADDED
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
# ComputeSDK
|
|
2
|
+
|
|
3
|
+
A unified abstraction layer for executing code in secure, isolated sandboxed environments across multiple cloud providers.
|
|
4
|
+
|
|
5
|
+
Similar to how Vercel's AI SDK abstracts different LLM providers, ComputeSDK abstracts different compute sandbox providers into a single, consistent TypeScript interface.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🚀 **Multi-provider support** - E2B, Vercel, Daytona
|
|
10
|
+
- 📁 **Filesystem operations** - Read, write, create directories across providers
|
|
11
|
+
- 🖥️ **Terminal support** - Interactive PTY terminals (E2B)
|
|
12
|
+
- ⚡ **Command execution** - Run shell commands directly
|
|
13
|
+
- 🔄 **Auto-detection** - Automatically selects providers based on environment variables
|
|
14
|
+
- 🛡️ **Type-safe** - Full TypeScript support with comprehensive error handling
|
|
15
|
+
- 📦 **Modular** - Install only the providers you need
|
|
16
|
+
- 🔧 **Extensible** - Easy to add custom providers
|
|
17
|
+
|
|
18
|
+
## Supported Providers
|
|
19
|
+
|
|
20
|
+
| Provider | Code Execution | Filesystem | Terminal | Use Cases |
|
|
21
|
+
|----------|----------------|------------|----------|-----------|
|
|
22
|
+
| **E2B** | Python | ✅ Full | ✅ PTY | Data science, AI/ML, interactive development |
|
|
23
|
+
| **Vercel** | Node.js, Python | ✅ Full | ❌ | Web apps, APIs, serverless functions |
|
|
24
|
+
| **Daytona** | Python, Node.js | ✅ Full | ❌ | Development workspaces, custom environments |
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Core SDK
|
|
30
|
+
npm install computesdk
|
|
31
|
+
|
|
32
|
+
# Provider packages (install only what you need)
|
|
33
|
+
npm install @computesdk/e2b # E2B provider
|
|
34
|
+
npm install @computesdk/vercel # Vercel provider
|
|
35
|
+
npm install @computesdk/daytona # Daytona provider
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
### Auto-detection (Recommended)
|
|
41
|
+
|
|
42
|
+
ComputeSDK automatically detects available providers based on environment variables:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { ComputeSDK } from 'computesdk';
|
|
46
|
+
|
|
47
|
+
// Automatically detects and uses the first available provider
|
|
48
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
49
|
+
|
|
50
|
+
const result = await sandbox.execute('print("Hello World!")');
|
|
51
|
+
console.log(result.stdout); // "Hello World!"
|
|
52
|
+
|
|
53
|
+
await sandbox.kill();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Provider-specific Usage
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { executeSandbox } from 'computesdk';
|
|
60
|
+
import { e2b } from '@computesdk/e2b';
|
|
61
|
+
|
|
62
|
+
// Execute with specific provider
|
|
63
|
+
const result = await executeSandbox({
|
|
64
|
+
sandbox: e2b(),
|
|
65
|
+
code: 'print("Hello from E2B!")',
|
|
66
|
+
runtime: 'python'
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
console.log(result.stdout);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Advanced Usage with Type Safety
|
|
73
|
+
|
|
74
|
+
ComputeSDK provides rich TypeScript interfaces for different provider capabilities:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { ComputeSDK, FilesystemComputeSandbox, TerminalComputeSandbox } from 'computesdk';
|
|
78
|
+
|
|
79
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
80
|
+
|
|
81
|
+
// Check provider capabilities at runtime
|
|
82
|
+
if ('filesystem' in sandbox) {
|
|
83
|
+
const fsSandbox = sandbox as FilesystemComputeSandbox;
|
|
84
|
+
|
|
85
|
+
// Use filesystem operations
|
|
86
|
+
await fsSandbox.filesystem.writeFile('/tmp/data.txt', 'Hello World!');
|
|
87
|
+
const content = await fsSandbox.filesystem.readFile('/tmp/data.txt');
|
|
88
|
+
console.log(content); // "Hello World!"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if ('terminal' in sandbox) {
|
|
92
|
+
const termSandbox = sandbox as TerminalComputeSandbox;
|
|
93
|
+
|
|
94
|
+
// Create interactive terminal (E2B only)
|
|
95
|
+
const terminal = await termSandbox.terminal.create({
|
|
96
|
+
command: 'bash',
|
|
97
|
+
cols: 80,
|
|
98
|
+
rows: 24
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await terminal.write('echo "Interactive terminal!"\n');
|
|
102
|
+
await terminal.kill();
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Environment Setup
|
|
107
|
+
|
|
108
|
+
Each provider requires specific environment variables for authentication:
|
|
109
|
+
|
|
110
|
+
### E2B (Full Features)
|
|
111
|
+
```bash
|
|
112
|
+
export E2B_API_KEY=e2b_your_api_key_here
|
|
113
|
+
```
|
|
114
|
+
Get your API key from [e2b.dev](https://e2b.dev/)
|
|
115
|
+
|
|
116
|
+
### Vercel (Filesystem + Code Execution)
|
|
117
|
+
```bash
|
|
118
|
+
export VERCEL_TOKEN=your_vercel_token_here
|
|
119
|
+
export VERCEL_TEAM_ID=your_team_id_here
|
|
120
|
+
export VERCEL_PROJECT_ID=your_project_id_here
|
|
121
|
+
```
|
|
122
|
+
Get your token from [Vercel Account Tokens](https://vercel.com/account/tokens)
|
|
123
|
+
|
|
124
|
+
### Daytona (Development Workspaces)
|
|
125
|
+
```bash
|
|
126
|
+
export DAYTONA_API_KEY=your_daytona_api_key_here
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
## API Reference
|
|
132
|
+
|
|
133
|
+
### Core SDK
|
|
134
|
+
|
|
135
|
+
#### `ComputeSDK.createSandbox(config?)`
|
|
136
|
+
|
|
137
|
+
Creates a sandbox using auto-detection or specified configuration.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Auto-detection
|
|
141
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
142
|
+
|
|
143
|
+
// With configuration
|
|
144
|
+
const sandbox = ComputeSDK.createSandbox({
|
|
145
|
+
provider: 'e2b',
|
|
146
|
+
runtime: 'python',
|
|
147
|
+
timeout: 600000 // 10 minutes
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Parameters:**
|
|
152
|
+
- `config` (optional): Sandbox configuration object
|
|
153
|
+
|
|
154
|
+
**Returns:** `ComputeSandbox` - The appropriate sandbox type based on provider capabilities
|
|
155
|
+
|
|
156
|
+
#### `ComputeSDK.detectProviders()`
|
|
157
|
+
|
|
158
|
+
Detects available providers based on environment variables.
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const providers = ComputeSDK.detectProviders();
|
|
162
|
+
console.log('Available providers:', providers); // ['e2b', 'vercel']
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Returns:** `ProviderType[]` - Array of available provider names
|
|
166
|
+
|
|
167
|
+
### Utility Functions
|
|
168
|
+
|
|
169
|
+
#### `executeSandbox(params)`
|
|
170
|
+
|
|
171
|
+
Utility function for one-off code execution.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { executeSandbox } from 'computesdk';
|
|
175
|
+
import { vercel } from '@computesdk/vercel';
|
|
176
|
+
|
|
177
|
+
const result = await executeSandbox({
|
|
178
|
+
sandbox: vercel({ runtime: 'node' }),
|
|
179
|
+
code: 'console.log("Hello from Node.js!");',
|
|
180
|
+
runtime: 'node'
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Parameters:**
|
|
185
|
+
```typescript
|
|
186
|
+
interface ExecuteSandboxParams {
|
|
187
|
+
sandbox: ComputeSandbox;
|
|
188
|
+
code: string;
|
|
189
|
+
runtime?: Runtime;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Sandbox Interfaces
|
|
194
|
+
|
|
195
|
+
ComputeSDK provides a rich type system for different provider capabilities:
|
|
196
|
+
|
|
197
|
+
#### `BaseComputeSandbox`
|
|
198
|
+
|
|
199
|
+
Basic code execution capabilities (all providers support this):
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
interface BaseComputeSandbox {
|
|
203
|
+
provider: string;
|
|
204
|
+
sandboxId: string;
|
|
205
|
+
|
|
206
|
+
execute(code: string, runtime?: Runtime): Promise<ExecutionResult>;
|
|
207
|
+
runCode(code: string, runtime?: Runtime): Promise<ExecutionResult>;
|
|
208
|
+
runCommand(command: string, args?: string[]): Promise<ExecutionResult>;
|
|
209
|
+
kill(): Promise<void>;
|
|
210
|
+
getInfo(): Promise<SandboxInfo>;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### `FilesystemComputeSandbox`
|
|
215
|
+
|
|
216
|
+
Extends base capabilities with filesystem operations (E2B, Vercel, Daytona):
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
interface FilesystemComputeSandbox extends BaseComputeSandbox {
|
|
220
|
+
readonly filesystem: SandboxFileSystem;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
interface SandboxFileSystem {
|
|
224
|
+
readFile(path: string): Promise<string>;
|
|
225
|
+
writeFile(path: string, content: string): Promise<void>;
|
|
226
|
+
mkdir(path: string): Promise<void>;
|
|
227
|
+
readdir(path: string): Promise<FileEntry[]>;
|
|
228
|
+
exists(path: string): Promise<boolean>;
|
|
229
|
+
remove(path: string): Promise<void>;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### `TerminalComputeSandbox`
|
|
234
|
+
|
|
235
|
+
Extends base capabilities with terminal operations (E2B only):
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
interface TerminalComputeSandbox extends BaseComputeSandbox {
|
|
239
|
+
readonly terminal: SandboxTerminal;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
interface SandboxTerminal {
|
|
243
|
+
create(options?: TerminalCreateOptions): Promise<InteractiveTerminalSession>;
|
|
244
|
+
list(): Promise<InteractiveTerminalSession[]>;
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### `FullComputeSandbox`
|
|
249
|
+
|
|
250
|
+
Full capabilities including filesystem and terminal (E2B only):
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
interface FullComputeSandbox extends FilesystemComputeSandbox, TerminalComputeSandbox {}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Data Types
|
|
257
|
+
|
|
258
|
+
#### `ExecutionResult`
|
|
259
|
+
|
|
260
|
+
Result object returned by all execution methods:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
interface ExecutionResult {
|
|
264
|
+
stdout: string;
|
|
265
|
+
stderr: string;
|
|
266
|
+
exitCode: number;
|
|
267
|
+
executionTime: number;
|
|
268
|
+
sandboxId: string;
|
|
269
|
+
provider: string;
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### `SandboxInfo`
|
|
274
|
+
|
|
275
|
+
Information about a sandbox instance:
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
interface SandboxInfo {
|
|
279
|
+
id: string;
|
|
280
|
+
provider: string;
|
|
281
|
+
runtime: Runtime;
|
|
282
|
+
status: 'running' | 'stopped' | 'error';
|
|
283
|
+
createdAt: Date;
|
|
284
|
+
timeout: number;
|
|
285
|
+
metadata?: Record<string, any>;
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### `FileEntry`
|
|
290
|
+
|
|
291
|
+
File system entry information:
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
interface FileEntry {
|
|
295
|
+
name: string;
|
|
296
|
+
path: string;
|
|
297
|
+
isDirectory: boolean;
|
|
298
|
+
size: number;
|
|
299
|
+
lastModified: Date;
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Examples
|
|
304
|
+
|
|
305
|
+
### Cross-Provider Data Processing
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { ComputeSDK, FilesystemComputeSandbox } from 'computesdk';
|
|
309
|
+
|
|
310
|
+
async function processData() {
|
|
311
|
+
// Auto-detect best available provider
|
|
312
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
313
|
+
|
|
314
|
+
if ('filesystem' in sandbox) {
|
|
315
|
+
const fsSandbox = sandbox as FilesystemComputeSandbox;
|
|
316
|
+
|
|
317
|
+
// Create project structure
|
|
318
|
+
await fsSandbox.filesystem.mkdir('/project/data');
|
|
319
|
+
await fsSandbox.filesystem.mkdir('/project/output');
|
|
320
|
+
|
|
321
|
+
// Write input data
|
|
322
|
+
const data = JSON.stringify([
|
|
323
|
+
{ name: 'Alice', sales: 1000 },
|
|
324
|
+
{ name: 'Bob', sales: 1500 },
|
|
325
|
+
{ name: 'Charlie', sales: 800 }
|
|
326
|
+
]);
|
|
327
|
+
|
|
328
|
+
await fsSandbox.filesystem.writeFile('/project/data/sales.json', data);
|
|
329
|
+
|
|
330
|
+
// Process data based on provider
|
|
331
|
+
let code: string;
|
|
332
|
+
if (sandbox.provider === 'e2b') {
|
|
333
|
+
// Python processing for E2B
|
|
334
|
+
code = `
|
|
335
|
+
import json
|
|
336
|
+
import pandas as pd
|
|
337
|
+
|
|
338
|
+
# Read data
|
|
339
|
+
with open('/project/data/sales.json', 'r') as f:
|
|
340
|
+
data = json.load(f)
|
|
341
|
+
|
|
342
|
+
# Process with pandas
|
|
343
|
+
df = pd.DataFrame(data)
|
|
344
|
+
total_sales = df['sales'].sum()
|
|
345
|
+
avg_sales = df['sales'].mean()
|
|
346
|
+
|
|
347
|
+
# Write results
|
|
348
|
+
results = {
|
|
349
|
+
'total_sales': total_sales,
|
|
350
|
+
'average_sales': avg_sales,
|
|
351
|
+
'top_performer': df.loc[df['sales'].idxmax(), 'name']
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
with open('/project/output/results.json', 'w') as f:
|
|
355
|
+
json.dump(results, f, indent=2)
|
|
356
|
+
|
|
357
|
+
print(f"Total Sales: ${total_sales}")
|
|
358
|
+
print(f"Average Sales: ${avg_sales:.2f}")
|
|
359
|
+
print(f"Top Performer: {results['top_performer']}")
|
|
360
|
+
`;
|
|
361
|
+
} else {
|
|
362
|
+
// JavaScript processing for Vercel/Daytona
|
|
363
|
+
code = `
|
|
364
|
+
const fs = require('fs');
|
|
365
|
+
|
|
366
|
+
// Read data
|
|
367
|
+
const data = JSON.parse(fs.readFileSync('/project/data/sales.json', 'utf8'));
|
|
368
|
+
|
|
369
|
+
// Process data
|
|
370
|
+
const totalSales = data.reduce((sum, person) => sum + person.sales, 0);
|
|
371
|
+
const avgSales = totalSales / data.length;
|
|
372
|
+
const topPerformer = data.reduce((top, person) =>
|
|
373
|
+
person.sales > top.sales ? person : top
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
// Write results
|
|
377
|
+
const results = {
|
|
378
|
+
total_sales: totalSales,
|
|
379
|
+
average_sales: avgSales,
|
|
380
|
+
top_performer: topPerformer.name
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
fs.writeFileSync('/project/output/results.json', JSON.stringify(results, null, 2));
|
|
384
|
+
|
|
385
|
+
console.log(\`Total Sales: $\${totalSales}\`);
|
|
386
|
+
console.log(\`Average Sales: $\${avgSales.toFixed(2)}\`);
|
|
387
|
+
console.log(\`Top Performer: \${results.top_performer}\`);
|
|
388
|
+
`;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Execute processing
|
|
392
|
+
const result = await fsSandbox.execute(code);
|
|
393
|
+
console.log('Processing Output:', result.stdout);
|
|
394
|
+
|
|
395
|
+
// Read results
|
|
396
|
+
const results = await fsSandbox.filesystem.readFile('/project/output/results.json');
|
|
397
|
+
console.log('Results:', JSON.parse(results));
|
|
398
|
+
|
|
399
|
+
// List generated files
|
|
400
|
+
const outputFiles = await fsSandbox.filesystem.readdir('/project/output');
|
|
401
|
+
console.log('Generated files:', outputFiles.map(f => f.name));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
await sandbox.kill();
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
processData().catch(console.error);
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Interactive Development with E2B
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
import { e2b } from '@computesdk/e2b';
|
|
414
|
+
import { TerminalComputeSandbox, FilesystemComputeSandbox } from 'computesdk';
|
|
415
|
+
|
|
416
|
+
async function interactiveDevelopment() {
|
|
417
|
+
const sandbox = e2b() as TerminalComputeSandbox & FilesystemComputeSandbox;
|
|
418
|
+
|
|
419
|
+
// Set up development environment
|
|
420
|
+
await sandbox.filesystem.mkdir('/workspace');
|
|
421
|
+
await sandbox.filesystem.writeFile('/workspace/requirements.txt',
|
|
422
|
+
'pandas\nnumpy\nmatplotlib\nscikit-learn'
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// Create interactive terminal
|
|
426
|
+
const terminal = await sandbox.terminal.create({
|
|
427
|
+
command: 'bash',
|
|
428
|
+
cols: 120,
|
|
429
|
+
rows: 30
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Set up output handler
|
|
433
|
+
terminal.onData = (data: Uint8Array) => {
|
|
434
|
+
const output = new TextDecoder().decode(data);
|
|
435
|
+
console.log('Terminal:', output);
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// Install dependencies
|
|
439
|
+
await terminal.write('cd /workspace\n');
|
|
440
|
+
await terminal.write('pip install -r requirements.txt\n');
|
|
441
|
+
|
|
442
|
+
// Start interactive Python session
|
|
443
|
+
await terminal.write('python3\n');
|
|
444
|
+
await terminal.write('import pandas as pd\n');
|
|
445
|
+
await terminal.write('import numpy as np\n');
|
|
446
|
+
await terminal.write('print("Development environment ready!")\n');
|
|
447
|
+
|
|
448
|
+
// Simulate interactive development
|
|
449
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
450
|
+
|
|
451
|
+
// Clean up
|
|
452
|
+
await terminal.kill();
|
|
453
|
+
await sandbox.kill();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
interactiveDevelopment().catch(console.error);
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Multi-Provider Comparison
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
import { executeSandbox } from 'computesdk';
|
|
463
|
+
import { e2b } from '@computesdk/e2b';
|
|
464
|
+
import { vercel } from '@computesdk/vercel';
|
|
465
|
+
import { daytona } from '@computesdk/daytona';
|
|
466
|
+
|
|
467
|
+
async function compareProviders() {
|
|
468
|
+
const testCode = `
|
|
469
|
+
import json
|
|
470
|
+
import time
|
|
471
|
+
start = time.time()
|
|
472
|
+
|
|
473
|
+
# Simple computation
|
|
474
|
+
result = sum(range(1000))
|
|
475
|
+
elapsed = time.time() - start
|
|
476
|
+
|
|
477
|
+
output = {
|
|
478
|
+
"result": result,
|
|
479
|
+
"elapsed_ms": round(elapsed * 1000, 2),
|
|
480
|
+
"provider": "will_be_set"
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
print(json.dumps(output))
|
|
484
|
+
`;
|
|
485
|
+
|
|
486
|
+
const providers = [
|
|
487
|
+
{ name: 'E2B', factory: () => e2b() },
|
|
488
|
+
{ name: 'Vercel', factory: () => vercel({ runtime: 'python' }) },
|
|
489
|
+
{ name: 'Daytona', factory: () => daytona({ runtime: 'python' }) },
|
|
490
|
+
];
|
|
491
|
+
|
|
492
|
+
console.log('Performance Comparison:');
|
|
493
|
+
console.log('='.repeat(50));
|
|
494
|
+
|
|
495
|
+
for (const { name, factory } of providers) {
|
|
496
|
+
try {
|
|
497
|
+
const start = Date.now();
|
|
498
|
+
const result = await executeSandbox({
|
|
499
|
+
sandbox: factory(),
|
|
500
|
+
code: testCode,
|
|
501
|
+
runtime: 'python'
|
|
502
|
+
});
|
|
503
|
+
const totalTime = Date.now() - start;
|
|
504
|
+
|
|
505
|
+
const output = JSON.parse(result.stdout);
|
|
506
|
+
console.log(`${name}:`);
|
|
507
|
+
console.log(` Computation: ${output.result}`);
|
|
508
|
+
console.log(` Execution time: ${output.elapsed_ms}ms`);
|
|
509
|
+
console.log(` Total time: ${totalTime}ms`);
|
|
510
|
+
console.log(` Provider overhead: ${totalTime - output.elapsed_ms}ms`);
|
|
511
|
+
console.log();
|
|
512
|
+
|
|
513
|
+
} catch (error) {
|
|
514
|
+
console.log(`${name}: Failed - ${error.message}`);
|
|
515
|
+
console.log();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
compareProviders().catch(console.error);
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
## Error Handling
|
|
524
|
+
|
|
525
|
+
ComputeSDK provides comprehensive error handling with specific error types:
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
import { ComputeSDK } from 'computesdk';
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
532
|
+
const result = await sandbox.execute('invalid python code');
|
|
533
|
+
} catch (error) {
|
|
534
|
+
if (error.message.includes('Missing') && error.message.includes('API key')) {
|
|
535
|
+
console.error('Authentication Error: Check your environment variables');
|
|
536
|
+
console.error('Required: E2B_API_KEY, VERCEL_TOKEN, etc.');
|
|
537
|
+
} else if (error.message.includes('timeout')) {
|
|
538
|
+
console.error('Timeout Error: Execution took too long');
|
|
539
|
+
} else if (error.message.includes('quota') || error.message.includes('limit')) {
|
|
540
|
+
console.error('Quota Error: API usage limits exceeded');
|
|
541
|
+
} else if (error.message.includes('not installed')) {
|
|
542
|
+
console.error('Configuration Error: Provider package not installed');
|
|
543
|
+
console.error('Run: npm install @computesdk/[provider-name]');
|
|
544
|
+
} else {
|
|
545
|
+
console.error('Execution Error:', error.message);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
## Provider-Specific Features
|
|
551
|
+
|
|
552
|
+
### E2B - Full Development Environment
|
|
553
|
+
|
|
554
|
+
E2B provides the richest feature set with full filesystem and terminal support:
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
import { e2b } from '@computesdk/e2b';
|
|
558
|
+
|
|
559
|
+
const sandbox = e2b();
|
|
560
|
+
|
|
561
|
+
// Full Python environment with data science libraries
|
|
562
|
+
const result = await sandbox.execute(`
|
|
563
|
+
import pandas as pd
|
|
564
|
+
import matplotlib.pyplot as plt
|
|
565
|
+
import numpy as np
|
|
566
|
+
|
|
567
|
+
# Create and visualize data
|
|
568
|
+
data = np.random.randn(1000)
|
|
569
|
+
plt.hist(data, bins=50)
|
|
570
|
+
plt.savefig('/tmp/histogram.png')
|
|
571
|
+
print("Histogram saved!")
|
|
572
|
+
`);
|
|
573
|
+
|
|
574
|
+
// Check if file was created
|
|
575
|
+
const exists = await sandbox.filesystem.exists('/tmp/histogram.png');
|
|
576
|
+
console.log('Histogram created:', exists);
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Vercel - Scalable Serverless Execution
|
|
580
|
+
|
|
581
|
+
Vercel provides reliable execution with filesystem support:
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
import { vercel } from '@computesdk/vercel';
|
|
585
|
+
|
|
586
|
+
const sandbox = vercel({ runtime: 'node' });
|
|
587
|
+
|
|
588
|
+
// Process data with Node.js
|
|
589
|
+
const result = await sandbox.execute(`
|
|
590
|
+
const fs = require('fs');
|
|
591
|
+
const path = require('path');
|
|
592
|
+
|
|
593
|
+
// Create API simulation
|
|
594
|
+
const apiData = {
|
|
595
|
+
users: 1000,
|
|
596
|
+
active: 750,
|
|
597
|
+
revenue: 50000
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// Write to filesystem
|
|
601
|
+
fs.writeFileSync('/tmp/api-data.json', JSON.stringify(apiData, null, 2));
|
|
602
|
+
|
|
603
|
+
console.log('API data processed and saved');
|
|
604
|
+
console.log('Active users:', apiData.active);
|
|
605
|
+
`);
|
|
606
|
+
|
|
607
|
+
// Read the generated data
|
|
608
|
+
const data = await sandbox.filesystem.readFile('/tmp/api-data.json');
|
|
609
|
+
console.log('Generated data:', JSON.parse(data));
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### Daytona - Development Workspaces
|
|
613
|
+
|
|
614
|
+
Daytona provides development workspace environments with full filesystem support:
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
import { daytona } from '@computesdk/daytona';
|
|
618
|
+
|
|
619
|
+
const sandbox = daytona({ runtime: 'python' });
|
|
620
|
+
|
|
621
|
+
// Execute Python code in workspace
|
|
622
|
+
const result = await sandbox.execute(`
|
|
623
|
+
import json
|
|
624
|
+
import os
|
|
625
|
+
|
|
626
|
+
# Create project structure
|
|
627
|
+
os.makedirs('/workspace/src', exist_ok=True)
|
|
628
|
+
os.makedirs('/workspace/tests', exist_ok=True)
|
|
629
|
+
|
|
630
|
+
# Write project files
|
|
631
|
+
with open('/workspace/src/main.py', 'w') as f:
|
|
632
|
+
f.write('def hello():\\n return "Hello from Daytona!"\\n')
|
|
633
|
+
|
|
634
|
+
with open('/workspace/tests/test_main.py', 'w') as f:
|
|
635
|
+
f.write('from src.main import hello\\n\\ndef test_hello():\\n assert hello() == "Hello from Daytona!"\\n')
|
|
636
|
+
|
|
637
|
+
print("Project structure created!")
|
|
638
|
+
print("Files:", os.listdir('/workspace'))
|
|
639
|
+
`);
|
|
640
|
+
|
|
641
|
+
// Check created files
|
|
642
|
+
const files = await sandbox.filesystem.readdir('/workspace');
|
|
643
|
+
console.log('Workspace files:', files.map(f => f.name));
|
|
644
|
+
|
|
645
|
+
// Read project file
|
|
646
|
+
const mainPy = await sandbox.filesystem.readFile('/workspace/src/main.py');
|
|
647
|
+
console.log('main.py content:', mainPy);
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
## Best Practices
|
|
653
|
+
|
|
654
|
+
### 1. Provider Selection
|
|
655
|
+
|
|
656
|
+
Choose providers based on your use case:
|
|
657
|
+
|
|
658
|
+
- **E2B**: Data science, ML, interactive development, full Python environment
|
|
659
|
+
- **Vercel**: Web applications, APIs, serverless functions, long-running tasks
|
|
660
|
+
- **Daytona**: Development workspaces, custom environments, team collaboration
|
|
661
|
+
|
|
662
|
+
### 2. Resource Management
|
|
663
|
+
|
|
664
|
+
Always clean up resources:
|
|
665
|
+
|
|
666
|
+
```typescript
|
|
667
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
668
|
+
try {
|
|
669
|
+
// Your code here
|
|
670
|
+
const result = await sandbox.execute('print("Hello")');
|
|
671
|
+
} finally {
|
|
672
|
+
// Always clean up
|
|
673
|
+
await sandbox.kill();
|
|
674
|
+
}
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### 3. Error Handling
|
|
678
|
+
|
|
679
|
+
Implement comprehensive error handling:
|
|
680
|
+
|
|
681
|
+
```typescript
|
|
682
|
+
async function robustExecution(code: string) {
|
|
683
|
+
let sandbox;
|
|
684
|
+
try {
|
|
685
|
+
sandbox = ComputeSDK.createSandbox();
|
|
686
|
+
return await sandbox.execute(code);
|
|
687
|
+
} catch (error) {
|
|
688
|
+
console.error('Execution failed:', error.message);
|
|
689
|
+
throw error;
|
|
690
|
+
} finally {
|
|
691
|
+
if (sandbox) {
|
|
692
|
+
await sandbox.kill();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
### 4. Type Safety
|
|
699
|
+
|
|
700
|
+
Use TypeScript interfaces for better development experience:
|
|
701
|
+
|
|
702
|
+
```typescript
|
|
703
|
+
import { FilesystemComputeSandbox, TerminalComputeSandbox } from 'computesdk';
|
|
704
|
+
|
|
705
|
+
function requiresFilesystem(sandbox: FilesystemComputeSandbox) {
|
|
706
|
+
// TypeScript ensures filesystem operations are available
|
|
707
|
+
return sandbox.filesystem.readFile('/path/to/file');
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function requiresTerminal(sandbox: TerminalComputeSandbox) {
|
|
711
|
+
// TypeScript ensures terminal operations are available
|
|
712
|
+
return sandbox.terminal.create({ command: 'bash' });
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
## Contributing
|
|
717
|
+
|
|
718
|
+
We welcome contributions! Please see our [Contributing Guide](https://github.com/computesdk/computesdk/blob/main/CONTRIBUTING.md) for details.
|
|
719
|
+
|
|
720
|
+
### Adding New Providers
|
|
721
|
+
|
|
722
|
+
1. Implement the appropriate `ComputeSpecification` interface:
|
|
723
|
+
- `BaseComputeSpecification` for basic execution
|
|
724
|
+
- `FilesystemComputeSpecification` for filesystem support
|
|
725
|
+
- `TerminalComputeSpecification` for terminal support
|
|
726
|
+
- `FullComputeSpecification` for complete functionality
|
|
727
|
+
|
|
728
|
+
2. Add comprehensive tests covering all implemented interfaces
|
|
729
|
+
|
|
730
|
+
3. Include documentation and examples
|
|
731
|
+
|
|
732
|
+
4. Submit a pull request
|
|
733
|
+
|
|
734
|
+
## License
|
|
735
|
+
|
|
736
|
+
MIT - see [LICENSE](https://github.com/computesdk/computesdk/blob/main/LICENSE) for details.
|
|
737
|
+
|
|
738
|
+
## Support
|
|
739
|
+
|
|
740
|
+
- [GitHub Issues](https://github.com/computesdk/computesdk/issues)
|
|
741
|
+
- [Documentation](https://github.com/computesdk/computesdk)
|
|
742
|
+
- [Examples](https://github.com/computesdk/computesdk/tree/main/examples)
|
|
743
|
+
|
|
744
|
+
---
|
|
745
|
+
|
|
746
|
+
Made with ❤️ by the ComputeSDK team
|