computesdk 1.0.2 → 2.0.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 +573 -185
- package/dist/index.d.mts +274 -25
- package/dist/index.d.ts +274 -25
- package/dist/index.js +230 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +226 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -31
package/README.md
CHANGED
|
@@ -6,48 +6,49 @@ Similar to how Vercel's AI SDK abstracts different LLM providers, ComputeSDK abs
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
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
|
|
15
17
|
|
|
16
18
|
## Supported Providers
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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 |
|
|
22
25
|
|
|
23
26
|
## Installation
|
|
24
27
|
|
|
25
28
|
```bash
|
|
29
|
+
# Core SDK
|
|
26
30
|
npm install computesdk
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### Install Provider Packages
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
# Install the providers you need
|
|
32
|
+
# Provider packages (install only what you need)
|
|
33
33
|
npm install @computesdk/e2b # E2B provider
|
|
34
34
|
npm install @computesdk/vercel # Vercel provider
|
|
35
|
-
npm install @computesdk/
|
|
35
|
+
npm install @computesdk/daytona # Daytona provider
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## Quick Start
|
|
39
39
|
|
|
40
40
|
### Auto-detection (Recommended)
|
|
41
41
|
|
|
42
|
+
ComputeSDK automatically detects available providers based on environment variables:
|
|
43
|
+
|
|
42
44
|
```typescript
|
|
43
45
|
import { ComputeSDK } from 'computesdk';
|
|
44
46
|
|
|
45
|
-
// Automatically detects and uses available
|
|
46
|
-
const
|
|
47
|
-
const sandbox = await sdk.createSandbox();
|
|
47
|
+
// Automatically detects and uses the first available provider
|
|
48
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
48
49
|
|
|
49
|
-
const result = await sandbox.execute('print("Hello
|
|
50
|
-
console.log(result.stdout); // "Hello
|
|
50
|
+
const result = await sandbox.execute('print("Hello World!")');
|
|
51
|
+
console.log(result.stdout); // "Hello World!"
|
|
51
52
|
|
|
52
53
|
await sandbox.kill();
|
|
53
54
|
```
|
|
@@ -68,66 +69,195 @@ const result = await executeSandbox({
|
|
|
68
69
|
console.log(result.stdout);
|
|
69
70
|
```
|
|
70
71
|
|
|
71
|
-
###
|
|
72
|
+
### Advanced Usage with Type Safety
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
import { executeSandbox } from 'computesdk';
|
|
75
|
-
import { e2b } from '@computesdk/e2b';
|
|
76
|
-
import { vercel } from '@computesdk/vercel';
|
|
77
|
-
import { cloudflare } from '@computesdk/cloudflare';
|
|
74
|
+
ComputeSDK provides rich TypeScript interfaces for different provider capabilities:
|
|
78
75
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
}
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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();
|
|
96
103
|
}
|
|
97
104
|
```
|
|
98
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
|
+
|
|
99
131
|
## API Reference
|
|
100
132
|
|
|
101
|
-
###
|
|
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()`
|
|
102
157
|
|
|
103
|
-
|
|
158
|
+
Detects available providers based on environment variables.
|
|
104
159
|
|
|
105
160
|
```typescript
|
|
106
|
-
const
|
|
161
|
+
const providers = ComputeSDK.detectProviders();
|
|
162
|
+
console.log('Available providers:', providers); // ['e2b', 'vercel']
|
|
107
163
|
```
|
|
108
164
|
|
|
109
|
-
|
|
165
|
+
**Returns:** `ProviderType[]` - Array of available provider names
|
|
110
166
|
|
|
111
|
-
|
|
112
|
-
- `getAvailableProviders()` - Returns list of available providers
|
|
113
|
-
- `registerProvider(name: string, provider: ComputeSpecification)` - Registers a custom provider
|
|
167
|
+
### Utility Functions
|
|
114
168
|
|
|
115
|
-
|
|
169
|
+
#### `executeSandbox(params)`
|
|
116
170
|
|
|
117
171
|
Utility function for one-off code execution.
|
|
118
172
|
|
|
119
173
|
```typescript
|
|
120
|
-
|
|
121
|
-
|
|
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;
|
|
122
188
|
code: string;
|
|
123
|
-
runtime?:
|
|
124
|
-
|
|
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[]>;
|
|
125
245
|
}
|
|
126
246
|
```
|
|
127
247
|
|
|
128
|
-
|
|
248
|
+
#### `FullComputeSandbox`
|
|
129
249
|
|
|
130
|
-
|
|
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:
|
|
131
261
|
|
|
132
262
|
```typescript
|
|
133
263
|
interface ExecutionResult {
|
|
@@ -140,197 +270,448 @@ interface ExecutionResult {
|
|
|
140
270
|
}
|
|
141
271
|
```
|
|
142
272
|
|
|
143
|
-
|
|
273
|
+
#### `SandboxInfo`
|
|
144
274
|
|
|
145
|
-
Information about a sandbox instance
|
|
275
|
+
Information about a sandbox instance:
|
|
146
276
|
|
|
147
277
|
```typescript
|
|
148
278
|
interface SandboxInfo {
|
|
149
279
|
id: string;
|
|
150
280
|
provider: string;
|
|
151
|
-
runtime:
|
|
152
|
-
status: 'running' | 'stopped';
|
|
281
|
+
runtime: Runtime;
|
|
282
|
+
status: 'running' | 'stopped' | 'error';
|
|
153
283
|
createdAt: Date;
|
|
154
284
|
timeout: number;
|
|
155
285
|
metadata?: Record<string, any>;
|
|
156
286
|
}
|
|
157
287
|
```
|
|
158
288
|
|
|
159
|
-
|
|
289
|
+
#### `FileEntry`
|
|
160
290
|
|
|
161
|
-
|
|
291
|
+
File system entry information:
|
|
162
292
|
|
|
163
|
-
|
|
293
|
+
```typescript
|
|
294
|
+
interface FileEntry {
|
|
295
|
+
name: string;
|
|
296
|
+
path: string;
|
|
297
|
+
isDirectory: boolean;
|
|
298
|
+
size: number;
|
|
299
|
+
lastModified: Date;
|
|
300
|
+
}
|
|
301
|
+
```
|
|
164
302
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
303
|
+
## Examples
|
|
304
|
+
|
|
305
|
+
### Cross-Provider Data Processing
|
|
168
306
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
+
};
|
|
173
382
|
|
|
174
|
-
|
|
175
|
-
|
|
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);
|
|
176
408
|
```
|
|
177
409
|
|
|
178
|
-
###
|
|
410
|
+
### Interactive Development with E2B
|
|
179
411
|
|
|
180
412
|
```typescript
|
|
181
|
-
import {
|
|
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';
|
|
182
463
|
import { e2b } from '@computesdk/e2b';
|
|
183
464
|
import { vercel } from '@computesdk/vercel';
|
|
465
|
+
import { daytona } from '@computesdk/daytona';
|
|
184
466
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
467
|
+
async function compareProviders() {
|
|
468
|
+
const testCode = `
|
|
469
|
+
import json
|
|
470
|
+
import time
|
|
471
|
+
start = time.time()
|
|
190
472
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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);
|
|
196
521
|
```
|
|
197
522
|
|
|
198
|
-
##
|
|
523
|
+
## Error Handling
|
|
199
524
|
|
|
200
|
-
|
|
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:
|
|
201
555
|
|
|
202
556
|
```typescript
|
|
203
|
-
import { executeSandbox } from 'computesdk';
|
|
204
557
|
import { e2b } from '@computesdk/e2b';
|
|
205
558
|
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
559
|
+
const sandbox = e2b();
|
|
560
|
+
|
|
561
|
+
// Full Python environment with data science libraries
|
|
562
|
+
const result = await sandbox.execute(`
|
|
209
563
|
import pandas as pd
|
|
564
|
+
import matplotlib.pyplot as plt
|
|
210
565
|
import numpy as np
|
|
211
566
|
|
|
212
|
-
# Create
|
|
213
|
-
data =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
# Calculate metrics
|
|
219
|
-
total_sales = data['sales'].sum()
|
|
220
|
-
avg_profit = data['profit'].mean()
|
|
221
|
-
profit_margin = (data['profit'].sum() / total_sales) * 100
|
|
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
|
+
`);
|
|
222
573
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
`
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
console.log(result.stdout);
|
|
574
|
+
// Check if file was created
|
|
575
|
+
const exists = await sandbox.filesystem.exists('/tmp/histogram.png');
|
|
576
|
+
console.log('Histogram created:', exists);
|
|
230
577
|
```
|
|
231
578
|
|
|
232
|
-
###
|
|
579
|
+
### Vercel - Scalable Serverless Execution
|
|
580
|
+
|
|
581
|
+
Vercel provides reliable execution with filesystem support:
|
|
233
582
|
|
|
234
583
|
```typescript
|
|
235
|
-
import { executeSandbox } from 'computesdk';
|
|
236
584
|
import { vercel } from '@computesdk/vercel';
|
|
237
585
|
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
|
248
598
|
};
|
|
249
599
|
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
const response = routes[path] || { error: 'Not found' };
|
|
600
|
+
// Write to filesystem
|
|
601
|
+
fs.writeFileSync('/tmp/api-data.json', JSON.stringify(apiData, null, 2));
|
|
253
602
|
|
|
254
|
-
console.log('API
|
|
255
|
-
|
|
256
|
-
|
|
603
|
+
console.log('API data processed and saved');
|
|
604
|
+
console.log('Active users:', apiData.active);
|
|
605
|
+
`);
|
|
257
606
|
|
|
258
|
-
|
|
607
|
+
// Read the generated data
|
|
608
|
+
const data = await sandbox.filesystem.readFile('/tmp/api-data.json');
|
|
609
|
+
console.log('Generated data:', JSON.parse(data));
|
|
259
610
|
```
|
|
260
611
|
|
|
261
|
-
###
|
|
612
|
+
### Daytona - Development Workspaces
|
|
613
|
+
|
|
614
|
+
Daytona provides development workspace environments with full filesystem support:
|
|
262
615
|
|
|
263
616
|
```typescript
|
|
264
|
-
import {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const result = await executeSandbox({
|
|
271
|
-
sandbox: cloudflare({ env }),
|
|
272
|
-
code: `
|
|
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(`
|
|
273
623
|
import json
|
|
274
|
-
|
|
624
|
+
import os
|
|
275
625
|
|
|
276
|
-
#
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
"region": "auto",
|
|
280
|
-
"processed": True
|
|
281
|
-
}
|
|
626
|
+
# Create project structure
|
|
627
|
+
os.makedirs('/workspace/src', exist_ok=True)
|
|
628
|
+
os.makedirs('/workspace/tests', exist_ok=True)
|
|
282
629
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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')
|
|
286
633
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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);
|
|
292
648
|
```
|
|
293
649
|
|
|
294
|
-
## Error Handling
|
|
295
650
|
|
|
296
|
-
ComputeSDK provides comprehensive error handling:
|
|
297
651
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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
|
|
305
663
|
|
|
664
|
+
Always clean up resources:
|
|
665
|
+
|
|
666
|
+
```typescript
|
|
667
|
+
const sandbox = ComputeSDK.createSandbox();
|
|
306
668
|
try {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
+
}
|
|
322
694
|
}
|
|
323
695
|
}
|
|
324
696
|
```
|
|
325
697
|
|
|
326
|
-
|
|
698
|
+
### 4. Type Safety
|
|
699
|
+
|
|
700
|
+
Use TypeScript interfaces for better development experience:
|
|
701
|
+
|
|
702
|
+
```typescript
|
|
703
|
+
import { FilesystemComputeSandbox, TerminalComputeSandbox } from 'computesdk';
|
|
327
704
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
+
```
|
|
334
715
|
|
|
335
716
|
## Contributing
|
|
336
717
|
|
|
@@ -338,9 +719,16 @@ We welcome contributions! Please see our [Contributing Guide](https://github.com
|
|
|
338
719
|
|
|
339
720
|
### Adding New Providers
|
|
340
721
|
|
|
341
|
-
1. Implement the `ComputeSpecification` interface
|
|
342
|
-
|
|
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
|
+
|
|
343
730
|
3. Include documentation and examples
|
|
731
|
+
|
|
344
732
|
4. Submit a pull request
|
|
345
733
|
|
|
346
734
|
## License
|