instavm 0.2.1 → 0.2.2

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.
@@ -0,0 +1,424 @@
1
+ import FormData from 'form-data';
2
+ import { EventEmitter } from 'eventemitter3';
3
+
4
+ interface ApiResponse<T = any> {
5
+ success?: boolean;
6
+ data?: T;
7
+ error?: string;
8
+ message?: string;
9
+ }
10
+ interface HttpClientConfig {
11
+ baseURL: string;
12
+ timeout: number;
13
+ maxRetries: number;
14
+ retryDelay: number;
15
+ apiKey: string;
16
+ }
17
+ interface RequestConfig {
18
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
19
+ url: string;
20
+ headers?: Record<string, string>;
21
+ data?: any;
22
+ params?: Record<string, any>;
23
+ timeout?: number;
24
+ }
25
+ interface RetryConfig {
26
+ retries: number;
27
+ retryDelay: number;
28
+ retryCondition?: (error: any) => boolean;
29
+ }
30
+
31
+ /**
32
+ * HTTP client with authentication, retry logic, and error handling
33
+ */
34
+ declare class HTTPClient {
35
+ private client;
36
+ private config;
37
+ get apiKey(): string;
38
+ constructor(config: HttpClientConfig);
39
+ private setupInterceptors;
40
+ /**
41
+ * Make an HTTP request with retry logic
42
+ */
43
+ request<T = any>(requestConfig: RequestConfig): Promise<T>;
44
+ /**
45
+ * POST request with JSON body
46
+ */
47
+ post<T = any>(url: string, data?: any, headers?: Record<string, string>): Promise<T>;
48
+ /**
49
+ * POST request for code execution (X-API-Key header is automatically added)
50
+ */
51
+ postExecution<T = any>(url: string, data: any, headers?: Record<string, string>): Promise<T>;
52
+ /**
53
+ * POST request with form data (for file uploads)
54
+ */
55
+ postFormData<T = any>(url: string, formData: FormData, headers?: Record<string, string>): Promise<T>;
56
+ /**
57
+ * GET request
58
+ */
59
+ get<T = any>(url: string, params?: Record<string, any>, headers?: Record<string, string>): Promise<T>;
60
+ /**
61
+ * DELETE request
62
+ */
63
+ delete<T = any>(url: string, headers?: Record<string, string>): Promise<T>;
64
+ }
65
+
66
+ interface BrowserSessionOptions {
67
+ viewportWidth?: number;
68
+ viewportHeight?: number;
69
+ userAgent?: string;
70
+ }
71
+ interface BrowserSessionInfo {
72
+ sessionId: string;
73
+ status: 'active' | 'inactive' | 'closed';
74
+ createdAt: string;
75
+ viewportWidth: number;
76
+ viewportHeight: number;
77
+ userAgent?: string;
78
+ }
79
+ interface NavigateOptions {
80
+ waitTimeout?: number;
81
+ waitUntil?: 'load' | 'domcontentloaded' | 'networkidle';
82
+ }
83
+ interface NavigationResult {
84
+ success: boolean;
85
+ url: string;
86
+ title?: string;
87
+ status?: number;
88
+ }
89
+ interface ClickOptions {
90
+ timeout?: number;
91
+ button?: 'left' | 'right' | 'middle';
92
+ clickCount?: number;
93
+ force?: boolean;
94
+ }
95
+ interface TypeOptions {
96
+ timeout?: number;
97
+ delay?: number;
98
+ clear?: boolean;
99
+ }
100
+ interface FillOptions {
101
+ timeout?: number;
102
+ force?: boolean;
103
+ }
104
+ interface ScrollOptions {
105
+ x?: number;
106
+ y?: number;
107
+ behavior?: 'auto' | 'smooth';
108
+ }
109
+ interface ScreenshotOptions {
110
+ fullPage?: boolean;
111
+ format?: 'png' | 'jpeg';
112
+ quality?: number;
113
+ clip?: {
114
+ x: number;
115
+ y: number;
116
+ width: number;
117
+ height: number;
118
+ };
119
+ }
120
+ type WaitCondition = {
121
+ type: 'visible';
122
+ selector: string;
123
+ } | {
124
+ type: 'hidden';
125
+ selector: string;
126
+ } | {
127
+ type: 'attached';
128
+ selector: string;
129
+ } | {
130
+ type: 'detached';
131
+ selector: string;
132
+ } | {
133
+ type: 'timeout';
134
+ ms: number;
135
+ };
136
+ interface ExtractedElement {
137
+ text?: string;
138
+ href?: string;
139
+ src?: string;
140
+ class?: string;
141
+ id?: string;
142
+ tagName?: string;
143
+ [attribute: string]: any;
144
+ }
145
+ interface ExtractOptions {
146
+ attributes?: string[];
147
+ maxResults?: number;
148
+ }
149
+
150
+ /**
151
+ * Browser session for automation
152
+ */
153
+ declare class BrowserSession extends EventEmitter {
154
+ readonly sessionId: string;
155
+ private httpClient;
156
+ private _isActive;
157
+ constructor(sessionId: string, httpClient: HTTPClient);
158
+ /**
159
+ * Navigate to a URL
160
+ */
161
+ navigate(url: string, options?: NavigateOptions): Promise<NavigationResult>;
162
+ /**
163
+ * Click an element
164
+ */
165
+ click(selector: string, options?: ClickOptions): Promise<void>;
166
+ /**
167
+ * Type text into an element
168
+ */
169
+ type(selector: string, text: string, options?: TypeOptions): Promise<void>;
170
+ /**
171
+ * Fill a form field
172
+ */
173
+ fill(selector: string, value: string, options?: FillOptions): Promise<void>;
174
+ /**
175
+ * Scroll the page
176
+ */
177
+ scroll(options?: ScrollOptions): Promise<void>;
178
+ /**
179
+ * Take a screenshot
180
+ */
181
+ screenshot(options?: ScreenshotOptions): Promise<string>;
182
+ /**
183
+ * Extract elements from the page
184
+ */
185
+ extractElements(selector: string, attributes?: string[], options?: ExtractOptions): Promise<ExtractedElement[]>;
186
+ /**
187
+ * Wait for a condition
188
+ */
189
+ wait(condition: WaitCondition, timeout?: number): Promise<void>;
190
+ /**
191
+ * Close the browser session
192
+ */
193
+ close(): Promise<void>;
194
+ /**
195
+ * Check if session is active
196
+ */
197
+ get isActive(): boolean;
198
+ /**
199
+ * Ensure session is active before operations
200
+ */
201
+ private ensureActive;
202
+ }
203
+
204
+ /**
205
+ * Browser automation manager
206
+ */
207
+ declare class BrowserManager {
208
+ private httpClient;
209
+ private activeSessions;
210
+ constructor(httpClient: HTTPClient);
211
+ /**
212
+ * Create a new browser session
213
+ */
214
+ createSession(options?: BrowserSessionOptions): Promise<BrowserSession>;
215
+ /**
216
+ * Get information about a specific session
217
+ */
218
+ getSession(sessionId: string): Promise<BrowserSessionInfo>;
219
+ /**
220
+ * List all browser sessions
221
+ */
222
+ listSessions(): Promise<BrowserSessionInfo[]>;
223
+ /**
224
+ * Get a locally tracked session
225
+ */
226
+ getLocalSession(sessionId: string): BrowserSession | undefined;
227
+ /**
228
+ * Get all locally tracked sessions
229
+ */
230
+ getLocalSessions(): BrowserSession[];
231
+ /**
232
+ * Close all active sessions
233
+ */
234
+ closeAllSessions(): Promise<void>;
235
+ /**
236
+ * Clean up resources
237
+ */
238
+ dispose(): Promise<void>;
239
+ }
240
+
241
+ interface ExecuteOptions {
242
+ language?: 'python' | 'bash';
243
+ timeout?: number;
244
+ sessionId?: string;
245
+ }
246
+ interface ExecutionResult {
247
+ output: string;
248
+ success: boolean;
249
+ executionTime: number;
250
+ sessionId?: string;
251
+ error?: string;
252
+ }
253
+ interface AsyncExecutionResult {
254
+ taskId: string;
255
+ status: 'pending' | 'running' | 'completed' | 'failed';
256
+ output?: string;
257
+ success?: boolean;
258
+ executionTime?: number;
259
+ sessionId?: string;
260
+ error?: string;
261
+ }
262
+ interface FileUpload {
263
+ name: string;
264
+ content: Buffer | string;
265
+ path?: string;
266
+ }
267
+ interface UploadOptions {
268
+ sessionId?: string;
269
+ remotePath?: string;
270
+ recursive?: boolean;
271
+ }
272
+ interface UploadResult {
273
+ success: boolean;
274
+ files: string[];
275
+ message?: string;
276
+ }
277
+ interface UsageStats {
278
+ sessionsUsed: number;
279
+ executionTime: number;
280
+ quotaRemaining: number;
281
+ quotaLimit: number;
282
+ }
283
+
284
+ interface InstaVMOptions {
285
+ baseURL?: string;
286
+ timeout?: number;
287
+ maxRetries?: number;
288
+ retryDelay?: number;
289
+ }
290
+ /**
291
+ * Main InstaVM client class
292
+ */
293
+ declare class InstaVM {
294
+ private httpClient;
295
+ private _sessionId;
296
+ readonly browser: BrowserManager;
297
+ constructor(apiKey: string, options?: InstaVMOptions);
298
+ /**
299
+ * Execute code synchronously
300
+ */
301
+ execute(command: string, options?: ExecuteOptions): Promise<ExecutionResult>;
302
+ /**
303
+ * Execute code asynchronously
304
+ */
305
+ executeAsync(command: string, options?: ExecuteOptions): Promise<AsyncExecutionResult>;
306
+ /**
307
+ * Upload files to the execution environment
308
+ */
309
+ upload(files: FileUpload[], options?: UploadOptions): Promise<UploadResult>;
310
+ /**
311
+ * Create a new execution session
312
+ */
313
+ createSession(): Promise<string>;
314
+ /**
315
+ * Close a session
316
+ */
317
+ closeSession(sessionId?: string): Promise<void>;
318
+ /**
319
+ * Get usage statistics for a session
320
+ */
321
+ getUsage(sessionId?: string): Promise<UsageStats>;
322
+ /**
323
+ * Get the current session ID
324
+ */
325
+ get sessionId(): string | null;
326
+ /**
327
+ * Clean up resources
328
+ */
329
+ dispose(): Promise<void>;
330
+ }
331
+
332
+ /**
333
+ * Base error class for all InstaVM SDK errors
334
+ */
335
+ declare class InstaVMError extends Error {
336
+ readonly name: string;
337
+ readonly code?: string;
338
+ readonly statusCode?: number;
339
+ readonly response?: any;
340
+ constructor(message: string, options?: {
341
+ code?: string;
342
+ statusCode?: number;
343
+ response?: any;
344
+ cause?: Error;
345
+ });
346
+ }
347
+ /**
348
+ * Authentication-related errors (401, invalid API key, etc.)
349
+ */
350
+ declare class AuthenticationError extends InstaVMError {
351
+ constructor(message?: string, options?: any);
352
+ }
353
+ /**
354
+ * Rate limiting errors (429)
355
+ */
356
+ declare class RateLimitError extends InstaVMError {
357
+ readonly retryAfter?: number;
358
+ constructor(message?: string, retryAfter?: number, options?: any);
359
+ }
360
+ /**
361
+ * Quota/usage limit exceeded errors
362
+ */
363
+ declare class QuotaExceededError extends InstaVMError {
364
+ constructor(message?: string, options?: any);
365
+ }
366
+ /**
367
+ * Network-related errors (timeouts, connection issues, 5xx errors)
368
+ */
369
+ declare class NetworkError extends InstaVMError {
370
+ constructor(message?: string, options?: any);
371
+ }
372
+ /**
373
+ * Code execution errors
374
+ */
375
+ declare class ExecutionError extends InstaVMError {
376
+ readonly executionOutput?: string;
377
+ readonly executionTime?: number;
378
+ constructor(message: string, executionOutput?: string, executionTime?: number, options?: any);
379
+ }
380
+ /**
381
+ * Session management errors
382
+ */
383
+ declare class SessionError extends InstaVMError {
384
+ constructor(message?: string, options?: any);
385
+ }
386
+ /**
387
+ * Browser automation base error
388
+ */
389
+ declare class BrowserError extends InstaVMError {
390
+ constructor(message?: string, options?: any);
391
+ }
392
+ /**
393
+ * Browser session management errors
394
+ */
395
+ declare class BrowserSessionError extends BrowserError {
396
+ constructor(message?: string, options?: any);
397
+ }
398
+ /**
399
+ * Browser interaction errors (click, type, etc.)
400
+ */
401
+ declare class BrowserInteractionError extends BrowserError {
402
+ constructor(message?: string, options?: any);
403
+ }
404
+ /**
405
+ * Browser timeout errors
406
+ */
407
+ declare class BrowserTimeoutError extends BrowserError {
408
+ constructor(message?: string, options?: any);
409
+ }
410
+ /**
411
+ * Browser navigation errors
412
+ */
413
+ declare class BrowserNavigationError extends BrowserError {
414
+ constructor(message?: string, options?: any);
415
+ }
416
+ /**
417
+ * Element not found errors
418
+ */
419
+ declare class ElementNotFoundError extends BrowserError {
420
+ readonly selector?: string;
421
+ constructor(message?: string, selector?: string, options?: any);
422
+ }
423
+
424
+ export { type ApiResponse, type AsyncExecutionResult, AuthenticationError, BrowserError, BrowserInteractionError, BrowserManager, BrowserNavigationError, BrowserSession, BrowserSessionError, type BrowserSessionInfo, type BrowserSessionOptions, BrowserTimeoutError, type ClickOptions, ElementNotFoundError, type ExecuteOptions, ExecutionError, type ExecutionResult, type ExtractOptions, type ExtractedElement, type FileUpload, type FillOptions, type HttpClientConfig, InstaVM, InstaVMError, type InstaVMOptions, 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 };
package/dist/index.js CHANGED
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,6 +31,92 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
34
+ // package.json
35
+ var require_package = __commonJS({
36
+ "package.json"(exports2, module2) {
37
+ module2.exports = {
38
+ name: "instavm",
39
+ version: "0.2.2",
40
+ description: "Official JavaScript SDK for InstaVM API",
41
+ main: "dist/index.js",
42
+ module: "dist/index.mjs",
43
+ types: "dist/index.d.ts",
44
+ exports: {
45
+ ".": {
46
+ types: "./dist/index.d.ts",
47
+ import: "./dist/index.mjs",
48
+ require: "./dist/index.js"
49
+ },
50
+ "./integrations/openai": {
51
+ types: "./dist/integrations/openai.d.ts",
52
+ import: "./dist/integrations/openai.mjs",
53
+ require: "./dist/integrations/openai.js"
54
+ }
55
+ },
56
+ files: [
57
+ "dist"
58
+ ],
59
+ scripts: {
60
+ dev: "tsup --watch",
61
+ build: "tsup",
62
+ "type-check": "tsc --noEmit",
63
+ test: "vitest",
64
+ "test:unit": "vitest run tests/unit",
65
+ "test:integration": "vitest run tests/integration",
66
+ "test:watch": "vitest --watch",
67
+ "test:coverage": "vitest --coverage",
68
+ lint: "eslint src --ext .ts,.tsx",
69
+ "lint:fix": "eslint src --ext .ts,.tsx --fix",
70
+ format: "prettier --write src/**/*.ts",
71
+ prepublishOnly: "npm run build && npm run test:unit",
72
+ clean: "rm -rf dist"
73
+ },
74
+ keywords: [
75
+ "instavm",
76
+ "api",
77
+ "sdk",
78
+ "browser-automation",
79
+ "code-execution",
80
+ "microvm",
81
+ "cloud"
82
+ ],
83
+ author: "InstaVM",
84
+ license: "UNLICENSED",
85
+ repository: {
86
+ type: "git",
87
+ url: "https://github.com/instavm/js.git"
88
+ },
89
+ bugs: {
90
+ url: "https://github.com/instavm/js/issues"
91
+ },
92
+ homepage: "https://github.com/instavm/js#readme",
93
+ engines: {
94
+ node: ">=16.0.0"
95
+ },
96
+ dependencies: {
97
+ axios: "^1.7.9",
98
+ eventemitter3: "^5.0.1",
99
+ "form-data": "^4.0.1",
100
+ ws: "^8.18.0"
101
+ },
102
+ devDependencies: {
103
+ "@types/node": "^22.10.5",
104
+ "@types/ws": "^8.5.13",
105
+ "@typescript-eslint/eslint-plugin": "^8.18.2",
106
+ "@typescript-eslint/parser": "^8.18.2",
107
+ "@vitest/coverage-v8": "^2.1.8",
108
+ eslint: "^9.18.0",
109
+ "eslint-config-prettier": "^9.1.0",
110
+ "eslint-plugin-prettier": "^5.2.1",
111
+ prettier: "^3.4.2",
112
+ tsup: "^8.3.5",
113
+ typescript: "^5.7.2",
114
+ vitest: "^2.1.8"
115
+ }
116
+ };
117
+ }
118
+ });
119
+
31
120
  // src/index.ts
32
121
  var index_exports = {};
33
122
  __export(index_exports, {
@@ -173,6 +262,14 @@ async function withRetry(fn, options) {
173
262
  }
174
263
 
175
264
  // src/client/HTTPClient.ts
265
+ function getPackageVersion() {
266
+ try {
267
+ const packageJson = require_package();
268
+ return packageJson.version || "0.1.0";
269
+ } catch {
270
+ return "0.1.0";
271
+ }
272
+ }
176
273
  var HTTPClient = class {
177
274
  get apiKey() {
178
275
  return this.config.apiKey;
@@ -184,7 +281,7 @@ var HTTPClient = class {
184
281
  timeout: config.timeout,
185
282
  headers: {
186
283
  "Content-Type": "application/json",
187
- "User-Agent": "instavm-js-sdk/0.1.0"
284
+ "User-Agent": `instavm-js-sdk/${getPackageVersion()}`
188
285
  }
189
286
  });
190
287
  this.setupInterceptors();
@@ -192,7 +289,7 @@ var HTTPClient = class {
192
289
  setupInterceptors() {
193
290
  this.client.interceptors.request.use(
194
291
  (config) => {
195
- if (config.url?.includes("/browser/")) {
292
+ if (!config.headers["X-API-Key"] && !config.url?.includes("/v1/sessions/session")) {
196
293
  config.headers["X-API-Key"] = this.config.apiKey;
197
294
  }
198
295
  return config;
@@ -281,18 +378,14 @@ var HTTPClient = class {
281
378
  });
282
379
  }
283
380
  /**
284
- * POST request for code execution (uses X-API-Key header like Python client)
381
+ * POST request for code execution (X-API-Key header is automatically added)
285
382
  */
286
383
  async postExecution(url, data, headers) {
287
- const requestHeaders = {
288
- "X-API-Key": this.config.apiKey,
289
- ...headers
290
- };
291
384
  return this.request({
292
385
  method: "POST",
293
386
  url,
294
387
  data,
295
- headers: requestHeaders
388
+ headers
296
389
  });
297
390
  }
298
391
  /**