instavm 0.3.0 → 0.8.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 +65 -16
- package/dist/index.d.mts +37 -4
- package/dist/index.d.ts +37 -4
- package/dist/index.js +135 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +133 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm install instavm
|
|
|
21
21
|
|
|
22
22
|
## Quick Start
|
|
23
23
|
|
|
24
|
-
### Code Execution
|
|
24
|
+
### Code Execution (Cloud Mode)
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
27
|
import { InstaVM, ExecutionError, NetworkError } from 'instavm';
|
|
@@ -30,7 +30,7 @@ import { InstaVM, ExecutionError, NetworkError } from 'instavm';
|
|
|
30
30
|
const client = new InstaVM('your_api_key');
|
|
31
31
|
|
|
32
32
|
try {
|
|
33
|
-
// Execute a command
|
|
33
|
+
// Execute a command
|
|
34
34
|
const result = await client.execute("print(100**100)");
|
|
35
35
|
console.log(result);
|
|
36
36
|
|
|
@@ -49,6 +49,44 @@ try {
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
### Local Execution Mode
|
|
53
|
+
|
|
54
|
+
Run code execution against a local container (e.g., [coderunner](https://github.com/instavm/coderunner)) instead of the cloud API:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { InstaVM } from 'instavm';
|
|
58
|
+
|
|
59
|
+
// Create client in local mode (no API key required)
|
|
60
|
+
const client = new InstaVM('', {
|
|
61
|
+
local: true,
|
|
62
|
+
localURL: 'http://coderunner.local:8222' // Optional, defaults to this URL
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Execute code locally without session management
|
|
66
|
+
const result = await client.execute("print('Hello from local container!')");
|
|
67
|
+
console.log(result.output);
|
|
68
|
+
|
|
69
|
+
// Browser automation in local mode (no session required)
|
|
70
|
+
const content = await client.browser.extractContent({
|
|
71
|
+
url: 'https://example.com',
|
|
72
|
+
includeInteractive: true,
|
|
73
|
+
includeAnchors: true
|
|
74
|
+
});
|
|
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
|
+
|
|
52
90
|
### File Upload
|
|
53
91
|
|
|
54
92
|
```typescript
|
|
@@ -494,19 +532,20 @@ if (signupLink) {
|
|
|
494
532
|
|
|
495
533
|
```typescript
|
|
496
534
|
import {
|
|
497
|
-
InstaVMError,
|
|
498
|
-
AuthenticationError,
|
|
499
|
-
RateLimitError,
|
|
500
|
-
QuotaExceededError,
|
|
501
|
-
NetworkError,
|
|
502
|
-
ExecutionError,
|
|
503
|
-
SessionError,
|
|
504
|
-
BrowserError,
|
|
505
|
-
BrowserSessionError,
|
|
506
|
-
BrowserInteractionError,
|
|
507
|
-
BrowserTimeoutError,
|
|
508
|
-
BrowserNavigationError,
|
|
509
|
-
ElementNotFoundError
|
|
535
|
+
InstaVMError, // Base error class
|
|
536
|
+
AuthenticationError, // API key issues
|
|
537
|
+
RateLimitError, // Rate limiting (has retryAfter property)
|
|
538
|
+
QuotaExceededError, // Usage quota exceeded
|
|
539
|
+
NetworkError, // Connection issues
|
|
540
|
+
ExecutionError, // Code execution failures
|
|
541
|
+
SessionError, // Session management issues
|
|
542
|
+
BrowserError, // General browser errors
|
|
543
|
+
BrowserSessionError, // Browser session issues
|
|
544
|
+
BrowserInteractionError, // Browser interaction failures
|
|
545
|
+
BrowserTimeoutError, // Browser operation timeouts
|
|
546
|
+
BrowserNavigationError, // Navigation failures
|
|
547
|
+
ElementNotFoundError, // Element selection issues (has selector property)
|
|
548
|
+
UnsupportedOperationError // Operation not supported in local mode
|
|
510
549
|
} from 'instavm';
|
|
511
550
|
|
|
512
551
|
// Specific error handling
|
|
@@ -573,10 +612,12 @@ class InstaVM {
|
|
|
573
612
|
|
|
574
613
|
```typescript
|
|
575
614
|
interface InstaVMOptions {
|
|
576
|
-
baseURL?: string; // Default: 'https://api.instavm.io'
|
|
615
|
+
baseURL?: string; // Default: 'https://api.instavm.io' (ignored if local=true)
|
|
577
616
|
timeout?: number; // Default: 300000 (5 minutes)
|
|
578
617
|
maxRetries?: number; // Default: 3
|
|
579
618
|
retryDelay?: number; // Default: 1000ms
|
|
619
|
+
local?: boolean; // Default: false - Use local container instead of cloud
|
|
620
|
+
localURL?: string; // Default: 'http://coderunner.local:8222' - Local container URL
|
|
580
621
|
}
|
|
581
622
|
|
|
582
623
|
interface ExecuteOptions {
|
|
@@ -845,6 +886,14 @@ All rights reserved. No redistribution or modification permitted.
|
|
|
845
886
|
|
|
846
887
|
## Changelog
|
|
847
888
|
|
|
889
|
+
### Version 0.4.0
|
|
890
|
+
|
|
891
|
+
- ✅ **NEW**: Local execution mode support - Run code execution against local containers
|
|
892
|
+
- ✅ **NEW**: Local browser automation - Navigate and extract content without sessions
|
|
893
|
+
- ✅ **NEW**: `UnsupportedOperationError` - Better error messages for cloud-only features
|
|
894
|
+
- ✅ Parity with Python SDK v0.4.0 local mode features
|
|
895
|
+
- ✅ Improved flexibility for on-premise deployments
|
|
896
|
+
|
|
848
897
|
### Version 0.3.0
|
|
849
898
|
|
|
850
899
|
- ✅ **NEW**: File download functionality - Download files from remote VM
|
package/dist/index.d.mts
CHANGED
|
@@ -44,11 +44,11 @@ declare class HTTPClient {
|
|
|
44
44
|
/**
|
|
45
45
|
* POST request with JSON body
|
|
46
46
|
*/
|
|
47
|
-
post<T = any>(url: string, data?: any, headers?: Record<string, string
|
|
47
|
+
post<T = any>(url: string, data?: any, headers?: Record<string, string>, timeout?: number): Promise<T>;
|
|
48
48
|
/**
|
|
49
49
|
* POST request for code execution (uses X-API-Key header like Python client)
|
|
50
50
|
*/
|
|
51
|
-
postExecution<T = any>(url: string, data: any, headers?: Record<string, string
|
|
51
|
+
postExecution<T = any>(url: string, data: any, headers?: Record<string, string>, timeout?: number): Promise<T>;
|
|
52
52
|
/**
|
|
53
53
|
* POST request with form data (for file uploads)
|
|
54
54
|
*/
|
|
@@ -151,6 +151,7 @@ interface ExtractOptions {
|
|
|
151
151
|
maxResults?: number;
|
|
152
152
|
}
|
|
153
153
|
interface ExtractContentOptions {
|
|
154
|
+
url?: string;
|
|
154
155
|
includeInteractive?: boolean;
|
|
155
156
|
includeAnchors?: boolean;
|
|
156
157
|
maxAnchors?: number;
|
|
@@ -265,7 +266,8 @@ declare class BrowserSession extends EventEmitter {
|
|
|
265
266
|
declare class BrowserManager {
|
|
266
267
|
private httpClient;
|
|
267
268
|
private activeSessions;
|
|
268
|
-
|
|
269
|
+
private local;
|
|
270
|
+
constructor(httpClient: HTTPClient, local?: boolean);
|
|
269
271
|
/**
|
|
270
272
|
* Create a new browser session
|
|
271
273
|
*/
|
|
@@ -290,6 +292,14 @@ declare class BrowserManager {
|
|
|
290
292
|
* Close all active sessions
|
|
291
293
|
*/
|
|
292
294
|
closeAllSessions(): Promise<void>;
|
|
295
|
+
/**
|
|
296
|
+
* Navigate to a URL (local mode support - no session required)
|
|
297
|
+
*/
|
|
298
|
+
navigate(url: string, options?: NavigateOptions): Promise<NavigationResult>;
|
|
299
|
+
/**
|
|
300
|
+
* Extract LLM-friendly content (local mode support - no session required)
|
|
301
|
+
*/
|
|
302
|
+
extractContent(options?: ExtractContentOptions): Promise<ExtractedContent>;
|
|
293
303
|
/**
|
|
294
304
|
* Clean up resources
|
|
295
305
|
*/
|
|
@@ -350,9 +360,15 @@ interface DownloadResult {
|
|
|
350
360
|
|
|
351
361
|
interface InstaVMOptions {
|
|
352
362
|
baseURL?: string;
|
|
363
|
+
/**
|
|
364
|
+
* Timeout in milliseconds. Used for HTTP request timeout and sent to API as VM lifetime (in seconds).
|
|
365
|
+
* Default: 300000 (5 minutes)
|
|
366
|
+
*/
|
|
353
367
|
timeout?: number;
|
|
354
368
|
maxRetries?: number;
|
|
355
369
|
retryDelay?: number;
|
|
370
|
+
local?: boolean;
|
|
371
|
+
localURL?: string;
|
|
356
372
|
}
|
|
357
373
|
/**
|
|
358
374
|
* Main InstaVM client class
|
|
@@ -361,9 +377,20 @@ declare class InstaVM {
|
|
|
361
377
|
private httpClient;
|
|
362
378
|
private _sessionId;
|
|
363
379
|
readonly browser: BrowserManager;
|
|
380
|
+
readonly local: boolean;
|
|
381
|
+
private readonly timeout;
|
|
364
382
|
constructor(apiKey: string, options?: InstaVMOptions);
|
|
383
|
+
/**
|
|
384
|
+
* Ensure operation is not called in local mode
|
|
385
|
+
*/
|
|
386
|
+
private ensureNotLocal;
|
|
365
387
|
/**
|
|
366
388
|
* Execute code synchronously
|
|
389
|
+
*
|
|
390
|
+
* @param command - Command to execute
|
|
391
|
+
* @param options - Execution options
|
|
392
|
+
* @param options.timeout - Request timeout in milliseconds (used for HTTP request timeout and sent to API in seconds)
|
|
393
|
+
* @returns Execution result
|
|
367
394
|
*/
|
|
368
395
|
execute(command: string, options?: ExecuteOptions): Promise<ExecutionResult>;
|
|
369
396
|
/**
|
|
@@ -491,5 +518,11 @@ declare class ElementNotFoundError extends BrowserError {
|
|
|
491
518
|
readonly selector?: string;
|
|
492
519
|
constructor(message?: string, selector?: string, options?: any);
|
|
493
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* Unsupported operation error (e.g., operations not available in local mode)
|
|
523
|
+
*/
|
|
524
|
+
declare class UnsupportedOperationError extends InstaVMError {
|
|
525
|
+
constructor(message?: string, options?: any);
|
|
526
|
+
}
|
|
494
527
|
|
|
495
|
-
export { type ApiResponse, type AsyncExecutionResult, AuthenticationError, BrowserError, BrowserInteractionError, BrowserManager, BrowserNavigationError, BrowserSession, BrowserSessionError, type BrowserSessionInfo, type BrowserSessionOptions, BrowserTimeoutError, type ClickOptions, type ContentAnchor, type DownloadOptions, type DownloadResult, ElementNotFoundError, type ExecuteOptions, ExecutionError, type ExecutionResult, type ExtractContentOptions, type ExtractOptions, type ExtractedContent, type ExtractedElement, type FileUpload, type FillOptions, type HttpClientConfig, InstaVM, InstaVMError, type InstaVMOptions, type InteractiveElement, type NavigateOptions, type NavigationResult, NetworkError, QuotaExceededError, RateLimitError, type RequestConfig, type RetryConfig, type ScreenshotOptions, type ScrollOptions, SessionError, type TypeOptions, type UploadOptions, type UploadResult, type UsageStats, type WaitCondition };
|
|
528
|
+
export { type ApiResponse, type AsyncExecutionResult, AuthenticationError, BrowserError, BrowserInteractionError, BrowserManager, BrowserNavigationError, BrowserSession, BrowserSessionError, type BrowserSessionInfo, type BrowserSessionOptions, BrowserTimeoutError, type ClickOptions, type ContentAnchor, type DownloadOptions, type DownloadResult, ElementNotFoundError, type ExecuteOptions, ExecutionError, type ExecutionResult, type ExtractContentOptions, type ExtractOptions, type ExtractedContent, type ExtractedElement, type FileUpload, type FillOptions, type HttpClientConfig, InstaVM, InstaVMError, type InstaVMOptions, type InteractiveElement, type NavigateOptions, type NavigationResult, NetworkError, QuotaExceededError, RateLimitError, type RequestConfig, type RetryConfig, type ScreenshotOptions, type ScrollOptions, SessionError, type TypeOptions, UnsupportedOperationError, type UploadOptions, type UploadResult, type UsageStats, type WaitCondition };
|
package/dist/index.d.ts
CHANGED
|
@@ -44,11 +44,11 @@ declare class HTTPClient {
|
|
|
44
44
|
/**
|
|
45
45
|
* POST request with JSON body
|
|
46
46
|
*/
|
|
47
|
-
post<T = any>(url: string, data?: any, headers?: Record<string, string
|
|
47
|
+
post<T = any>(url: string, data?: any, headers?: Record<string, string>, timeout?: number): Promise<T>;
|
|
48
48
|
/**
|
|
49
49
|
* POST request for code execution (uses X-API-Key header like Python client)
|
|
50
50
|
*/
|
|
51
|
-
postExecution<T = any>(url: string, data: any, headers?: Record<string, string
|
|
51
|
+
postExecution<T = any>(url: string, data: any, headers?: Record<string, string>, timeout?: number): Promise<T>;
|
|
52
52
|
/**
|
|
53
53
|
* POST request with form data (for file uploads)
|
|
54
54
|
*/
|
|
@@ -151,6 +151,7 @@ interface ExtractOptions {
|
|
|
151
151
|
maxResults?: number;
|
|
152
152
|
}
|
|
153
153
|
interface ExtractContentOptions {
|
|
154
|
+
url?: string;
|
|
154
155
|
includeInteractive?: boolean;
|
|
155
156
|
includeAnchors?: boolean;
|
|
156
157
|
maxAnchors?: number;
|
|
@@ -265,7 +266,8 @@ declare class BrowserSession extends EventEmitter {
|
|
|
265
266
|
declare class BrowserManager {
|
|
266
267
|
private httpClient;
|
|
267
268
|
private activeSessions;
|
|
268
|
-
|
|
269
|
+
private local;
|
|
270
|
+
constructor(httpClient: HTTPClient, local?: boolean);
|
|
269
271
|
/**
|
|
270
272
|
* Create a new browser session
|
|
271
273
|
*/
|
|
@@ -290,6 +292,14 @@ declare class BrowserManager {
|
|
|
290
292
|
* Close all active sessions
|
|
291
293
|
*/
|
|
292
294
|
closeAllSessions(): Promise<void>;
|
|
295
|
+
/**
|
|
296
|
+
* Navigate to a URL (local mode support - no session required)
|
|
297
|
+
*/
|
|
298
|
+
navigate(url: string, options?: NavigateOptions): Promise<NavigationResult>;
|
|
299
|
+
/**
|
|
300
|
+
* Extract LLM-friendly content (local mode support - no session required)
|
|
301
|
+
*/
|
|
302
|
+
extractContent(options?: ExtractContentOptions): Promise<ExtractedContent>;
|
|
293
303
|
/**
|
|
294
304
|
* Clean up resources
|
|
295
305
|
*/
|
|
@@ -350,9 +360,15 @@ interface DownloadResult {
|
|
|
350
360
|
|
|
351
361
|
interface InstaVMOptions {
|
|
352
362
|
baseURL?: string;
|
|
363
|
+
/**
|
|
364
|
+
* Timeout in milliseconds. Used for HTTP request timeout and sent to API as VM lifetime (in seconds).
|
|
365
|
+
* Default: 300000 (5 minutes)
|
|
366
|
+
*/
|
|
353
367
|
timeout?: number;
|
|
354
368
|
maxRetries?: number;
|
|
355
369
|
retryDelay?: number;
|
|
370
|
+
local?: boolean;
|
|
371
|
+
localURL?: string;
|
|
356
372
|
}
|
|
357
373
|
/**
|
|
358
374
|
* Main InstaVM client class
|
|
@@ -361,9 +377,20 @@ declare class InstaVM {
|
|
|
361
377
|
private httpClient;
|
|
362
378
|
private _sessionId;
|
|
363
379
|
readonly browser: BrowserManager;
|
|
380
|
+
readonly local: boolean;
|
|
381
|
+
private readonly timeout;
|
|
364
382
|
constructor(apiKey: string, options?: InstaVMOptions);
|
|
383
|
+
/**
|
|
384
|
+
* Ensure operation is not called in local mode
|
|
385
|
+
*/
|
|
386
|
+
private ensureNotLocal;
|
|
365
387
|
/**
|
|
366
388
|
* Execute code synchronously
|
|
389
|
+
*
|
|
390
|
+
* @param command - Command to execute
|
|
391
|
+
* @param options - Execution options
|
|
392
|
+
* @param options.timeout - Request timeout in milliseconds (used for HTTP request timeout and sent to API in seconds)
|
|
393
|
+
* @returns Execution result
|
|
367
394
|
*/
|
|
368
395
|
execute(command: string, options?: ExecuteOptions): Promise<ExecutionResult>;
|
|
369
396
|
/**
|
|
@@ -491,5 +518,11 @@ declare class ElementNotFoundError extends BrowserError {
|
|
|
491
518
|
readonly selector?: string;
|
|
492
519
|
constructor(message?: string, selector?: string, options?: any);
|
|
493
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* Unsupported operation error (e.g., operations not available in local mode)
|
|
523
|
+
*/
|
|
524
|
+
declare class UnsupportedOperationError extends InstaVMError {
|
|
525
|
+
constructor(message?: string, options?: any);
|
|
526
|
+
}
|
|
494
527
|
|
|
495
|
-
export { type ApiResponse, type AsyncExecutionResult, AuthenticationError, BrowserError, BrowserInteractionError, BrowserManager, BrowserNavigationError, BrowserSession, BrowserSessionError, type BrowserSessionInfo, type BrowserSessionOptions, BrowserTimeoutError, type ClickOptions, type ContentAnchor, type DownloadOptions, type DownloadResult, ElementNotFoundError, type ExecuteOptions, ExecutionError, type ExecutionResult, type ExtractContentOptions, type ExtractOptions, type ExtractedContent, type ExtractedElement, type FileUpload, type FillOptions, type HttpClientConfig, InstaVM, InstaVMError, type InstaVMOptions, type InteractiveElement, type NavigateOptions, type NavigationResult, NetworkError, QuotaExceededError, RateLimitError, type RequestConfig, type RetryConfig, type ScreenshotOptions, type ScrollOptions, SessionError, type TypeOptions, type UploadOptions, type UploadResult, type UsageStats, type WaitCondition };
|
|
528
|
+
export { type ApiResponse, type AsyncExecutionResult, AuthenticationError, BrowserError, BrowserInteractionError, BrowserManager, BrowserNavigationError, BrowserSession, BrowserSessionError, type BrowserSessionInfo, type BrowserSessionOptions, BrowserTimeoutError, type ClickOptions, type ContentAnchor, type DownloadOptions, type DownloadResult, ElementNotFoundError, type ExecuteOptions, ExecutionError, type ExecutionResult, type ExtractContentOptions, type ExtractOptions, type ExtractedContent, type ExtractedElement, type FileUpload, type FillOptions, type HttpClientConfig, InstaVM, InstaVMError, type InstaVMOptions, type InteractiveElement, type NavigateOptions, type NavigationResult, NetworkError, QuotaExceededError, RateLimitError, type RequestConfig, type RetryConfig, type ScreenshotOptions, type ScrollOptions, SessionError, type TypeOptions, UnsupportedOperationError, type UploadOptions, type UploadResult, type UsageStats, type WaitCondition };
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,8 @@ __export(index_exports, {
|
|
|
46
46
|
NetworkError: () => NetworkError,
|
|
47
47
|
QuotaExceededError: () => QuotaExceededError,
|
|
48
48
|
RateLimitError: () => RateLimitError,
|
|
49
|
-
SessionError: () => SessionError
|
|
49
|
+
SessionError: () => SessionError,
|
|
50
|
+
UnsupportedOperationError: () => UnsupportedOperationError
|
|
50
51
|
});
|
|
51
52
|
module.exports = __toCommonJS(index_exports);
|
|
52
53
|
|
|
@@ -131,6 +132,11 @@ var ElementNotFoundError = class extends BrowserError {
|
|
|
131
132
|
this.selector = selector;
|
|
132
133
|
}
|
|
133
134
|
};
|
|
135
|
+
var UnsupportedOperationError = class extends InstaVMError {
|
|
136
|
+
constructor(message = "Operation not supported", options) {
|
|
137
|
+
super(message, options);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
134
140
|
|
|
135
141
|
// src/utils/retry.ts
|
|
136
142
|
function defaultRetryCondition(error) {
|
|
@@ -272,18 +278,19 @@ var HTTPClient = class {
|
|
|
272
278
|
/**
|
|
273
279
|
* POST request with JSON body
|
|
274
280
|
*/
|
|
275
|
-
async post(url, data, headers) {
|
|
281
|
+
async post(url, data, headers, timeout) {
|
|
276
282
|
return this.request({
|
|
277
283
|
method: "POST",
|
|
278
284
|
url,
|
|
279
285
|
data,
|
|
280
|
-
headers
|
|
286
|
+
headers,
|
|
287
|
+
timeout
|
|
281
288
|
});
|
|
282
289
|
}
|
|
283
290
|
/**
|
|
284
291
|
* POST request for code execution (uses X-API-Key header like Python client)
|
|
285
292
|
*/
|
|
286
|
-
async postExecution(url, data, headers) {
|
|
293
|
+
async postExecution(url, data, headers, timeout) {
|
|
287
294
|
const requestHeaders = {
|
|
288
295
|
"X-API-Key": this.config.apiKey,
|
|
289
296
|
...headers
|
|
@@ -292,7 +299,8 @@ var HTTPClient = class {
|
|
|
292
299
|
method: "POST",
|
|
293
300
|
url,
|
|
294
301
|
data,
|
|
295
|
-
headers: requestHeaders
|
|
302
|
+
headers: requestHeaders,
|
|
303
|
+
timeout
|
|
296
304
|
});
|
|
297
305
|
}
|
|
298
306
|
/**
|
|
@@ -706,14 +714,20 @@ var BrowserSession = class extends import_eventemitter3.EventEmitter {
|
|
|
706
714
|
|
|
707
715
|
// src/client/BrowserManager.ts
|
|
708
716
|
var BrowserManager = class {
|
|
709
|
-
constructor(httpClient) {
|
|
717
|
+
constructor(httpClient, local = false) {
|
|
710
718
|
this.activeSessions = /* @__PURE__ */ new Map();
|
|
711
719
|
this.httpClient = httpClient;
|
|
720
|
+
this.local = local;
|
|
712
721
|
}
|
|
713
722
|
/**
|
|
714
723
|
* Create a new browser session
|
|
715
724
|
*/
|
|
716
725
|
async createSession(options = {}) {
|
|
726
|
+
if (this.local) {
|
|
727
|
+
throw new UnsupportedOperationError(
|
|
728
|
+
"Browser session management is not supported in local mode. Use navigate() or extractContent() with URL directly."
|
|
729
|
+
);
|
|
730
|
+
}
|
|
717
731
|
const requestData = {
|
|
718
732
|
viewport_width: options.viewportWidth || 1920,
|
|
719
733
|
viewport_height: options.viewportHeight || 1080,
|
|
@@ -812,6 +826,77 @@ var BrowserManager = class {
|
|
|
812
826
|
);
|
|
813
827
|
this.activeSessions.clear();
|
|
814
828
|
}
|
|
829
|
+
/**
|
|
830
|
+
* Navigate to a URL (local mode support - no session required)
|
|
831
|
+
*/
|
|
832
|
+
async navigate(url, options = {}) {
|
|
833
|
+
if (!this.local) {
|
|
834
|
+
throw new UnsupportedOperationError(
|
|
835
|
+
"navigate() without session is only supported in local mode. In cloud mode, create a session first."
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
const requestData = {
|
|
839
|
+
url,
|
|
840
|
+
wait_timeout: options.waitTimeout || 3e4
|
|
841
|
+
};
|
|
842
|
+
try {
|
|
843
|
+
const response = await this.httpClient.post(
|
|
844
|
+
"/v1/browser/interactions/navigate",
|
|
845
|
+
requestData
|
|
846
|
+
);
|
|
847
|
+
return {
|
|
848
|
+
success: response.success !== false,
|
|
849
|
+
url: response.url || url,
|
|
850
|
+
title: response.title,
|
|
851
|
+
status: response.status
|
|
852
|
+
};
|
|
853
|
+
} catch (error) {
|
|
854
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
855
|
+
throw new BrowserNavigationError(
|
|
856
|
+
`Navigation failed: ${errorMessage}`,
|
|
857
|
+
{ cause: error }
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Extract LLM-friendly content (local mode support - no session required)
|
|
863
|
+
*/
|
|
864
|
+
async extractContent(options = {}) {
|
|
865
|
+
if (!this.local) {
|
|
866
|
+
throw new UnsupportedOperationError(
|
|
867
|
+
"extractContent() without session is only supported in local mode. In cloud mode, create a session first."
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
if (!options.url) {
|
|
871
|
+
throw new BrowserInteractionError("url is required in local mode");
|
|
872
|
+
}
|
|
873
|
+
const requestData = {
|
|
874
|
+
url: options.url,
|
|
875
|
+
include_interactive: options.includeInteractive !== false,
|
|
876
|
+
include_anchors: options.includeAnchors !== false,
|
|
877
|
+
max_anchors: options.maxAnchors ?? 50
|
|
878
|
+
};
|
|
879
|
+
try {
|
|
880
|
+
const response = await this.httpClient.post(
|
|
881
|
+
"/v1/browser/interactions/content",
|
|
882
|
+
requestData
|
|
883
|
+
);
|
|
884
|
+
return {
|
|
885
|
+
readableContent: {
|
|
886
|
+
...response.readable_content || {},
|
|
887
|
+
content: response.readable_content?.content || ""
|
|
888
|
+
},
|
|
889
|
+
interactiveElements: response.interactive_elements,
|
|
890
|
+
contentAnchors: response.content_anchors
|
|
891
|
+
};
|
|
892
|
+
} catch (error) {
|
|
893
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
894
|
+
throw new BrowserInteractionError(
|
|
895
|
+
`Content extraction failed: ${errorMessage}`,
|
|
896
|
+
{ cause: error }
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
815
900
|
/**
|
|
816
901
|
* Clean up resources
|
|
817
902
|
*/
|
|
@@ -825,38 +910,61 @@ var import_form_data = __toESM(require("form-data"));
|
|
|
825
910
|
var InstaVM = class {
|
|
826
911
|
constructor(apiKey, options = {}) {
|
|
827
912
|
this._sessionId = null;
|
|
828
|
-
|
|
829
|
-
|
|
913
|
+
this.local = options.local || false;
|
|
914
|
+
this.timeout = options.timeout || 3e5;
|
|
915
|
+
if (!this.local && !apiKey) {
|
|
916
|
+
throw new AuthenticationError("API key is required for cloud mode");
|
|
830
917
|
}
|
|
831
918
|
const config = {
|
|
832
|
-
baseURL: options.baseURL || "https://api.instavm.io",
|
|
833
|
-
timeout:
|
|
834
|
-
// 5 minutes
|
|
919
|
+
baseURL: this.local ? options.localURL || "http://coderunner.local:8222" : options.baseURL || "https://api.instavm.io",
|
|
920
|
+
timeout: this.timeout,
|
|
835
921
|
maxRetries: options.maxRetries || 3,
|
|
836
922
|
retryDelay: options.retryDelay || 1e3,
|
|
837
|
-
apiKey
|
|
923
|
+
apiKey: apiKey || ""
|
|
838
924
|
};
|
|
839
925
|
this.httpClient = new HTTPClient(config);
|
|
840
|
-
this.browser = new BrowserManager(this.httpClient);
|
|
926
|
+
this.browser = new BrowserManager(this.httpClient, this.local);
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Ensure operation is not called in local mode
|
|
930
|
+
*/
|
|
931
|
+
ensureNotLocal(operationName) {
|
|
932
|
+
if (this.local) {
|
|
933
|
+
throw new UnsupportedOperationError(
|
|
934
|
+
`${operationName} is not supported in local mode. This operation is only available when using the cloud API.`
|
|
935
|
+
);
|
|
936
|
+
}
|
|
841
937
|
}
|
|
842
938
|
/**
|
|
843
939
|
* Execute code synchronously
|
|
940
|
+
*
|
|
941
|
+
* @param command - Command to execute
|
|
942
|
+
* @param options - Execution options
|
|
943
|
+
* @param options.timeout - Request timeout in milliseconds (used for HTTP request timeout and sent to API in seconds)
|
|
944
|
+
* @returns Execution result
|
|
844
945
|
*/
|
|
845
946
|
async execute(command, options = {}) {
|
|
846
947
|
let sessionId = options.sessionId || this._sessionId;
|
|
847
|
-
if (!sessionId) {
|
|
948
|
+
if (!this.local && !sessionId) {
|
|
848
949
|
sessionId = await this.createSession();
|
|
849
950
|
}
|
|
850
951
|
const requestData = {
|
|
851
952
|
command,
|
|
852
|
-
language: options.language || "python"
|
|
853
|
-
timeout: options.timeout || 15,
|
|
854
|
-
session_id: sessionId
|
|
953
|
+
language: options.language || "python"
|
|
855
954
|
};
|
|
955
|
+
if (options.timeout !== void 0) {
|
|
956
|
+
requestData.timeout = Math.floor(options.timeout / 1e3);
|
|
957
|
+
}
|
|
958
|
+
if (!this.local && sessionId) {
|
|
959
|
+
requestData.session_id = sessionId;
|
|
960
|
+
}
|
|
961
|
+
const requestTimeout = options.timeout !== void 0 ? options.timeout : this.timeout;
|
|
856
962
|
try {
|
|
857
963
|
const response = await this.httpClient.postExecution(
|
|
858
964
|
"/execute",
|
|
859
|
-
requestData
|
|
965
|
+
requestData,
|
|
966
|
+
void 0,
|
|
967
|
+
requestTimeout
|
|
860
968
|
);
|
|
861
969
|
if (response.session_id) {
|
|
862
970
|
this._sessionId = response.session_id;
|
|
@@ -882,6 +990,7 @@ var InstaVM = class {
|
|
|
882
990
|
* Execute code asynchronously
|
|
883
991
|
*/
|
|
884
992
|
async executeAsync(command, options = {}) {
|
|
993
|
+
this.ensureNotLocal("Async execution");
|
|
885
994
|
let sessionId = options.sessionId || this._sessionId;
|
|
886
995
|
if (!sessionId) {
|
|
887
996
|
sessionId = await this.createSession();
|
|
@@ -923,6 +1032,7 @@ var InstaVM = class {
|
|
|
923
1032
|
* Upload files to the execution environment
|
|
924
1033
|
*/
|
|
925
1034
|
async upload(files, options = {}) {
|
|
1035
|
+
this.ensureNotLocal("File upload");
|
|
926
1036
|
const formData = new import_form_data.default();
|
|
927
1037
|
for (const file of files) {
|
|
928
1038
|
if (Buffer.isBuffer(file.content)) {
|
|
@@ -965,9 +1075,11 @@ var InstaVM = class {
|
|
|
965
1075
|
* Create a new execution session
|
|
966
1076
|
*/
|
|
967
1077
|
async createSession() {
|
|
1078
|
+
this.ensureNotLocal("Session management");
|
|
968
1079
|
try {
|
|
969
1080
|
const response = await this.httpClient.post("/v1/sessions/session", {
|
|
970
|
-
api_key: this.httpClient.apiKey
|
|
1081
|
+
api_key: this.httpClient.apiKey,
|
|
1082
|
+
vm_lifetime_seconds: Math.floor(this.timeout / 1e3)
|
|
971
1083
|
});
|
|
972
1084
|
if (response.session_id) {
|
|
973
1085
|
this._sessionId = response.session_id;
|
|
@@ -1004,6 +1116,7 @@ var InstaVM = class {
|
|
|
1004
1116
|
* Get usage statistics for a session
|
|
1005
1117
|
*/
|
|
1006
1118
|
async getUsage(sessionId) {
|
|
1119
|
+
this.ensureNotLocal("Usage tracking");
|
|
1007
1120
|
const targetSessionId = sessionId || this._sessionId;
|
|
1008
1121
|
if (!targetSessionId) {
|
|
1009
1122
|
throw new SessionError("No active session to get usage for");
|
|
@@ -1030,6 +1143,7 @@ var InstaVM = class {
|
|
|
1030
1143
|
* Download a file from the remote VM
|
|
1031
1144
|
*/
|
|
1032
1145
|
async download(filename, options = {}) {
|
|
1146
|
+
this.ensureNotLocal("File download");
|
|
1033
1147
|
const targetSessionId = options.sessionId || this._sessionId;
|
|
1034
1148
|
if (!targetSessionId) {
|
|
1035
1149
|
throw new SessionError("No active session to download from");
|
|
@@ -1087,6 +1201,7 @@ var InstaVM = class {
|
|
|
1087
1201
|
NetworkError,
|
|
1088
1202
|
QuotaExceededError,
|
|
1089
1203
|
RateLimitError,
|
|
1090
|
-
SessionError
|
|
1204
|
+
SessionError,
|
|
1205
|
+
UnsupportedOperationError
|
|
1091
1206
|
});
|
|
1092
1207
|
//# sourceMappingURL=index.js.map
|