instavm 0.11.0 → 0.15.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/LICENSE +21 -0
- package/README.md +291 -133
- package/dist/cli.js +3446 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.mts +142 -3
- package/dist/index.d.ts +142 -3
- package/dist/index.js +302 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +301 -23
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/openai/index.js +0 -1
- package/dist/integrations/openai/index.js.map +1 -1
- package/dist/integrations/openai/index.mjs +0 -2
- package/dist/integrations/openai/index.mjs.map +1 -1
- package/package.json +17 -8
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
1
|
// src/client/HTTPClient.ts
|
|
4
2
|
import axios from "axios";
|
|
5
3
|
|
|
@@ -139,7 +137,7 @@ var HTTPClient = class {
|
|
|
139
137
|
timeout: config.timeout,
|
|
140
138
|
headers: {
|
|
141
139
|
"Content-Type": "application/json",
|
|
142
|
-
"User-Agent": "instavm-js-sdk/0.
|
|
140
|
+
"User-Agent": "instavm-js-sdk/0.15.0"
|
|
143
141
|
}
|
|
144
142
|
});
|
|
145
143
|
this.setupInterceptors();
|
|
@@ -912,10 +910,14 @@ var BrowserManager = class {
|
|
|
912
910
|
|
|
913
911
|
// src/utils/path.ts
|
|
914
912
|
function encodePathSegment(value) {
|
|
915
|
-
|
|
913
|
+
const segment = String(value);
|
|
914
|
+
if (segment === "." || segment === "..") {
|
|
915
|
+
throw new Error("Path traversal not allowed in path segment");
|
|
916
|
+
}
|
|
917
|
+
return encodeURIComponent(segment);
|
|
916
918
|
}
|
|
917
|
-
function encodePathSegments(
|
|
918
|
-
const segments =
|
|
919
|
+
function encodePathSegments(path2) {
|
|
920
|
+
const segments = path2.replace(/^\/+/, "").split("/").filter((segment) => segment.length > 0 && segment !== ".");
|
|
919
921
|
if (segments.some((segment) => segment === "..")) {
|
|
920
922
|
throw new Error("Path traversal not allowed in proxy path");
|
|
921
923
|
}
|
|
@@ -1015,6 +1017,37 @@ var VMsManager = class {
|
|
|
1015
1017
|
headers: { "X-API-Key": this.httpClient.apiKey }
|
|
1016
1018
|
});
|
|
1017
1019
|
}
|
|
1020
|
+
async mountVolume(vmId, payload, wait = true) {
|
|
1021
|
+
this.ensureCloud("VM volume mount");
|
|
1022
|
+
const safeVmId = encodePathSegment(vmId);
|
|
1023
|
+
return this.httpClient.request({
|
|
1024
|
+
method: "POST",
|
|
1025
|
+
url: `/v1/vms/${safeVmId}/volumes`,
|
|
1026
|
+
params: { wait },
|
|
1027
|
+
data: payload,
|
|
1028
|
+
headers: { "X-API-Key": this.httpClient.apiKey }
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
async listVolumes(vmId) {
|
|
1032
|
+
this.ensureCloud("VM volume listing");
|
|
1033
|
+
const safeVmId = encodePathSegment(vmId);
|
|
1034
|
+
return this.httpClient.get(
|
|
1035
|
+
`/v1/vms/${safeVmId}/volumes`,
|
|
1036
|
+
void 0,
|
|
1037
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
async unmountVolume(vmId, volumeId, mountPath, wait = true) {
|
|
1041
|
+
this.ensureCloud("VM volume unmount");
|
|
1042
|
+
const safeVmId = encodePathSegment(vmId);
|
|
1043
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1044
|
+
return this.httpClient.request({
|
|
1045
|
+
method: "DELETE",
|
|
1046
|
+
url: `/v1/vms/${safeVmId}/volumes/${safeVolumeId}`,
|
|
1047
|
+
params: { mount_path: mountPath, wait },
|
|
1048
|
+
headers: { "X-API-Key": this.httpClient.apiKey }
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1018
1051
|
};
|
|
1019
1052
|
|
|
1020
1053
|
// src/client/SnapshotsManager.ts
|
|
@@ -1187,10 +1220,10 @@ var ComputerUseManager = class {
|
|
|
1187
1220
|
{ "X-API-Key": this.httpClient.apiKey }
|
|
1188
1221
|
);
|
|
1189
1222
|
}
|
|
1190
|
-
async proxy(sessionId,
|
|
1223
|
+
async proxy(sessionId, path2, method = "GET", options = {}) {
|
|
1191
1224
|
this.ensureCloud("Computer-use proxy");
|
|
1192
1225
|
const safeSessionId = encodePathSegment(sessionId);
|
|
1193
|
-
const cleanPath = encodePathSegments(
|
|
1226
|
+
const cleanPath = encodePathSegments(path2);
|
|
1194
1227
|
return this.httpClient.request({
|
|
1195
1228
|
method,
|
|
1196
1229
|
url: `/v1/computeruse/${safeSessionId}/${cleanPath}`,
|
|
@@ -1199,23 +1232,39 @@ var ComputerUseManager = class {
|
|
|
1199
1232
|
headers: { "X-API-Key": this.httpClient.apiKey }
|
|
1200
1233
|
});
|
|
1201
1234
|
}
|
|
1202
|
-
async get(sessionId,
|
|
1203
|
-
return this.proxy(sessionId,
|
|
1235
|
+
async get(sessionId, path2, params) {
|
|
1236
|
+
return this.proxy(sessionId, path2, "GET", { params });
|
|
1204
1237
|
}
|
|
1205
|
-
async post(sessionId,
|
|
1206
|
-
return this.proxy(sessionId,
|
|
1238
|
+
async post(sessionId, path2, body) {
|
|
1239
|
+
return this.proxy(sessionId, path2, "POST", { body });
|
|
1207
1240
|
}
|
|
1208
|
-
async put(sessionId,
|
|
1209
|
-
return this.proxy(sessionId,
|
|
1241
|
+
async put(sessionId, path2, body) {
|
|
1242
|
+
return this.proxy(sessionId, path2, "PUT", { body });
|
|
1210
1243
|
}
|
|
1211
|
-
async patch(sessionId,
|
|
1212
|
-
return this.proxy(sessionId,
|
|
1244
|
+
async patch(sessionId, path2, body) {
|
|
1245
|
+
return this.proxy(sessionId, path2, "PATCH", { body });
|
|
1213
1246
|
}
|
|
1214
|
-
async delete(sessionId,
|
|
1215
|
-
return this.proxy(sessionId,
|
|
1247
|
+
async delete(sessionId, path2, params) {
|
|
1248
|
+
return this.proxy(sessionId, path2, "DELETE", { params });
|
|
1216
1249
|
}
|
|
1217
|
-
async options(sessionId,
|
|
1218
|
-
return this.proxy(sessionId,
|
|
1250
|
+
async options(sessionId, path2, params) {
|
|
1251
|
+
return this.proxy(sessionId, path2, "OPTIONS", { params });
|
|
1252
|
+
}
|
|
1253
|
+
async head(sessionId, path2, params) {
|
|
1254
|
+
return this.proxy(sessionId, path2, "HEAD", { params });
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Get the VNC WebSocket URL for a computer-use session.
|
|
1258
|
+
* Returns the URL to connect to; the actual connection requires a WebSocket client.
|
|
1259
|
+
*/
|
|
1260
|
+
async vncWebsockify(sessionId) {
|
|
1261
|
+
this.ensureCloud("Computer-use VNC websockify");
|
|
1262
|
+
const safeSessionId = encodePathSegment(sessionId);
|
|
1263
|
+
return this.httpClient.get(
|
|
1264
|
+
`/v1/computeruse/${safeSessionId}/vnc/websockify`,
|
|
1265
|
+
void 0,
|
|
1266
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1267
|
+
);
|
|
1219
1268
|
}
|
|
1220
1269
|
};
|
|
1221
1270
|
|
|
@@ -1417,8 +1466,164 @@ var WebhooksManager = class {
|
|
|
1417
1466
|
}
|
|
1418
1467
|
};
|
|
1419
1468
|
|
|
1420
|
-
// src/client/
|
|
1469
|
+
// src/client/VolumesManager.ts
|
|
1470
|
+
import fs from "fs";
|
|
1471
|
+
import path from "path";
|
|
1421
1472
|
import FormData from "form-data";
|
|
1473
|
+
var VolumesManager = class {
|
|
1474
|
+
constructor(httpClient, local = false) {
|
|
1475
|
+
this.httpClient = httpClient;
|
|
1476
|
+
this.local = local;
|
|
1477
|
+
}
|
|
1478
|
+
ensureCloud(operation) {
|
|
1479
|
+
if (this.local) {
|
|
1480
|
+
throw new UnsupportedOperationError(
|
|
1481
|
+
`${operation} is not supported in local mode.`
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
async create(payload) {
|
|
1486
|
+
this.ensureCloud("Volume creation");
|
|
1487
|
+
return this.httpClient.post(
|
|
1488
|
+
"/v1/volumes",
|
|
1489
|
+
payload,
|
|
1490
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
async list(refreshUsage = false) {
|
|
1494
|
+
this.ensureCloud("Volume listing");
|
|
1495
|
+
return this.httpClient.get(
|
|
1496
|
+
"/v1/volumes",
|
|
1497
|
+
{ refresh_usage: refreshUsage },
|
|
1498
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1499
|
+
);
|
|
1500
|
+
}
|
|
1501
|
+
async get(volumeId, refreshUsage = false) {
|
|
1502
|
+
this.ensureCloud("Volume lookup");
|
|
1503
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1504
|
+
return this.httpClient.get(
|
|
1505
|
+
`/v1/volumes/${safeVolumeId}`,
|
|
1506
|
+
{ refresh_usage: refreshUsage },
|
|
1507
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
async update(volumeId, payload) {
|
|
1511
|
+
this.ensureCloud("Volume update");
|
|
1512
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1513
|
+
return this.httpClient.patch(
|
|
1514
|
+
`/v1/volumes/${safeVolumeId}`,
|
|
1515
|
+
payload,
|
|
1516
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1517
|
+
);
|
|
1518
|
+
}
|
|
1519
|
+
async delete(volumeId) {
|
|
1520
|
+
this.ensureCloud("Volume deletion");
|
|
1521
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1522
|
+
return this.httpClient.delete(
|
|
1523
|
+
`/v1/volumes/${safeVolumeId}`,
|
|
1524
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
async createCheckpoint(volumeId, payload = {}) {
|
|
1528
|
+
this.ensureCloud("Volume checkpoint creation");
|
|
1529
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1530
|
+
return this.httpClient.post(
|
|
1531
|
+
`/v1/volumes/${safeVolumeId}/checkpoints`,
|
|
1532
|
+
payload,
|
|
1533
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
async listCheckpoints(volumeId) {
|
|
1537
|
+
this.ensureCloud("Volume checkpoint listing");
|
|
1538
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1539
|
+
return this.httpClient.get(
|
|
1540
|
+
`/v1/volumes/${safeVolumeId}/checkpoints`,
|
|
1541
|
+
void 0,
|
|
1542
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1543
|
+
);
|
|
1544
|
+
}
|
|
1545
|
+
async deleteCheckpoint(volumeId, checkpointId) {
|
|
1546
|
+
this.ensureCloud("Volume checkpoint deletion");
|
|
1547
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1548
|
+
const safeCheckpointId = encodePathSegment(checkpointId);
|
|
1549
|
+
return this.httpClient.delete(
|
|
1550
|
+
`/v1/volumes/${safeVolumeId}/checkpoints/${safeCheckpointId}`,
|
|
1551
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
async uploadFile(volumeId, payload) {
|
|
1555
|
+
this.ensureCloud("Volume file upload");
|
|
1556
|
+
if (!payload.path || payload.path.trim().length === 0) {
|
|
1557
|
+
throw new Error("payload.path is required");
|
|
1558
|
+
}
|
|
1559
|
+
const hasFilePath = typeof payload.filePath === "string" && payload.filePath.length > 0;
|
|
1560
|
+
const hasFileContent = payload.fileContent !== void 0;
|
|
1561
|
+
if (hasFilePath === hasFileContent) {
|
|
1562
|
+
throw new Error("Provide exactly one of payload.filePath or payload.fileContent");
|
|
1563
|
+
}
|
|
1564
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1565
|
+
const formData = new FormData();
|
|
1566
|
+
if (hasFilePath) {
|
|
1567
|
+
const sourcePath = payload.filePath;
|
|
1568
|
+
const filename = payload.filename || path.basename(sourcePath);
|
|
1569
|
+
formData.append("file", fs.createReadStream(sourcePath), { filename });
|
|
1570
|
+
} else {
|
|
1571
|
+
const filename = payload.filename || "upload.bin";
|
|
1572
|
+
const raw = payload.fileContent;
|
|
1573
|
+
const buffer = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
|
|
1574
|
+
formData.append("file", buffer, { filename });
|
|
1575
|
+
}
|
|
1576
|
+
formData.append("path", payload.path);
|
|
1577
|
+
if (payload.overwrite !== void 0) {
|
|
1578
|
+
formData.append("overwrite", String(payload.overwrite));
|
|
1579
|
+
}
|
|
1580
|
+
return this.httpClient.postFormData(
|
|
1581
|
+
`/v1/volumes/${safeVolumeId}/files/upload`,
|
|
1582
|
+
formData
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
async downloadFile(volumeId, path2) {
|
|
1586
|
+
this.ensureCloud("Volume file download");
|
|
1587
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1588
|
+
const response = await this.httpClient.post(
|
|
1589
|
+
`/v1/volumes/${safeVolumeId}/files/download`,
|
|
1590
|
+
{ path: path2 },
|
|
1591
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1592
|
+
);
|
|
1593
|
+
return {
|
|
1594
|
+
path: response.path,
|
|
1595
|
+
filename: response.filename,
|
|
1596
|
+
size: response.size,
|
|
1597
|
+
content: Buffer.from(response.content || "", "base64")
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
async listFiles(volumeId, options = {}) {
|
|
1601
|
+
this.ensureCloud("Volume file listing");
|
|
1602
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1603
|
+
return this.httpClient.get(
|
|
1604
|
+
`/v1/volumes/${safeVolumeId}/files`,
|
|
1605
|
+
{
|
|
1606
|
+
prefix: options.prefix ?? "",
|
|
1607
|
+
recursive: options.recursive ?? true,
|
|
1608
|
+
limit: options.limit ?? 1e3
|
|
1609
|
+
},
|
|
1610
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
async deleteFile(volumeId, targetPath) {
|
|
1614
|
+
this.ensureCloud("Volume file deletion");
|
|
1615
|
+
const safeVolumeId = encodePathSegment(volumeId);
|
|
1616
|
+
return this.httpClient.request({
|
|
1617
|
+
method: "DELETE",
|
|
1618
|
+
url: `/v1/volumes/${safeVolumeId}/files`,
|
|
1619
|
+
params: { path: targetPath },
|
|
1620
|
+
headers: { "X-API-Key": this.httpClient.apiKey }
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1625
|
+
// src/client/InstaVM.ts
|
|
1626
|
+
import FormData2 from "form-data";
|
|
1422
1627
|
var InstaVM = class {
|
|
1423
1628
|
constructor(apiKey, options = {}) {
|
|
1424
1629
|
this._sessionId = null;
|
|
@@ -1449,6 +1654,7 @@ var InstaVM = class {
|
|
|
1449
1654
|
this.apiKeys = new APIKeysManager(this.httpClient, this.local);
|
|
1450
1655
|
this.audit = new AuditManager(this.httpClient, this.local);
|
|
1451
1656
|
this.webhooks = new WebhooksManager(this.httpClient, this.local);
|
|
1657
|
+
this.volumes = new VolumesManager(this.httpClient, this.local);
|
|
1452
1658
|
}
|
|
1453
1659
|
/**
|
|
1454
1660
|
* Ensure operation is not called in local mode
|
|
@@ -1612,7 +1818,7 @@ var InstaVM = class {
|
|
|
1612
1818
|
if (!sessionId) {
|
|
1613
1819
|
throw new SessionError("Session ID not set. Please create a session first using createSession().");
|
|
1614
1820
|
}
|
|
1615
|
-
const formData = new
|
|
1821
|
+
const formData = new FormData2();
|
|
1616
1822
|
for (const file of files) {
|
|
1617
1823
|
if (Buffer.isBuffer(file.content)) {
|
|
1618
1824
|
formData.append("files", file.content, file.name);
|
|
@@ -1724,6 +1930,49 @@ var InstaVM = class {
|
|
|
1724
1930
|
return false;
|
|
1725
1931
|
}
|
|
1726
1932
|
}
|
|
1933
|
+
/**
|
|
1934
|
+
* Get the app URL for a session
|
|
1935
|
+
*
|
|
1936
|
+
* @param sessionId - Session ID (uses current session if not provided)
|
|
1937
|
+
* @param port - Port to expose (1-65535, default: 80)
|
|
1938
|
+
*/
|
|
1939
|
+
async getSessionAppUrl(sessionId, port) {
|
|
1940
|
+
this.ensureNotLocal("Session app URL");
|
|
1941
|
+
const targetSessionId = sessionId || this._sessionId;
|
|
1942
|
+
if (!targetSessionId) {
|
|
1943
|
+
throw new SessionError("Session ID not set. Please create a session first.");
|
|
1944
|
+
}
|
|
1945
|
+
const params = {};
|
|
1946
|
+
if (port !== void 0) {
|
|
1947
|
+
params.port = port;
|
|
1948
|
+
}
|
|
1949
|
+
return this.httpClient.get(
|
|
1950
|
+
`/v1/sessions/app-url/${targetSessionId}`,
|
|
1951
|
+
params,
|
|
1952
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1955
|
+
/**
|
|
1956
|
+
* List sandbox records with optional filtering
|
|
1957
|
+
*
|
|
1958
|
+
* @param options.metadata - JSON-serializable metadata filters
|
|
1959
|
+
* @param options.limit - Maximum number of results (1-1000, default: 100)
|
|
1960
|
+
*/
|
|
1961
|
+
async listSandboxes(options = {}) {
|
|
1962
|
+
this.ensureNotLocal("Sandbox listing");
|
|
1963
|
+
const params = {};
|
|
1964
|
+
if (options.metadata !== void 0) {
|
|
1965
|
+
params.metadata = JSON.stringify(options.metadata);
|
|
1966
|
+
}
|
|
1967
|
+
if (options.limit !== void 0) {
|
|
1968
|
+
params.limit = options.limit;
|
|
1969
|
+
}
|
|
1970
|
+
return this.httpClient.get(
|
|
1971
|
+
"/v1/sessions/sandboxes",
|
|
1972
|
+
params,
|
|
1973
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1974
|
+
);
|
|
1975
|
+
}
|
|
1727
1976
|
/**
|
|
1728
1977
|
* Get usage statistics for a session
|
|
1729
1978
|
*/
|
|
@@ -1735,7 +1984,9 @@ var InstaVM = class {
|
|
|
1735
1984
|
}
|
|
1736
1985
|
try {
|
|
1737
1986
|
const response = await this.httpClient.get(
|
|
1738
|
-
`/v1/sessions/usage/${targetSessionId}
|
|
1987
|
+
`/v1/sessions/usage/${targetSessionId}`,
|
|
1988
|
+
void 0,
|
|
1989
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
1739
1990
|
);
|
|
1740
1991
|
return {
|
|
1741
1992
|
sessionsUsed: response.sessions_used || 0,
|
|
@@ -1751,6 +2002,32 @@ var InstaVM = class {
|
|
|
1751
2002
|
);
|
|
1752
2003
|
}
|
|
1753
2004
|
}
|
|
2005
|
+
/**
|
|
2006
|
+
* Get the current user profile.
|
|
2007
|
+
*/
|
|
2008
|
+
async getCurrentUser() {
|
|
2009
|
+
this.ensureNotLocal("User profile lookup");
|
|
2010
|
+
return this.httpClient.get(
|
|
2011
|
+
"/v1/me",
|
|
2012
|
+
void 0,
|
|
2013
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
2014
|
+
);
|
|
2015
|
+
}
|
|
2016
|
+
/**
|
|
2017
|
+
* Get the current status of a session.
|
|
2018
|
+
*/
|
|
2019
|
+
async getSessionStatus(sessionId) {
|
|
2020
|
+
this.ensureNotLocal("Session management");
|
|
2021
|
+
const targetSessionId = sessionId || this._sessionId;
|
|
2022
|
+
if (!targetSessionId) {
|
|
2023
|
+
throw new SessionError("Session ID not set. Please create a session first.");
|
|
2024
|
+
}
|
|
2025
|
+
return this.httpClient.get(
|
|
2026
|
+
`/v1/sessions/status/${targetSessionId}`,
|
|
2027
|
+
void 0,
|
|
2028
|
+
{ "X-API-Key": this.httpClient.apiKey }
|
|
2029
|
+
);
|
|
2030
|
+
}
|
|
1754
2031
|
/**
|
|
1755
2032
|
* Download a file from the remote VM
|
|
1756
2033
|
*/
|
|
@@ -1996,6 +2273,7 @@ export {
|
|
|
1996
2273
|
SnapshotsManager,
|
|
1997
2274
|
UnsupportedOperationError,
|
|
1998
2275
|
VMsManager,
|
|
2276
|
+
VolumesManager,
|
|
1999
2277
|
WebhooksManager
|
|
2000
2278
|
};
|
|
2001
2279
|
//# sourceMappingURL=index.mjs.map
|