computesdk 3.0.0 → 4.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/README.md +102 -409
- package/dist/index.d.mts +111 -4070
- package/dist/index.d.ts +111 -4070
- package/dist/index.js +220 -4391
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -4361
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# computesdk
|
|
2
2
|
|
|
3
|
-
The
|
|
3
|
+
The universal SDK for running code in remote sandboxes.
|
|
4
|
+
|
|
5
|
+
> Gateway/control-plane transport has been removed from `computesdk`.
|
|
6
|
+
> Configure `compute` with `provider` or `providers`, or use provider packages directly.
|
|
4
7
|
|
|
5
8
|
## Installation
|
|
6
9
|
|
|
@@ -10,23 +13,23 @@ npm install computesdk
|
|
|
10
13
|
|
|
11
14
|
## Quick Start
|
|
12
15
|
|
|
13
|
-
###
|
|
14
|
-
|
|
15
|
-
Set your provider credentials as environment variables and ComputeSDK automatically detects and configures everything:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
export E2B_API_KEY=your_e2b_api_key
|
|
19
|
-
```
|
|
16
|
+
### Direct Provider Mode (Recommended)
|
|
20
17
|
|
|
21
18
|
```typescript
|
|
22
19
|
import { compute } from 'computesdk';
|
|
20
|
+
import { e2b } from '@computesdk/e2b';
|
|
21
|
+
|
|
22
|
+
compute.setConfig({
|
|
23
|
+
provider: e2b({
|
|
24
|
+
apiKey: process.env.E2B_API_KEY,
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
23
27
|
|
|
24
|
-
// Auto-detects E2B from environment
|
|
25
28
|
const sandbox = await compute.sandbox.create();
|
|
26
29
|
|
|
27
30
|
// Execute code
|
|
28
|
-
const result = await sandbox.
|
|
29
|
-
console.log(result.
|
|
31
|
+
const result = await sandbox.runCommand('python -c "print(\"Hello World!\")"');
|
|
32
|
+
console.log(result.stdout); // "Hello World!"
|
|
30
33
|
|
|
31
34
|
// Clean up
|
|
32
35
|
await sandbox.destroy();
|
|
@@ -34,47 +37,72 @@ await sandbox.destroy();
|
|
|
34
37
|
|
|
35
38
|
### Explicit Configuration
|
|
36
39
|
|
|
37
|
-
For more control,
|
|
40
|
+
For more control, configure `compute` with an explicit provider:
|
|
38
41
|
|
|
39
42
|
```typescript
|
|
40
43
|
import { compute } from 'computesdk';
|
|
44
|
+
import { modal } from '@computesdk/modal';
|
|
41
45
|
|
|
42
46
|
compute.setConfig({
|
|
43
|
-
provider:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
47
|
+
provider: modal({
|
|
48
|
+
tokenId: process.env.MODAL_TOKEN_ID,
|
|
49
|
+
tokenSecret: process.env.MODAL_TOKEN_SECRET,
|
|
50
|
+
}),
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
const sandbox = await compute.sandbox.create();
|
|
51
54
|
```
|
|
52
55
|
|
|
56
|
+
### Multi-Provider Configuration
|
|
57
|
+
|
|
58
|
+
Configure multiple providers for resilience and routing:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { compute } from 'computesdk';
|
|
62
|
+
import { e2b } from '@computesdk/e2b';
|
|
63
|
+
import { modal } from '@computesdk/modal';
|
|
64
|
+
|
|
65
|
+
compute.setConfig({
|
|
66
|
+
providers: [
|
|
67
|
+
e2b({ apiKey: process.env.E2B_API_KEY }),
|
|
68
|
+
modal({
|
|
69
|
+
tokenId: process.env.MODAL_TOKEN_ID,
|
|
70
|
+
tokenSecret: process.env.MODAL_TOKEN_SECRET,
|
|
71
|
+
}),
|
|
72
|
+
],
|
|
73
|
+
providerStrategy: 'round-robin', // or 'priority'
|
|
74
|
+
fallbackOnError: true,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Uses configured strategy
|
|
78
|
+
const sandbox = await compute.sandbox.create();
|
|
79
|
+
|
|
80
|
+
// Force a specific provider for one call
|
|
81
|
+
const modalSandbox = await compute.sandbox.create({ provider: 'modal' });
|
|
82
|
+
```
|
|
83
|
+
|
|
53
84
|
## Supported Providers
|
|
54
85
|
|
|
55
|
-
|
|
86
|
+
Use provider packages directly to create provider instances:
|
|
56
87
|
|
|
57
88
|
| Provider | Environment Variables | Use Cases |
|
|
58
89
|
|----------|----------------------|-----------|
|
|
59
90
|
| **E2B** | `E2B_API_KEY` | Data science, Python/Node.js, interactive terminals |
|
|
60
91
|
| **Modal** | `MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET` | GPU computing, ML inference, Python workloads |
|
|
61
|
-
| **Railway** | `
|
|
92
|
+
| **Railway** | `RAILWAY_API_KEY`, `RAILWAY_PROJECT_ID`, `RAILWAY_ENVIRONMENT_ID` | Full-stack deployments, persistent storage |
|
|
62
93
|
| **Daytona** | `DAYTONA_API_KEY` | Development workspaces, custom environments |
|
|
63
94
|
| **Runloop** | `RUNLOOP_API_KEY` | Code execution, automation |
|
|
64
95
|
| **Vercel** | `VERCEL_TOKEN` or `VERCEL_OIDC_TOKEN` | Serverless functions, web apps |
|
|
65
|
-
| **Cloudflare** | `
|
|
66
|
-
| **CodeSandbox** | `
|
|
67
|
-
|
|
68
|
-
### Provider Detection Order
|
|
96
|
+
| **Cloudflare** | `CLOUDFLARE_SANDBOX_URL`, `CLOUDFLARE_SANDBOX_SECRET` | Edge computing |
|
|
97
|
+
| **CodeSandbox** | `CSB_API_KEY` | Collaborative development |
|
|
69
98
|
|
|
70
|
-
|
|
99
|
+
Example imports:
|
|
71
100
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
export COMPUTESDK_PROVIDER=modal
|
|
101
|
+
```typescript
|
|
102
|
+
import { e2b } from '@computesdk/e2b';
|
|
103
|
+
import { modal } from '@computesdk/modal';
|
|
104
|
+
import { vercel } from '@computesdk/vercel';
|
|
105
|
+
import { daytona } from '@computesdk/daytona';
|
|
78
106
|
```
|
|
79
107
|
|
|
80
108
|
## API Reference
|
|
@@ -83,71 +111,51 @@ export COMPUTESDK_PROVIDER=modal
|
|
|
83
111
|
|
|
84
112
|
#### `compute.setConfig(config)`
|
|
85
113
|
|
|
86
|
-
Configure
|
|
114
|
+
Configure `compute` with `provider` or `providers`.
|
|
87
115
|
|
|
88
116
|
```typescript
|
|
89
117
|
compute.setConfig({
|
|
90
|
-
provider:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
apiKey: process.env.YOUR_PROVIDER_API_KEY
|
|
94
|
-
}
|
|
118
|
+
provider: e2b({
|
|
119
|
+
apiKey: process.env.E2B_API_KEY,
|
|
120
|
+
}),
|
|
95
121
|
});
|
|
96
122
|
```
|
|
97
123
|
|
|
98
|
-
|
|
124
|
+
`compute(...)` callable mode is also supported:
|
|
99
125
|
|
|
100
126
|
```typescript
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
templateId: 'optional_template'
|
|
108
|
-
}
|
|
127
|
+
const scopedCompute = compute({
|
|
128
|
+
provider: vercel({
|
|
129
|
+
token: process.env.VERCEL_TOKEN,
|
|
130
|
+
teamId: process.env.VERCEL_TEAM_ID,
|
|
131
|
+
projectId: process.env.VERCEL_PROJECT_ID,
|
|
132
|
+
}),
|
|
109
133
|
});
|
|
110
134
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
provider: 'modal',
|
|
114
|
-
apiKey: process.env.COMPUTESDK_API_KEY,
|
|
115
|
-
modal: {
|
|
116
|
-
tokenId: 'ak-xxx',
|
|
117
|
-
tokenSecret: 'as-xxx'
|
|
118
|
-
}
|
|
119
|
-
});
|
|
135
|
+
const sandbox = await scopedCompute.sandbox.create();
|
|
136
|
+
```
|
|
120
137
|
|
|
121
|
-
|
|
122
|
-
compute.setConfig({
|
|
123
|
-
provider: 'railway',
|
|
124
|
-
apiKey: process.env.COMPUTESDK_API_KEY,
|
|
125
|
-
railway: {
|
|
126
|
-
apiToken: 'your_token',
|
|
127
|
-
projectId: 'project_id',
|
|
128
|
-
environmentId: 'env_id'
|
|
129
|
-
}
|
|
130
|
-
});
|
|
138
|
+
Multi-provider config shape:
|
|
131
139
|
|
|
132
|
-
|
|
140
|
+
```typescript
|
|
133
141
|
compute.setConfig({
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
142
|
+
providers: [e2b({...}), modal({...})],
|
|
143
|
+
providerStrategy: 'priority', // default: 'priority'
|
|
144
|
+
fallbackOnError: true, // default: true
|
|
137
145
|
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
You can also combine both `provider` and `providers`:
|
|
138
149
|
|
|
139
|
-
|
|
150
|
+
```typescript
|
|
140
151
|
compute.setConfig({
|
|
141
|
-
provider:
|
|
142
|
-
|
|
143
|
-
vercel: {
|
|
144
|
-
token: 'your_token',
|
|
145
|
-
teamId: 'team_xxx',
|
|
146
|
-
projectId: 'prj_xxx'
|
|
147
|
-
}
|
|
152
|
+
provider: e2b({...}), // primary provider (first choice)
|
|
153
|
+
providers: [modal({...})], // fallback/secondary providers
|
|
148
154
|
});
|
|
149
155
|
```
|
|
150
156
|
|
|
157
|
+
When both are present, `provider` is treated as the primary provider and is placed first.
|
|
158
|
+
|
|
151
159
|
### Sandbox Management
|
|
152
160
|
|
|
153
161
|
#### `compute.sandbox.create(options?)`
|
|
@@ -171,9 +179,9 @@ const sandbox = await compute.sandbox.create({
|
|
|
171
179
|
- `metadata?: Record<string, any>` - Custom metadata
|
|
172
180
|
- `envs?: Record<string, string>` - Environment variables
|
|
173
181
|
- `namespace?: string` - Namespace for organizing sandboxes
|
|
174
|
-
- `name?: string` -
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
- `name?: string` - Human-readable name for the sandbox
|
|
183
|
+
|
|
184
|
+
> **Note:** Not every provider honors every option. Support for fields like `name`, `metadata`, and `envs` depends on the underlying provider SDK — some pass them through, some map them to a different field, and some ignore them silently. Check your provider package's README for the exact set of options it respects.
|
|
177
185
|
|
|
178
186
|
#### `compute.sandbox.getById(sandboxId)`
|
|
179
187
|
|
|
@@ -183,40 +191,8 @@ Get an existing sandbox by ID.
|
|
|
183
191
|
const sandbox = await compute.sandbox.getById('sandbox-id');
|
|
184
192
|
```
|
|
185
193
|
|
|
186
|
-
#### `compute.sandbox.findOrCreate(options)`
|
|
187
|
-
|
|
188
|
-
Find an existing sandbox by namespace and name, or create a new one.
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
const sandbox = await compute.sandbox.findOrCreate({
|
|
192
|
-
namespace: 'my-org',
|
|
193
|
-
name: 'my-project',
|
|
194
|
-
});
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
#### `compute.sandbox.find(options)`
|
|
198
|
-
|
|
199
|
-
Find an existing sandbox by namespace and name (returns null if not found).
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
const sandbox = await compute.sandbox.find({
|
|
203
|
-
namespace: 'my-org',
|
|
204
|
-
name: 'my-project',
|
|
205
|
-
});
|
|
206
|
-
```
|
|
207
|
-
|
|
208
194
|
### Sandbox Operations
|
|
209
195
|
|
|
210
|
-
#### `sandbox.runCode(code, language?)`
|
|
211
|
-
|
|
212
|
-
Execute code in the sandbox.
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
const result = await sandbox.runCode('print("Hello")', 'python');
|
|
216
|
-
console.log(result.output); // "Hello"
|
|
217
|
-
console.log(result.exitCode);
|
|
218
|
-
```
|
|
219
|
-
|
|
220
196
|
#### `sandbox.runCommand(command, options?)`
|
|
221
197
|
|
|
222
198
|
Run a shell command.
|
|
@@ -297,209 +273,6 @@ Remove a file or directory.
|
|
|
297
273
|
await sandbox.filesystem.remove('/tmp/hello.py');
|
|
298
274
|
```
|
|
299
275
|
|
|
300
|
-
### Terminal Operations
|
|
301
|
-
|
|
302
|
-
The sandbox provides terminal access in two modes: **PTY mode** (interactive shell) and **Exec mode** (command tracking).
|
|
303
|
-
|
|
304
|
-
#### `sandbox.terminal.create(options?)`
|
|
305
|
-
|
|
306
|
-
Create a new terminal session.
|
|
307
|
-
|
|
308
|
-
```typescript
|
|
309
|
-
// PTY mode - Interactive shell
|
|
310
|
-
const pty = await sandbox.terminal.create({ pty: true, shell: '/bin/bash' });
|
|
311
|
-
|
|
312
|
-
// Exec mode - Command tracking (default)
|
|
313
|
-
const exec = await sandbox.terminal.create({ pty: false });
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
**Options:**
|
|
317
|
-
- `pty?: boolean` - Terminal mode: `true` = PTY (interactive), `false` = exec (command tracking). Default: `false`
|
|
318
|
-
- `shell?: string` - Shell to use (e.g., '/bin/bash'). PTY mode only
|
|
319
|
-
- `encoding?: 'raw' | 'base64'` - Output encoding. Default: `'raw'`
|
|
320
|
-
|
|
321
|
-
**Returns:** `TerminalInstance`
|
|
322
|
-
|
|
323
|
-
#### `sandbox.terminal.list()`
|
|
324
|
-
|
|
325
|
-
List all active terminals.
|
|
326
|
-
|
|
327
|
-
```typescript
|
|
328
|
-
const terminals = await sandbox.terminal.list();
|
|
329
|
-
console.log(terminals); // [{ id: 'term-1', pty: true, status: 'running', ... }]
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
#### `sandbox.terminal.retrieve(id)`
|
|
333
|
-
|
|
334
|
-
Retrieve a specific terminal by ID.
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
const terminal = await sandbox.terminal.retrieve('term-123');
|
|
338
|
-
console.log(terminal.id, terminal.status);
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
#### `sandbox.terminal.destroy(id)`
|
|
342
|
-
|
|
343
|
-
Destroy a terminal by ID.
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
await sandbox.terminal.destroy('term-123');
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### PTY Mode (Interactive Shell)
|
|
350
|
-
|
|
351
|
-
PTY mode creates an interactive shell session with real-time input/output over WebSocket.
|
|
352
|
-
|
|
353
|
-
#### `terminal.write(input)`
|
|
354
|
-
|
|
355
|
-
Send input to the terminal shell.
|
|
356
|
-
|
|
357
|
-
```typescript
|
|
358
|
-
const pty = await sandbox.terminal.create({ pty: true });
|
|
359
|
-
pty.on('output', (data) => console.log(data));
|
|
360
|
-
pty.write('ls -la\n');
|
|
361
|
-
pty.write('pwd\n');
|
|
362
|
-
await pty.destroy();
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
#### `terminal.resize(cols, rows)`
|
|
366
|
-
|
|
367
|
-
Resize the terminal window.
|
|
368
|
-
|
|
369
|
-
```typescript
|
|
370
|
-
pty.resize(120, 40);
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
#### `terminal.on(event, handler)`
|
|
374
|
-
|
|
375
|
-
Register an event handler. Events: `'output'`, `'error'`, `'destroyed'`.
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
pty.on('output', (data) => console.log('Output:', data));
|
|
379
|
-
pty.on('error', (error) => console.error('Error:', error));
|
|
380
|
-
pty.on('destroyed', () => console.log('Terminal destroyed'));
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
#### `terminal.off(event, handler)`
|
|
384
|
-
|
|
385
|
-
Unregister an event handler.
|
|
386
|
-
|
|
387
|
-
```typescript
|
|
388
|
-
const handler = (data) => console.log(data);
|
|
389
|
-
pty.on('output', handler);
|
|
390
|
-
pty.off('output', handler);
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
#### Terminal Properties
|
|
394
|
-
|
|
395
|
-
```typescript
|
|
396
|
-
console.log(pty.id); // Terminal ID
|
|
397
|
-
console.log(pty.status); // 'running' | 'stopped' | 'active' | 'ready'
|
|
398
|
-
console.log(pty.channel); // WebSocket channel (PTY only)
|
|
399
|
-
console.log(pty.pty); // true for PTY mode
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
### Exec Mode (Command Tracking)
|
|
403
|
-
|
|
404
|
-
Exec mode executes commands with structured result tracking, suitable for automation.
|
|
405
|
-
|
|
406
|
-
#### `terminal.command.run(command, options?)`
|
|
407
|
-
|
|
408
|
-
Execute a command in the terminal.
|
|
409
|
-
|
|
410
|
-
```typescript
|
|
411
|
-
const exec = await sandbox.terminal.create({ pty: false });
|
|
412
|
-
|
|
413
|
-
// Foreground execution (waits for completion)
|
|
414
|
-
const cmd = await exec.command.run('npm test');
|
|
415
|
-
console.log(cmd.stdout);
|
|
416
|
-
console.log(cmd.stderr);
|
|
417
|
-
console.log(cmd.exitCode);
|
|
418
|
-
|
|
419
|
-
// Background execution (returns immediately)
|
|
420
|
-
const bgCmd = await exec.command.run('npm install', { background: true });
|
|
421
|
-
console.log(bgCmd.status); // 'running'
|
|
422
|
-
await bgCmd.wait(); // Wait for completion
|
|
423
|
-
console.log(bgCmd.exitCode);
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
**Parameters:**
|
|
427
|
-
- `command: string` - The command to execute
|
|
428
|
-
- `options?: { background?: boolean }` - Execution options
|
|
429
|
-
|
|
430
|
-
**Returns:** `Command` object
|
|
431
|
-
|
|
432
|
-
#### `terminal.command.list()`
|
|
433
|
-
|
|
434
|
-
List all commands executed in this terminal.
|
|
435
|
-
|
|
436
|
-
```typescript
|
|
437
|
-
const commands = await exec.command.list();
|
|
438
|
-
commands.forEach(cmd => {
|
|
439
|
-
console.log(cmd.id, cmd.command, cmd.status, cmd.exitCode);
|
|
440
|
-
});
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
#### `terminal.command.retrieve(cmdId)`
|
|
444
|
-
|
|
445
|
-
Retrieve a specific command by ID.
|
|
446
|
-
|
|
447
|
-
```typescript
|
|
448
|
-
const cmd = await exec.command.retrieve('cmd-123');
|
|
449
|
-
console.log(cmd.stdout);
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### Command Object
|
|
453
|
-
|
|
454
|
-
The `Command` object represents a command execution result.
|
|
455
|
-
|
|
456
|
-
#### Command Properties
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
console.log(cmd.id); // Command ID
|
|
460
|
-
console.log(cmd.terminalId); // Parent terminal ID
|
|
461
|
-
console.log(cmd.command); // Executed command
|
|
462
|
-
console.log(cmd.status); // 'running' | 'completed' | 'failed'
|
|
463
|
-
console.log(cmd.stdout); // Standard output
|
|
464
|
-
console.log(cmd.stderr); // Standard error
|
|
465
|
-
console.log(cmd.exitCode); // Exit code (undefined if running)
|
|
466
|
-
console.log(cmd.durationMs); // Execution time in milliseconds
|
|
467
|
-
console.log(cmd.startedAt); // Start timestamp
|
|
468
|
-
console.log(cmd.finishedAt); // Finish timestamp (undefined if running)
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
#### `command.wait(timeout?)`
|
|
472
|
-
|
|
473
|
-
Wait for a background command to complete.
|
|
474
|
-
|
|
475
|
-
```typescript
|
|
476
|
-
const cmd = await exec.command.run('sleep 5', { background: true });
|
|
477
|
-
await cmd.wait(); // Waits up to default timeout
|
|
478
|
-
console.log(cmd.exitCode);
|
|
479
|
-
|
|
480
|
-
// With custom timeout (in seconds, 0 = no timeout)
|
|
481
|
-
await cmd.wait(10);
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
#### `command.refresh()`
|
|
485
|
-
|
|
486
|
-
Refresh the command status from the server.
|
|
487
|
-
|
|
488
|
-
```typescript
|
|
489
|
-
const cmd = await exec.command.run('npm build', { background: true });
|
|
490
|
-
// ... later ...
|
|
491
|
-
await cmd.refresh();
|
|
492
|
-
console.log(cmd.status, cmd.exitCode);
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
#### `terminal.destroy()`
|
|
496
|
-
|
|
497
|
-
Destroy the terminal and clean up resources.
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
await exec.destroy();
|
|
501
|
-
```
|
|
502
|
-
|
|
503
276
|
## Examples
|
|
504
277
|
|
|
505
278
|
### Multi-Step Build Process
|
|
@@ -539,119 +312,39 @@ const installResult = await sandbox.runCommand('npm install', { cwd: '/app' });
|
|
|
539
312
|
console.log('Install:', installResult.stdout);
|
|
540
313
|
|
|
541
314
|
// Run the app
|
|
542
|
-
const runResult = await sandbox.
|
|
543
|
-
const { spawn } = require('child_process');
|
|
544
|
-
const proc = spawn('node', ['src/index.js'], { cwd: '/app' });
|
|
545
|
-
proc.stdout.on('data', (data) => console.log(data.toString()));
|
|
546
|
-
`);
|
|
315
|
+
const runResult = await sandbox.runCommand('node src/index.js', { cwd: '/app' });
|
|
547
316
|
|
|
548
|
-
console.log(runResult.
|
|
317
|
+
console.log(runResult.stdout);
|
|
549
318
|
|
|
550
319
|
await sandbox.destroy();
|
|
551
320
|
```
|
|
552
321
|
|
|
553
|
-
### Terminal Command Execution
|
|
554
|
-
|
|
555
|
-
```typescript
|
|
556
|
-
import { compute } from 'computesdk';
|
|
557
|
-
|
|
558
|
-
const sandbox = await compute.sandbox.create();
|
|
559
|
-
|
|
560
|
-
// Create exec mode terminal for command tracking
|
|
561
|
-
const terminal = await sandbox.terminal.create({ pty: false });
|
|
562
|
-
|
|
563
|
-
// Run build commands with tracking
|
|
564
|
-
const install = await terminal.command.run('npm install');
|
|
565
|
-
console.log('Install exit code:', install.exitCode);
|
|
566
|
-
|
|
567
|
-
const build = await terminal.command.run('npm run build');
|
|
568
|
-
console.log('Build output:', build.stdout);
|
|
569
|
-
|
|
570
|
-
// Run tests in background
|
|
571
|
-
const tests = await terminal.command.run('npm test', { background: true });
|
|
572
|
-
console.log('Tests started:', tests.status);
|
|
573
|
-
|
|
574
|
-
// Wait for tests to complete
|
|
575
|
-
await tests.wait(60); // 60 second timeout
|
|
576
|
-
console.log('Tests completed:', tests.exitCode === 0 ? 'PASSED' : 'FAILED');
|
|
577
|
-
console.log('Test output:', tests.stdout);
|
|
578
|
-
|
|
579
|
-
// List all commands
|
|
580
|
-
const commands = await terminal.command.list();
|
|
581
|
-
console.log(`Executed ${commands.length} commands`);
|
|
582
|
-
|
|
583
|
-
await terminal.destroy();
|
|
584
|
-
await sandbox.destroy();
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
### Interactive Terminal Session
|
|
588
|
-
|
|
589
|
-
```typescript
|
|
590
|
-
import { compute } from 'computesdk';
|
|
591
|
-
|
|
592
|
-
const sandbox = await compute.sandbox.create();
|
|
593
|
-
|
|
594
|
-
// Create PTY terminal for interactive shell
|
|
595
|
-
const pty = await sandbox.terminal.create({
|
|
596
|
-
pty: true,
|
|
597
|
-
shell: '/bin/bash'
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
// Collect all output
|
|
601
|
-
let output = '';
|
|
602
|
-
pty.on('output', (data) => {
|
|
603
|
-
output += data;
|
|
604
|
-
console.log(data);
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
pty.on('error', (error) => {
|
|
608
|
-
console.error('Terminal error:', error);
|
|
609
|
-
});
|
|
610
|
-
|
|
611
|
-
// Execute interactive commands
|
|
612
|
-
pty.write('echo "Starting project setup"\n');
|
|
613
|
-
pty.write('mkdir -p /workspace/myproject\n');
|
|
614
|
-
pty.write('cd /workspace/myproject\n');
|
|
615
|
-
pty.write('npm init -y\n');
|
|
616
|
-
pty.write('npm install express\n');
|
|
617
|
-
pty.write('echo "Setup complete"\n');
|
|
618
|
-
|
|
619
|
-
// Wait for operations to complete
|
|
620
|
-
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
621
|
-
|
|
622
|
-
// Clean up
|
|
623
|
-
await pty.destroy();
|
|
624
|
-
await sandbox.destroy();
|
|
625
|
-
|
|
626
|
-
console.log('Complete output:', output);
|
|
627
|
-
```
|
|
628
|
-
|
|
629
322
|
### Using Different Providers
|
|
630
323
|
|
|
631
324
|
```typescript
|
|
632
325
|
import { compute } from 'computesdk';
|
|
326
|
+
import { e2b } from '@computesdk/e2b';
|
|
327
|
+
import { modal } from '@computesdk/modal';
|
|
633
328
|
|
|
634
329
|
// Use E2B for data science
|
|
635
330
|
compute.setConfig({
|
|
636
|
-
provider:
|
|
637
|
-
e2b: { apiKey: process.env.E2B_API_KEY }
|
|
331
|
+
provider: e2b({ apiKey: process.env.E2B_API_KEY }),
|
|
638
332
|
});
|
|
639
333
|
|
|
640
334
|
const e2bSandbox = await compute.sandbox.create();
|
|
641
|
-
await e2bSandbox.
|
|
335
|
+
await e2bSandbox.runCommand('python -c "import pandas as pd; print(pd.__version__)"');
|
|
642
336
|
await e2bSandbox.destroy();
|
|
643
337
|
|
|
644
338
|
// Switch to Modal for GPU workloads
|
|
645
339
|
compute.setConfig({
|
|
646
|
-
provider:
|
|
647
|
-
modal: {
|
|
340
|
+
provider: modal({
|
|
648
341
|
tokenId: process.env.MODAL_TOKEN_ID,
|
|
649
|
-
tokenSecret: process.env.MODAL_TOKEN_SECRET
|
|
650
|
-
}
|
|
342
|
+
tokenSecret: process.env.MODAL_TOKEN_SECRET,
|
|
343
|
+
}),
|
|
651
344
|
});
|
|
652
345
|
|
|
653
346
|
const modalSandbox = await compute.sandbox.create();
|
|
654
|
-
await modalSandbox.
|
|
347
|
+
await modalSandbox.runCommand('python -c "import torch; print(torch.cuda.is_available())"');
|
|
655
348
|
await modalSandbox.destroy();
|
|
656
349
|
```
|
|
657
350
|
|
|
@@ -660,20 +353,20 @@ await modalSandbox.destroy();
|
|
|
660
353
|
```typescript
|
|
661
354
|
try {
|
|
662
355
|
const sandbox = await compute.sandbox.create();
|
|
663
|
-
const result = await sandbox.
|
|
356
|
+
const result = await sandbox.runCommand('invalid python code');
|
|
664
357
|
} catch (error) {
|
|
665
358
|
console.error('Execution failed:', error.message);
|
|
666
359
|
|
|
667
360
|
// Check for specific error types
|
|
668
|
-
if (error.message.includes('No provider
|
|
669
|
-
console.error('
|
|
361
|
+
if (error.message.includes('No provider instance configured')) {
|
|
362
|
+
console.error('Configure compute.setConfig({ provider: e2b({...}) }) first');
|
|
670
363
|
}
|
|
671
364
|
}
|
|
672
365
|
```
|
|
673
366
|
|
|
674
|
-
##
|
|
367
|
+
## Provider Packages (Advanced)
|
|
675
368
|
|
|
676
|
-
For advanced use cases where you want to
|
|
369
|
+
For advanced use cases where you want to use provider SDKs directly, see individual provider packages:
|
|
677
370
|
|
|
678
371
|
- **[@computesdk/e2b](../e2b)** - E2B provider
|
|
679
372
|
- **[@computesdk/modal](../modal)** - Modal provider
|