@arker-ai/sdk 0.5.2 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/e2b.d.cts ADDED
@@ -0,0 +1,29 @@
1
+ import { C as CreateOptions } from './common-C5zJ-LkS.cjs';
2
+ import 'computesdk';
3
+
4
+ interface CommandExitResult {
5
+ stdout: string;
6
+ stderr: string;
7
+ exitCode: number;
8
+ }
9
+ declare class Sandbox {
10
+ #private;
11
+ readonly sandboxId: string;
12
+ readonly commands: {
13
+ run: (command: string) => Promise<CommandExitResult>;
14
+ };
15
+ readonly files: {
16
+ read: (path: string) => Promise<string>;
17
+ write: (path: string, content: string) => Promise<void>;
18
+ makeDir: (path: string) => Promise<void>;
19
+ list: (path: string) => Promise<unknown[]>;
20
+ exists: (path: string) => Promise<boolean>;
21
+ remove: (path: string) => Promise<void>;
22
+ };
23
+ private constructor();
24
+ static create(templateId?: string, opts?: CreateOptions): Promise<Sandbox>;
25
+ static connect(sandboxId: string): Promise<Sandbox>;
26
+ kill(): Promise<void>;
27
+ }
28
+
29
+ export { type CommandExitResult, Sandbox };
package/dist/e2b.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { C as CreateOptions } from './common-C5zJ-LkS.js';
2
+ import 'computesdk';
3
+
4
+ interface CommandExitResult {
5
+ stdout: string;
6
+ stderr: string;
7
+ exitCode: number;
8
+ }
9
+ declare class Sandbox {
10
+ #private;
11
+ readonly sandboxId: string;
12
+ readonly commands: {
13
+ run: (command: string) => Promise<CommandExitResult>;
14
+ };
15
+ readonly files: {
16
+ read: (path: string) => Promise<string>;
17
+ write: (path: string, content: string) => Promise<void>;
18
+ makeDir: (path: string) => Promise<void>;
19
+ list: (path: string) => Promise<unknown[]>;
20
+ exists: (path: string) => Promise<boolean>;
21
+ remove: (path: string) => Promise<void>;
22
+ };
23
+ private constructor();
24
+ static create(templateId?: string, opts?: CreateOptions): Promise<Sandbox>;
25
+ static connect(sandboxId: string): Promise<Sandbox>;
26
+ kill(): Promise<void>;
27
+ }
28
+
29
+ export { type CommandExitResult, Sandbox };
package/dist/e2b.js ADDED
@@ -0,0 +1,75 @@
1
+ import {
2
+ assertSupportedObjectKeys,
3
+ createCompatSdk,
4
+ guardUnsupported,
5
+ resolveTimeout
6
+ } from "./chunk-35IEV6BU.js";
7
+ import "./chunk-7BHPVQNG.js";
8
+
9
+ // src/e2b.ts
10
+ import { e2b as createE2BProvider } from "@computesdk/e2b";
11
+ var E2B_CREATE_OPTION_KEYS = ["timeout", "timeoutMs"];
12
+ function sdk() {
13
+ return createCompatSdk({
14
+ fallbackProvider: createE2BProvider({})
15
+ });
16
+ }
17
+ var Sandbox = class _Sandbox {
18
+ sandboxId;
19
+ #box;
20
+ commands;
21
+ files;
22
+ constructor(box) {
23
+ this.#box = box;
24
+ this.sandboxId = box.sandboxId;
25
+ this.commands = {
26
+ run: async (command) => {
27
+ const result = await this.#box.runCommand(command);
28
+ return {
29
+ stdout: result.stdout,
30
+ stderr: result.stderr,
31
+ exitCode: result.exitCode
32
+ };
33
+ }
34
+ };
35
+ this.files = {
36
+ read: (path) => this.#box.filesystem.readFile(path),
37
+ write: async (path, content) => {
38
+ await this.#box.filesystem.writeFile(path, content);
39
+ },
40
+ makeDir: async (path) => {
41
+ await this.#box.filesystem.mkdir(path);
42
+ },
43
+ list: (path) => this.#box.filesystem.readdir(path),
44
+ exists: (path) => this.#box.filesystem.exists(path),
45
+ remove: async (path) => {
46
+ await this.#box.filesystem.remove(path);
47
+ }
48
+ };
49
+ }
50
+ static async create(templateId, opts) {
51
+ if (templateId !== void 0 && typeof templateId !== "string") {
52
+ throw new Error(
53
+ `Sandbox.create only supports create() or create(templateId, { timeoutMs }) in the Arker compatibility layer for e2b. Use the native e2b SDK for unsupported create signatures.`
54
+ );
55
+ }
56
+ assertSupportedObjectKeys(opts, E2B_CREATE_OPTION_KEYS, "e2b", "Sandbox.create");
57
+ const timeout = resolveTimeout(opts);
58
+ const box = await sdk().sandbox.create({
59
+ ...templateId ? { templateId } : {},
60
+ ...timeout !== void 0 ? { timeout } : {}
61
+ });
62
+ return guardUnsupported(new _Sandbox(box), "e2b");
63
+ }
64
+ static async connect(sandboxId) {
65
+ const box = await sdk().sandbox.getById(sandboxId);
66
+ if (!box) throw new Error(`Sandbox ${sandboxId} not found`);
67
+ return guardUnsupported(new _Sandbox(box), "e2b");
68
+ }
69
+ async kill() {
70
+ await this.#box.destroy();
71
+ }
72
+ };
73
+ export {
74
+ Sandbox
75
+ };
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -149,6 +159,12 @@ var Arker = class {
149
159
  );
150
160
  }
151
161
  const sourceOrgId = src.sourceOrgId ?? (src.sourceVmName !== void 0 && GOLDEN_NAMES.has(src.sourceVmName) ? ARKER_ORG_ID : void 0);
162
+ const legacy = src;
163
+ const resources = src.resources ?? (legacy.vcpu_count != null || legacy.memory_mib != null || legacy.disk_mib != null ? {
164
+ vcpu: legacy.vcpu_count ?? null,
165
+ memory_mib: legacy.memory_mib ?? null,
166
+ disk_mib: legacy.disk_mib ?? null
167
+ } : null);
152
168
  const body = {
153
169
  source_vm_id: src.sourceVmId ?? null,
154
170
  source_vm_name: src.sourceVmName ?? null,
@@ -156,13 +172,10 @@ var Arker = class {
156
172
  name: src.name ?? null,
157
173
  public: src.public ?? null,
158
174
  network: src.network ?? null,
175
+ egress: src.egress ?? null,
159
176
  disk: src.disk ?? true,
160
- vcpu_count: src.vcpu_count ?? null,
161
- memory_mib: src.memory_mib ?? null,
162
- max_memory_mib: src.max_memory_mib ?? null,
163
- disk_mib: src.disk_mib ?? null,
164
177
  durable: src.durable ?? null,
165
- tunnel: src.tunnel ?? null
178
+ resources
166
179
  };
167
180
  const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
168
181
  const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
@@ -309,6 +322,10 @@ var Arker = class {
309
322
  return retryDelay(this.retry, attempt);
310
323
  }
311
324
  /** @internal */
325
+ _authHeaders() {
326
+ return { authorization: `Bearer ${this.apiKey}` };
327
+ }
328
+ /** @internal */
312
329
  _baseUrlFor(ref) {
313
330
  if (isBurstRef(ref) && this.burstBaseUrl) return this.burstBaseUrl;
314
331
  return this.baseUrl;
@@ -343,7 +360,6 @@ var VM = class _VM {
343
360
  root_source_vm_name;
344
361
  worker_id;
345
362
  sessions;
346
- tunnels;
347
363
  constructor(client, vmId, baseUrl = client._baseUrlFor(vmId), data) {
348
364
  this._client = client;
349
365
  this.id = vmId;
@@ -466,8 +482,25 @@ var VM = class _VM {
466
482
  }
467
483
  throw new ArkerError(lastError?.code ?? "internal", lastError?.message ?? "write failed", 200);
468
484
  }
485
+ /**
486
+ * Update this VM's resource allocation and/or network settings via
487
+ * `PATCH /v1/vms/{id}`. Returns the updated `Vm`.
488
+ *
489
+ * Accepts either a `PatchVmRequest` (`{ resources, network }`) or, for
490
+ * convenience, flat resource fields (`{ vcpu, memory_mib, disk_mib }`)
491
+ * which are folded into `resources`.
492
+ */
469
493
  async resize(request) {
470
- return this._client._request("POST", `${vmPath(this.id)}/resize`, request, this.baseUrl);
494
+ const r = request;
495
+ const body = r.resources !== void 0 || r.vcpu === void 0 && r.memory_mib === void 0 && r.disk_mib === void 0 ? { resources: r.resources ?? null, network: r.network ?? null } : {
496
+ resources: {
497
+ vcpu: r.vcpu ?? null,
498
+ memory_mib: r.memory_mib ?? null,
499
+ disk_mib: r.disk_mib ?? null
500
+ },
501
+ network: r.network ?? null
502
+ };
503
+ return this._client._request("PATCH", vmPath(this.id), body, this.baseUrl);
471
504
  }
472
505
  async delete() {
473
506
  return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
@@ -523,22 +556,30 @@ var VM = class _VM {
523
556
  async deleteSession(sessionId) {
524
557
  return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
525
558
  }
526
- // ── Tunnels: VM-scoped, addressed by recoverable tunnel key ───────
527
- async listTunnels(opts = {}) {
528
- return this._client._request("GET", buildQuery(`${vmPath(this.id)}/tunnels`, {
529
- cursor: opts.cursor,
530
- limit: opts.limit,
531
- state: opts.state
532
- }), void 0, this.baseUrl);
533
- }
534
- async createTunnel(request = {}) {
535
- return this._client._request("POST", `${vmPath(this.id)}/tunnels`, request, this.baseUrl);
536
- }
537
- async getTunnel(key) {
538
- return this._client._request("GET", `${vmPath(this.id)}/tunnels/${pathSegment(key)}`, void 0, this.baseUrl);
539
- }
540
- async deleteTunnel(key) {
541
- return this._client._request("DELETE", `${vmPath(this.id)}/tunnels/${pathSegment(key)}`, void 0, this.baseUrl);
559
+ async connectPty(options = {}) {
560
+ const sessionId = options.sessionId ?? sessionIdFrom(await this.createSession());
561
+ const useTicket = options.useTicket ?? !isNodeRuntime();
562
+ const params = {
563
+ cols: options.cols,
564
+ rows: options.rows,
565
+ command: options.command,
566
+ persist: options.persist,
567
+ cancel_ttl_secs: options.cancelTtlSecs && options.cancelTtlSecs > 0 ? Math.floor(options.cancelTtlSecs) : void 0
568
+ };
569
+ let ticket;
570
+ if (useTicket) {
571
+ const response = await this._client._request(
572
+ "POST",
573
+ `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}/pty-ticket`,
574
+ {},
575
+ this.baseUrl
576
+ );
577
+ ticket = response.ticket;
578
+ }
579
+ const url = buildPtyWebSocketUrl(this.baseUrl, this.id, sessionId, { ...params, ticket });
580
+ const factory = options.webSocketFactory ?? (useTicket ? browserPtyWebSocketFactory : nodePtyWebSocketFactory);
581
+ const socket = await factory(url, useTicket ? {} : { headers: this._client._authHeaders() });
582
+ return new PtyConnectionImpl(sessionId, socket);
542
583
  }
543
584
  };
544
585
  function buildQuery(path, params) {
@@ -550,6 +591,176 @@ function buildQuery(path, params) {
550
591
  const qs = usp.toString();
551
592
  return qs ? `${path}?${qs}` : path;
552
593
  }
594
+ function buildPtyWebSocketUrl(baseUrl, vmId, sessionId, params) {
595
+ const url = new URL(`${normalizeBaseUrl(baseUrl)}${vmPath(vmId)}/sessions/${pathSegment(sessionId)}/pty`);
596
+ if (url.protocol === "https:") url.protocol = "wss:";
597
+ else if (url.protocol === "http:") url.protocol = "ws:";
598
+ else throw new Error(`unsupported PTY WebSocket protocol: ${url.protocol}`);
599
+ for (const [key, value] of Object.entries(params)) {
600
+ if (value === void 0 || value === null) continue;
601
+ url.searchParams.set(key, String(value));
602
+ }
603
+ return url.toString();
604
+ }
605
+ function sessionIdFrom(session) {
606
+ const id = session.session_id ?? session.id;
607
+ if (!id) throw new ArkerError("internal", "createSession response missing session_id", 200);
608
+ return id;
609
+ }
610
+ function isNodeRuntime() {
611
+ return typeof process !== "undefined" && Boolean(process.versions?.node);
612
+ }
613
+ async function nodePtyWebSocketFactory(url, init) {
614
+ const ws = await import("ws");
615
+ return new ws.default(url, { headers: init.headers });
616
+ }
617
+ function browserPtyWebSocketFactory(url) {
618
+ if (typeof globalThis.WebSocket !== "function") {
619
+ throw new Error("WebSocket is not available in this runtime");
620
+ }
621
+ return new globalThis.WebSocket(url);
622
+ }
623
+ var PtyConnectionImpl = class {
624
+ constructor(sessionId, socket) {
625
+ this.sessionId = sessionId;
626
+ this.socket = socket;
627
+ try {
628
+ socket.binaryType = "arraybuffer";
629
+ } catch {
630
+ }
631
+ this.ready = waitForSocketOpen(socket);
632
+ addSocketListener(socket, "message", (event) => {
633
+ const data = messageData(event);
634
+ if (data !== void 0) this.emitData(bytesFromMessageData(data));
635
+ });
636
+ addSocketListener(socket, "close", (event) => this.emitClose(closeEvent(event)));
637
+ addSocketListener(socket, "error", (event) => this.emitError(event));
638
+ }
639
+ sessionId;
640
+ socket;
641
+ ready;
642
+ dataListeners = /* @__PURE__ */ new Set();
643
+ closeListeners = /* @__PURE__ */ new Set();
644
+ errorListeners = /* @__PURE__ */ new Set();
645
+ onData(listener) {
646
+ this.dataListeners.add(listener);
647
+ return () => this.dataListeners.delete(listener);
648
+ }
649
+ onClose(listener) {
650
+ this.closeListeners.add(listener);
651
+ return () => this.closeListeners.delete(listener);
652
+ }
653
+ onError(listener) {
654
+ this.errorListeners.add(listener);
655
+ return () => this.errorListeners.delete(listener);
656
+ }
657
+ send(data) {
658
+ this.socket.send(ptyInputBytes(data));
659
+ }
660
+ resize(cols, rows) {
661
+ this.socket.send(JSON.stringify({ type: "resize", cols: clampPtyDimension(cols), rows: clampPtyDimension(rows) }));
662
+ }
663
+ kill() {
664
+ this.socket.send(JSON.stringify({ type: "kill" }));
665
+ }
666
+ close(code, reason) {
667
+ this.socket.close(code, reason);
668
+ }
669
+ emitData(data) {
670
+ for (const listener of this.dataListeners) listener(data);
671
+ }
672
+ emitClose(event) {
673
+ for (const listener of this.closeListeners) listener(event);
674
+ }
675
+ emitError(error) {
676
+ for (const listener of this.errorListeners) listener(error);
677
+ }
678
+ };
679
+ function waitForSocketOpen(socket) {
680
+ if (socket.readyState === 1) return Promise.resolve();
681
+ return new Promise((resolve, reject) => {
682
+ let removeOpen;
683
+ let removeError;
684
+ let removeClose;
685
+ const cleanup = () => {
686
+ removeOpen?.();
687
+ removeError?.();
688
+ removeClose?.();
689
+ };
690
+ removeOpen = addSocketListener(socket, "open", () => {
691
+ cleanup();
692
+ resolve();
693
+ });
694
+ removeError = addSocketListener(socket, "error", (event) => {
695
+ cleanup();
696
+ reject(event instanceof Error ? event : new Error("PTY WebSocket failed to open"));
697
+ });
698
+ removeClose = addSocketListener(socket, "close", (event) => {
699
+ cleanup();
700
+ const ev = closeEvent(event);
701
+ reject(new Error(`PTY WebSocket closed before opening${ev.code ? ` (${ev.code})` : ""}`));
702
+ });
703
+ });
704
+ }
705
+ function addSocketListener(socket, type, listener) {
706
+ if (socket.addEventListener) {
707
+ socket.addEventListener(type, listener);
708
+ return () => socket.removeEventListener?.(type, listener);
709
+ }
710
+ if (socket.on) {
711
+ const nodeListener = (...args) => {
712
+ if (type === "message") listener({ data: args[0] });
713
+ else if (type === "close") listener({ code: args[0], reason: args[1] });
714
+ else listener(args[0]);
715
+ };
716
+ socket.on(type, nodeListener);
717
+ return () => socket.off?.(type, nodeListener);
718
+ }
719
+ return () => {
720
+ };
721
+ }
722
+ function messageData(event) {
723
+ if (event && typeof event === "object" && "data" in event) {
724
+ return event.data;
725
+ }
726
+ return void 0;
727
+ }
728
+ function closeEvent(event) {
729
+ if (!event || typeof event !== "object") return {};
730
+ const raw = event;
731
+ return {
732
+ code: typeof raw.code === "number" ? raw.code : void 0,
733
+ reason: typeof raw.reason === "string" ? raw.reason : void 0
734
+ };
735
+ }
736
+ function bytesFromMessageData(data) {
737
+ if (typeof data === "string") return new TextEncoder().encode(data);
738
+ if (data instanceof Uint8Array) return data;
739
+ if (data instanceof ArrayBuffer) return new Uint8Array(data);
740
+ if (ArrayBuffer.isView(data)) {
741
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
742
+ }
743
+ if (Array.isArray(data)) {
744
+ const chunks = data.map(bytesFromMessageData);
745
+ const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
746
+ const out = new Uint8Array(total);
747
+ let offset = 0;
748
+ for (const chunk of chunks) {
749
+ out.set(chunk, offset);
750
+ offset += chunk.length;
751
+ }
752
+ return out;
753
+ }
754
+ return new Uint8Array();
755
+ }
756
+ function ptyInputBytes(data) {
757
+ if (typeof data === "string") return new TextEncoder().encode(data);
758
+ return data;
759
+ }
760
+ function clampPtyDimension(value) {
761
+ if (!Number.isFinite(value)) return 1;
762
+ return Math.max(1, Math.min(1e3, Math.trunc(value)));
763
+ }
553
764
  function normalizeBaseUrl(baseUrl) {
554
765
  const trimmed = baseUrl.trim().replace(/\/+$/, "");
555
766
  if (!trimmed) throw new Error("baseUrl must not be empty");
@@ -632,7 +843,10 @@ function parseRunResponse(payload) {
632
843
  stderr: decodeBytes(stderr, stderrEncoding),
633
844
  stderrEncoding,
634
845
  exitCode: numberField(body.exit_code, "run response.exit_code"),
635
- failReason: typeof body.fail_reason === "string" ? body.fail_reason : null
846
+ failReason: typeof body.fail_reason === "string" ? body.fail_reason : null,
847
+ memoryRequestedMib: optionalNumberOrNull(body.memory_requested_mib),
848
+ memoryAchievedMib: optionalNumberOrNull(body.memory_achieved_mib),
849
+ memoryPartial: typeof body.memory_partial === "boolean" ? body.memory_partial : void 0
636
850
  };
637
851
  }
638
852
  if (typeof body.run_id === "string") {
@@ -703,6 +917,10 @@ function numberField(value, context) {
703
917
  if (typeof value !== "number") throw new ArkerError("internal", `${context} must be a number`, 200);
704
918
  return value;
705
919
  }
920
+ function optionalNumberOrNull(value) {
921
+ if (value === null || typeof value === "number") return value;
922
+ return void 0;
923
+ }
706
924
  function assertWriteComplete(result, context) {
707
925
  if (result.complete && result.written) return;
708
926
  throw new ArkerError("internal", `${context} did not complete`, 200);