@arker-ai/sdk 0.6.2 → 0.7.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/{chunk-7BHPVQNG.js → chunk-4NHUAVXK.js} +132 -10
- package/dist/{chunk-35IEV6BU.js → chunk-YFJEL7PF.js} +1 -1
- package/dist/cli.cjs +150 -164
- package/dist/cli.js +18 -155
- package/dist/daytona.cjs +132 -10
- package/dist/daytona.js +2 -2
- package/dist/e2b.cjs +132 -10
- package/dist/e2b.js +2 -2
- package/dist/index.cjs +132 -10
- package/dist/index.d.cts +103 -2
- package/dist/index.d.ts +103 -2
- package/dist/index.js +1 -1
- package/dist/modal.cjs +132 -10
- package/dist/modal.js +2 -2
- package/package.json +2 -2
package/dist/modal.cjs
CHANGED
|
@@ -182,6 +182,7 @@ var Arker = class {
|
|
|
182
182
|
provider;
|
|
183
183
|
apiKey;
|
|
184
184
|
fetchImpl;
|
|
185
|
+
http2;
|
|
185
186
|
retry;
|
|
186
187
|
constructor(opts = {}) {
|
|
187
188
|
const apiKey = opts.apiKey ?? env("ARKER_API_KEY") ?? env("AUTH_KEY");
|
|
@@ -203,6 +204,7 @@ var Arker = class {
|
|
|
203
204
|
this.region = region ? normalizeRegion(region) : void 0;
|
|
204
205
|
this.provider = effectiveProvider;
|
|
205
206
|
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
207
|
+
this.http2 = opts.fetch === void 0;
|
|
206
208
|
this.retry = normalizeRetry(opts.retry);
|
|
207
209
|
if (!this.fetchImpl) throw new Error("fetch is required in this runtime");
|
|
208
210
|
}
|
|
@@ -263,7 +265,10 @@ var Arker = class {
|
|
|
263
265
|
egress: src.egress ?? null,
|
|
264
266
|
disk: src.disk ?? true,
|
|
265
267
|
durable: src.durable ?? null,
|
|
266
|
-
resources
|
|
268
|
+
resources,
|
|
269
|
+
// ARK-125: omit to inherit the source's policy; pass a doc to override
|
|
270
|
+
// (an empty `{ policies: [] }` clears to allow-all, NOT inherit).
|
|
271
|
+
policies: src.policies ?? null
|
|
267
272
|
};
|
|
268
273
|
const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
|
|
269
274
|
const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
|
|
@@ -358,30 +363,29 @@ var Arker = class {
|
|
|
358
363
|
if (value !== void 0) headers[key] = value;
|
|
359
364
|
}
|
|
360
365
|
}
|
|
361
|
-
|
|
366
|
+
let requestBody;
|
|
362
367
|
if (body !== void 0) {
|
|
363
368
|
headers["content-type"] = "application/json";
|
|
364
|
-
|
|
369
|
+
requestBody = JSON.stringify(withoutUndefined(body));
|
|
365
370
|
}
|
|
366
371
|
let lastStatus = 0;
|
|
367
372
|
let lastText = "";
|
|
368
373
|
let lastError;
|
|
369
374
|
for (let attempt = 0; attempt < this.retry.attempts; attempt++) {
|
|
370
375
|
try {
|
|
371
|
-
const
|
|
372
|
-
const text = await response.text();
|
|
376
|
+
const { status, ok, text } = await sendRequest(url, { method, headers, body: requestBody }, this.fetchImpl, this.http2);
|
|
373
377
|
const payload = parseJson(text);
|
|
374
378
|
const parsedError = extractError(payload);
|
|
375
|
-
lastStatus =
|
|
379
|
+
lastStatus = status;
|
|
376
380
|
lastText = text;
|
|
377
381
|
lastError = parsedError;
|
|
378
|
-
if (isRetryable(
|
|
382
|
+
if (isRetryable(status, parsedError) && attempt < this.retry.attempts - 1) {
|
|
379
383
|
await sleep(retryDelay(this.retry, attempt));
|
|
380
384
|
continue;
|
|
381
385
|
}
|
|
382
|
-
if (parsedError) throw new ArkerError(parsedError.code, parsedError.message,
|
|
383
|
-
if (!
|
|
384
|
-
throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${
|
|
386
|
+
if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, status);
|
|
387
|
+
if (!ok) {
|
|
388
|
+
throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${status}`, status);
|
|
385
389
|
}
|
|
386
390
|
return payload;
|
|
387
391
|
} catch (error) {
|
|
@@ -593,6 +597,32 @@ var VM = class _VM {
|
|
|
593
597
|
async delete() {
|
|
594
598
|
return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
|
|
595
599
|
}
|
|
600
|
+
// ── ARK-125 egress policy ────────────────────────────────────────
|
|
601
|
+
/**
|
|
602
|
+
* Read this VM's outbound egress policy document (ARK-125). Returns an
|
|
603
|
+
* empty doc (`{}`) when no policy is set.
|
|
604
|
+
*/
|
|
605
|
+
async getPolicies() {
|
|
606
|
+
return this._client._request("GET", `${vmPath(this.id)}/policies`, void 0, this.baseUrl);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Replace this VM's outbound egress policy with `doc` — an ordered,
|
|
610
|
+
* first-match-wins rule list. An empty doc (`{}` or `{ policies: [] }`)
|
|
611
|
+
* clears the policy to allow-all. Returns the stored policy plus the
|
|
612
|
+
* domains it escalates to MITM and any degrade warnings.
|
|
613
|
+
*
|
|
614
|
+
* await vm.setPolicies({
|
|
615
|
+
* policies: [
|
|
616
|
+
* { type: "network.outbound",
|
|
617
|
+
* match: { domains: ["github.com"], ports: [443] },
|
|
618
|
+
* action: "allow" },
|
|
619
|
+
* { type: "network.outbound", action: "deny" },
|
|
620
|
+
* ],
|
|
621
|
+
* });
|
|
622
|
+
*/
|
|
623
|
+
async setPolicies(doc) {
|
|
624
|
+
return this._client._request("PUT", `${vmPath(this.id)}/policies`, doc, this.baseUrl);
|
|
625
|
+
}
|
|
596
626
|
// ── Syncs: bindings of a filesystem into this VM at a path ────────
|
|
597
627
|
async listSyncs(opts = {}) {
|
|
598
628
|
return this._client._request("GET", buildQuery(`${vmPath(this.id)}/syncs`, {
|
|
@@ -644,6 +674,20 @@ var VM = class _VM {
|
|
|
644
674
|
async deleteSession(sessionId) {
|
|
645
675
|
return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
|
|
646
676
|
}
|
|
677
|
+
/**
|
|
678
|
+
* Update a session via `PATCH /v1/vms/{id}/sessions/{sid}`: resize its PTY
|
|
679
|
+
* (`cols`/`rows`) and/or set the idle `timeoutSecs`. Works whether or not a
|
|
680
|
+
* PTY is currently attached — the REST equivalent of {@link PtyConnection.resize}
|
|
681
|
+
* (which sends an in-band control frame on the live WebSocket).
|
|
682
|
+
*/
|
|
683
|
+
async updateSession(sessionId, update) {
|
|
684
|
+
return this._client._request(
|
|
685
|
+
"PATCH",
|
|
686
|
+
`${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`,
|
|
687
|
+
{ cols: update.cols, rows: update.rows, timeout_secs: update.timeoutSecs },
|
|
688
|
+
this.baseUrl
|
|
689
|
+
);
|
|
690
|
+
}
|
|
647
691
|
async connectPty(options = {}) {
|
|
648
692
|
const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
|
|
649
693
|
const useTicket = options.useTicket ?? !isNodeRuntime();
|
|
@@ -1055,6 +1099,84 @@ function base64ToBytes(text) {
|
|
|
1055
1099
|
function bufferConstructor() {
|
|
1056
1100
|
return globalThis.Buffer;
|
|
1057
1101
|
}
|
|
1102
|
+
var http2Module;
|
|
1103
|
+
function loadHttp2() {
|
|
1104
|
+
return http2Module ??= (async () => {
|
|
1105
|
+
const proc = globalThis.process;
|
|
1106
|
+
if (!proc?.versions?.node) return null;
|
|
1107
|
+
try {
|
|
1108
|
+
return await import(
|
|
1109
|
+
/* webpackIgnore: true */
|
|
1110
|
+
/* @vite-ignore */
|
|
1111
|
+
"http2"
|
|
1112
|
+
);
|
|
1113
|
+
} catch {
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1116
|
+
})();
|
|
1117
|
+
}
|
|
1118
|
+
var HTTP2_REQUEST_TIMEOUT_MS = 12e4;
|
|
1119
|
+
var Http2Connection = class {
|
|
1120
|
+
confirmed = false;
|
|
1121
|
+
streams = 0;
|
|
1122
|
+
session;
|
|
1123
|
+
constructor(http2, origin) {
|
|
1124
|
+
this.session = http2.connect(origin);
|
|
1125
|
+
this.session.on("error", () => {
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
get closed() {
|
|
1129
|
+
return this.session.closed || this.session.destroyed;
|
|
1130
|
+
}
|
|
1131
|
+
request(method, path, headers, body) {
|
|
1132
|
+
if (this.streams === 0) this.session.ref();
|
|
1133
|
+
this.streams++;
|
|
1134
|
+
return new Promise((resolve, reject) => {
|
|
1135
|
+
const stream = this.session.request({ ...headers, ":method": method, ":path": path });
|
|
1136
|
+
let status = 0;
|
|
1137
|
+
let text = "";
|
|
1138
|
+
stream.setEncoding("utf8");
|
|
1139
|
+
stream.setTimeout(HTTP2_REQUEST_TIMEOUT_MS, () => stream.destroy(new Error("HTTP/2 request timed out")));
|
|
1140
|
+
stream.on("response", (responseHeaders) => {
|
|
1141
|
+
this.confirmed = true;
|
|
1142
|
+
status = Number(responseHeaders[":status"]) || 0;
|
|
1143
|
+
});
|
|
1144
|
+
stream.on("data", (chunk) => {
|
|
1145
|
+
text += chunk;
|
|
1146
|
+
});
|
|
1147
|
+
stream.on("end", () => resolve({ status, ok: status >= 200 && status < 300, text }));
|
|
1148
|
+
stream.on("error", reject);
|
|
1149
|
+
stream.end(body);
|
|
1150
|
+
}).finally(() => {
|
|
1151
|
+
if (--this.streams === 0) this.session.unref();
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
var http2Connections = /* @__PURE__ */ new Map();
|
|
1156
|
+
async function sendRequest(url, init, fetchImpl, http2Enabled) {
|
|
1157
|
+
if (http2Enabled) {
|
|
1158
|
+
const http2 = await loadHttp2();
|
|
1159
|
+
if (http2) {
|
|
1160
|
+
const { origin, pathname, search } = new URL(url);
|
|
1161
|
+
const cached = http2Connections.get(origin);
|
|
1162
|
+
if (cached !== null) {
|
|
1163
|
+
let connection = cached;
|
|
1164
|
+
if (!connection || connection.closed) {
|
|
1165
|
+
connection = new Http2Connection(http2, origin);
|
|
1166
|
+
http2Connections.set(origin, connection);
|
|
1167
|
+
}
|
|
1168
|
+
try {
|
|
1169
|
+
return await connection.request(init.method, `${pathname}${search}`, init.headers, init.body);
|
|
1170
|
+
} catch (error) {
|
|
1171
|
+
if (connection.confirmed) throw error;
|
|
1172
|
+
http2Connections.set(origin, null);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
const response = await fetchImpl(url, init);
|
|
1178
|
+
return { status: response.status, ok: response.ok, text: await response.text() };
|
|
1179
|
+
}
|
|
1058
1180
|
|
|
1059
1181
|
// src/compat/arker-provider.ts
|
|
1060
1182
|
var DEFAULT_REGION = "aws-us-east-1";
|
package/dist/modal.js
CHANGED
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
createCompatSdk,
|
|
6
6
|
guardUnsupported,
|
|
7
7
|
isStringRecord
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-YFJEL7PF.js";
|
|
9
|
+
import "./chunk-4NHUAVXK.js";
|
|
10
10
|
|
|
11
11
|
// src/modal.ts
|
|
12
12
|
import { modal as createModalProvider } from "@computesdk/modal";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arker-ai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "TypeScript SDK for the Arker virtual computer platform \u2014 spawn sandboxed VMs, run code, sync files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"demo": "tsx tests/demo.ts",
|
|
46
46
|
"generate:api-types": "openapi-typescript ../contract/openapi.json --default-non-nullable false -o src/generated/api-types.ts",
|
|
47
47
|
"smoke": "tsx tests/conformance/fork-run-sync.ts",
|
|
48
|
-
"test": "tsx tests/unit.ts && tsx tests/compat.ts && tsx tests/cli.ts",
|
|
48
|
+
"test": "tsx tests/unit.ts && tsx tests/compat.ts && tsx tests/cli.ts && tsx tests/http2.ts",
|
|
49
49
|
"test:compat": "tsx tests/compat.ts",
|
|
50
50
|
"test:compat-live": "tsx tests/compat-live.ts",
|
|
51
51
|
"test:compat-fallback-live": "tsx tests/compat-fallback-live.ts",
|