instavm 0.8.3 → 0.11.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 +200 -812
- package/dist/index.d.mts +323 -2
- package/dist/index.d.ts +323 -2
- package/dist/index.js +769 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +760 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
# InstaVM JavaScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **Code Execution**: Run Python, Bash, and other languages in secure cloud environments
|
|
8
|
-
- **Browser Automation**: Control web browsers for testing, scraping, and automation
|
|
9
|
-
- **Session Management**: Automatic session creation and persistent execution contexts
|
|
10
|
-
- **File Operations**: Upload files to execution environments
|
|
11
|
-
- **Async Support**: Execute commands asynchronously for long-running tasks
|
|
12
|
-
- **Error Handling**: Comprehensive exception hierarchy for different failure modes
|
|
13
|
-
- **TypeScript Support**: Full type safety with comprehensive TypeScript definitions
|
|
14
|
-
- **Modern JavaScript**: ES modules, CommonJS, and UMD support
|
|
5
|
+
Official JavaScript/TypeScript client for InstaVM code execution, VM lifecycle, snapshots, networking controls, browser automation, and platform APIs.
|
|
15
6
|
|
|
16
7
|
## Installation
|
|
17
8
|
|
|
@@ -21,949 +12,346 @@ npm install instavm
|
|
|
21
12
|
|
|
22
13
|
## Quick Start
|
|
23
14
|
|
|
24
|
-
###
|
|
15
|
+
### Cloud Quick Start
|
|
25
16
|
|
|
26
17
|
```typescript
|
|
27
|
-
import { InstaVM
|
|
18
|
+
import { InstaVM } from 'instavm';
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
const client = new InstaVM('your_api_key');
|
|
20
|
+
const client = new InstaVM(process.env.INSTAVM_API_KEY || 'your_api_key');
|
|
31
21
|
|
|
32
22
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
console.log(result);
|
|
36
|
-
|
|
37
|
-
// Get usage info for the session
|
|
38
|
-
const usage = await client.getUsage();
|
|
39
|
-
console.log(usage);
|
|
23
|
+
const result = await client.execute("print('hello from instavm')");
|
|
24
|
+
console.log(result.stdout);
|
|
40
25
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
console.log(`Code execution failed: ${error.message}`);
|
|
44
|
-
} else if (error instanceof NetworkError) {
|
|
45
|
-
console.log(`Network issue: ${error.message}`);
|
|
46
|
-
}
|
|
26
|
+
const usage = await client.getUsage();
|
|
27
|
+
console.log(usage);
|
|
47
28
|
} finally {
|
|
48
|
-
|
|
29
|
+
await client.dispose();
|
|
49
30
|
}
|
|
50
31
|
```
|
|
51
32
|
|
|
52
|
-
### Local
|
|
53
|
-
|
|
54
|
-
Run code execution against a local container (e.g., [coderunner](https://github.com/instavm/coderunner)) instead of the cloud API:
|
|
33
|
+
### Local Mode Quick Start
|
|
55
34
|
|
|
56
35
|
```typescript
|
|
57
36
|
import { InstaVM } from 'instavm';
|
|
58
37
|
|
|
59
|
-
// Create client in local mode (no API key required)
|
|
60
38
|
const client = new InstaVM('', {
|
|
61
|
-
|
|
62
|
-
|
|
39
|
+
local: true,
|
|
40
|
+
localURL: 'http://coderunner.local:8222',
|
|
63
41
|
});
|
|
64
42
|
|
|
65
|
-
|
|
66
|
-
const result = await client.execute("print('Hello from local container!')");
|
|
43
|
+
const result = await client.execute("print('hello from local mode')");
|
|
67
44
|
console.log(result.stdout);
|
|
68
45
|
|
|
69
|
-
// Browser automation in local mode (no session required)
|
|
70
46
|
const content = await client.browser.extractContent({
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
47
|
+
url: 'https://example.com',
|
|
48
|
+
includeInteractive: true,
|
|
49
|
+
includeAnchors: true,
|
|
74
50
|
});
|
|
75
|
-
console.log('Page title:', content.readableContent.title);
|
|
76
|
-
console.log('Clean content:', content.readableContent.content);
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
**Note:** Local mode supports:
|
|
80
|
-
- ✅ Code execution (`execute()`)
|
|
81
|
-
- ✅ Browser navigation (`browser.navigate()`)
|
|
82
|
-
- ✅ Content extraction (`browser.extractContent()`)
|
|
83
|
-
|
|
84
|
-
Local mode does NOT support (cloud-only features):
|
|
85
|
-
- ❌ Session management (`createSession()`, `closeSession()`, `getUsage()`)
|
|
86
|
-
- ❌ File upload/download
|
|
87
|
-
- ❌ Async execution
|
|
88
|
-
- ❌ Browser session creation and complex interactions
|
|
89
|
-
|
|
90
|
-
### File Upload
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
import { InstaVM } from 'instavm';
|
|
94
51
|
|
|
95
|
-
|
|
52
|
+
console.log(content.readableContent.title);
|
|
53
|
+
```
|
|
96
54
|
|
|
97
|
-
|
|
98
|
-
await client.createSession();
|
|
55
|
+
## Table of Contents
|
|
99
56
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
];
|
|
57
|
+
- [Core Workflows](#core-workflows)
|
|
58
|
+
- [Infrastructure & Platform APIs](#infrastructure-platform-apis)
|
|
59
|
+
- [Browser & Computer Use](#browser-computer-use)
|
|
60
|
+
- [Error Handling](#error-handling)
|
|
61
|
+
- [Development & Testing](#development-testing)
|
|
62
|
+
- [Docs Map (Further Reading)](#docs-map-further-reading)
|
|
63
|
+
- [Version / Changelog](#version-changelog)
|
|
108
64
|
|
|
109
|
-
|
|
110
|
-
|
|
65
|
+
<a id="core-workflows"></a>
|
|
66
|
+
## Core Workflows
|
|
111
67
|
|
|
112
|
-
|
|
113
|
-
const execution = await client.execute('python /remote/path/script.py', {
|
|
114
|
-
language: 'bash'
|
|
115
|
-
});
|
|
116
|
-
console.log(execution.stdout);
|
|
117
|
-
```
|
|
68
|
+
### Cloud Quick Start
|
|
118
69
|
|
|
119
|
-
|
|
70
|
+
Cloud mode supports sessions, VM/network controls, platform APIs, and browser sessions.
|
|
120
71
|
|
|
121
72
|
```typescript
|
|
122
73
|
import { InstaVM } from 'instavm';
|
|
123
|
-
import fs from 'fs';
|
|
124
|
-
|
|
125
|
-
const client = new InstaVM('your_api_key');
|
|
126
|
-
|
|
127
|
-
// Create a file in the remote environment
|
|
128
|
-
await client.execute(`
|
|
129
|
-
import pandas as pd
|
|
130
|
-
df = pd.DataFrame({'name': ['Alice', 'Bob'], 'age': [25, 30]})
|
|
131
|
-
df.to_csv('data.csv', index=False)
|
|
132
|
-
`);
|
|
133
74
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
75
|
+
const client = new InstaVM('your_api_key', {
|
|
76
|
+
cpu_count: 2,
|
|
77
|
+
memory_mb: 1024,
|
|
78
|
+
env: { APP_ENV: 'dev' },
|
|
79
|
+
metadata: { team: 'platform' },
|
|
80
|
+
});
|
|
137
81
|
|
|
138
|
-
|
|
139
|
-
|
|
82
|
+
const sessionId = await client.createSession();
|
|
83
|
+
console.log('session:', sessionId);
|
|
140
84
|
```
|
|
141
85
|
|
|
142
|
-
###
|
|
86
|
+
### Local Mode Quick Start
|
|
143
87
|
|
|
144
|
-
|
|
145
|
-
import {
|
|
146
|
-
InstaVM,
|
|
147
|
-
AuthenticationError,
|
|
148
|
-
RateLimitError,
|
|
149
|
-
SessionError,
|
|
150
|
-
QuotaExceededError
|
|
151
|
-
} from 'instavm';
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
const client = new InstaVM('invalid_key');
|
|
155
|
-
await client.execute('print("test")');
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (error instanceof AuthenticationError) {
|
|
158
|
-
console.log("Invalid API key");
|
|
159
|
-
} else if (error instanceof RateLimitError) {
|
|
160
|
-
console.log(`Rate limit exceeded - retry after ${error.retryAfter} seconds`);
|
|
161
|
-
} else if (error instanceof QuotaExceededError) {
|
|
162
|
-
console.log("Usage quota exceeded");
|
|
163
|
-
} else if (error instanceof SessionError) {
|
|
164
|
-
console.log(`Session error: ${error.message}`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Async Execution
|
|
88
|
+
Local mode is optimized for direct execution and lightweight browser helpers.
|
|
170
89
|
|
|
171
90
|
```typescript
|
|
172
91
|
import { InstaVM } from 'instavm';
|
|
173
92
|
|
|
174
|
-
const client = new InstaVM('
|
|
93
|
+
const client = new InstaVM('', { local: true });
|
|
175
94
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
language: 'bash'
|
|
179
|
-
});
|
|
180
|
-
const taskId = result.taskId;
|
|
181
|
-
console.log(`Task ${taskId} is running in background...`);
|
|
182
|
-
|
|
183
|
-
// Poll for task result
|
|
184
|
-
const taskResult = await client.getTaskResult(taskId, 2, 30);
|
|
185
|
-
console.log('Task complete!');
|
|
186
|
-
console.log(`Stdout: ${taskResult.stdout}`);
|
|
187
|
-
console.log(`Stderr: ${taskResult.stderr}`);
|
|
95
|
+
await client.execute("print('local execution works')");
|
|
96
|
+
await client.browser.navigate('https://example.com');
|
|
188
97
|
```
|
|
189
98
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
### Basic Browser Usage
|
|
99
|
+
### File Operations
|
|
193
100
|
|
|
194
101
|
```typescript
|
|
195
102
|
import { InstaVM } from 'instavm';
|
|
196
103
|
|
|
197
104
|
const client = new InstaVM('your_api_key');
|
|
105
|
+
const sessionId = await client.createSession();
|
|
198
106
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// Navigate to website
|
|
206
|
-
await session.navigate('https://example.com');
|
|
207
|
-
|
|
208
|
-
// Take screenshot
|
|
209
|
-
const screenshot = await session.screenshot();
|
|
210
|
-
console.log(`Screenshot captured: ${screenshot.length} chars`);
|
|
211
|
-
|
|
212
|
-
// Extract page data
|
|
213
|
-
const elements = await session.extractElements('h1, p', ['text', 'href']);
|
|
214
|
-
console.log('Page content:', elements);
|
|
215
|
-
|
|
216
|
-
// Clean up
|
|
217
|
-
await session.close();
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Advanced Browser Interactions
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
// Navigate with options
|
|
224
|
-
await session.navigate('https://github.com/login', {
|
|
225
|
-
waitTimeout: 30000,
|
|
226
|
-
waitUntil: 'networkidle'
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Fill login form
|
|
230
|
-
await session.fill('input[name="login"]', 'username');
|
|
231
|
-
await session.fill('input[name="password"]', 'password');
|
|
232
|
-
|
|
233
|
-
// Click submit button
|
|
234
|
-
await session.click('input[type="submit"]');
|
|
235
|
-
|
|
236
|
-
// Wait for navigation
|
|
237
|
-
await session.wait({ type: 'navigation' });
|
|
107
|
+
await client.upload(
|
|
108
|
+
[{ name: 'script.py', content: "print('uploaded')", path: '/app/script.py' }],
|
|
109
|
+
{ sessionId }
|
|
110
|
+
);
|
|
238
111
|
|
|
239
|
-
|
|
240
|
-
await session.scroll({ y: 1000 });
|
|
112
|
+
await client.execute('python /app/script.py', { language: 'bash', sessionId });
|
|
241
113
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
console.log('Repositories found:', repos.length);
|
|
114
|
+
const download = await client.download('output.json', { sessionId });
|
|
115
|
+
console.log(download.filename, download.size);
|
|
245
116
|
```
|
|
246
117
|
|
|
247
|
-
###
|
|
118
|
+
### Async Execution
|
|
248
119
|
|
|
249
120
|
```typescript
|
|
250
|
-
|
|
251
|
-
const session = await client.browser.createSession({
|
|
252
|
-
viewportWidth: 1280,
|
|
253
|
-
viewportHeight: 720,
|
|
254
|
-
userAgent: 'CustomBot/1.0'
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// Session supports event listeners
|
|
258
|
-
session.on('navigation', (result) => {
|
|
259
|
-
console.log(`Navigated to: ${result.url}`);
|
|
260
|
-
console.log(`Page title: ${result.title}`);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
session.on('error', (error) => {
|
|
264
|
-
console.error('Session error:', error.message);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
session.on('close', () => {
|
|
268
|
-
console.log('Session closed');
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
// Check if session is still active
|
|
272
|
-
if (session.isActive) {
|
|
273
|
-
await session.navigate('https://example.com');
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Context Manager Pattern
|
|
121
|
+
import { InstaVM } from 'instavm';
|
|
278
122
|
|
|
279
|
-
```typescript
|
|
280
|
-
// Use browser session with automatic cleanup
|
|
281
123
|
const client = new InstaVM('your_api_key');
|
|
282
124
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
try {
|
|
287
|
-
await session.navigate('https://httpbin.org/forms/post');
|
|
288
|
-
|
|
289
|
-
// Fill and submit form
|
|
290
|
-
await session.fill('input[name="custname"]', 'John Doe');
|
|
291
|
-
await session.fill('input[name="custtel"]', '555-1234');
|
|
292
|
-
await session.click('input[type="submit"]');
|
|
293
|
-
|
|
294
|
-
// Wait for result
|
|
295
|
-
await session.wait({ type: 'visible', selector: 'pre' });
|
|
296
|
-
|
|
297
|
-
// Extract result
|
|
298
|
-
const result = await session.extractElements('pre', ['text']);
|
|
299
|
-
return result[0]?.text;
|
|
300
|
-
|
|
301
|
-
} finally {
|
|
302
|
-
await session.close();
|
|
303
|
-
}
|
|
304
|
-
}
|
|
125
|
+
const task = await client.executeAsync("sleep 5 && echo 'done'", { language: 'bash' });
|
|
126
|
+
const result = await client.getTaskResult(task.taskId, 2, 60);
|
|
305
127
|
|
|
306
|
-
|
|
307
|
-
console.log('Form submission result:', result);
|
|
128
|
+
console.log(result.stdout);
|
|
308
129
|
```
|
|
309
130
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
Combine code execution with browser automation for powerful workflows:
|
|
131
|
+
### VMs + Snapshots
|
|
313
132
|
|
|
314
133
|
```typescript
|
|
315
134
|
import { InstaVM } from 'instavm';
|
|
316
135
|
|
|
317
136
|
const client = new InstaVM('your_api_key');
|
|
318
137
|
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const headlines = await session.extractElements('.titleline > a', ['text', 'href']);
|
|
340
|
-
results.push({
|
|
341
|
-
term,
|
|
342
|
-
headlines: headlines.slice(0, 5) // Top 5 results
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
await session.close();
|
|
347
|
-
|
|
348
|
-
// Process results with Python
|
|
349
|
-
const analysis = await client.execute(`
|
|
350
|
-
import json
|
|
351
|
-
data = ${JSON.stringify(results)}
|
|
352
|
-
|
|
353
|
-
# Analyze results
|
|
354
|
-
total_headlines = sum(len(item['headlines']) for item in data)
|
|
355
|
-
print(f"Collected {total_headlines} headlines across {len(data)} search terms")
|
|
356
|
-
|
|
357
|
-
# Find most common words
|
|
358
|
-
all_text = ' '.join([headline['text'] for item in data for headline in item['headlines']])
|
|
359
|
-
words = all_text.lower().split()
|
|
360
|
-
word_counts = {}
|
|
361
|
-
for word in words:
|
|
362
|
-
if len(word) > 3: # Filter short words
|
|
363
|
-
word_counts[word] = word_counts.get(word, 0) + 1
|
|
364
|
-
|
|
365
|
-
# Top 10 words
|
|
366
|
-
top_words = sorted(word_counts.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
367
|
-
print("Top words:", top_words)
|
|
368
|
-
`);
|
|
369
|
-
|
|
370
|
-
console.log(analysis.stdout);
|
|
371
|
-
await client.dispose();
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
## Language Support
|
|
375
|
-
|
|
376
|
-
### Python Code Execution
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
// Python with libraries
|
|
380
|
-
const result = await client.execute(`
|
|
381
|
-
import pandas as pd
|
|
382
|
-
import numpy as np
|
|
383
|
-
|
|
384
|
-
# Create sample data
|
|
385
|
-
data = pd.DataFrame({
|
|
386
|
-
'numbers': np.random.randn(100),
|
|
387
|
-
'categories': np.random.choice(['A', 'B', 'C'], 100)
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
# Basic statistics
|
|
391
|
-
print(f"Mean: {data['numbers'].mean():.2f}")
|
|
392
|
-
print(f"Std: {data['numbers'].std():.2f}")
|
|
393
|
-
print(f"Categories: {data['categories'].value_counts().to_dict()}")
|
|
394
|
-
`);
|
|
395
|
-
|
|
396
|
-
console.log(result.stdout);
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### Bash Commands
|
|
138
|
+
const vm = await client.vms.create({ metadata: { purpose: 'dev' } }, true);
|
|
139
|
+
const vmId = String(vm.vm_id);
|
|
140
|
+
|
|
141
|
+
const vmList = await client.vms.list(); // GET /v1/vms
|
|
142
|
+
const vmAllRecords = await client.vms.listAllRecords(); // GET /v1/vms/
|
|
143
|
+
|
|
144
|
+
await client.vms.snapshot(vmId, { name: 'dev-base' }, true);
|
|
145
|
+
|
|
146
|
+
await client.snapshots.create({
|
|
147
|
+
oci_image: 'docker.io/library/python:3.11-slim',
|
|
148
|
+
name: 'python-3-11-dev',
|
|
149
|
+
vcpu_count: 2,
|
|
150
|
+
memory_mb: 1024,
|
|
151
|
+
type: 'user',
|
|
152
|
+
build_args: {
|
|
153
|
+
git_clone_url: 'https://github.com/example/repo.git',
|
|
154
|
+
git_clone_branch: 'main',
|
|
155
|
+
envs: { NODE_ENV: 'production' },
|
|
156
|
+
},
|
|
157
|
+
});
|
|
400
158
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const sysInfo = await client.execute(`
|
|
404
|
-
echo "System Information:"
|
|
405
|
-
echo "==================="
|
|
406
|
-
uname -a
|
|
407
|
-
echo
|
|
408
|
-
echo "Disk Usage:"
|
|
409
|
-
df -h
|
|
410
|
-
echo
|
|
411
|
-
echo "Memory Info:"
|
|
412
|
-
free -h
|
|
413
|
-
`, { language: 'bash' });
|
|
414
|
-
|
|
415
|
-
console.log(sysInfo.stdout);
|
|
159
|
+
const userSnapshots = await client.snapshots.list({ type: 'user' });
|
|
160
|
+
console.log(vmList.length, vmAllRecords.length, userSnapshots.length);
|
|
416
161
|
```
|
|
417
162
|
|
|
418
|
-
###
|
|
163
|
+
### Networking (Egress, Shares, SSH)
|
|
419
164
|
|
|
420
165
|
```typescript
|
|
421
|
-
|
|
422
|
-
await client.execute('data = [1, 2, 3, 4, 5]');
|
|
423
|
-
await client.execute('total = sum(data)');
|
|
424
|
-
|
|
425
|
-
const result = await client.execute('print(f"Total: {total}, Average: {total/len(data)}")');
|
|
426
|
-
console.log(result.stdout); // Output: Total: 15, Average: 3.0
|
|
427
|
-
```
|
|
166
|
+
import { InstaVM } from 'instavm';
|
|
428
167
|
|
|
429
|
-
|
|
168
|
+
const client = new InstaVM('your_api_key');
|
|
169
|
+
const sessionId = await client.createSession();
|
|
170
|
+
|
|
171
|
+
await client.setSessionEgress(
|
|
172
|
+
{
|
|
173
|
+
allowPackageManagers: true,
|
|
174
|
+
allowHttp: false,
|
|
175
|
+
allowHttps: true,
|
|
176
|
+
allowedDomains: ['npmjs.com', 'registry.npmjs.org'],
|
|
177
|
+
},
|
|
178
|
+
sessionId
|
|
179
|
+
);
|
|
430
180
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const isActive = await client.isSessionActive();
|
|
434
|
-
console.log(`Session active: ${isActive}`);
|
|
181
|
+
const share = await client.shares.create({ session_id: sessionId, port: 3000, is_public: false });
|
|
182
|
+
await client.shares.update(String(share.share_id), { is_public: true });
|
|
435
183
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
console.log(`Other session active: ${isOtherActive}`);
|
|
184
|
+
const key = await client.addSshKey('ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host');
|
|
185
|
+
console.log(key);
|
|
439
186
|
```
|
|
440
187
|
|
|
441
|
-
|
|
188
|
+
<a id="infrastructure-platform-apis"></a>
|
|
189
|
+
## Infrastructure & Platform APIs
|
|
442
190
|
|
|
443
|
-
###
|
|
191
|
+
### Platform APIs (API Keys, Audit, Webhooks)
|
|
444
192
|
|
|
445
193
|
```typescript
|
|
446
|
-
|
|
447
|
-
await session.wait({
|
|
448
|
-
type: 'visible',
|
|
449
|
-
selector: '.loading-complete',
|
|
450
|
-
timeout: 30000
|
|
451
|
-
});
|
|
452
|
-
|
|
453
|
-
// Wait for element to disappear
|
|
454
|
-
await session.wait({
|
|
455
|
-
type: 'hidden',
|
|
456
|
-
selector: '.spinner'
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
// Wait for page load
|
|
460
|
-
await session.wait({
|
|
461
|
-
type: 'networkidle'
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
// Simple timeout
|
|
465
|
-
await session.wait({
|
|
466
|
-
type: 'timeout',
|
|
467
|
-
ms: 5000
|
|
468
|
-
});
|
|
469
|
-
```
|
|
194
|
+
import { InstaVM } from 'instavm';
|
|
470
195
|
|
|
471
|
-
|
|
196
|
+
const client = new InstaVM('your_api_key');
|
|
472
197
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
const fullPage = await session.screenshot({
|
|
476
|
-
fullPage: true,
|
|
477
|
-
format: 'png'
|
|
478
|
-
});
|
|
198
|
+
const apiKey = await client.apiKeys.create({ description: 'ci key' });
|
|
199
|
+
const events = await client.audit.events({ status: 'success', limit: 25 });
|
|
479
200
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
x: 0,
|
|
484
|
-
y: 0,
|
|
485
|
-
width: 800,
|
|
486
|
-
height: 600
|
|
487
|
-
},
|
|
488
|
-
format: 'jpeg',
|
|
489
|
-
quality: 90
|
|
201
|
+
const endpoint = await client.webhooks.createEndpoint({
|
|
202
|
+
url: 'https://example.com/instavm/webhook',
|
|
203
|
+
event_patterns: ['vm.*', 'snapshot.*'],
|
|
490
204
|
});
|
|
491
205
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
// Save to file if needed
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
### Element Extraction
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
// Extract multiple attributes
|
|
501
|
-
const links = await session.extractElements('a', ['href', 'text', 'title']);
|
|
502
|
-
|
|
503
|
-
// Extract with CSS selectors
|
|
504
|
-
const articles = await session.extractElements('article h2, .post-title', ['text']);
|
|
505
|
-
|
|
506
|
-
// Extract form data
|
|
507
|
-
const formData = await session.extractElements('input, select, textarea', [
|
|
508
|
-
'name', 'value', 'type', 'placeholder'
|
|
509
|
-
]);
|
|
510
|
-
|
|
511
|
-
console.log('Links found:', links);
|
|
512
|
-
console.log('Articles:', articles);
|
|
513
|
-
console.log('Form fields:', formData);
|
|
206
|
+
const deliveries = await client.webhooks.listDeliveries({ limit: 10 });
|
|
207
|
+
console.log(apiKey, events, endpoint, deliveries);
|
|
514
208
|
```
|
|
515
209
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
```typescript
|
|
519
|
-
// Extract clean, LLM-optimized content from a webpage
|
|
520
|
-
const content = await session.extractContent({
|
|
521
|
-
includeInteractive: true, // Include clickable/typeable elements
|
|
522
|
-
includeAnchors: true, // Include content-to-selector mappings
|
|
523
|
-
maxAnchors: 50 // Limit number of anchors
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
// Get clean article text (no ads, no navigation, no scripts)
|
|
527
|
-
console.log('Title:', content.readableContent.title);
|
|
528
|
-
console.log('Article:', content.readableContent.content);
|
|
529
|
-
console.log('Author:', content.readableContent.byline);
|
|
530
|
-
|
|
531
|
-
// Find interactive elements (buttons, links, inputs)
|
|
532
|
-
const loginButton = content.interactiveElements?.find(
|
|
533
|
-
el => el.text?.toLowerCase().includes('login')
|
|
534
|
-
);
|
|
535
|
-
if (loginButton) {
|
|
536
|
-
await session.click(loginButton.selector);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// Use content anchors to map text to selectors
|
|
540
|
-
// Perfect for LLM agents that need to "read then click"
|
|
541
|
-
const signupLink = content.contentAnchors?.find(
|
|
542
|
-
anchor => anchor.text.toLowerCase().includes('sign up')
|
|
543
|
-
);
|
|
544
|
-
if (signupLink) {
|
|
545
|
-
await session.click(signupLink.selector);
|
|
546
|
-
}
|
|
547
|
-
```
|
|
210
|
+
<a id="browser-computer-use"></a>
|
|
211
|
+
## Browser & Computer Use
|
|
548
212
|
|
|
549
|
-
|
|
213
|
+
### Browser Automation
|
|
550
214
|
|
|
551
|
-
|
|
215
|
+
Basic browser session flow:
|
|
552
216
|
|
|
553
217
|
```typescript
|
|
554
|
-
import {
|
|
555
|
-
InstaVMError, // Base error class
|
|
556
|
-
AuthenticationError, // API key issues
|
|
557
|
-
RateLimitError, // Rate limiting (has retryAfter property)
|
|
558
|
-
QuotaExceededError, // Usage quota exceeded
|
|
559
|
-
NetworkError, // Connection issues
|
|
560
|
-
ExecutionError, // Code execution failures
|
|
561
|
-
SessionError, // Session management issues
|
|
562
|
-
BrowserError, // General browser errors
|
|
563
|
-
BrowserSessionError, // Browser session issues
|
|
564
|
-
BrowserInteractionError, // Browser interaction failures
|
|
565
|
-
BrowserTimeoutError, // Browser operation timeouts
|
|
566
|
-
BrowserNavigationError, // Navigation failures
|
|
567
|
-
ElementNotFoundError, // Element selection issues (has selector property)
|
|
568
|
-
UnsupportedOperationError // Operation not supported in local mode
|
|
569
|
-
} from 'instavm';
|
|
570
|
-
|
|
571
|
-
// Specific error handling
|
|
572
|
-
try {
|
|
573
|
-
await session.click('.non-existent-button');
|
|
574
|
-
} catch (error) {
|
|
575
|
-
if (error instanceof ElementNotFoundError) {
|
|
576
|
-
console.log(`Element not found: ${error.selector}`);
|
|
577
|
-
} else if (error instanceof BrowserTimeoutError) {
|
|
578
|
-
console.log('Operation timed out');
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
```
|
|
218
|
+
import { InstaVM } from 'instavm';
|
|
582
219
|
|
|
583
|
-
|
|
220
|
+
const client = new InstaVM('your_api_key');
|
|
584
221
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
222
|
+
const browser = await client.browser.createSession({ viewportWidth: 1366, viewportHeight: 768 });
|
|
223
|
+
await browser.navigate('https://example.com');
|
|
224
|
+
await browser.click('a');
|
|
225
|
+
const screenshot = await browser.screenshot({ fullPage: true });
|
|
589
226
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
const client = new InstaVM('your_api_key', {
|
|
593
|
-
maxRetries: 5,
|
|
594
|
-
retryDelay: 2000, // Base delay in milliseconds
|
|
595
|
-
timeout: 300000 // 5 minute timeout
|
|
596
|
-
});
|
|
227
|
+
console.log(screenshot.length);
|
|
228
|
+
await browser.close();
|
|
597
229
|
```
|
|
598
230
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
### InstaVM Client
|
|
231
|
+
Advanced flow with waits and extraction:
|
|
602
232
|
|
|
603
233
|
```typescript
|
|
604
|
-
|
|
605
|
-
constructor(apiKey: string, options?: InstaVMOptions)
|
|
606
|
-
|
|
607
|
-
// Code execution
|
|
608
|
-
execute(command: string, options?: ExecuteOptions): Promise<ExecutionResult>
|
|
609
|
-
executeAsync(command: string, options?: ExecuteOptions): Promise<AsyncExecutionResult>
|
|
610
|
-
getTaskResult(taskId: string, pollInterval?: number, timeout?: number): Promise<TaskResult>
|
|
611
|
-
|
|
612
|
-
// File operations
|
|
613
|
-
upload(files: FileUpload[], options?: UploadOptions): Promise<UploadResult>
|
|
614
|
-
download(filename: string, options?: DownloadOptions): Promise<DownloadResult>
|
|
234
|
+
import { InstaVM } from 'instavm';
|
|
615
235
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
closeSession(sessionId?: string): Promise<void>
|
|
619
|
-
isSessionActive(sessionId?: string): Promise<boolean>
|
|
620
|
-
getUsage(sessionId?: string): Promise<UsageStats>
|
|
236
|
+
const client = new InstaVM('your_api_key');
|
|
237
|
+
const browser = await client.browser.createSession();
|
|
621
238
|
|
|
622
|
-
|
|
623
|
-
|
|
239
|
+
await browser.navigate('https://news.ycombinator.com');
|
|
240
|
+
await browser.wait({ type: 'visible', selector: 'a.storylink' }, 10000);
|
|
624
241
|
|
|
625
|
-
|
|
626
|
-
|
|
242
|
+
const links = await browser.extractElements('a.storylink', ['text', 'href']);
|
|
243
|
+
console.log(links.slice(0, 5));
|
|
627
244
|
|
|
628
|
-
|
|
629
|
-
dispose(): Promise<void>
|
|
630
|
-
}
|
|
245
|
+
await browser.close();
|
|
631
246
|
```
|
|
632
247
|
|
|
633
|
-
###
|
|
248
|
+
### LLM-Friendly Content Extraction (concise pattern only)
|
|
634
249
|
|
|
635
250
|
```typescript
|
|
636
|
-
|
|
637
|
-
baseURL?: string; // Default: 'https://api.instavm.io' (ignored if local=true)
|
|
638
|
-
timeout?: number; // Default: 300000 (5 minutes)
|
|
639
|
-
maxRetries?: number; // Default: 3
|
|
640
|
-
retryDelay?: number; // Default: 1000ms
|
|
641
|
-
local?: boolean; // Default: false - Use local container instead of cloud
|
|
642
|
-
localURL?: string; // Default: 'http://coderunner.local:8222' - Local container URL
|
|
643
|
-
}
|
|
251
|
+
import { InstaVM } from 'instavm';
|
|
644
252
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
timeout?: number; // Default: 15 seconds
|
|
648
|
-
sessionId?: string; // Use specific session
|
|
649
|
-
}
|
|
650
|
-
```
|
|
253
|
+
const client = new InstaVM('your_api_key');
|
|
254
|
+
const browser = await client.browser.createSession();
|
|
651
255
|
|
|
652
|
-
|
|
256
|
+
await browser.navigate('https://example.com/docs');
|
|
653
257
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
getLocalSession(sessionId: string): BrowserSession | undefined
|
|
660
|
-
getLocalSessions(): BrowserSession[]
|
|
661
|
-
closeAllSessions(): Promise<void>
|
|
662
|
-
dispose(): Promise<void>
|
|
663
|
-
}
|
|
258
|
+
const content = await browser.extractContent({
|
|
259
|
+
includeInteractive: true,
|
|
260
|
+
includeAnchors: true,
|
|
261
|
+
maxAnchors: 30,
|
|
262
|
+
});
|
|
664
263
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
userAgent?: string; // Custom user agent
|
|
264
|
+
console.log(content.readableContent.title);
|
|
265
|
+
for (const anchor of (content.contentAnchors || []).slice(0, 5)) {
|
|
266
|
+
console.log(anchor.text, anchor.selector);
|
|
669
267
|
}
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
### Browser Session
|
|
673
268
|
|
|
674
|
-
|
|
675
|
-
class BrowserSession extends EventEmitter {
|
|
676
|
-
// Navigation
|
|
677
|
-
navigate(url: string, options?: NavigateOptions): Promise<NavigationResult>
|
|
678
|
-
|
|
679
|
-
// Interaction
|
|
680
|
-
click(selector: string, options?: ClickOptions): Promise<void>
|
|
681
|
-
type(selector: string, text: string, options?: TypeOptions): Promise<void>
|
|
682
|
-
fill(selector: string, value: string, options?: FillOptions): Promise<void>
|
|
683
|
-
scroll(options?: ScrollOptions): Promise<void>
|
|
684
|
-
|
|
685
|
-
// Data extraction
|
|
686
|
-
screenshot(options?: ScreenshotOptions): Promise<string>
|
|
687
|
-
extractElements(selector: string, attributes?: string[]): Promise<ExtractedElement[]>
|
|
688
|
-
extractContent(options?: ExtractContentOptions): Promise<ExtractedContent>
|
|
689
|
-
|
|
690
|
-
// Utilities
|
|
691
|
-
wait(condition: WaitCondition, timeout?: number): Promise<void>
|
|
692
|
-
close(): Promise<void>
|
|
693
|
-
|
|
694
|
-
// Properties
|
|
695
|
-
readonly sessionId: string
|
|
696
|
-
readonly isActive: boolean
|
|
697
|
-
|
|
698
|
-
// Events: 'navigation', 'error', 'close'
|
|
699
|
-
}
|
|
269
|
+
await browser.close();
|
|
700
270
|
```
|
|
701
271
|
|
|
702
|
-
###
|
|
272
|
+
### Computer Use
|
|
703
273
|
|
|
704
274
|
```typescript
|
|
705
|
-
|
|
706
|
-
stdout: string;
|
|
707
|
-
stderr: string;
|
|
708
|
-
success: boolean;
|
|
709
|
-
executionTime?: number;
|
|
710
|
-
cpuTime?: number;
|
|
711
|
-
createdAt?: string;
|
|
712
|
-
sessionId?: string;
|
|
713
|
-
error?: string;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
interface TaskResult {
|
|
717
|
-
stdout: string;
|
|
718
|
-
stderr: string;
|
|
719
|
-
executionTime?: number;
|
|
720
|
-
cpuTime?: number;
|
|
721
|
-
createdAt?: string;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
interface NavigationResult {
|
|
725
|
-
success: boolean;
|
|
726
|
-
url: string;
|
|
727
|
-
title?: string;
|
|
728
|
-
status?: number;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
interface ExtractedElement {
|
|
732
|
-
text?: string;
|
|
733
|
-
href?: string;
|
|
734
|
-
[attribute: string]: string | undefined;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
type WaitCondition =
|
|
738
|
-
| { type: 'timeout'; ms: number }
|
|
739
|
-
| { type: 'visible'; selector: string }
|
|
740
|
-
| { type: 'hidden'; selector: string }
|
|
741
|
-
| { type: 'navigation' }
|
|
742
|
-
| { type: 'networkidle' };
|
|
743
|
-
```
|
|
744
|
-
|
|
745
|
-
## Best Practices
|
|
746
|
-
|
|
747
|
-
### Resource Management
|
|
275
|
+
import { InstaVM } from 'instavm';
|
|
748
276
|
|
|
749
|
-
```typescript
|
|
750
|
-
// Always dispose of the client when done
|
|
751
277
|
const client = new InstaVM('your_api_key');
|
|
752
|
-
|
|
753
|
-
// Your automation code
|
|
754
|
-
} finally {
|
|
755
|
-
await client.dispose(); // Closes all sessions and cleans up
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
// Or use a wrapper function
|
|
759
|
-
async function withInstaVM(apiKey: string, callback: (client: InstaVM) => Promise<void>) {
|
|
760
|
-
const client = new InstaVM(apiKey);
|
|
761
|
-
try {
|
|
762
|
-
await callback(client);
|
|
763
|
-
} finally {
|
|
764
|
-
await client.dispose();
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
await withInstaVM('your_api_key', async (client) => {
|
|
769
|
-
const result = await client.execute('print("Hello, World!")');
|
|
770
|
-
console.log(result.stdout);
|
|
771
|
-
});
|
|
772
|
-
```
|
|
278
|
+
const sessionId = await client.createSession();
|
|
773
279
|
|
|
774
|
-
|
|
280
|
+
const viewer = await client.computerUse.viewerUrl(sessionId);
|
|
281
|
+
const state = await client.computerUse.get(sessionId, '/state');
|
|
775
282
|
|
|
776
|
-
|
|
777
|
-
// Implement comprehensive error handling
|
|
778
|
-
async function robustAutomation(client: InstaVM) {
|
|
779
|
-
let session: BrowserSession | null = null;
|
|
780
|
-
|
|
781
|
-
try {
|
|
782
|
-
session = await client.browser.createSession();
|
|
783
|
-
|
|
784
|
-
// Retry navigation with timeout
|
|
785
|
-
let retries = 3;
|
|
786
|
-
while (retries > 0) {
|
|
787
|
-
try {
|
|
788
|
-
await session.navigate('https://example.com');
|
|
789
|
-
break;
|
|
790
|
-
} catch (error) {
|
|
791
|
-
if (error instanceof BrowserTimeoutError && retries > 1) {
|
|
792
|
-
console.log(`Navigation timeout, retrying... (${retries - 1} attempts left)`);
|
|
793
|
-
retries--;
|
|
794
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
795
|
-
} else {
|
|
796
|
-
throw error;
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
// Safe element interaction
|
|
802
|
-
try {
|
|
803
|
-
await session.click('button.submit');
|
|
804
|
-
} catch (error) {
|
|
805
|
-
if (error instanceof ElementNotFoundError) {
|
|
806
|
-
console.log('Submit button not found, trying alternative selector');
|
|
807
|
-
await session.click('input[type="submit"]');
|
|
808
|
-
} else {
|
|
809
|
-
throw error;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
} catch (error) {
|
|
814
|
-
console.error('Automation failed:', error.message);
|
|
815
|
-
throw error;
|
|
816
|
-
} finally {
|
|
817
|
-
if (session) {
|
|
818
|
-
await session.close();
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
283
|
+
console.log(viewer, state);
|
|
822
284
|
```
|
|
823
285
|
|
|
824
|
-
|
|
286
|
+
<a id="error-handling"></a>
|
|
287
|
+
## Error Handling
|
|
825
288
|
|
|
826
289
|
```typescript
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
// Consider using a single extraction call for related elements
|
|
837
|
-
const pageData = await session.extractElements('title, a, img', ['text', 'href', 'src', 'alt']);
|
|
838
|
-
|
|
839
|
-
// Use appropriate timeouts
|
|
840
|
-
await session.navigate('https://slow-site.com', {
|
|
841
|
-
waitTimeout: 60000 // Increase timeout for slow sites
|
|
842
|
-
});
|
|
290
|
+
import {
|
|
291
|
+
InstaVM,
|
|
292
|
+
AuthenticationError,
|
|
293
|
+
ExecutionError,
|
|
294
|
+
NetworkError,
|
|
295
|
+
RateLimitError,
|
|
296
|
+
SessionError,
|
|
297
|
+
} from 'instavm';
|
|
843
298
|
|
|
844
|
-
|
|
845
|
-
const thumbnail = await session.screenshot({
|
|
846
|
-
clip: { x: 0, y: 0, width: 400, height: 300 },
|
|
847
|
-
format: 'jpeg',
|
|
848
|
-
quality: 70
|
|
849
|
-
});
|
|
850
|
-
```
|
|
299
|
+
const client = new InstaVM('your_api_key');
|
|
851
300
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
}
|
|
869
|
-
} finally {
|
|
870
|
-
await client.dispose();
|
|
871
|
-
}
|
|
301
|
+
try {
|
|
302
|
+
await client.execute("raise Exception('boom')");
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (error instanceof AuthenticationError) {
|
|
305
|
+
console.error('Invalid API key');
|
|
306
|
+
} else if (error instanceof RateLimitError) {
|
|
307
|
+
console.error('Rate limited');
|
|
308
|
+
} else if (error instanceof SessionError) {
|
|
309
|
+
console.error('Session issue:', error.message);
|
|
310
|
+
} else if (error instanceof ExecutionError) {
|
|
311
|
+
console.error('Execution failed:', error.message);
|
|
312
|
+
} else if (error instanceof NetworkError) {
|
|
313
|
+
console.error('Network issue:', error.message);
|
|
314
|
+
} else {
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
872
317
|
}
|
|
873
|
-
|
|
874
|
-
main().catch(console.error);
|
|
875
318
|
```
|
|
876
319
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
### Running Tests
|
|
320
|
+
<a id="development-testing"></a>
|
|
321
|
+
## Development & Testing
|
|
880
322
|
|
|
881
323
|
```bash
|
|
882
324
|
# Install dependencies
|
|
883
325
|
npm install
|
|
884
326
|
|
|
885
|
-
# Run unit tests
|
|
327
|
+
# Run unit tests
|
|
886
328
|
npm run test:unit
|
|
887
329
|
|
|
888
|
-
#
|
|
889
|
-
INSTAVM_API_KEY=your_api_key npm run test:integration
|
|
890
|
-
|
|
891
|
-
# Run all tests
|
|
330
|
+
# Optional: full test run
|
|
892
331
|
npm test
|
|
893
332
|
|
|
894
|
-
# Build
|
|
333
|
+
# Build package
|
|
895
334
|
npm run build
|
|
896
|
-
|
|
897
|
-
# Type checking
|
|
898
|
-
npm run type-check
|
|
899
335
|
```
|
|
900
336
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
### Contributing
|
|
904
|
-
|
|
905
|
-
This is an official SDK. For issues and feature requests, please use the GitHub repository.
|
|
906
|
-
|
|
907
|
-
## Requirements
|
|
908
|
-
|
|
909
|
-
- Node.js 16+
|
|
910
|
-
- TypeScript 5+ (for TypeScript projects)
|
|
911
|
-
|
|
912
|
-
## License
|
|
913
|
-
|
|
914
|
-
Proprietary. This SDK is provided for use with InstaVM services only.
|
|
915
|
-
|
|
916
|
-
All rights reserved. No redistribution or modification permitted.
|
|
917
|
-
|
|
918
|
-
---
|
|
919
|
-
|
|
920
|
-
## Changelog
|
|
921
|
-
|
|
922
|
-
### Version 0.8.3
|
|
923
|
-
|
|
924
|
-
- ✅ **NEW**: `getTaskResult()` method - Poll for async task completion with configurable intervals
|
|
925
|
-
- ✅ **NEW**: `isSessionActive()` method - Check if session is still active by querying VM status
|
|
926
|
-
- ✅ **IMPROVED**: Execution result format - Now returns `stdout` and `stderr` separately (matching Python SDK)
|
|
927
|
-
- ✅ **IMPROVED**: Enhanced execution results - Added `cpuTime`, `executionTime`, and `createdAt` fields
|
|
928
|
-
- ✅ **IMPROVED**: Better error messages - Rate limit errors now show `detail` field from API response
|
|
929
|
-
- ✅ **FIXED**: Session status check - Now uses `/v1/sessions/status/` endpoint for accurate VM status
|
|
930
|
-
- ✅ **UPDATED**: closeSession behavior - Sessions auto-expire on server, no longer makes DELETE API call
|
|
931
|
-
- ✅ Full parity with Python SDK v0.8.3
|
|
932
|
-
|
|
933
|
-
### Version 0.4.0
|
|
934
|
-
|
|
935
|
-
- ✅ **NEW**: Local execution mode support - Run code execution against local containers
|
|
936
|
-
- ✅ **NEW**: Local browser automation - Navigate and extract content without sessions
|
|
937
|
-
- ✅ **NEW**: `UnsupportedOperationError` - Better error messages for cloud-only features
|
|
938
|
-
- ✅ Parity with Python SDK v0.4.0 local mode features
|
|
939
|
-
- ✅ Improved flexibility for on-premise deployments
|
|
940
|
-
|
|
941
|
-
### Version 0.3.0
|
|
942
|
-
|
|
943
|
-
- ✅ **NEW**: File download functionality - Download files from remote VM
|
|
944
|
-
- ✅ **NEW**: LLM-friendly content extraction - Extract clean, readable content with interactive element mapping
|
|
945
|
-
- ✅ Enhanced browser automation with content anchors for intelligent LLM agents
|
|
946
|
-
- ✅ Full API parity with Python SDK
|
|
947
|
-
|
|
948
|
-
### Version 0.2.1
|
|
949
|
-
|
|
950
|
-
- ✅ Bug fixes and improvements
|
|
337
|
+
<a id="docs-map-further-reading"></a>
|
|
338
|
+
## Docs Map (Further Reading)
|
|
951
339
|
|
|
952
|
-
|
|
340
|
+
- [JavaScript SDK Docs](https://instavm.io/docs/sdks/javascript)
|
|
341
|
+
- [VMs API](https://instavm.io/docs/api/vms/)
|
|
342
|
+
- [Snapshots API](https://instavm.io/docs/api/snapshots/)
|
|
343
|
+
- [Shares API](https://instavm.io/docs/api/shares/)
|
|
344
|
+
- [Computer Use API (REST API Reference)](https://instavm.io/docs/api#endpoint-categories)
|
|
345
|
+
- [Webhooks API (REST API Reference)](https://instavm.io/docs/api#endpoint-categories)
|
|
953
346
|
|
|
954
|
-
-
|
|
955
|
-
|
|
347
|
+
<a id="version-changelog"></a>
|
|
348
|
+
## Version / Changelog
|
|
956
349
|
|
|
957
|
-
|
|
350
|
+
Current package version: `0.11.0`.
|
|
958
351
|
|
|
959
|
-
|
|
960
|
-
-
|
|
961
|
-
-
|
|
962
|
-
-
|
|
963
|
-
- ✅ Session management and automatic cleanup
|
|
964
|
-
- ✅ File upload capabilities
|
|
965
|
-
- ✅ Async execution support
|
|
966
|
-
- ✅ Event-driven browser sessions
|
|
967
|
-
- ✅ Modern build system with multiple output formats
|
|
352
|
+
Highlights in this line:
|
|
353
|
+
- Manager-based infrastructure APIs (VMs, snapshots, shares, custom domains, computer use, API keys, audit, webhooks)
|
|
354
|
+
- Snapshot build args support for env vars and Git clone inputs
|
|
355
|
+
- Distinct VM list helpers for `/v1/vms` and `/v1/vms/`
|
|
968
356
|
|
|
969
|
-
|
|
357
|
+
For detailed release history, see [GitHub Releases](https://github.com/instavm/js/releases).
|