instavm 0.8.1 → 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/dist/index.js CHANGED
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ APIKeysManager: () => APIKeysManager,
35
+ AuditManager: () => AuditManager,
34
36
  AuthenticationError: () => AuthenticationError,
35
37
  BrowserError: () => BrowserError,
36
38
  BrowserInteractionError: () => BrowserInteractionError,
@@ -39,6 +41,8 @@ __export(index_exports, {
39
41
  BrowserSession: () => BrowserSession,
40
42
  BrowserSessionError: () => BrowserSessionError,
41
43
  BrowserTimeoutError: () => BrowserTimeoutError,
44
+ ComputerUseManager: () => ComputerUseManager,
45
+ CustomDomainsManager: () => CustomDomainsManager,
42
46
  ElementNotFoundError: () => ElementNotFoundError,
43
47
  ExecutionError: () => ExecutionError,
44
48
  InstaVM: () => InstaVM,
@@ -47,7 +51,11 @@ __export(index_exports, {
47
51
  QuotaExceededError: () => QuotaExceededError,
48
52
  RateLimitError: () => RateLimitError,
49
53
  SessionError: () => SessionError,
50
- UnsupportedOperationError: () => UnsupportedOperationError
54
+ SharesManager: () => SharesManager,
55
+ SnapshotsManager: () => SnapshotsManager,
56
+ UnsupportedOperationError: () => UnsupportedOperationError,
57
+ VMsManager: () => VMsManager,
58
+ WebhooksManager: () => WebhooksManager
51
59
  });
52
60
  module.exports = __toCommonJS(index_exports);
53
61
 
@@ -190,7 +198,7 @@ var HTTPClient = class {
190
198
  timeout: config.timeout,
191
199
  headers: {
192
200
  "Content-Type": "application/json",
193
- "User-Agent": "instavm-js-sdk/0.1.0"
201
+ "User-Agent": "instavm-js-sdk/0.11.0"
194
202
  }
195
203
  });
196
204
  this.setupInterceptors();
@@ -211,7 +219,7 @@ var HTTPClient = class {
211
219
  const axiosError = error;
212
220
  const status = axiosError.response?.status;
213
221
  const data = axiosError.response?.data;
214
- const message = data?.message || data?.error || axiosError.message;
222
+ const message = data?.message || data?.error || data?.detail || axiosError.message;
215
223
  switch (status) {
216
224
  case 401:
217
225
  throw new AuthenticationError(message, {
@@ -223,14 +231,16 @@ var HTTPClient = class {
223
231
  statusCode: status,
224
232
  response: data
225
233
  });
226
- case 429:
234
+ case 429: {
227
235
  const retryAfter = parseInt(
228
236
  axiosError.response?.headers["retry-after"] || "60"
229
237
  );
230
- throw new RateLimitError(message, retryAfter, {
238
+ const rateLimitMessage = data?.detail || message;
239
+ throw new RateLimitError(rateLimitMessage, retryAfter, {
231
240
  statusCode: status,
232
241
  response: data
233
242
  });
243
+ }
234
244
  case 500:
235
245
  case 502:
236
246
  case 503:
@@ -308,6 +318,7 @@ var HTTPClient = class {
308
318
  */
309
319
  async postFormData(url, formData, headers) {
310
320
  const requestHeaders = {
321
+ "X-API-Key": this.config.apiKey,
311
322
  ...formData.getHeaders(),
312
323
  ...headers
313
324
  };
@@ -359,6 +370,39 @@ var HTTPClient = class {
359
370
  headers
360
371
  });
361
372
  }
373
+ /**
374
+ * PUT request
375
+ */
376
+ async put(url, data, headers) {
377
+ return this.request({
378
+ method: "PUT",
379
+ url,
380
+ data,
381
+ headers
382
+ });
383
+ }
384
+ /**
385
+ * PATCH request
386
+ */
387
+ async patch(url, data, headers) {
388
+ return this.request({
389
+ method: "PATCH",
390
+ url,
391
+ data,
392
+ headers
393
+ });
394
+ }
395
+ /**
396
+ * OPTIONS request
397
+ */
398
+ async options(url, headers, params) {
399
+ return this.request({
400
+ method: "OPTIONS",
401
+ url,
402
+ headers,
403
+ params
404
+ });
405
+ }
362
406
  /**
363
407
  * POST request that returns raw binary data (for file downloads)
364
408
  */
@@ -925,13 +969,525 @@ var BrowserManager = class {
925
969
  }
926
970
  };
927
971
 
972
+ // src/utils/path.ts
973
+ function encodePathSegment(value) {
974
+ return encodeURIComponent(String(value));
975
+ }
976
+ function encodePathSegments(path) {
977
+ const segments = path.replace(/^\/+/, "").split("/").filter((segment) => segment.length > 0 && segment !== ".");
978
+ if (segments.some((segment) => segment === "..")) {
979
+ throw new Error("Path traversal not allowed in proxy path");
980
+ }
981
+ return segments.map((segment) => encodeURIComponent(segment)).join("/");
982
+ }
983
+
984
+ // src/client/VMsManager.ts
985
+ var VMsManager = class {
986
+ constructor(httpClient, local = false) {
987
+ this.httpClient = httpClient;
988
+ this.local = local;
989
+ }
990
+ ensureCloud(operation) {
991
+ if (this.local) {
992
+ throw new UnsupportedOperationError(
993
+ `${operation} is not supported in local mode.`
994
+ );
995
+ }
996
+ }
997
+ async create(payload = {}, wait = true) {
998
+ this.ensureCloud("VM creation");
999
+ return this.httpClient.request({
1000
+ method: "POST",
1001
+ url: "/v1/vms",
1002
+ params: { wait },
1003
+ data: payload,
1004
+ headers: { "X-API-Key": this.httpClient.apiKey }
1005
+ });
1006
+ }
1007
+ async list() {
1008
+ this.ensureCloud("VM listing");
1009
+ return this.httpClient.get(
1010
+ "/v1/vms",
1011
+ void 0,
1012
+ { "X-API-Key": this.httpClient.apiKey }
1013
+ );
1014
+ }
1015
+ async listAll() {
1016
+ return this.listAllRecords();
1017
+ }
1018
+ /**
1019
+ * Calls GET /v1/vms/ (trailing slash), a distinct route from GET /v1/vms.
1020
+ */
1021
+ async listAllRecords() {
1022
+ this.ensureCloud("VM listing");
1023
+ return this.httpClient.get(
1024
+ "/v1/vms/",
1025
+ void 0,
1026
+ { "X-API-Key": this.httpClient.apiKey }
1027
+ );
1028
+ }
1029
+ async get(itemId) {
1030
+ this.ensureCloud("VM lookup");
1031
+ const safeItemId = encodePathSegment(itemId);
1032
+ return this.httpClient.get(
1033
+ `/v1/vms/${safeItemId}`,
1034
+ void 0,
1035
+ { "X-API-Key": this.httpClient.apiKey }
1036
+ );
1037
+ }
1038
+ async update(vmId, payload = {}) {
1039
+ this.ensureCloud("VM update");
1040
+ const safeVmId = encodePathSegment(vmId);
1041
+ return this.httpClient.patch(
1042
+ `/v1/vms/${safeVmId}`,
1043
+ payload,
1044
+ { "X-API-Key": this.httpClient.apiKey }
1045
+ );
1046
+ }
1047
+ async delete(vmId) {
1048
+ this.ensureCloud("VM deletion");
1049
+ const safeVmId = encodePathSegment(vmId);
1050
+ return this.httpClient.delete(
1051
+ `/v1/vms/${safeVmId}`,
1052
+ { "X-API-Key": this.httpClient.apiKey }
1053
+ );
1054
+ }
1055
+ async clone(vmId, payload = {}, wait = true) {
1056
+ this.ensureCloud("VM clone");
1057
+ const safeVmId = encodePathSegment(vmId);
1058
+ return this.httpClient.request({
1059
+ method: "POST",
1060
+ url: `/v1/vms/${safeVmId}/clone`,
1061
+ params: { wait },
1062
+ data: payload,
1063
+ headers: { "X-API-Key": this.httpClient.apiKey }
1064
+ });
1065
+ }
1066
+ async snapshot(vmId, payload = {}, wait = true) {
1067
+ this.ensureCloud("VM snapshot");
1068
+ const safeVmId = encodePathSegment(vmId);
1069
+ return this.httpClient.request({
1070
+ method: "POST",
1071
+ url: `/v1/vms/${safeVmId}/snapshot`,
1072
+ params: { wait },
1073
+ data: payload,
1074
+ headers: { "X-API-Key": this.httpClient.apiKey }
1075
+ });
1076
+ }
1077
+ };
1078
+
1079
+ // src/client/SnapshotsManager.ts
1080
+ var SnapshotsManager = class {
1081
+ constructor(httpClient, local = false) {
1082
+ this.httpClient = httpClient;
1083
+ this.local = local;
1084
+ }
1085
+ ensureCloud(operation) {
1086
+ if (this.local) {
1087
+ throw new UnsupportedOperationError(
1088
+ `${operation} is not supported in local mode.`
1089
+ );
1090
+ }
1091
+ }
1092
+ async create(payload) {
1093
+ this.ensureCloud("Snapshot creation");
1094
+ return this.httpClient.post(
1095
+ "/v1/snapshots",
1096
+ payload,
1097
+ { "X-API-Key": this.httpClient.apiKey }
1098
+ );
1099
+ }
1100
+ async list(options = {}) {
1101
+ this.ensureCloud("Snapshot listing");
1102
+ return this.httpClient.get(
1103
+ "/v1/snapshots",
1104
+ options,
1105
+ { "X-API-Key": this.httpClient.apiKey }
1106
+ );
1107
+ }
1108
+ async get(snapshotId) {
1109
+ this.ensureCloud("Snapshot lookup");
1110
+ const safeSnapshotId = encodePathSegment(snapshotId);
1111
+ return this.httpClient.get(
1112
+ `/v1/snapshots/${safeSnapshotId}`,
1113
+ void 0,
1114
+ { "X-API-Key": this.httpClient.apiKey }
1115
+ );
1116
+ }
1117
+ async delete(snapshotId) {
1118
+ this.ensureCloud("Snapshot deletion");
1119
+ const safeSnapshotId = encodePathSegment(snapshotId);
1120
+ return this.httpClient.delete(
1121
+ `/v1/snapshots/${safeSnapshotId}`,
1122
+ { "X-API-Key": this.httpClient.apiKey }
1123
+ );
1124
+ }
1125
+ };
1126
+
1127
+ // src/client/SharesManager.ts
1128
+ var SharesManager = class {
1129
+ constructor(httpClient, local = false, getSessionId = () => null) {
1130
+ this.httpClient = httpClient;
1131
+ this.local = local;
1132
+ this.getSessionId = getSessionId;
1133
+ }
1134
+ ensureCloud(operation) {
1135
+ if (this.local) {
1136
+ throw new UnsupportedOperationError(
1137
+ `${operation} is not supported in local mode.`
1138
+ );
1139
+ }
1140
+ }
1141
+ async create(payload) {
1142
+ this.ensureCloud("Share creation");
1143
+ const body = { ...payload };
1144
+ if (!body.session_id && !body.vm_id) {
1145
+ const sid = this.getSessionId();
1146
+ if (!sid) {
1147
+ throw new SessionError(
1148
+ "Provide session_id/vm_id or create a session before creating a share."
1149
+ );
1150
+ }
1151
+ body.session_id = sid;
1152
+ }
1153
+ return this.httpClient.post(
1154
+ "/v1/shares",
1155
+ body,
1156
+ { "X-API-Key": this.httpClient.apiKey }
1157
+ );
1158
+ }
1159
+ async update(shareId, payload) {
1160
+ this.ensureCloud("Share update");
1161
+ const safeShareId = encodePathSegment(shareId);
1162
+ return this.httpClient.patch(
1163
+ `/v1/shares/${safeShareId}`,
1164
+ payload,
1165
+ { "X-API-Key": this.httpClient.apiKey }
1166
+ );
1167
+ }
1168
+ };
1169
+
1170
+ // src/client/CustomDomainsManager.ts
1171
+ var CustomDomainsManager = class {
1172
+ constructor(httpClient, local = false) {
1173
+ this.httpClient = httpClient;
1174
+ this.local = local;
1175
+ }
1176
+ ensureCloud(operation) {
1177
+ if (this.local) {
1178
+ throw new UnsupportedOperationError(
1179
+ `${operation} is not supported in local mode.`
1180
+ );
1181
+ }
1182
+ }
1183
+ async create(payload) {
1184
+ this.ensureCloud("Custom domain creation");
1185
+ return this.httpClient.post(
1186
+ "/v1/custom-domains",
1187
+ payload,
1188
+ { "X-API-Key": this.httpClient.apiKey }
1189
+ );
1190
+ }
1191
+ async list() {
1192
+ this.ensureCloud("Custom domain listing");
1193
+ return this.httpClient.get(
1194
+ "/v1/custom-domains",
1195
+ void 0,
1196
+ { "X-API-Key": this.httpClient.apiKey }
1197
+ );
1198
+ }
1199
+ async health(domainId) {
1200
+ this.ensureCloud("Custom domain health");
1201
+ const safeDomainId = encodePathSegment(domainId);
1202
+ return this.httpClient.get(
1203
+ `/v1/custom-domains/${safeDomainId}/health`,
1204
+ void 0,
1205
+ { "X-API-Key": this.httpClient.apiKey }
1206
+ );
1207
+ }
1208
+ async verify(domainId) {
1209
+ this.ensureCloud("Custom domain verification");
1210
+ const safeDomainId = encodePathSegment(domainId);
1211
+ return this.httpClient.post(
1212
+ `/v1/custom-domains/${safeDomainId}/verify`,
1213
+ {},
1214
+ { "X-API-Key": this.httpClient.apiKey }
1215
+ );
1216
+ }
1217
+ async delete(domainId) {
1218
+ this.ensureCloud("Custom domain deletion");
1219
+ const safeDomainId = encodePathSegment(domainId);
1220
+ return this.httpClient.delete(
1221
+ `/v1/custom-domains/${safeDomainId}`,
1222
+ { "X-API-Key": this.httpClient.apiKey }
1223
+ );
1224
+ }
1225
+ };
1226
+
1227
+ // src/client/ComputerUseManager.ts
1228
+ var ComputerUseManager = class {
1229
+ constructor(httpClient, local = false) {
1230
+ this.httpClient = httpClient;
1231
+ this.local = local;
1232
+ }
1233
+ ensureCloud(operation) {
1234
+ if (this.local) {
1235
+ throw new UnsupportedOperationError(
1236
+ `${operation} is not supported in local mode.`
1237
+ );
1238
+ }
1239
+ }
1240
+ async viewerUrl(sessionId) {
1241
+ this.ensureCloud("Computer-use viewer URL");
1242
+ const safeSessionId = encodePathSegment(sessionId);
1243
+ return this.httpClient.get(
1244
+ `/v1/computeruse/${safeSessionId}/viewer-url`,
1245
+ void 0,
1246
+ { "X-API-Key": this.httpClient.apiKey }
1247
+ );
1248
+ }
1249
+ async proxy(sessionId, path, method = "GET", options = {}) {
1250
+ this.ensureCloud("Computer-use proxy");
1251
+ const safeSessionId = encodePathSegment(sessionId);
1252
+ const cleanPath = encodePathSegments(path);
1253
+ return this.httpClient.request({
1254
+ method,
1255
+ url: `/v1/computeruse/${safeSessionId}/${cleanPath}`,
1256
+ params: options.params,
1257
+ data: options.body,
1258
+ headers: { "X-API-Key": this.httpClient.apiKey }
1259
+ });
1260
+ }
1261
+ async get(sessionId, path, params) {
1262
+ return this.proxy(sessionId, path, "GET", { params });
1263
+ }
1264
+ async post(sessionId, path, body) {
1265
+ return this.proxy(sessionId, path, "POST", { body });
1266
+ }
1267
+ async put(sessionId, path, body) {
1268
+ return this.proxy(sessionId, path, "PUT", { body });
1269
+ }
1270
+ async patch(sessionId, path, body) {
1271
+ return this.proxy(sessionId, path, "PATCH", { body });
1272
+ }
1273
+ async delete(sessionId, path, params) {
1274
+ return this.proxy(sessionId, path, "DELETE", { params });
1275
+ }
1276
+ async options(sessionId, path, params) {
1277
+ return this.proxy(sessionId, path, "OPTIONS", { params });
1278
+ }
1279
+ };
1280
+
1281
+ // src/client/APIKeysManager.ts
1282
+ var APIKeysManager = class {
1283
+ constructor(httpClient, local = false) {
1284
+ this.httpClient = httpClient;
1285
+ this.local = local;
1286
+ }
1287
+ ensureCloud(operation) {
1288
+ if (this.local) {
1289
+ throw new UnsupportedOperationError(
1290
+ `${operation} is not supported in local mode.`
1291
+ );
1292
+ }
1293
+ }
1294
+ async create(payload = {}) {
1295
+ this.ensureCloud("API key creation");
1296
+ return this.httpClient.post(
1297
+ "/v1/api-keys/",
1298
+ payload,
1299
+ { "X-API-Key": this.httpClient.apiKey }
1300
+ );
1301
+ }
1302
+ async list() {
1303
+ this.ensureCloud("API key listing");
1304
+ return this.httpClient.get(
1305
+ "/v1/api-keys/",
1306
+ void 0,
1307
+ { "X-API-Key": this.httpClient.apiKey }
1308
+ );
1309
+ }
1310
+ async get(itemId) {
1311
+ this.ensureCloud("API key lookup");
1312
+ const safeItemId = encodePathSegment(itemId);
1313
+ return this.httpClient.get(
1314
+ `/v1/api-keys/${safeItemId}`,
1315
+ void 0,
1316
+ { "X-API-Key": this.httpClient.apiKey }
1317
+ );
1318
+ }
1319
+ async update(itemId, payload) {
1320
+ this.ensureCloud("API key update");
1321
+ const safeItemId = encodePathSegment(itemId);
1322
+ return this.httpClient.patch(
1323
+ `/v1/api-keys/${safeItemId}`,
1324
+ payload,
1325
+ { "X-API-Key": this.httpClient.apiKey }
1326
+ );
1327
+ }
1328
+ async delete(itemId) {
1329
+ this.ensureCloud("API key deletion");
1330
+ const safeItemId = encodePathSegment(itemId);
1331
+ return this.httpClient.delete(
1332
+ `/v1/api-keys/${safeItemId}`,
1333
+ { "X-API-Key": this.httpClient.apiKey }
1334
+ );
1335
+ }
1336
+ };
1337
+
1338
+ // src/client/AuditManager.ts
1339
+ var AuditManager = class {
1340
+ constructor(httpClient, local = false) {
1341
+ this.httpClient = httpClient;
1342
+ this.local = local;
1343
+ }
1344
+ ensureCloud(operation) {
1345
+ if (this.local) {
1346
+ throw new UnsupportedOperationError(
1347
+ `${operation} is not supported in local mode.`
1348
+ );
1349
+ }
1350
+ }
1351
+ async catalog() {
1352
+ this.ensureCloud("Audit catalog");
1353
+ return this.httpClient.get(
1354
+ "/v1/audit/catalog",
1355
+ void 0,
1356
+ { "X-API-Key": this.httpClient.apiKey }
1357
+ );
1358
+ }
1359
+ async events(query = {}) {
1360
+ this.ensureCloud("Audit event listing");
1361
+ return this.httpClient.get(
1362
+ "/v1/audit/events",
1363
+ query,
1364
+ { "X-API-Key": this.httpClient.apiKey }
1365
+ );
1366
+ }
1367
+ async getEvent(eventId) {
1368
+ this.ensureCloud("Audit event lookup");
1369
+ const safeEventId = encodePathSegment(eventId);
1370
+ return this.httpClient.get(
1371
+ `/v1/audit/events/${safeEventId}`,
1372
+ void 0,
1373
+ { "X-API-Key": this.httpClient.apiKey }
1374
+ );
1375
+ }
1376
+ };
1377
+
1378
+ // src/client/WebhooksManager.ts
1379
+ var WebhooksManager = class {
1380
+ constructor(httpClient, local = false) {
1381
+ this.httpClient = httpClient;
1382
+ this.local = local;
1383
+ }
1384
+ ensureCloud(operation) {
1385
+ if (this.local) {
1386
+ throw new UnsupportedOperationError(
1387
+ `${operation} is not supported in local mode.`
1388
+ );
1389
+ }
1390
+ }
1391
+ async createEndpoint(payload) {
1392
+ this.ensureCloud("Webhook endpoint creation");
1393
+ return this.httpClient.post(
1394
+ "/v1/webhooks/endpoints",
1395
+ payload,
1396
+ { "X-API-Key": this.httpClient.apiKey }
1397
+ );
1398
+ }
1399
+ async listEndpoints() {
1400
+ this.ensureCloud("Webhook endpoint listing");
1401
+ return this.httpClient.get(
1402
+ "/v1/webhooks/endpoints",
1403
+ void 0,
1404
+ { "X-API-Key": this.httpClient.apiKey }
1405
+ );
1406
+ }
1407
+ async getEndpoint(endpointId) {
1408
+ this.ensureCloud("Webhook endpoint lookup");
1409
+ const safeEndpointId = encodePathSegment(endpointId);
1410
+ return this.httpClient.get(
1411
+ `/v1/webhooks/endpoints/${safeEndpointId}`,
1412
+ void 0,
1413
+ { "X-API-Key": this.httpClient.apiKey }
1414
+ );
1415
+ }
1416
+ async updateEndpoint(endpointId, payload) {
1417
+ this.ensureCloud("Webhook endpoint update");
1418
+ const safeEndpointId = encodePathSegment(endpointId);
1419
+ return this.httpClient.patch(
1420
+ `/v1/webhooks/endpoints/${safeEndpointId}`,
1421
+ payload,
1422
+ { "X-API-Key": this.httpClient.apiKey }
1423
+ );
1424
+ }
1425
+ async deleteEndpoint(endpointId) {
1426
+ this.ensureCloud("Webhook endpoint deletion");
1427
+ const safeEndpointId = encodePathSegment(endpointId);
1428
+ return this.httpClient.delete(
1429
+ `/v1/webhooks/endpoints/${safeEndpointId}`,
1430
+ { "X-API-Key": this.httpClient.apiKey }
1431
+ );
1432
+ }
1433
+ async rotateSecret(endpointId) {
1434
+ this.ensureCloud("Webhook secret rotation");
1435
+ const safeEndpointId = encodePathSegment(endpointId);
1436
+ return this.httpClient.post(
1437
+ `/v1/webhooks/endpoints/${safeEndpointId}/rotate-secret`,
1438
+ {},
1439
+ { "X-API-Key": this.httpClient.apiKey }
1440
+ );
1441
+ }
1442
+ async sendTestEvent(endpointId) {
1443
+ this.ensureCloud("Webhook test event");
1444
+ const safeEndpointId = encodePathSegment(endpointId);
1445
+ return this.httpClient.post(
1446
+ `/v1/webhooks/endpoints/${safeEndpointId}/test`,
1447
+ {},
1448
+ { "X-API-Key": this.httpClient.apiKey }
1449
+ );
1450
+ }
1451
+ async verifyEndpoint(endpointId) {
1452
+ this.ensureCloud("Webhook endpoint verification");
1453
+ const safeEndpointId = encodePathSegment(endpointId);
1454
+ return this.httpClient.post(
1455
+ `/v1/webhooks/endpoints/${safeEndpointId}/verify`,
1456
+ {},
1457
+ { "X-API-Key": this.httpClient.apiKey }
1458
+ );
1459
+ }
1460
+ async listDeliveries(query = {}) {
1461
+ this.ensureCloud("Webhook delivery listing");
1462
+ return this.httpClient.get(
1463
+ "/v1/webhooks/deliveries",
1464
+ query,
1465
+ { "X-API-Key": this.httpClient.apiKey }
1466
+ );
1467
+ }
1468
+ async replayDelivery(deliveryId) {
1469
+ this.ensureCloud("Webhook delivery replay");
1470
+ const safeDeliveryId = encodePathSegment(deliveryId);
1471
+ return this.httpClient.post(
1472
+ `/v1/webhooks/deliveries/${safeDeliveryId}/replay`,
1473
+ {},
1474
+ { "X-API-Key": this.httpClient.apiKey }
1475
+ );
1476
+ }
1477
+ };
1478
+
928
1479
  // src/client/InstaVM.ts
929
1480
  var import_form_data = __toESM(require("form-data"));
930
1481
  var InstaVM = class {
931
1482
  constructor(apiKey, options = {}) {
932
1483
  this._sessionId = null;
1484
+ this._vmUsed = false;
933
1485
  this.local = options.local || false;
934
1486
  this.timeout = options.timeout || 3e5;
1487
+ this.memory_mb = options.memory_mb;
1488
+ this.cpu_count = options.cpu_count;
1489
+ this.metadata = options.metadata;
1490
+ this.env = options.env;
935
1491
  if (!this.local && !apiKey) {
936
1492
  throw new AuthenticationError("API key is required for cloud mode");
937
1493
  }
@@ -944,6 +1500,14 @@ var InstaVM = class {
944
1500
  };
945
1501
  this.httpClient = new HTTPClient(config);
946
1502
  this.browser = new BrowserManager(this.httpClient, this.local);
1503
+ this.vms = new VMsManager(this.httpClient, this.local);
1504
+ this.snapshots = new SnapshotsManager(this.httpClient, this.local);
1505
+ this.shares = new SharesManager(this.httpClient, this.local, () => this._sessionId);
1506
+ this.customDomains = new CustomDomainsManager(this.httpClient, this.local);
1507
+ this.computerUse = new ComputerUseManager(this.httpClient, this.local);
1508
+ this.apiKeys = new APIKeysManager(this.httpClient, this.local);
1509
+ this.audit = new AuditManager(this.httpClient, this.local);
1510
+ this.webhooks = new WebhooksManager(this.httpClient, this.local);
947
1511
  }
948
1512
  /**
949
1513
  * Ensure operation is not called in local mode
@@ -989,10 +1553,16 @@ var InstaVM = class {
989
1553
  if (response.session_id) {
990
1554
  this._sessionId = response.session_id;
991
1555
  }
1556
+ if (!this.local) {
1557
+ this._vmUsed = true;
1558
+ }
992
1559
  return {
993
- output: response.stdout || response.output || "",
1560
+ stdout: response.stdout || "",
1561
+ stderr: response.stderr || "",
994
1562
  success: response.success !== false,
995
- executionTime: response.execution_time || 0,
1563
+ executionTime: response.execution_time,
1564
+ cpuTime: response.cpu_time,
1565
+ createdAt: response.created_at,
996
1566
  sessionId: response.session_id,
997
1567
  error: response.error
998
1568
  };
@@ -1029,6 +1599,7 @@ var InstaVM = class {
1029
1599
  if (response.session_id) {
1030
1600
  this._sessionId = response.session_id;
1031
1601
  }
1602
+ this._vmUsed = true;
1032
1603
  return {
1033
1604
  taskId: response.task_id,
1034
1605
  status: response.status || "pending",
@@ -1048,11 +1619,58 @@ var InstaVM = class {
1048
1619
  );
1049
1620
  }
1050
1621
  }
1622
+ /**
1623
+ * Poll for async task result
1624
+ *
1625
+ * @param taskId - The task ID from executeAsync
1626
+ * @param pollInterval - Seconds between polls (default: 1)
1627
+ * @param timeout - Maximum seconds to wait (default: 60)
1628
+ * @returns Task result with stdout, stderr, execution time, etc.
1629
+ * @throws Error if task doesn't complete within timeout
1630
+ */
1631
+ async getTaskResult(taskId, pollInterval = 1, timeout = 60) {
1632
+ this.ensureNotLocal("Async task result retrieval");
1633
+ const startTime = Date.now();
1634
+ while (Date.now() - startTime < timeout * 1e3) {
1635
+ try {
1636
+ const response = await this.httpClient.get(
1637
+ `/v1/executions/${taskId}`,
1638
+ void 0,
1639
+ { "X-API-Key": this.httpClient.apiKey }
1640
+ );
1641
+ if (response.is_complete) {
1642
+ return {
1643
+ stdout: response.serialized_stdout || "",
1644
+ stderr: response.serialized_stderr || "",
1645
+ cpuTime: response.cpu_time,
1646
+ executionTime: response.execution_time,
1647
+ createdAt: response.created_at
1648
+ };
1649
+ }
1650
+ await new Promise((resolve) => setTimeout(resolve, pollInterval * 1e3));
1651
+ } catch (error) {
1652
+ if (error instanceof AuthenticationError || error instanceof RateLimitError || error instanceof NetworkError) {
1653
+ throw error;
1654
+ }
1655
+ if (Date.now() - startTime >= timeout * 1e3) {
1656
+ throw new ExecutionError(
1657
+ `Failed to get task result: ${error instanceof Error ? error.message : String(error)}`
1658
+ );
1659
+ }
1660
+ await new Promise((resolve) => setTimeout(resolve, pollInterval * 1e3));
1661
+ }
1662
+ }
1663
+ throw new ExecutionError(`Task ${taskId} timed out after ${timeout}s`);
1664
+ }
1051
1665
  /**
1052
1666
  * Upload files to the execution environment
1053
1667
  */
1054
1668
  async upload(files, options = {}) {
1055
1669
  this.ensureNotLocal("File upload");
1670
+ const sessionId = options.sessionId || this._sessionId;
1671
+ if (!sessionId) {
1672
+ throw new SessionError("Session ID not set. Please create a session first using createSession().");
1673
+ }
1056
1674
  const formData = new import_form_data.default();
1057
1675
  for (const file of files) {
1058
1676
  if (Buffer.isBuffer(file.content)) {
@@ -1064,9 +1682,7 @@ var InstaVM = class {
1064
1682
  formData.append("paths", file.path);
1065
1683
  }
1066
1684
  }
1067
- if (options.sessionId || this._sessionId) {
1068
- formData.append("session_id", options.sessionId || this._sessionId);
1069
- }
1685
+ formData.append("session_id", sessionId);
1070
1686
  if (options.remotePath) {
1071
1687
  formData.append("remote_path", options.remotePath);
1072
1688
  }
@@ -1097,10 +1713,26 @@ var InstaVM = class {
1097
1713
  async createSession() {
1098
1714
  this.ensureNotLocal("Session management");
1099
1715
  try {
1100
- const response = await this.httpClient.post("/v1/sessions/session", {
1716
+ const requestBody = {
1101
1717
  api_key: this.httpClient.apiKey,
1102
1718
  vm_lifetime_seconds: Math.floor(this.timeout / 1e3)
1103
- });
1719
+ };
1720
+ if (this.memory_mb !== void 0) {
1721
+ requestBody.memory_mb = this.memory_mb;
1722
+ }
1723
+ if (this.cpu_count !== void 0) {
1724
+ requestBody.vcpu_count = this.cpu_count;
1725
+ }
1726
+ if (this.metadata !== void 0) {
1727
+ requestBody.metadata = this.metadata;
1728
+ }
1729
+ if (this.env !== void 0) {
1730
+ requestBody.env = this.env;
1731
+ }
1732
+ const response = await this.httpClient.post(
1733
+ "/v1/sessions/session",
1734
+ requestBody
1735
+ );
1104
1736
  if (response.session_id) {
1105
1737
  this._sessionId = response.session_id;
1106
1738
  return response.session_id;
@@ -1127,6 +1759,30 @@ var InstaVM = class {
1127
1759
  this._sessionId = null;
1128
1760
  }
1129
1761
  }
1762
+ /**
1763
+ * Check if current session is still active by checking VM status
1764
+ *
1765
+ * @returns true if session is active, false otherwise
1766
+ */
1767
+ async isSessionActive(sessionId) {
1768
+ const targetSessionId = sessionId || this._sessionId;
1769
+ if (!targetSessionId) {
1770
+ return false;
1771
+ }
1772
+ try {
1773
+ const response = await this.httpClient.get(
1774
+ `/v1/sessions/status/${targetSessionId}`,
1775
+ void 0,
1776
+ { "X-API-Key": this.httpClient.apiKey }
1777
+ );
1778
+ return response.vm_status === "active";
1779
+ } catch (error) {
1780
+ if (error instanceof SessionError || error instanceof AuthenticationError || error instanceof NetworkError) {
1781
+ return false;
1782
+ }
1783
+ return false;
1784
+ }
1785
+ }
1130
1786
  /**
1131
1787
  * Get usage statistics for a session
1132
1788
  */
@@ -1190,11 +1846,185 @@ var InstaVM = class {
1190
1846
  get sessionId() {
1191
1847
  return this._sessionId;
1192
1848
  }
1849
+ /**
1850
+ * Kill the VM associated with a session
1851
+ *
1852
+ * @param sessionId - The session UUID whose VM should be killed. If not provided, uses current sessionId
1853
+ * @returns Result containing success message and killed VM ID
1854
+ */
1855
+ async kill(sessionId) {
1856
+ this.ensureNotLocal("VM kill operation");
1857
+ const targetSessionId = sessionId || this._sessionId;
1858
+ if (!targetSessionId) {
1859
+ throw new SessionError("Session ID not set. Please provide a sessionId or start a session first.");
1860
+ }
1861
+ try {
1862
+ const response = await this.httpClient.post(
1863
+ "/kill",
1864
+ { session_id: targetSessionId },
1865
+ { "X-API-Key": this.httpClient.apiKey }
1866
+ );
1867
+ if (!sessionId && this._sessionId === targetSessionId) {
1868
+ this._sessionId = null;
1869
+ }
1870
+ return response;
1871
+ } catch (error) {
1872
+ if (error instanceof Error && "statusCode" in error) {
1873
+ const statusCode = error.statusCode;
1874
+ if (statusCode === 403) {
1875
+ throw new AuthenticationError("You don't own this session", { cause: error });
1876
+ }
1877
+ if (statusCode === 404) {
1878
+ throw new SessionError("Session not found or no VM assigned to session (has execute() been called?)", { cause: error });
1879
+ }
1880
+ }
1881
+ const errorMessage = error instanceof Error ? error.message : String(error);
1882
+ throw new SessionError(
1883
+ `Failed to kill VM: ${errorMessage}`,
1884
+ { cause: error }
1885
+ );
1886
+ }
1887
+ }
1888
+ // --- Egress Policy Methods ---
1889
+ /**
1890
+ * Set egress policy for a session
1891
+ */
1892
+ async setSessionEgress(options = {}, sessionId) {
1893
+ this.ensureNotLocal("Egress policy management");
1894
+ const targetSessionId = sessionId || this._sessionId;
1895
+ if (!targetSessionId) {
1896
+ throw new SessionError("Session ID not set. Please create a session first.");
1897
+ }
1898
+ const response = await this.httpClient.post(
1899
+ `/v1/egress/session/${targetSessionId}`,
1900
+ {
1901
+ allow_public_repos: options.allowPackageManagers ?? true,
1902
+ allow_http: options.allowHttp ?? true,
1903
+ allow_https: options.allowHttps ?? true,
1904
+ allowed_domains: options.allowedDomains ?? [],
1905
+ allowed_cidrs: options.allowedCidrs ?? []
1906
+ },
1907
+ { "X-API-Key": this.httpClient.apiKey }
1908
+ );
1909
+ return response;
1910
+ }
1911
+ /**
1912
+ * Get egress policy for a session
1913
+ */
1914
+ async getSessionEgress(sessionId) {
1915
+ this.ensureNotLocal("Egress policy management");
1916
+ const targetSessionId = sessionId || this._sessionId;
1917
+ if (!targetSessionId) {
1918
+ throw new SessionError("Session ID not set. Please create a session first.");
1919
+ }
1920
+ const response = await this.httpClient.get(
1921
+ `/v1/egress/session/${targetSessionId}`,
1922
+ void 0,
1923
+ { "X-API-Key": this.httpClient.apiKey }
1924
+ );
1925
+ return {
1926
+ allowPackageManagers: response.allow_public_repos,
1927
+ allowHttp: response.allow_http,
1928
+ allowHttps: response.allow_https,
1929
+ allowedDomains: response.allowed_domains || [],
1930
+ allowedCidrs: response.allowed_cidrs || []
1931
+ };
1932
+ }
1933
+ /**
1934
+ * Set egress policy for a specific VM
1935
+ */
1936
+ async setVmEgress(vmId, options = {}) {
1937
+ this.ensureNotLocal("Egress policy management");
1938
+ const response = await this.httpClient.post(
1939
+ `/v1/egress/vm/${vmId}`,
1940
+ {
1941
+ allow_public_repos: options.allowPackageManagers ?? true,
1942
+ allow_http: options.allowHttp ?? true,
1943
+ allow_https: options.allowHttps ?? true,
1944
+ allowed_domains: options.allowedDomains ?? [],
1945
+ allowed_cidrs: options.allowedCidrs ?? []
1946
+ },
1947
+ { "X-API-Key": this.httpClient.apiKey }
1948
+ );
1949
+ return response;
1950
+ }
1951
+ /**
1952
+ * Get egress policy for a specific VM
1953
+ */
1954
+ async getVmEgress(vmId) {
1955
+ this.ensureNotLocal("Egress policy management");
1956
+ const response = await this.httpClient.get(
1957
+ `/v1/egress/vm/${vmId}`,
1958
+ void 0,
1959
+ { "X-API-Key": this.httpClient.apiKey }
1960
+ );
1961
+ return {
1962
+ allowPackageManagers: response.allow_public_repos,
1963
+ allowHttp: response.allow_http,
1964
+ allowHttps: response.allow_https,
1965
+ allowedDomains: response.allowed_domains || [],
1966
+ allowedCidrs: response.allowed_cidrs || []
1967
+ };
1968
+ }
1969
+ // --- SSH Key Methods ---
1970
+ /**
1971
+ * Add an SSH public key
1972
+ */
1973
+ async addSshKey(publicKey) {
1974
+ this.ensureNotLocal("SSH key management");
1975
+ const response = await this.httpClient.post(
1976
+ "/v1/ssh-keys",
1977
+ { public_key: publicKey },
1978
+ { "X-API-Key": this.httpClient.apiKey }
1979
+ );
1980
+ return {
1981
+ id: response.id,
1982
+ fingerprint: response.fingerprint,
1983
+ keyType: response.key_type,
1984
+ comment: response.comment ?? null,
1985
+ createdAt: response.created_at
1986
+ };
1987
+ }
1988
+ /**
1989
+ * List all active SSH keys
1990
+ */
1991
+ async listSshKeys() {
1992
+ this.ensureNotLocal("SSH key management");
1993
+ const response = await this.httpClient.get(
1994
+ "/v1/ssh-keys",
1995
+ void 0,
1996
+ { "X-API-Key": this.httpClient.apiKey }
1997
+ );
1998
+ const keys = response.keys || [];
1999
+ return keys.map((k) => ({
2000
+ id: k.id,
2001
+ fingerprint: k.fingerprint,
2002
+ keyType: k.key_type,
2003
+ comment: k.comment ?? null,
2004
+ createdAt: k.created_at
2005
+ }));
2006
+ }
2007
+ /**
2008
+ * Delete an SSH key by ID
2009
+ */
2010
+ async deleteSshKey(keyId) {
2011
+ this.ensureNotLocal("SSH key management");
2012
+ const response = await this.httpClient.delete(
2013
+ `/v1/ssh-keys/${keyId}`,
2014
+ { "X-API-Key": this.httpClient.apiKey }
2015
+ );
2016
+ return response;
2017
+ }
1193
2018
  /**
1194
2019
  * Clean up resources
1195
2020
  */
1196
2021
  async dispose() {
1197
- if (this._sessionId) {
2022
+ if (this._sessionId && !this.local && this._vmUsed) {
2023
+ try {
2024
+ await this.kill();
2025
+ } catch (e) {
2026
+ }
2027
+ } else if (this._sessionId) {
1198
2028
  await this.closeSession();
1199
2029
  }
1200
2030
  await this.browser.dispose();
@@ -1202,6 +2032,8 @@ var InstaVM = class {
1202
2032
  };
1203
2033
  // Annotate the CommonJS export names for ESM import in node:
1204
2034
  0 && (module.exports = {
2035
+ APIKeysManager,
2036
+ AuditManager,
1205
2037
  AuthenticationError,
1206
2038
  BrowserError,
1207
2039
  BrowserInteractionError,
@@ -1210,6 +2042,8 @@ var InstaVM = class {
1210
2042
  BrowserSession,
1211
2043
  BrowserSessionError,
1212
2044
  BrowserTimeoutError,
2045
+ ComputerUseManager,
2046
+ CustomDomainsManager,
1213
2047
  ElementNotFoundError,
1214
2048
  ExecutionError,
1215
2049
  InstaVM,
@@ -1218,6 +2052,10 @@ var InstaVM = class {
1218
2052
  QuotaExceededError,
1219
2053
  RateLimitError,
1220
2054
  SessionError,
1221
- UnsupportedOperationError
2055
+ SharesManager,
2056
+ SnapshotsManager,
2057
+ UnsupportedOperationError,
2058
+ VMsManager,
2059
+ WebhooksManager
1222
2060
  });
1223
2061
  //# sourceMappingURL=index.js.map