@voidrun/sdk 0.0.11 → 0.0.13
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 +637 -0
- package/dist/utils/runtime.d.ts.map +1 -1
- package/dist/utils/runtime.js +25 -6
- package/dist/utils/runtime.js.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
# VoidRun TypeScript SDK
|
|
2
|
+
|
|
3
|
+
A powerful, type-safe SDK for interacting with VoidRun AI Sandboxes. Execute code, manage files, watch file changes, and interact with pseudo-terminals in isolated environments.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@voidrun/sdk)
|
|
6
|
+
[](https://opensource.org/licenses/ISC)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🏗️ **Sandbox Management** - Create, list, snapshot, and restore sandboxes
|
|
11
|
+
- 🚀 **Code Execution** - Execute commands with real-time output capture
|
|
12
|
+
- 📁 **File Operations** - Create, read, delete, compress, and extract files
|
|
13
|
+
- 👀 **File Watching** - Monitor file changes in real-time via WebSocket
|
|
14
|
+
- 💻 **Pseudo-Terminal (PTY)** - Interactive terminal sessions (ephemeral & persistent)
|
|
15
|
+
- 🔐 **Type-Safe** - Full TypeScript support with generated types from OpenAPI
|
|
16
|
+
- ⚡ **WebSocket Support** - Real-time streaming for PTY, file watches, and execution
|
|
17
|
+
- 🎯 **Promise-Based** - Modern async/await API
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @voidrun/sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or with yarn:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add @voidrun/sdk
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### Authentication
|
|
34
|
+
|
|
35
|
+
Set your API key via environment variable:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
export API_KEY="your-api-key-here"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Basic Usage
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { VoidRun } from '@voidrun/sdk';
|
|
45
|
+
|
|
46
|
+
// Initialize the SDK
|
|
47
|
+
const vr = new VoidRun({});
|
|
48
|
+
|
|
49
|
+
// Create a sandbox
|
|
50
|
+
const sandbox = await vr.createSandbox({ mem: 1024, cpu: 1 });
|
|
51
|
+
|
|
52
|
+
// Execute a command
|
|
53
|
+
const result = await sandbox.exec({ command: 'echo "Hello from VoidRun"' });
|
|
54
|
+
console.log(result.data?.stdout);
|
|
55
|
+
|
|
56
|
+
// Clean up
|
|
57
|
+
await sandbox.remove();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Core Concepts
|
|
61
|
+
|
|
62
|
+
### Sandboxes
|
|
63
|
+
|
|
64
|
+
An isolated environment where you can execute code, manage files, and run terminals.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// Create a sandbox
|
|
68
|
+
const sandbox = await vr.createSandbox({
|
|
69
|
+
mem: 1024, // Memory in MB (optional, has defaults)
|
|
70
|
+
cpu: 1 // CPU cores (optional, has defaults)
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// List all sandboxes
|
|
74
|
+
const { sandboxes, meta } = await vr.listSandboxes();
|
|
75
|
+
console.log(`Total sandboxes: ${sandboxes.length}`);
|
|
76
|
+
|
|
77
|
+
// Get a specific sandbox
|
|
78
|
+
const existingSandbox = await vr.getSandbox(sandboxId);
|
|
79
|
+
|
|
80
|
+
// Remove a sandbox
|
|
81
|
+
await sandbox.remove();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Code Execution
|
|
85
|
+
|
|
86
|
+
Execute commands and capture output, errors, and exit codes.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const result = await sandbox.exec({ command: 'ls -la /home' });
|
|
90
|
+
|
|
91
|
+
console.log(result.data?.stdout); // stdout
|
|
92
|
+
console.log(result.data?.stderr); // stderr
|
|
93
|
+
console.log(result.data?.exitCode); // exit code
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### File Operations
|
|
97
|
+
|
|
98
|
+
Create, read, update, and manage files in the sandbox.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// Create a file
|
|
102
|
+
await sandbox.fs.createFile('/tmp/hello.txt');
|
|
103
|
+
|
|
104
|
+
// Upload content to file
|
|
105
|
+
await sandbox.fs.uploadFile('/tmp/hello.txt', 'Hello, World!');
|
|
106
|
+
|
|
107
|
+
// Read a file
|
|
108
|
+
const buffer = await sandbox.fs.downloadFile('/tmp/hello.txt');
|
|
109
|
+
const content = buffer.toString();
|
|
110
|
+
|
|
111
|
+
// Delete a file
|
|
112
|
+
await sandbox.fs.deleteFile('/tmp/hello.txt');
|
|
113
|
+
|
|
114
|
+
// List directory
|
|
115
|
+
const result = await sandbox.fs.listFiles('/tmp');
|
|
116
|
+
const files = result.data?.files;
|
|
117
|
+
|
|
118
|
+
// Get file stats
|
|
119
|
+
const stats = await sandbox.fs.statFile('/tmp/hello.txt');
|
|
120
|
+
|
|
121
|
+
// Compress files
|
|
122
|
+
await sandbox.fs.compressFile('/tmp', 'tar.gz');
|
|
123
|
+
|
|
124
|
+
// Extract archive
|
|
125
|
+
await sandbox.fs.extractArchive('/tmp/archive.tar.gz', '/tmp/extracted');
|
|
126
|
+
|
|
127
|
+
// Create directory
|
|
128
|
+
await sandbox.fs.createDirectory('/tmp/mydir');
|
|
129
|
+
|
|
130
|
+
// Move file
|
|
131
|
+
await sandbox.fs.moveFile('/tmp/file.txt', '/tmp/newfile.txt');
|
|
132
|
+
|
|
133
|
+
// Copy file
|
|
134
|
+
await sandbox.fs.copyFile('/tmp/file.txt', '/tmp/copy.txt');
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### File Watching
|
|
138
|
+
|
|
139
|
+
Monitor file changes in real-time.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
const watcher = await sandbox.fs.watch('/app', {
|
|
143
|
+
recursive: true,
|
|
144
|
+
onEvent: (event) => {
|
|
145
|
+
console.log(`File changed: ${event.path} - ${event.type}`);
|
|
146
|
+
},
|
|
147
|
+
onError: (err) => {
|
|
148
|
+
console.error('Watch error:', err);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Stop watching
|
|
153
|
+
watcher.close();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Pseudo-Terminal (PTY)
|
|
157
|
+
|
|
158
|
+
Interactive terminal sessions with two modes:
|
|
159
|
+
|
|
160
|
+
#### Ephemeral Sessions (Temporary)
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// No session management - temporary shell
|
|
164
|
+
const pty = await sandbox.pty.connect({
|
|
165
|
+
onData: (data) => {
|
|
166
|
+
process.stdout.write(data);
|
|
167
|
+
},
|
|
168
|
+
onError: (err) => {
|
|
169
|
+
console.error('PTY error:', err);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Send commands
|
|
174
|
+
pty.write('echo "Hello"\n');
|
|
175
|
+
pty.write('pwd\n');
|
|
176
|
+
|
|
177
|
+
// Close connection
|
|
178
|
+
pty.close();
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Persistent Sessions
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// Create a persistent session
|
|
185
|
+
const response = await sandbox.pty.createSession();
|
|
186
|
+
const sessionId = response.data?.sessionId;
|
|
187
|
+
|
|
188
|
+
// Connect to the session
|
|
189
|
+
const pty = await sandbox.pty.connect({
|
|
190
|
+
sessionId,
|
|
191
|
+
onData: (data) => {
|
|
192
|
+
process.stdout.write(data);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Send commands
|
|
197
|
+
pty.write('echo "Hello"\n');
|
|
198
|
+
|
|
199
|
+
// Close connection
|
|
200
|
+
pty.close();
|
|
201
|
+
|
|
202
|
+
// Reconnect later - session and output persist
|
|
203
|
+
const reconnected = await sandbox.pty.connect({
|
|
204
|
+
sessionId,
|
|
205
|
+
onData: (data) => {
|
|
206
|
+
process.stdout.write(data); // Includes buffered output
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Interactive Commands
|
|
212
|
+
|
|
213
|
+
Run commands with automatic prompt detection:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const pty = await sandbox.pty.connect({ sessionId });
|
|
217
|
+
|
|
218
|
+
const output = await pty.runCommand('echo $SHELL', {
|
|
219
|
+
timeout: 5000,
|
|
220
|
+
prompt: /[#$] $/ // Regex to detect shell prompt
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
console.log('Output:', output);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Resize Terminal
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
pty.resize(80, 24); // columns, rows
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Session Management
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// List all sessions
|
|
236
|
+
const sessions = await sandbox.pty.list();
|
|
237
|
+
|
|
238
|
+
// Delete a session
|
|
239
|
+
await sandbox.pty.deleteSession(sessionId);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## API Reference
|
|
243
|
+
|
|
244
|
+
### VoidRun Class
|
|
245
|
+
|
|
246
|
+
Main client for interacting with the API.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
new VoidRun(options?: VoidRunOptions)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Options:**
|
|
253
|
+
- `apiKey?: string` - API key (defaults to `process.env.API_KEY`)
|
|
254
|
+
- `baseUrl?: string` - Base API URL (defaults to `process.env.VOIDRUN_BASE_URL`)
|
|
255
|
+
- `orgId?: string` - Organization ID (optional)
|
|
256
|
+
|
|
257
|
+
**Methods:**
|
|
258
|
+
- `createSandbox(options: SandboxOptions)` - Create a new sandbox
|
|
259
|
+
- `name?: string` - Sandbox name
|
|
260
|
+
- `templateId?: string` - Template ID
|
|
261
|
+
- `cpu?: number` - CPU cores
|
|
262
|
+
- `mem?: number` - Memory in MB
|
|
263
|
+
- `orgId?: string` - Organization ID
|
|
264
|
+
- `userId?: string` - User ID
|
|
265
|
+
- `sync?: boolean` - Sync mode
|
|
266
|
+
- `language?: 'javascript' | 'typescript' | 'python'` - Language
|
|
267
|
+
- `listSandboxes()` - List all sandboxes (returns `{ sandboxes: Sandbox[], meta }`)
|
|
268
|
+
- `getSandbox(id: string)` - Get a specific sandbox
|
|
269
|
+
- `removeSandbox(id: string)` - Delete a sandbox
|
|
270
|
+
|
|
271
|
+
### Sandbox Class
|
|
272
|
+
|
|
273
|
+
Represents an isolated sandbox environment.
|
|
274
|
+
|
|
275
|
+
**Properties:**
|
|
276
|
+
- `id: string` - Sandbox ID
|
|
277
|
+
- `name: string` - Sandbox name
|
|
278
|
+
- `cpu: number` - CPU cores
|
|
279
|
+
- `mem: number` - Memory in MB
|
|
280
|
+
- `orgId: string` - Organization ID
|
|
281
|
+
- `createdAt: Date` - Creation timestamp
|
|
282
|
+
- `createdBy: string` - Creator ID
|
|
283
|
+
- `status: string` - Sandbox status
|
|
284
|
+
- `language?: string` - Language (optional)
|
|
285
|
+
- `fs: FS` - File system interface
|
|
286
|
+
- `pty: PTY` - PTY interface
|
|
287
|
+
|
|
288
|
+
**Methods:**
|
|
289
|
+
- `exec(request: ExecRequest)` - Execute a command
|
|
290
|
+
- `request.command: string` - Command to execute
|
|
291
|
+
- `request.cwd?: string` - Working directory (optional)
|
|
292
|
+
- `request.env?: Record<string, string>` - Environment variables (optional)
|
|
293
|
+
- `request.timeout?: number` - Timeout in seconds (optional)
|
|
294
|
+
- `remove()` - Delete the sandbox
|
|
295
|
+
- `info()` - Get sandbox information
|
|
296
|
+
|
|
297
|
+
**Exec Response:**
|
|
298
|
+
```typescript
|
|
299
|
+
{
|
|
300
|
+
data?: {
|
|
301
|
+
stdout: string; // standard output
|
|
302
|
+
stderr: string; // standard error
|
|
303
|
+
exitCode: number; // exit code
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### FileSystem Interface
|
|
309
|
+
|
|
310
|
+
Manage files and directories.
|
|
311
|
+
|
|
312
|
+
**Methods:**
|
|
313
|
+
- `createFile(path: string)` - Create a file
|
|
314
|
+
- `uploadFile(path: string, content: string)` - Upload file content
|
|
315
|
+
- `uploadFileStream(path: string, stream: ReadableStream)` - Upload file as stream
|
|
316
|
+
- `uploadFileFromPath(remotePath: string, localPath: string)` - Upload from local file
|
|
317
|
+
- `downloadFile(path: string)` - Download file as Buffer
|
|
318
|
+
- `downloadFileStream(path: string)` - Download file as ReadableStream
|
|
319
|
+
- `deleteFile(path: string)` - Delete a file
|
|
320
|
+
- `listFiles(path: string)` - List directory contents
|
|
321
|
+
- `statFile(path: string)` - Get file metadata
|
|
322
|
+
- `createDirectory(path: string)` - Create a directory
|
|
323
|
+
- `compressFile(path: string, format: 'tar' | 'tar.gz' | 'tar.bz2' | 'zip')` - Create archive
|
|
324
|
+
- `extractArchive(archivePath: string, destPath?: string)` - Extract archive
|
|
325
|
+
- `moveFile(from: string, to: string)` - Move/rename file
|
|
326
|
+
- `copyFile(from: string, to: string)` - Copy file
|
|
327
|
+
- `changePermissions(path: string, mode: string)` - Change file permissions
|
|
328
|
+
- `headTail(path: string, options?: { lines?: number; head?: boolean })` - Read file head/tail
|
|
329
|
+
- `searchFiles(path: string, pattern: string)` - Search files by pattern
|
|
330
|
+
- `folderSize(path: string)` - Get folder size
|
|
331
|
+
- `watch(path: string, options: FileWatchOptions)` - Watch for file changes
|
|
332
|
+
|
|
333
|
+
### FileWatcher Interface
|
|
334
|
+
|
|
335
|
+
Monitor file changes in real-time.
|
|
336
|
+
|
|
337
|
+
**Methods:**
|
|
338
|
+
- `watch(path: string, options: FileWatchOptions)` - Start watching a path
|
|
339
|
+
- `recursive?: boolean` - Watch subdirectories
|
|
340
|
+
- `onEvent(event: FileChangeEvent)` - Called on file change
|
|
341
|
+
- `onError(error: Error)` - Called on error
|
|
342
|
+
- `onClose()` - Called when watcher closes (optional)
|
|
343
|
+
|
|
344
|
+
**Watcher Methods:**
|
|
345
|
+
- `close()` - Stop watching
|
|
346
|
+
|
|
347
|
+
### PTY Interface
|
|
348
|
+
|
|
349
|
+
Pseudo-terminal operations.
|
|
350
|
+
|
|
351
|
+
**Methods:**
|
|
352
|
+
- `list()` - List active sessions
|
|
353
|
+
- `createSession()` - Create a persistent session
|
|
354
|
+
- `connect(options: PtyOptions)` - Connect to PTY
|
|
355
|
+
- `sessionId?: string` - For persistent sessions
|
|
356
|
+
- `onData(data: string)` - Receive data
|
|
357
|
+
- `onError(error: Error)` - Handle errors
|
|
358
|
+
- `onClose()` - Connection closed (optional)
|
|
359
|
+
- `deleteSession(sessionId: string)` - Delete a session
|
|
360
|
+
|
|
361
|
+
**PtySession Methods:**
|
|
362
|
+
- `write(data: string)` - Send data
|
|
363
|
+
- `runCommand(cmd: string, options: RunCommandOptions)` - Execute with prompt detection
|
|
364
|
+
- `resize(cols: number, rows: number)` - Resize terminal
|
|
365
|
+
- `close()` - Close connection
|
|
366
|
+
|
|
367
|
+
## Examples
|
|
368
|
+
|
|
369
|
+
### Execute Python Script
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { VoidRun } from '@voidrun/sdk';
|
|
373
|
+
|
|
374
|
+
const vr = new VoidRun({});
|
|
375
|
+
const sandbox = await vr.createSandbox({ mem: 1024, cpu: 1 });
|
|
376
|
+
|
|
377
|
+
// Create Python script
|
|
378
|
+
await sandbox.fs.createFile('/tmp/script.py');
|
|
379
|
+
await sandbox.fs.uploadFile('/tmp/script.py', `
|
|
380
|
+
import sys
|
|
381
|
+
print("Python version:", sys.version)
|
|
382
|
+
print("Hello from Python!")
|
|
383
|
+
`);
|
|
384
|
+
|
|
385
|
+
const result = await sandbox.exec({ command: 'python3 /tmp/script.py' });
|
|
386
|
+
console.log(result.data?.stdout);
|
|
387
|
+
|
|
388
|
+
await sandbox.remove();
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Monitor Code Changes
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
const sandbox = await vr.createSandbox({ mem: 1024, cpu: 1 });
|
|
395
|
+
|
|
396
|
+
// Watch for TypeScript file changes
|
|
397
|
+
const watcher = await sandbox.fs.watch('/app/src', {
|
|
398
|
+
recursive: true,
|
|
399
|
+
onEvent: async (event) => {
|
|
400
|
+
console.log(`File ${event.type}: ${event.path}`);
|
|
401
|
+
|
|
402
|
+
// Auto-compile on change
|
|
403
|
+
await sandbox.exec({ command: 'npm run build' });
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
// Clean up
|
|
408
|
+
setTimeout(() => watcher.close(), 60000);
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Build & Test Workflow
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
const sandbox = await vr.createSandbox({ mem: 2048, cpu: 2 });
|
|
415
|
+
|
|
416
|
+
// Upload source code
|
|
417
|
+
const sourceCode = `console.log('Hello World');`;
|
|
418
|
+
await sandbox.fs.createFile('/app/main.js');
|
|
419
|
+
await sandbox.fs.uploadFile('/app/main.js', sourceCode);
|
|
420
|
+
|
|
421
|
+
// Install dependencies
|
|
422
|
+
let result = await sandbox.exec({ command: 'npm install' });
|
|
423
|
+
if (result.data?.exitCode !== 0) throw new Error('Install failed');
|
|
424
|
+
|
|
425
|
+
// Run tests
|
|
426
|
+
result = await sandbox.exec({ command: 'npm test' });
|
|
427
|
+
console.log('Test output:', result.data?.stdout);
|
|
428
|
+
|
|
429
|
+
// Build
|
|
430
|
+
result = await sandbox.exec({ command: 'npm run build' });
|
|
431
|
+
console.log('Build output:', result.data?.stdout);
|
|
432
|
+
|
|
433
|
+
await sandbox.remove();
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Interactive Development Shell
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
const sandbox = await vr.createSandbox({ mem: 1024, cpu: 1 });
|
|
440
|
+
|
|
441
|
+
// Create a persistent session
|
|
442
|
+
const sessionResp = await sandbox.pty.createSession();
|
|
443
|
+
const sessionId = sessionResp.data?.sessionId;
|
|
444
|
+
|
|
445
|
+
const pty = await sandbox.pty.connect({
|
|
446
|
+
sessionId,
|
|
447
|
+
onData: (data) => process.stdout.write(data),
|
|
448
|
+
onClose: () => console.log('Shell closed')
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Interactive commands
|
|
452
|
+
pty.write('npm init -y\n');
|
|
453
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
454
|
+
|
|
455
|
+
pty.write('npm install express\n');
|
|
456
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
457
|
+
|
|
458
|
+
pty.write('node -e "console.log(process.version)"\n');
|
|
459
|
+
await new Promise(r => setTimeout(r, 500));
|
|
460
|
+
|
|
461
|
+
pty.close();
|
|
462
|
+
await sandbox.remove();
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Configuration
|
|
466
|
+
|
|
467
|
+
### Environment Variables
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
# API Key (required)
|
|
471
|
+
export API_KEY="your-api-key-here"
|
|
472
|
+
|
|
473
|
+
# Base URL (optional)
|
|
474
|
+
export VOIDRUN_BASE_URL="https://api.voidrun.com"
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### .env File
|
|
478
|
+
|
|
479
|
+
Create a `.env` file in your project root:
|
|
480
|
+
|
|
481
|
+
```env
|
|
482
|
+
API_KEY=your-api-key-here
|
|
483
|
+
VOIDRUN_BASE_URL=https://api.voidrun.com
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Then run with:
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
npx tsx --env-file=.env your-script.ts
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## Error Handling
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
try {
|
|
496
|
+
const sandbox = await vr.createSandbox({ mem: 256, cpu: 0.5 });
|
|
497
|
+
// ...
|
|
498
|
+
} catch (error) {
|
|
499
|
+
if (error instanceof Error) {
|
|
500
|
+
console.error('Error:', error.message);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Common errors:
|
|
506
|
+
- **Validation Error** - Invalid sandbox parameters
|
|
507
|
+
- **Authentication Error** - Invalid or missing API key
|
|
508
|
+
- **Not Found** - Sandbox or session doesn't exist
|
|
509
|
+
- **Timeout** - Operation took too long
|
|
510
|
+
|
|
511
|
+
## Testing
|
|
512
|
+
|
|
513
|
+
Run the comprehensive test suite:
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
npm install
|
|
517
|
+
npx tsx --env-file=.env example/test-pty-comprehensive.ts
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
Available examples:
|
|
521
|
+
- `test-pty-comprehensive.ts` - Full PTY testing (9 scenarios)
|
|
522
|
+
- `test-sandbox-exec.ts` - Code execution examples
|
|
523
|
+
- `test-sandbox-fs.ts` - File system operations
|
|
524
|
+
- `test-sandbox-lifecycle.ts` - Sandbox management
|
|
525
|
+
- `test-watch.ts` - File watching
|
|
526
|
+
- `js-example.ts` - JavaScript example
|
|
527
|
+
- `py-example.ts` - Python example
|
|
528
|
+
|
|
529
|
+
## Building from Source
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
# Install dependencies
|
|
533
|
+
npm install
|
|
534
|
+
|
|
535
|
+
# Build TypeScript
|
|
536
|
+
npm run build
|
|
537
|
+
|
|
538
|
+
# Clean build artifacts
|
|
539
|
+
npm run clean
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
## Publishing
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
# Build and publish to npm
|
|
546
|
+
npm run publish
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Troubleshooting
|
|
550
|
+
|
|
551
|
+
### "API_KEY is not set"
|
|
552
|
+
|
|
553
|
+
Set your API key:
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
export API_KEY="your-api-key"
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### "Sandbox creation failed"
|
|
560
|
+
|
|
561
|
+
Ensure your sandbox parameters are valid:
|
|
562
|
+
- `mem`: minimum 1024 MB
|
|
563
|
+
- `cpu`: minimum 1 core
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
const sandbox = await vr.createSandbox({
|
|
567
|
+
mem: 1024, // At least 1GB
|
|
568
|
+
cpu: 1 // At least 1 core
|
|
569
|
+
});
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### "PTY Connection Timeout"
|
|
573
|
+
|
|
574
|
+
Increase timeout for slow systems:
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
const pty = await sandbox.pty.connect({
|
|
578
|
+
sessionId,
|
|
579
|
+
onData: (data) => console.log(data)
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
// For runCommand
|
|
583
|
+
const output = await pty.runCommand('slow-command', {
|
|
584
|
+
timeout: 30000 // 30 seconds
|
|
585
|
+
});
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### "File Not Found"
|
|
589
|
+
|
|
590
|
+
Check the file path:
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
// List files to verify path
|
|
594
|
+
const files = await sandbox.fs.listFiles('/app');
|
|
595
|
+
console.log(files.data?.files);
|
|
596
|
+
|
|
597
|
+
// Then access specific file
|
|
598
|
+
const content = await sandbox.fs.readFile('/app/file.txt');
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
## API Documentation
|
|
602
|
+
|
|
603
|
+
Full API documentation is available at:
|
|
604
|
+
- [OpenAPI Spec](./openapi.yml)
|
|
605
|
+
- [API Docs](./src/api-client/docs/)
|
|
606
|
+
|
|
607
|
+
## Contributing
|
|
608
|
+
|
|
609
|
+
Contributions are welcome! Please check the main repository for guidelines.
|
|
610
|
+
|
|
611
|
+
## License
|
|
612
|
+
|
|
613
|
+
ISC License - See LICENSE file for details
|
|
614
|
+
|
|
615
|
+
## Support
|
|
616
|
+
|
|
617
|
+
- 📧 Email: support@voidrun.com
|
|
618
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/voidrun/ts-sdk/issues)
|
|
619
|
+
- 💬 Discussions: [GitHub Discussions](https://github.com/voidrun/ts-sdk/discussions)
|
|
620
|
+
|
|
621
|
+
## Changelog
|
|
622
|
+
|
|
623
|
+
### v0.0.2
|
|
624
|
+
- Fixed PTY session response field mapping
|
|
625
|
+
- Added fallback logic for empty sessionId
|
|
626
|
+
- Improved error handling and validation
|
|
627
|
+
|
|
628
|
+
### v0.0.1
|
|
629
|
+
- Initial release
|
|
630
|
+
- Sandbox management
|
|
631
|
+
- File operations
|
|
632
|
+
- Code execution
|
|
633
|
+
- PTY support
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
**Made with ❤️ by VoidRun**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/utils/runtime.ts"],"names":[],"mappings":"AAQA,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/utils/runtime.ts"],"names":[],"mappings":"AAQA,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAiCpE"}
|
package/dist/utils/runtime.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ResponseError } from "../api-client/index.js";
|
|
2
2
|
class RuntimeError extends Error {
|
|
3
|
-
|
|
3
|
+
cause;
|
|
4
|
+
constructor(message, cause) {
|
|
4
5
|
super(message);
|
|
6
|
+
this.cause = cause;
|
|
5
7
|
}
|
|
6
8
|
}
|
|
7
9
|
export async function wrapRequest(promise) {
|
|
@@ -11,13 +13,30 @@ export async function wrapRequest(promise) {
|
|
|
11
13
|
}
|
|
12
14
|
catch (err) {
|
|
13
15
|
if (err instanceof ResponseError) {
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const status = err.response.status;
|
|
17
|
+
const statusText = err.response.statusText || 'HTTP Error';
|
|
18
|
+
let bodyMessage;
|
|
19
|
+
try {
|
|
20
|
+
const errorBody = await err.response.json();
|
|
21
|
+
bodyMessage = errorBody?.error || errorBody?.message;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
try {
|
|
25
|
+
const errorText = await err.response.text();
|
|
26
|
+
bodyMessage = errorText?.trim();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
bodyMessage = undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const message = bodyMessage
|
|
33
|
+
? `Request failed (${status} ${statusText}): ${bodyMessage}`
|
|
34
|
+
: `Request failed (${status} ${statusText})`;
|
|
35
|
+
throw new RuntimeError(message, err);
|
|
18
36
|
}
|
|
19
37
|
// Handle network errors (e.g., server down)
|
|
20
|
-
|
|
38
|
+
const fallback = err instanceof Error ? err.message : 'Network or unexpected error';
|
|
39
|
+
throw new RuntimeError(`Network error: ${fallback}`, err);
|
|
21
40
|
}
|
|
22
41
|
}
|
|
23
42
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/utils/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,YAAa,SAAQ,KAAK;
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/utils/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,YAAa,SAAQ,KAAK;IACiB;IAA7C,YAAY,OAAe,EAAkB,KAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD0B,UAAK,GAAL,KAAK,CAAU;IAE5D,CAAC;CACJ;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAI,OAAmB;IACpD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC;QAC3B,OAAO,IAAI,CAAA;IACf,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;YACnC,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,YAAY,CAAC;YAC3D,IAAI,WAA+B,CAAC;YAEpC,IAAI,CAAC;gBACD,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC5C,WAAW,GAAG,SAAS,EAAE,KAAK,IAAI,SAAS,EAAE,OAAO,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACL,IAAI,CAAC;oBACD,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAC5C,WAAW,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC;gBACpC,CAAC;gBAAC,MAAM,CAAC;oBACL,WAAW,GAAG,SAAS,CAAC;gBAC5B,CAAC;YACL,CAAC;YAED,MAAM,OAAO,GAAG,WAAW;gBACvB,CAAC,CAAC,mBAAmB,MAAM,IAAI,UAAU,MAAM,WAAW,EAAE;gBAC5D,CAAC,CAAC,mBAAmB,MAAM,IAAI,UAAU,GAAG,CAAC;YAEjD,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACzC,CAAC;QAED,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;QACpF,MAAM,IAAI,YAAY,CAAC,kBAAkB,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;IAC9D,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voidrun/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "VoidRun AI Sandbox SDK",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "tsc",
|
|
13
13
|
"clean": "rm -rf dist",
|
|
14
|
-
"
|
|
14
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [],
|
|
17
17
|
"author": "VoidRun",
|