computesdk 1.11.0 → 1.11.1
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 +279 -0
- package/dist/index.js +40 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -283,6 +283,209 @@ Remove a file or directory.
|
|
|
283
283
|
await sandbox.filesystem.remove('/tmp/hello.py');
|
|
284
284
|
```
|
|
285
285
|
|
|
286
|
+
### Terminal Operations
|
|
287
|
+
|
|
288
|
+
The sandbox provides terminal access in two modes: **PTY mode** (interactive shell) and **Exec mode** (command tracking).
|
|
289
|
+
|
|
290
|
+
#### `sandbox.terminal.create(options?)`
|
|
291
|
+
|
|
292
|
+
Create a new terminal session.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// PTY mode - Interactive shell
|
|
296
|
+
const pty = await sandbox.terminal.create({ pty: true, shell: '/bin/bash' });
|
|
297
|
+
|
|
298
|
+
// Exec mode - Command tracking (default)
|
|
299
|
+
const exec = await sandbox.terminal.create({ pty: false });
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Options:**
|
|
303
|
+
- `pty?: boolean` - Terminal mode: `true` = PTY (interactive), `false` = exec (command tracking). Default: `false`
|
|
304
|
+
- `shell?: string` - Shell to use (e.g., '/bin/bash'). PTY mode only
|
|
305
|
+
- `encoding?: 'raw' | 'base64'` - Output encoding. Default: `'raw'`
|
|
306
|
+
|
|
307
|
+
**Returns:** `TerminalInstance`
|
|
308
|
+
|
|
309
|
+
#### `sandbox.terminal.list()`
|
|
310
|
+
|
|
311
|
+
List all active terminals.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
const terminals = await sandbox.terminal.list();
|
|
315
|
+
console.log(terminals); // [{ id: 'term-1', pty: true, status: 'running', ... }]
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### `sandbox.terminal.retrieve(id)`
|
|
319
|
+
|
|
320
|
+
Retrieve a specific terminal by ID.
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const terminal = await sandbox.terminal.retrieve('term-123');
|
|
324
|
+
console.log(terminal.id, terminal.status);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### `sandbox.terminal.destroy(id)`
|
|
328
|
+
|
|
329
|
+
Destroy a terminal by ID.
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
await sandbox.terminal.destroy('term-123');
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### PTY Mode (Interactive Shell)
|
|
336
|
+
|
|
337
|
+
PTY mode creates an interactive shell session with real-time input/output over WebSocket.
|
|
338
|
+
|
|
339
|
+
#### `terminal.write(input)`
|
|
340
|
+
|
|
341
|
+
Send input to the terminal shell.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
const pty = await sandbox.terminal.create({ pty: true });
|
|
345
|
+
pty.on('output', (data) => console.log(data));
|
|
346
|
+
pty.write('ls -la\n');
|
|
347
|
+
pty.write('pwd\n');
|
|
348
|
+
await pty.destroy();
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### `terminal.resize(cols, rows)`
|
|
352
|
+
|
|
353
|
+
Resize the terminal window.
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
pty.resize(120, 40);
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### `terminal.on(event, handler)`
|
|
360
|
+
|
|
361
|
+
Register an event handler. Events: `'output'`, `'error'`, `'destroyed'`.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
pty.on('output', (data) => console.log('Output:', data));
|
|
365
|
+
pty.on('error', (error) => console.error('Error:', error));
|
|
366
|
+
pty.on('destroyed', () => console.log('Terminal destroyed'));
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### `terminal.off(event, handler)`
|
|
370
|
+
|
|
371
|
+
Unregister an event handler.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const handler = (data) => console.log(data);
|
|
375
|
+
pty.on('output', handler);
|
|
376
|
+
pty.off('output', handler);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Terminal Properties
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
console.log(pty.id); // Terminal ID
|
|
383
|
+
console.log(pty.status); // 'running' | 'stopped' | 'active' | 'ready'
|
|
384
|
+
console.log(pty.channel); // WebSocket channel (PTY only)
|
|
385
|
+
console.log(pty.pty); // true for PTY mode
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Exec Mode (Command Tracking)
|
|
389
|
+
|
|
390
|
+
Exec mode executes commands with structured result tracking, suitable for automation.
|
|
391
|
+
|
|
392
|
+
#### `terminal.command.run(command, options?)`
|
|
393
|
+
|
|
394
|
+
Execute a command in the terminal.
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
const exec = await sandbox.terminal.create({ pty: false });
|
|
398
|
+
|
|
399
|
+
// Foreground execution (waits for completion)
|
|
400
|
+
const cmd = await exec.command.run('npm test');
|
|
401
|
+
console.log(cmd.stdout);
|
|
402
|
+
console.log(cmd.stderr);
|
|
403
|
+
console.log(cmd.exitCode);
|
|
404
|
+
|
|
405
|
+
// Background execution (returns immediately)
|
|
406
|
+
const bgCmd = await exec.command.run('npm install', { background: true });
|
|
407
|
+
console.log(bgCmd.status); // 'running'
|
|
408
|
+
await bgCmd.wait(); // Wait for completion
|
|
409
|
+
console.log(bgCmd.exitCode);
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Parameters:**
|
|
413
|
+
- `command: string` - The command to execute
|
|
414
|
+
- `options?: { background?: boolean }` - Execution options
|
|
415
|
+
|
|
416
|
+
**Returns:** `Command` object
|
|
417
|
+
|
|
418
|
+
#### `terminal.command.list()`
|
|
419
|
+
|
|
420
|
+
List all commands executed in this terminal.
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
const commands = await exec.command.list();
|
|
424
|
+
commands.forEach(cmd => {
|
|
425
|
+
console.log(cmd.id, cmd.command, cmd.status, cmd.exitCode);
|
|
426
|
+
});
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
#### `terminal.command.retrieve(cmdId)`
|
|
430
|
+
|
|
431
|
+
Retrieve a specific command by ID.
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
const cmd = await exec.command.retrieve('cmd-123');
|
|
435
|
+
console.log(cmd.stdout);
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Command Object
|
|
439
|
+
|
|
440
|
+
The `Command` object represents a command execution result.
|
|
441
|
+
|
|
442
|
+
#### Command Properties
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
console.log(cmd.id); // Command ID
|
|
446
|
+
console.log(cmd.terminalId); // Parent terminal ID
|
|
447
|
+
console.log(cmd.command); // Executed command
|
|
448
|
+
console.log(cmd.status); // 'running' | 'completed' | 'failed'
|
|
449
|
+
console.log(cmd.stdout); // Standard output
|
|
450
|
+
console.log(cmd.stderr); // Standard error
|
|
451
|
+
console.log(cmd.exitCode); // Exit code (undefined if running)
|
|
452
|
+
console.log(cmd.durationMs); // Execution time in milliseconds
|
|
453
|
+
console.log(cmd.startedAt); // Start timestamp
|
|
454
|
+
console.log(cmd.finishedAt); // Finish timestamp (undefined if running)
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
#### `command.wait(timeout?)`
|
|
458
|
+
|
|
459
|
+
Wait for a background command to complete.
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
const cmd = await exec.command.run('sleep 5', { background: true });
|
|
463
|
+
await cmd.wait(); // Waits up to default timeout
|
|
464
|
+
console.log(cmd.exitCode);
|
|
465
|
+
|
|
466
|
+
// With custom timeout (in seconds, 0 = no timeout)
|
|
467
|
+
await cmd.wait(10);
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### `command.refresh()`
|
|
471
|
+
|
|
472
|
+
Refresh the command status from the server.
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
const cmd = await exec.command.run('npm build', { background: true });
|
|
476
|
+
// ... later ...
|
|
477
|
+
await cmd.refresh();
|
|
478
|
+
console.log(cmd.status, cmd.exitCode);
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### `terminal.destroy()`
|
|
482
|
+
|
|
483
|
+
Destroy the terminal and clean up resources.
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
await exec.destroy();
|
|
487
|
+
```
|
|
488
|
+
|
|
286
489
|
## Examples
|
|
287
490
|
|
|
288
491
|
### Data Science Workflow
|
|
@@ -391,6 +594,82 @@ console.log(runResult.stdout);
|
|
|
391
594
|
await sandbox.destroy();
|
|
392
595
|
```
|
|
393
596
|
|
|
597
|
+
### Terminal Command Execution
|
|
598
|
+
|
|
599
|
+
```typescript
|
|
600
|
+
import { compute } from 'computesdk';
|
|
601
|
+
|
|
602
|
+
const sandbox = await compute.sandbox.create({ runtime: 'node' });
|
|
603
|
+
|
|
604
|
+
// Create exec mode terminal for command tracking
|
|
605
|
+
const terminal = await sandbox.terminal.create({ pty: false });
|
|
606
|
+
|
|
607
|
+
// Run build commands with tracking
|
|
608
|
+
const install = await terminal.command.run('npm install');
|
|
609
|
+
console.log('Install exit code:', install.exitCode);
|
|
610
|
+
|
|
611
|
+
const build = await terminal.command.run('npm run build');
|
|
612
|
+
console.log('Build output:', build.stdout);
|
|
613
|
+
|
|
614
|
+
// Run tests in background
|
|
615
|
+
const tests = await terminal.command.run('npm test', { background: true });
|
|
616
|
+
console.log('Tests started:', tests.status);
|
|
617
|
+
|
|
618
|
+
// Wait for tests to complete
|
|
619
|
+
await tests.wait(60); // 60 second timeout
|
|
620
|
+
console.log('Tests completed:', tests.exitCode === 0 ? 'PASSED' : 'FAILED');
|
|
621
|
+
console.log('Test output:', tests.stdout);
|
|
622
|
+
|
|
623
|
+
// List all commands
|
|
624
|
+
const commands = await terminal.command.list();
|
|
625
|
+
console.log(`Executed ${commands.length} commands`);
|
|
626
|
+
|
|
627
|
+
await terminal.destroy();
|
|
628
|
+
await sandbox.destroy();
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
### Interactive Terminal Session
|
|
632
|
+
|
|
633
|
+
```typescript
|
|
634
|
+
import { compute } from 'computesdk';
|
|
635
|
+
|
|
636
|
+
const sandbox = await compute.sandbox.create({ runtime: 'node' });
|
|
637
|
+
|
|
638
|
+
// Create PTY terminal for interactive shell
|
|
639
|
+
const pty = await sandbox.terminal.create({
|
|
640
|
+
pty: true,
|
|
641
|
+
shell: '/bin/bash'
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
// Collect all output
|
|
645
|
+
let output = '';
|
|
646
|
+
pty.on('output', (data) => {
|
|
647
|
+
output += data;
|
|
648
|
+
console.log(data);
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
pty.on('error', (error) => {
|
|
652
|
+
console.error('Terminal error:', error);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// Execute interactive commands
|
|
656
|
+
pty.write('echo "Starting project setup"\n');
|
|
657
|
+
pty.write('mkdir -p /workspace/myproject\n');
|
|
658
|
+
pty.write('cd /workspace/myproject\n');
|
|
659
|
+
pty.write('npm init -y\n');
|
|
660
|
+
pty.write('npm install express\n');
|
|
661
|
+
pty.write('echo "Setup complete"\n');
|
|
662
|
+
|
|
663
|
+
// Wait for operations to complete
|
|
664
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
665
|
+
|
|
666
|
+
// Clean up
|
|
667
|
+
await pty.destroy();
|
|
668
|
+
await sandbox.destroy();
|
|
669
|
+
|
|
670
|
+
console.log('Complete output:', output);
|
|
671
|
+
```
|
|
672
|
+
|
|
394
673
|
### Using Different Providers
|
|
395
674
|
|
|
396
675
|
```typescript
|
package/dist/index.js
CHANGED
|
@@ -3620,6 +3620,34 @@ async function gatewayFetch(url, config, options = {}) {
|
|
|
3620
3620
|
throw error;
|
|
3621
3621
|
}
|
|
3622
3622
|
}
|
|
3623
|
+
async function waitForSandboxStatus(config, endpoint, body, options = {}) {
|
|
3624
|
+
const maxWaitMs = options.maxWaitMs ?? 6e4;
|
|
3625
|
+
const initialDelayMs = 500;
|
|
3626
|
+
const maxDelayMs = 2e3;
|
|
3627
|
+
const backoffFactor = 1.5;
|
|
3628
|
+
const startTime = Date.now();
|
|
3629
|
+
let currentDelay = initialDelayMs;
|
|
3630
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
3631
|
+
const result = await gatewayFetch(endpoint, config, {
|
|
3632
|
+
method: "POST",
|
|
3633
|
+
body: JSON.stringify(body)
|
|
3634
|
+
});
|
|
3635
|
+
if (!result.success || !result.data) {
|
|
3636
|
+
return result;
|
|
3637
|
+
}
|
|
3638
|
+
if (result.data.status !== "creating") {
|
|
3639
|
+
return result;
|
|
3640
|
+
}
|
|
3641
|
+
if (process.env.COMPUTESDK_DEBUG) {
|
|
3642
|
+
console.log(`[Compute] Sandbox still creating, waiting ${currentDelay}ms...`);
|
|
3643
|
+
}
|
|
3644
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
3645
|
+
currentDelay = Math.min(currentDelay * backoffFactor, maxDelayMs);
|
|
3646
|
+
}
|
|
3647
|
+
throw new Error(
|
|
3648
|
+
`Sandbox is still being created after ${maxWaitMs}ms. This may indicate the sandbox failed to start. Check your provider dashboard.`
|
|
3649
|
+
);
|
|
3650
|
+
}
|
|
3623
3651
|
var ComputeManager = class {
|
|
3624
3652
|
constructor() {
|
|
3625
3653
|
this.config = null;
|
|
@@ -3707,14 +3735,15 @@ var ComputeManager = class {
|
|
|
3707
3735
|
findOrCreate: async (options) => {
|
|
3708
3736
|
const config = this.getGatewayConfig();
|
|
3709
3737
|
const { name, namespace, ...restOptions } = options;
|
|
3710
|
-
const result = await
|
|
3711
|
-
|
|
3712
|
-
|
|
3738
|
+
const result = await waitForSandboxStatus(
|
|
3739
|
+
config,
|
|
3740
|
+
`${config.gatewayUrl}/v1/sandboxes/find-or-create`,
|
|
3741
|
+
{
|
|
3713
3742
|
namespace: namespace || "default",
|
|
3714
3743
|
name,
|
|
3715
3744
|
...restOptions
|
|
3716
|
-
}
|
|
3717
|
-
|
|
3745
|
+
}
|
|
3746
|
+
);
|
|
3718
3747
|
if (!result.success || !result.data) {
|
|
3719
3748
|
throw new Error(`Gateway returned invalid response`);
|
|
3720
3749
|
}
|
|
@@ -3744,13 +3773,14 @@ var ComputeManager = class {
|
|
|
3744
3773
|
*/
|
|
3745
3774
|
find: async (options) => {
|
|
3746
3775
|
const config = this.getGatewayConfig();
|
|
3747
|
-
const result = await
|
|
3748
|
-
|
|
3749
|
-
|
|
3776
|
+
const result = await waitForSandboxStatus(
|
|
3777
|
+
config,
|
|
3778
|
+
`${config.gatewayUrl}/v1/sandboxes/find`,
|
|
3779
|
+
{
|
|
3750
3780
|
namespace: options.namespace || "default",
|
|
3751
3781
|
name: options.name
|
|
3752
|
-
}
|
|
3753
|
-
|
|
3782
|
+
}
|
|
3783
|
+
);
|
|
3754
3784
|
if (!result.success || !result.data) {
|
|
3755
3785
|
return null;
|
|
3756
3786
|
}
|