@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/cli.js
CHANGED
|
@@ -3,14 +3,22 @@ import {
|
|
|
3
3
|
ARKER_ORG_ID,
|
|
4
4
|
Arker,
|
|
5
5
|
ArkerError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4NHUAVXK.js";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
import { readFileSync, existsSync } from "fs";
|
|
10
10
|
import { spawnSync } from "child_process";
|
|
11
|
+
import { createRequire } from "module";
|
|
11
12
|
import { homedir } from "os";
|
|
12
13
|
import { join } from "path";
|
|
13
14
|
import { stdin as input, stdout as output } from "process";
|
|
15
|
+
var VERSION = (() => {
|
|
16
|
+
try {
|
|
17
|
+
return createRequire(import.meta.url)("../package.json").version;
|
|
18
|
+
} catch {
|
|
19
|
+
return "unknown";
|
|
20
|
+
}
|
|
21
|
+
})();
|
|
14
22
|
function parseArgs(argv) {
|
|
15
23
|
const positional = [];
|
|
16
24
|
const flags = {};
|
|
@@ -49,6 +57,7 @@ function readFileConfig() {
|
|
|
49
57
|
}
|
|
50
58
|
return {};
|
|
51
59
|
}
|
|
60
|
+
var DEFAULT_REGION = "us-west-2";
|
|
52
61
|
function clientFromArgs(args) {
|
|
53
62
|
const file = readFileConfig();
|
|
54
63
|
const explicitBaseUrl = args.flags["base-url"] ?? process.env.ARKER_BASE_URL;
|
|
@@ -56,14 +65,11 @@ function clientFromArgs(args) {
|
|
|
56
65
|
const apiKey = args.flags["api-key"] ?? process.env.ARKER_API_KEY ?? file.apiKey;
|
|
57
66
|
const baseUrl = explicitBaseUrl ?? (explicitRegion ? void 0 : file.baseUrl);
|
|
58
67
|
const controlBaseUrl = args.flags["control-base-url"] ?? process.env.ARKER_CONTROL_BASE_URL;
|
|
59
|
-
const region = explicitRegion ?? file.region;
|
|
68
|
+
const region = explicitRegion ?? file.region ?? (baseUrl ? void 0 : DEFAULT_REGION);
|
|
60
69
|
const provider = args.flags.provider ?? process.env.ARKER_PROVIDER;
|
|
61
70
|
if (!apiKey) {
|
|
62
71
|
die("Missing API key. Set ARKER_API_KEY or pass --api-key.");
|
|
63
72
|
}
|
|
64
|
-
if (!baseUrl && !region) {
|
|
65
|
-
die("Missing region. Set ARKER_REGION or pass --region (e.g. us-west-2). --provider (aws|aws-burst) defaults to aws.");
|
|
66
|
-
}
|
|
67
73
|
return new Arker({ apiKey, baseUrl, region, provider, controlBaseUrl });
|
|
68
74
|
}
|
|
69
75
|
function out(value) {
|
|
@@ -551,134 +557,6 @@ function bridgePty(pty, options) {
|
|
|
551
557
|
});
|
|
552
558
|
});
|
|
553
559
|
}
|
|
554
|
-
var SSH_PORT_DEFAULT = 22;
|
|
555
|
-
function defaultIdentityBase() {
|
|
556
|
-
return join(homedir(), ".ssh", "id_ed25519");
|
|
557
|
-
}
|
|
558
|
-
function resolveLocalSshKey(args) {
|
|
559
|
-
const explicit = args.flags.identity;
|
|
560
|
-
const privateKeyPath = explicit ? explicit.replace(/\.pub$/, "") : defaultIdentityBase();
|
|
561
|
-
const publicKeyPath = `${privateKeyPath}.pub`;
|
|
562
|
-
if (!existsSync(publicKeyPath)) {
|
|
563
|
-
if (!boolFlag(args, "generate")) {
|
|
564
|
-
die(
|
|
565
|
-
`no SSH public key at ${publicKeyPath}. Pass --identity <path>, or --generate to create an ed25519 key pair.`
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
err(`generating ed25519 key pair at ${privateKeyPath}`);
|
|
569
|
-
const gen = spawnSync(
|
|
570
|
-
"ssh-keygen",
|
|
571
|
-
["-t", "ed25519", "-N", "", "-f", privateKeyPath, "-C", "arker-cli"],
|
|
572
|
-
{ stdio: "inherit" }
|
|
573
|
-
);
|
|
574
|
-
if (gen.status !== 0) die("ssh-keygen failed to generate a key pair");
|
|
575
|
-
}
|
|
576
|
-
const publicKey = readFileSync(publicKeyPath, "utf8").trim();
|
|
577
|
-
if (!publicKey) die(`SSH public key at ${publicKeyPath} is empty`);
|
|
578
|
-
return { publicKey, privateKeyPath, publicKeyPath };
|
|
579
|
-
}
|
|
580
|
-
async function registerAccountSshKey(client, publicKey, label) {
|
|
581
|
-
return client._request(
|
|
582
|
-
"POST",
|
|
583
|
-
"/v1/account/ssh-keys",
|
|
584
|
-
{ public_key: publicKey, label: label ?? null },
|
|
585
|
-
client.baseUrl
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
function resolveSshHost(args, client) {
|
|
589
|
-
const explicit = args.flags.host ?? process.env.ARKER_SSH_HOST;
|
|
590
|
-
if (explicit) return explicit;
|
|
591
|
-
if (client.region) return `aws-${client.region}.arker.ai`;
|
|
592
|
-
try {
|
|
593
|
-
return new URL(client.baseUrl).hostname;
|
|
594
|
-
} catch {
|
|
595
|
-
die("could not determine SSH host; pass --host <hostname>");
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
async function cmdSsh(args, client) {
|
|
599
|
-
const vmId = args.flags["vm-id"] ?? args.positional[0];
|
|
600
|
-
if (!vmId) {
|
|
601
|
-
die(
|
|
602
|
-
"usage: arker ssh <vm_id> [--identity <path>] [--generate] [--host <h>] [--port <n>] [--connect|-c] [--skip-register]"
|
|
603
|
-
);
|
|
604
|
-
}
|
|
605
|
-
const { publicKey, privateKeyPath } = resolveLocalSshKey(args);
|
|
606
|
-
if (!boolFlag(args, "skip-register")) {
|
|
607
|
-
const label = args.flags.label ?? `arker-cli ${homedir().split("/").pop() ?? ""}`.trim();
|
|
608
|
-
try {
|
|
609
|
-
const key = await registerAccountSshKey(client, publicKey, label);
|
|
610
|
-
err(`registered SSH key ${key.fingerprint}${key.label ? ` (${key.label})` : ""}`);
|
|
611
|
-
} catch (e) {
|
|
612
|
-
if (e instanceof ArkerError && e.status === 409) {
|
|
613
|
-
die(`this SSH key is already registered to a different account: ${e.message}`);
|
|
614
|
-
}
|
|
615
|
-
if (e instanceof ArkerError && e.status === 403) {
|
|
616
|
-
die(
|
|
617
|
-
"your API key lacks the developer role required to register SSH keys. Register the key in the console, then re-run with --skip-register."
|
|
618
|
-
);
|
|
619
|
-
}
|
|
620
|
-
throw e;
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
const host = resolveSshHost(args, client);
|
|
624
|
-
const port = numFlag(args, "port") ?? SSH_PORT_DEFAULT;
|
|
625
|
-
const sshArgs = [
|
|
626
|
-
"-i",
|
|
627
|
-
privateKeyPath,
|
|
628
|
-
...port !== 22 ? ["-p", String(port)] : [],
|
|
629
|
-
`${vmId}@${host}`
|
|
630
|
-
];
|
|
631
|
-
const command = `ssh ${sshArgs.join(" ")}`;
|
|
632
|
-
if (boolFlag(args, "connect") || boolFlag(args, "c")) {
|
|
633
|
-
err(`connecting: ${command}`);
|
|
634
|
-
const r = spawnSync("ssh", sshArgs, { stdio: "inherit" });
|
|
635
|
-
process.exit(r.status ?? 1);
|
|
636
|
-
}
|
|
637
|
-
out(command);
|
|
638
|
-
}
|
|
639
|
-
async function cmdSshKeys(args, client) {
|
|
640
|
-
const sub = args.positional[0];
|
|
641
|
-
const rest = args.positional.slice(1);
|
|
642
|
-
switch (sub) {
|
|
643
|
-
case void 0:
|
|
644
|
-
case "ls":
|
|
645
|
-
case "list": {
|
|
646
|
-
const res = await client._request(
|
|
647
|
-
"GET",
|
|
648
|
-
"/v1/account/ssh-keys",
|
|
649
|
-
void 0,
|
|
650
|
-
client.baseUrl
|
|
651
|
-
);
|
|
652
|
-
if (args.flags.json) return out(res);
|
|
653
|
-
for (const k of res.keys) {
|
|
654
|
-
out(`${k.id} ${k.fingerprint} ${k.label ?? "\u2014"}`);
|
|
655
|
-
}
|
|
656
|
-
return;
|
|
657
|
-
}
|
|
658
|
-
case "add": {
|
|
659
|
-
const { publicKey } = resolveLocalSshKey(args);
|
|
660
|
-
const label = args.flags.label;
|
|
661
|
-
const key = await registerAccountSshKey(client, publicKey, label);
|
|
662
|
-
if (args.flags.json) return out(key);
|
|
663
|
-
out(`${key.id} ${key.fingerprint} ${key.label ?? "\u2014"}`);
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
case "rm":
|
|
667
|
-
case "delete": {
|
|
668
|
-
const id = rest[0] ?? die("usage: arker ssh-keys rm <key_id>");
|
|
669
|
-
const r = await client._request(
|
|
670
|
-
"DELETE",
|
|
671
|
-
`/v1/account/ssh-keys/${encodeURIComponent(id)}`,
|
|
672
|
-
void 0,
|
|
673
|
-
client.baseUrl
|
|
674
|
-
);
|
|
675
|
-
out(r.deleted ? `deleted ${id}` : "delete failed");
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
default:
|
|
679
|
-
die("usage: arker ssh-keys <ls|add|rm> ...");
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
560
|
function numFlag(args, name) {
|
|
683
561
|
const v = args.flags[name];
|
|
684
562
|
if (typeof v === "string") return Number(v);
|
|
@@ -699,7 +577,7 @@ async function readAllStdin() {
|
|
|
699
577
|
function usage() {
|
|
700
578
|
out(
|
|
701
579
|
[
|
|
702
|
-
|
|
580
|
+
`arker v${VERSION}`,
|
|
703
581
|
"",
|
|
704
582
|
"Usage:",
|
|
705
583
|
" arker <command> [args]",
|
|
@@ -716,8 +594,6 @@ function usage() {
|
|
|
716
594
|
" arker run <vm> <command> [--session-id <id>] [--session-idx N] run a command",
|
|
717
595
|
" arker resize <vm> [--memory-mib N] [--vcpu N] [--disk-mib N] resize a VM (PATCH)",
|
|
718
596
|
" arker shell [vm_id] native PTY shell (forks ubuntu-full if no vm)",
|
|
719
|
-
" arker ssh <vm_id> register your SSH key + print the ssh command",
|
|
720
|
-
" arker ssh <vm_id> --connect register + drop straight into the ssh session",
|
|
721
597
|
"",
|
|
722
598
|
"Resources:",
|
|
723
599
|
" arker vms <ls|get|rm|fork|run> ...",
|
|
@@ -725,12 +601,11 @@ function usage() {
|
|
|
725
601
|
" arker sessions <ls|get|create|rm> <vm_id> ...",
|
|
726
602
|
" arker syncs <ls|create|rm> <vm_id> ...",
|
|
727
603
|
" arker filesystems <ls|create|get|rm> ... (alias: fs)",
|
|
728
|
-
" arker ssh-keys <ls|add|rm> ... manage account SSH keys",
|
|
729
604
|
"",
|
|
730
605
|
"Flags:",
|
|
731
606
|
" --api-key <key> (or env ARKER_API_KEY)",
|
|
732
607
|
" --region <region> (or env ARKER_REGION; e.g. us-west-2)",
|
|
733
|
-
" --provider <aws
|
|
608
|
+
" --provider <aws> (or env ARKER_PROVIDER; default aws)",
|
|
734
609
|
" --base-url <url> override compute URL (env ARKER_BASE_URL)",
|
|
735
610
|
" --control-base-url <url> override CF Worker URL (env ARKER_CONTROL_BASE_URL)",
|
|
736
611
|
" --json emit JSON instead of tabular output",
|
|
@@ -753,18 +628,7 @@ function usage() {
|
|
|
753
628
|
" --session-id <id> reconnect to an existing PTY session",
|
|
754
629
|
" --command <path> shell executable path (default: /bin/bash)",
|
|
755
630
|
" --cols <n> --rows <n> initial terminal size",
|
|
756
|
-
" --no-persist close the remote PTY process on disconnect"
|
|
757
|
-
"",
|
|
758
|
-
"SSH flags:",
|
|
759
|
-
" --identity <path> local key (private or .pub); default ~/.ssh/id_ed25519",
|
|
760
|
-
" --generate create an ed25519 key pair if none exists",
|
|
761
|
-
" --host <hostname> SSH host (or env ARKER_SSH_HOST; default aws-<region>.arker.ai)",
|
|
762
|
-
" --port <n> SSH port (default 22)",
|
|
763
|
-
" --connect, -c exec ssh instead of just printing the command",
|
|
764
|
-
" --skip-register don't register the key (assume already registered)",
|
|
765
|
-
" --label <text> label for the registered key",
|
|
766
|
-
"",
|
|
767
|
-
`Arker org id: ${ARKER_ORG_ID}`
|
|
631
|
+
" --no-persist close the remote PTY process on disconnect"
|
|
768
632
|
].join("\n")
|
|
769
633
|
);
|
|
770
634
|
process.exit(2);
|
|
@@ -794,11 +658,10 @@ async function main() {
|
|
|
794
658
|
return await cmdSyncs(args, client);
|
|
795
659
|
case "shell":
|
|
796
660
|
return await cmdShell(args, client);
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
return await cmdSshKeys(args, client);
|
|
661
|
+
// SSH is descoped/unsupported and hidden from the interface. The
|
|
662
|
+
// implementation below (cmdSsh / cmdSshKeys) is kept intact; re-add
|
|
663
|
+
// the `ssh` / `ssh-keys` cases here and their help entries to expose
|
|
664
|
+
// it once the server-side SSH path is supported.
|
|
802
665
|
// Resources.
|
|
803
666
|
case "vms":
|
|
804
667
|
return await cmdVms(args, client);
|
package/dist/daytona.cjs
CHANGED
|
@@ -162,6 +162,7 @@ var Arker = class {
|
|
|
162
162
|
provider;
|
|
163
163
|
apiKey;
|
|
164
164
|
fetchImpl;
|
|
165
|
+
http2;
|
|
165
166
|
retry;
|
|
166
167
|
constructor(opts = {}) {
|
|
167
168
|
const apiKey = opts.apiKey ?? env("ARKER_API_KEY") ?? env("AUTH_KEY");
|
|
@@ -183,6 +184,7 @@ var Arker = class {
|
|
|
183
184
|
this.region = region ? normalizeRegion(region) : void 0;
|
|
184
185
|
this.provider = effectiveProvider;
|
|
185
186
|
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
187
|
+
this.http2 = opts.fetch === void 0;
|
|
186
188
|
this.retry = normalizeRetry(opts.retry);
|
|
187
189
|
if (!this.fetchImpl) throw new Error("fetch is required in this runtime");
|
|
188
190
|
}
|
|
@@ -243,7 +245,10 @@ var Arker = class {
|
|
|
243
245
|
egress: src.egress ?? null,
|
|
244
246
|
disk: src.disk ?? true,
|
|
245
247
|
durable: src.durable ?? null,
|
|
246
|
-
resources
|
|
248
|
+
resources,
|
|
249
|
+
// ARK-125: omit to inherit the source's policy; pass a doc to override
|
|
250
|
+
// (an empty `{ policies: [] }` clears to allow-all, NOT inherit).
|
|
251
|
+
policies: src.policies ?? null
|
|
247
252
|
};
|
|
248
253
|
const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
|
|
249
254
|
const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
|
|
@@ -338,30 +343,29 @@ var Arker = class {
|
|
|
338
343
|
if (value !== void 0) headers[key] = value;
|
|
339
344
|
}
|
|
340
345
|
}
|
|
341
|
-
|
|
346
|
+
let requestBody;
|
|
342
347
|
if (body !== void 0) {
|
|
343
348
|
headers["content-type"] = "application/json";
|
|
344
|
-
|
|
349
|
+
requestBody = JSON.stringify(withoutUndefined(body));
|
|
345
350
|
}
|
|
346
351
|
let lastStatus = 0;
|
|
347
352
|
let lastText = "";
|
|
348
353
|
let lastError;
|
|
349
354
|
for (let attempt = 0; attempt < this.retry.attempts; attempt++) {
|
|
350
355
|
try {
|
|
351
|
-
const
|
|
352
|
-
const text = await response.text();
|
|
356
|
+
const { status, ok, text } = await sendRequest(url, { method, headers, body: requestBody }, this.fetchImpl, this.http2);
|
|
353
357
|
const payload = parseJson(text);
|
|
354
358
|
const parsedError = extractError(payload);
|
|
355
|
-
lastStatus =
|
|
359
|
+
lastStatus = status;
|
|
356
360
|
lastText = text;
|
|
357
361
|
lastError = parsedError;
|
|
358
|
-
if (isRetryable(
|
|
362
|
+
if (isRetryable(status, parsedError) && attempt < this.retry.attempts - 1) {
|
|
359
363
|
await sleep(retryDelay(this.retry, attempt));
|
|
360
364
|
continue;
|
|
361
365
|
}
|
|
362
|
-
if (parsedError) throw new ArkerError(parsedError.code, parsedError.message,
|
|
363
|
-
if (!
|
|
364
|
-
throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${
|
|
366
|
+
if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, status);
|
|
367
|
+
if (!ok) {
|
|
368
|
+
throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${status}`, status);
|
|
365
369
|
}
|
|
366
370
|
return payload;
|
|
367
371
|
} catch (error) {
|
|
@@ -573,6 +577,32 @@ var VM = class _VM {
|
|
|
573
577
|
async delete() {
|
|
574
578
|
return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
|
|
575
579
|
}
|
|
580
|
+
// ── ARK-125 egress policy ────────────────────────────────────────
|
|
581
|
+
/**
|
|
582
|
+
* Read this VM's outbound egress policy document (ARK-125). Returns an
|
|
583
|
+
* empty doc (`{}`) when no policy is set.
|
|
584
|
+
*/
|
|
585
|
+
async getPolicies() {
|
|
586
|
+
return this._client._request("GET", `${vmPath(this.id)}/policies`, void 0, this.baseUrl);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Replace this VM's outbound egress policy with `doc` — an ordered,
|
|
590
|
+
* first-match-wins rule list. An empty doc (`{}` or `{ policies: [] }`)
|
|
591
|
+
* clears the policy to allow-all. Returns the stored policy plus the
|
|
592
|
+
* domains it escalates to MITM and any degrade warnings.
|
|
593
|
+
*
|
|
594
|
+
* await vm.setPolicies({
|
|
595
|
+
* policies: [
|
|
596
|
+
* { type: "network.outbound",
|
|
597
|
+
* match: { domains: ["github.com"], ports: [443] },
|
|
598
|
+
* action: "allow" },
|
|
599
|
+
* { type: "network.outbound", action: "deny" },
|
|
600
|
+
* ],
|
|
601
|
+
* });
|
|
602
|
+
*/
|
|
603
|
+
async setPolicies(doc) {
|
|
604
|
+
return this._client._request("PUT", `${vmPath(this.id)}/policies`, doc, this.baseUrl);
|
|
605
|
+
}
|
|
576
606
|
// ── Syncs: bindings of a filesystem into this VM at a path ────────
|
|
577
607
|
async listSyncs(opts = {}) {
|
|
578
608
|
return this._client._request("GET", buildQuery(`${vmPath(this.id)}/syncs`, {
|
|
@@ -624,6 +654,20 @@ var VM = class _VM {
|
|
|
624
654
|
async deleteSession(sessionId) {
|
|
625
655
|
return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
|
|
626
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Update a session via `PATCH /v1/vms/{id}/sessions/{sid}`: resize its PTY
|
|
659
|
+
* (`cols`/`rows`) and/or set the idle `timeoutSecs`. Works whether or not a
|
|
660
|
+
* PTY is currently attached — the REST equivalent of {@link PtyConnection.resize}
|
|
661
|
+
* (which sends an in-band control frame on the live WebSocket).
|
|
662
|
+
*/
|
|
663
|
+
async updateSession(sessionId, update) {
|
|
664
|
+
return this._client._request(
|
|
665
|
+
"PATCH",
|
|
666
|
+
`${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`,
|
|
667
|
+
{ cols: update.cols, rows: update.rows, timeout_secs: update.timeoutSecs },
|
|
668
|
+
this.baseUrl
|
|
669
|
+
);
|
|
670
|
+
}
|
|
627
671
|
async connectPty(options = {}) {
|
|
628
672
|
const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
|
|
629
673
|
const useTicket = options.useTicket ?? !isNodeRuntime();
|
|
@@ -1035,6 +1079,84 @@ function base64ToBytes(text) {
|
|
|
1035
1079
|
function bufferConstructor() {
|
|
1036
1080
|
return globalThis.Buffer;
|
|
1037
1081
|
}
|
|
1082
|
+
var http2Module;
|
|
1083
|
+
function loadHttp2() {
|
|
1084
|
+
return http2Module ??= (async () => {
|
|
1085
|
+
const proc = globalThis.process;
|
|
1086
|
+
if (!proc?.versions?.node) return null;
|
|
1087
|
+
try {
|
|
1088
|
+
return await import(
|
|
1089
|
+
/* webpackIgnore: true */
|
|
1090
|
+
/* @vite-ignore */
|
|
1091
|
+
"http2"
|
|
1092
|
+
);
|
|
1093
|
+
} catch {
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
})();
|
|
1097
|
+
}
|
|
1098
|
+
var HTTP2_REQUEST_TIMEOUT_MS = 12e4;
|
|
1099
|
+
var Http2Connection = class {
|
|
1100
|
+
confirmed = false;
|
|
1101
|
+
streams = 0;
|
|
1102
|
+
session;
|
|
1103
|
+
constructor(http2, origin) {
|
|
1104
|
+
this.session = http2.connect(origin);
|
|
1105
|
+
this.session.on("error", () => {
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
get closed() {
|
|
1109
|
+
return this.session.closed || this.session.destroyed;
|
|
1110
|
+
}
|
|
1111
|
+
request(method, path, headers, body) {
|
|
1112
|
+
if (this.streams === 0) this.session.ref();
|
|
1113
|
+
this.streams++;
|
|
1114
|
+
return new Promise((resolve, reject) => {
|
|
1115
|
+
const stream = this.session.request({ ...headers, ":method": method, ":path": path });
|
|
1116
|
+
let status = 0;
|
|
1117
|
+
let text = "";
|
|
1118
|
+
stream.setEncoding("utf8");
|
|
1119
|
+
stream.setTimeout(HTTP2_REQUEST_TIMEOUT_MS, () => stream.destroy(new Error("HTTP/2 request timed out")));
|
|
1120
|
+
stream.on("response", (responseHeaders) => {
|
|
1121
|
+
this.confirmed = true;
|
|
1122
|
+
status = Number(responseHeaders[":status"]) || 0;
|
|
1123
|
+
});
|
|
1124
|
+
stream.on("data", (chunk) => {
|
|
1125
|
+
text += chunk;
|
|
1126
|
+
});
|
|
1127
|
+
stream.on("end", () => resolve({ status, ok: status >= 200 && status < 300, text }));
|
|
1128
|
+
stream.on("error", reject);
|
|
1129
|
+
stream.end(body);
|
|
1130
|
+
}).finally(() => {
|
|
1131
|
+
if (--this.streams === 0) this.session.unref();
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
var http2Connections = /* @__PURE__ */ new Map();
|
|
1136
|
+
async function sendRequest(url, init, fetchImpl, http2Enabled) {
|
|
1137
|
+
if (http2Enabled) {
|
|
1138
|
+
const http2 = await loadHttp2();
|
|
1139
|
+
if (http2) {
|
|
1140
|
+
const { origin, pathname, search } = new URL(url);
|
|
1141
|
+
const cached = http2Connections.get(origin);
|
|
1142
|
+
if (cached !== null) {
|
|
1143
|
+
let connection = cached;
|
|
1144
|
+
if (!connection || connection.closed) {
|
|
1145
|
+
connection = new Http2Connection(http2, origin);
|
|
1146
|
+
http2Connections.set(origin, connection);
|
|
1147
|
+
}
|
|
1148
|
+
try {
|
|
1149
|
+
return await connection.request(init.method, `${pathname}${search}`, init.headers, init.body);
|
|
1150
|
+
} catch (error) {
|
|
1151
|
+
if (connection.confirmed) throw error;
|
|
1152
|
+
http2Connections.set(origin, null);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
const response = await fetchImpl(url, init);
|
|
1158
|
+
return { status: response.status, ok: response.ok, text: await response.text() };
|
|
1159
|
+
}
|
|
1038
1160
|
|
|
1039
1161
|
// src/compat/arker-provider.ts
|
|
1040
1162
|
var DEFAULT_REGION = "aws-us-east-1";
|
package/dist/daytona.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
assertSupportedObjectKeys,
|
|
3
3
|
createCompatSdk,
|
|
4
4
|
guardUnsupported
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-YFJEL7PF.js";
|
|
6
|
+
import "./chunk-4NHUAVXK.js";
|
|
7
7
|
|
|
8
8
|
// src/daytona.ts
|
|
9
9
|
import { daytona as createDaytonaProvider } from "@computesdk/daytona";
|
package/dist/e2b.cjs
CHANGED
|
@@ -167,6 +167,7 @@ var Arker = class {
|
|
|
167
167
|
provider;
|
|
168
168
|
apiKey;
|
|
169
169
|
fetchImpl;
|
|
170
|
+
http2;
|
|
170
171
|
retry;
|
|
171
172
|
constructor(opts = {}) {
|
|
172
173
|
const apiKey = opts.apiKey ?? env("ARKER_API_KEY") ?? env("AUTH_KEY");
|
|
@@ -188,6 +189,7 @@ var Arker = class {
|
|
|
188
189
|
this.region = region ? normalizeRegion(region) : void 0;
|
|
189
190
|
this.provider = effectiveProvider;
|
|
190
191
|
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
192
|
+
this.http2 = opts.fetch === void 0;
|
|
191
193
|
this.retry = normalizeRetry(opts.retry);
|
|
192
194
|
if (!this.fetchImpl) throw new Error("fetch is required in this runtime");
|
|
193
195
|
}
|
|
@@ -248,7 +250,10 @@ var Arker = class {
|
|
|
248
250
|
egress: src.egress ?? null,
|
|
249
251
|
disk: src.disk ?? true,
|
|
250
252
|
durable: src.durable ?? null,
|
|
251
|
-
resources
|
|
253
|
+
resources,
|
|
254
|
+
// ARK-125: omit to inherit the source's policy; pass a doc to override
|
|
255
|
+
// (an empty `{ policies: [] }` clears to allow-all, NOT inherit).
|
|
256
|
+
policies: src.policies ?? null
|
|
252
257
|
};
|
|
253
258
|
const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
|
|
254
259
|
const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
|
|
@@ -343,30 +348,29 @@ var Arker = class {
|
|
|
343
348
|
if (value !== void 0) headers[key] = value;
|
|
344
349
|
}
|
|
345
350
|
}
|
|
346
|
-
|
|
351
|
+
let requestBody;
|
|
347
352
|
if (body !== void 0) {
|
|
348
353
|
headers["content-type"] = "application/json";
|
|
349
|
-
|
|
354
|
+
requestBody = JSON.stringify(withoutUndefined(body));
|
|
350
355
|
}
|
|
351
356
|
let lastStatus = 0;
|
|
352
357
|
let lastText = "";
|
|
353
358
|
let lastError;
|
|
354
359
|
for (let attempt = 0; attempt < this.retry.attempts; attempt++) {
|
|
355
360
|
try {
|
|
356
|
-
const
|
|
357
|
-
const text = await response.text();
|
|
361
|
+
const { status, ok, text } = await sendRequest(url, { method, headers, body: requestBody }, this.fetchImpl, this.http2);
|
|
358
362
|
const payload = parseJson(text);
|
|
359
363
|
const parsedError = extractError(payload);
|
|
360
|
-
lastStatus =
|
|
364
|
+
lastStatus = status;
|
|
361
365
|
lastText = text;
|
|
362
366
|
lastError = parsedError;
|
|
363
|
-
if (isRetryable(
|
|
367
|
+
if (isRetryable(status, parsedError) && attempt < this.retry.attempts - 1) {
|
|
364
368
|
await sleep(retryDelay(this.retry, attempt));
|
|
365
369
|
continue;
|
|
366
370
|
}
|
|
367
|
-
if (parsedError) throw new ArkerError(parsedError.code, parsedError.message,
|
|
368
|
-
if (!
|
|
369
|
-
throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${
|
|
371
|
+
if (parsedError) throw new ArkerError(parsedError.code, parsedError.message, status);
|
|
372
|
+
if (!ok) {
|
|
373
|
+
throw new ArkerError("internal", lastText.slice(0, 300) || `HTTP ${status}`, status);
|
|
370
374
|
}
|
|
371
375
|
return payload;
|
|
372
376
|
} catch (error) {
|
|
@@ -578,6 +582,32 @@ var VM = class _VM {
|
|
|
578
582
|
async delete() {
|
|
579
583
|
return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
|
|
580
584
|
}
|
|
585
|
+
// ── ARK-125 egress policy ────────────────────────────────────────
|
|
586
|
+
/**
|
|
587
|
+
* Read this VM's outbound egress policy document (ARK-125). Returns an
|
|
588
|
+
* empty doc (`{}`) when no policy is set.
|
|
589
|
+
*/
|
|
590
|
+
async getPolicies() {
|
|
591
|
+
return this._client._request("GET", `${vmPath(this.id)}/policies`, void 0, this.baseUrl);
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Replace this VM's outbound egress policy with `doc` — an ordered,
|
|
595
|
+
* first-match-wins rule list. An empty doc (`{}` or `{ policies: [] }`)
|
|
596
|
+
* clears the policy to allow-all. Returns the stored policy plus the
|
|
597
|
+
* domains it escalates to MITM and any degrade warnings.
|
|
598
|
+
*
|
|
599
|
+
* await vm.setPolicies({
|
|
600
|
+
* policies: [
|
|
601
|
+
* { type: "network.outbound",
|
|
602
|
+
* match: { domains: ["github.com"], ports: [443] },
|
|
603
|
+
* action: "allow" },
|
|
604
|
+
* { type: "network.outbound", action: "deny" },
|
|
605
|
+
* ],
|
|
606
|
+
* });
|
|
607
|
+
*/
|
|
608
|
+
async setPolicies(doc) {
|
|
609
|
+
return this._client._request("PUT", `${vmPath(this.id)}/policies`, doc, this.baseUrl);
|
|
610
|
+
}
|
|
581
611
|
// ── Syncs: bindings of a filesystem into this VM at a path ────────
|
|
582
612
|
async listSyncs(opts = {}) {
|
|
583
613
|
return this._client._request("GET", buildQuery(`${vmPath(this.id)}/syncs`, {
|
|
@@ -629,6 +659,20 @@ var VM = class _VM {
|
|
|
629
659
|
async deleteSession(sessionId) {
|
|
630
660
|
return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
|
|
631
661
|
}
|
|
662
|
+
/**
|
|
663
|
+
* Update a session via `PATCH /v1/vms/{id}/sessions/{sid}`: resize its PTY
|
|
664
|
+
* (`cols`/`rows`) and/or set the idle `timeoutSecs`. Works whether or not a
|
|
665
|
+
* PTY is currently attached — the REST equivalent of {@link PtyConnection.resize}
|
|
666
|
+
* (which sends an in-band control frame on the live WebSocket).
|
|
667
|
+
*/
|
|
668
|
+
async updateSession(sessionId, update) {
|
|
669
|
+
return this._client._request(
|
|
670
|
+
"PATCH",
|
|
671
|
+
`${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`,
|
|
672
|
+
{ cols: update.cols, rows: update.rows, timeout_secs: update.timeoutSecs },
|
|
673
|
+
this.baseUrl
|
|
674
|
+
);
|
|
675
|
+
}
|
|
632
676
|
async connectPty(options = {}) {
|
|
633
677
|
const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
|
|
634
678
|
const useTicket = options.useTicket ?? !isNodeRuntime();
|
|
@@ -1040,6 +1084,84 @@ function base64ToBytes(text) {
|
|
|
1040
1084
|
function bufferConstructor() {
|
|
1041
1085
|
return globalThis.Buffer;
|
|
1042
1086
|
}
|
|
1087
|
+
var http2Module;
|
|
1088
|
+
function loadHttp2() {
|
|
1089
|
+
return http2Module ??= (async () => {
|
|
1090
|
+
const proc = globalThis.process;
|
|
1091
|
+
if (!proc?.versions?.node) return null;
|
|
1092
|
+
try {
|
|
1093
|
+
return await import(
|
|
1094
|
+
/* webpackIgnore: true */
|
|
1095
|
+
/* @vite-ignore */
|
|
1096
|
+
"http2"
|
|
1097
|
+
);
|
|
1098
|
+
} catch {
|
|
1099
|
+
return null;
|
|
1100
|
+
}
|
|
1101
|
+
})();
|
|
1102
|
+
}
|
|
1103
|
+
var HTTP2_REQUEST_TIMEOUT_MS = 12e4;
|
|
1104
|
+
var Http2Connection = class {
|
|
1105
|
+
confirmed = false;
|
|
1106
|
+
streams = 0;
|
|
1107
|
+
session;
|
|
1108
|
+
constructor(http2, origin) {
|
|
1109
|
+
this.session = http2.connect(origin);
|
|
1110
|
+
this.session.on("error", () => {
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
get closed() {
|
|
1114
|
+
return this.session.closed || this.session.destroyed;
|
|
1115
|
+
}
|
|
1116
|
+
request(method, path, headers, body) {
|
|
1117
|
+
if (this.streams === 0) this.session.ref();
|
|
1118
|
+
this.streams++;
|
|
1119
|
+
return new Promise((resolve, reject) => {
|
|
1120
|
+
const stream = this.session.request({ ...headers, ":method": method, ":path": path });
|
|
1121
|
+
let status = 0;
|
|
1122
|
+
let text = "";
|
|
1123
|
+
stream.setEncoding("utf8");
|
|
1124
|
+
stream.setTimeout(HTTP2_REQUEST_TIMEOUT_MS, () => stream.destroy(new Error("HTTP/2 request timed out")));
|
|
1125
|
+
stream.on("response", (responseHeaders) => {
|
|
1126
|
+
this.confirmed = true;
|
|
1127
|
+
status = Number(responseHeaders[":status"]) || 0;
|
|
1128
|
+
});
|
|
1129
|
+
stream.on("data", (chunk) => {
|
|
1130
|
+
text += chunk;
|
|
1131
|
+
});
|
|
1132
|
+
stream.on("end", () => resolve({ status, ok: status >= 200 && status < 300, text }));
|
|
1133
|
+
stream.on("error", reject);
|
|
1134
|
+
stream.end(body);
|
|
1135
|
+
}).finally(() => {
|
|
1136
|
+
if (--this.streams === 0) this.session.unref();
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
var http2Connections = /* @__PURE__ */ new Map();
|
|
1141
|
+
async function sendRequest(url, init, fetchImpl, http2Enabled) {
|
|
1142
|
+
if (http2Enabled) {
|
|
1143
|
+
const http2 = await loadHttp2();
|
|
1144
|
+
if (http2) {
|
|
1145
|
+
const { origin, pathname, search } = new URL(url);
|
|
1146
|
+
const cached = http2Connections.get(origin);
|
|
1147
|
+
if (cached !== null) {
|
|
1148
|
+
let connection = cached;
|
|
1149
|
+
if (!connection || connection.closed) {
|
|
1150
|
+
connection = new Http2Connection(http2, origin);
|
|
1151
|
+
http2Connections.set(origin, connection);
|
|
1152
|
+
}
|
|
1153
|
+
try {
|
|
1154
|
+
return await connection.request(init.method, `${pathname}${search}`, init.headers, init.body);
|
|
1155
|
+
} catch (error) {
|
|
1156
|
+
if (connection.confirmed) throw error;
|
|
1157
|
+
http2Connections.set(origin, null);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
const response = await fetchImpl(url, init);
|
|
1163
|
+
return { status: response.status, ok: response.ok, text: await response.text() };
|
|
1164
|
+
}
|
|
1043
1165
|
|
|
1044
1166
|
// src/compat/arker-provider.ts
|
|
1045
1167
|
var DEFAULT_REGION = "aws-us-east-1";
|
package/dist/e2b.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
createCompatSdk,
|
|
4
4
|
guardUnsupported,
|
|
5
5
|
resolveTimeout
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-YFJEL7PF.js";
|
|
7
|
+
import "./chunk-4NHUAVXK.js";
|
|
8
8
|
|
|
9
9
|
// src/e2b.ts
|
|
10
10
|
import { e2b as createE2BProvider } from "@computesdk/e2b";
|