@arker-ai/sdk 0.5.1 → 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/README.md +154 -0
- package/dist/arker-provider-BNIL8NdM.d.ts +7 -0
- package/dist/arker-provider-DwUib5ZW.d.cts +7 -0
- package/dist/chunk-35IEV6BU.js +286 -0
- package/dist/{chunk-PI3H3TGC.js → chunk-7BHPVQNG.js} +265 -23
- package/dist/cli.cjs +621 -160
- package/dist/cli.js +356 -137
- package/dist/common-C5zJ-LkS.d.cts +9 -0
- package/dist/common-C5zJ-LkS.d.ts +9 -0
- package/dist/daytona.cjs +1274 -0
- package/dist/daytona.d.cts +37 -0
- package/dist/daytona.d.ts +37 -0
- package/dist/daytona.js +65 -0
- package/dist/e2b.cjs +1288 -0
- package/dist/e2b.d.cts +29 -0
- package/dist/e2b.d.ts +29 -0
- package/dist/e2b.js +75 -0
- package/dist/index.cjs +275 -23
- package/dist/index.d.cts +229 -101
- package/dist/index.d.ts +229 -101
- package/dist/index.js +1 -1
- package/dist/modal.cjs +1356 -0
- package/dist/modal.d.cts +49 -0
- package/dist/modal.d.ts +49 -0
- package/dist/modal.js +130 -0
- package/package.json +30 -4
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,12 +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
|
-
|
|
161
|
-
|
|
162
|
-
max_memory_mib: src.max_memory_mib ?? null,
|
|
163
|
-
disk_mib: src.disk_mib ?? null,
|
|
164
|
-
durable: src.durable ?? null
|
|
177
|
+
durable: src.durable ?? null,
|
|
178
|
+
resources
|
|
165
179
|
};
|
|
166
180
|
const useBurst = sourceOrgId === ARKER_ORG_ID && src.sourceVmName !== void 0 && isBurstRef(src.sourceVmName);
|
|
167
181
|
const baseUrl = useBurst && this.burstBaseUrl ? this.burstBaseUrl : this.baseUrl;
|
|
@@ -192,6 +206,33 @@ var Arker = class {
|
|
|
192
206
|
});
|
|
193
207
|
return { vms, nextCursor: resp.next_cursor ?? null };
|
|
194
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* List run activity visible to the authenticated caller across VMs,
|
|
211
|
+
* providers, and regions. Admin call — routed through the control plane.
|
|
212
|
+
*/
|
|
213
|
+
async listRuns(opts = {}) {
|
|
214
|
+
return this._request("GET", buildQuery("/v1/runs", {
|
|
215
|
+
since: opts.since,
|
|
216
|
+
until: opts.until,
|
|
217
|
+
vm: opts.vm,
|
|
218
|
+
vms: opts.vmIds && opts.vmIds.length > 0 ? opts.vmIds.join(",") : void 0,
|
|
219
|
+
region: opts.region,
|
|
220
|
+
provider: opts.provider,
|
|
221
|
+
source: opts.source,
|
|
222
|
+
search: opts.search,
|
|
223
|
+
limit: opts.limit,
|
|
224
|
+
offset: opts.offset,
|
|
225
|
+
lite: opts.lite === void 0 ? void 0 : opts.lite,
|
|
226
|
+
runtime: opts.runtime,
|
|
227
|
+
endpoint: opts.endpoint,
|
|
228
|
+
actions: opts.actions && opts.actions.length > 0 ? opts.actions.join(",") : void 0,
|
|
229
|
+
status: opts.status && opts.status.length > 0 ? opts.status.join(",") : void 0,
|
|
230
|
+
status_min: opts.statusMin,
|
|
231
|
+
status_max: opts.statusMax,
|
|
232
|
+
sort: opts.sort,
|
|
233
|
+
dir: opts.dir
|
|
234
|
+
}), void 0, this.controlBaseUrl);
|
|
235
|
+
}
|
|
195
236
|
/** Compute call — goes direct to the backend hosting this VM (no
|
|
196
237
|
* control-plane hop). Returns a fully-populated VM handle. */
|
|
197
238
|
async getVm(vmId) {
|
|
@@ -281,6 +322,10 @@ var Arker = class {
|
|
|
281
322
|
return retryDelay(this.retry, attempt);
|
|
282
323
|
}
|
|
283
324
|
/** @internal */
|
|
325
|
+
_authHeaders() {
|
|
326
|
+
return { authorization: `Bearer ${this.apiKey}` };
|
|
327
|
+
}
|
|
328
|
+
/** @internal */
|
|
284
329
|
_baseUrlFor(ref) {
|
|
285
330
|
if (isBurstRef(ref) && this.burstBaseUrl) return this.burstBaseUrl;
|
|
286
331
|
return this.baseUrl;
|
|
@@ -306,12 +351,15 @@ var VM = class _VM {
|
|
|
306
351
|
vcpu_count;
|
|
307
352
|
memory_mib;
|
|
308
353
|
disk_mib;
|
|
354
|
+
network;
|
|
355
|
+
max_vcpus;
|
|
356
|
+
max_memory_mib;
|
|
357
|
+
min_memory_mib;
|
|
309
358
|
started_at;
|
|
310
359
|
root_source_vm_id;
|
|
311
360
|
root_source_vm_name;
|
|
312
361
|
worker_id;
|
|
313
362
|
sessions;
|
|
314
|
-
tunnels;
|
|
315
363
|
constructor(client, vmId, baseUrl = client._baseUrlFor(vmId), data) {
|
|
316
364
|
this._client = client;
|
|
317
365
|
this.id = vmId;
|
|
@@ -434,8 +482,25 @@ var VM = class _VM {
|
|
|
434
482
|
}
|
|
435
483
|
throw new ArkerError(lastError?.code ?? "internal", lastError?.message ?? "write failed", 200);
|
|
436
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
|
+
*/
|
|
437
493
|
async resize(request) {
|
|
438
|
-
|
|
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);
|
|
439
504
|
}
|
|
440
505
|
async delete() {
|
|
441
506
|
return this._client._request("DELETE", vmPath(this.id), void 0, this.baseUrl);
|
|
@@ -491,19 +556,30 @@ var VM = class _VM {
|
|
|
491
556
|
async deleteSession(sessionId) {
|
|
492
557
|
return this._client._request("DELETE", `${vmPath(this.id)}/sessions/${pathSegment(sessionId)}`, void 0, this.baseUrl);
|
|
493
558
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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);
|
|
507
583
|
}
|
|
508
584
|
};
|
|
509
585
|
function buildQuery(path, params) {
|
|
@@ -515,6 +591,176 @@ function buildQuery(path, params) {
|
|
|
515
591
|
const qs = usp.toString();
|
|
516
592
|
return qs ? `${path}?${qs}` : path;
|
|
517
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
|
+
}
|
|
518
764
|
function normalizeBaseUrl(baseUrl) {
|
|
519
765
|
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
520
766
|
if (!trimmed) throw new Error("baseUrl must not be empty");
|
|
@@ -597,15 +843,17 @@ function parseRunResponse(payload) {
|
|
|
597
843
|
stderr: decodeBytes(stderr, stderrEncoding),
|
|
598
844
|
stderrEncoding,
|
|
599
845
|
exitCode: numberField(body.exit_code, "run response.exit_code"),
|
|
600
|
-
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
|
|
601
850
|
};
|
|
602
851
|
}
|
|
603
852
|
if (typeof body.run_id === "string") {
|
|
604
853
|
return {
|
|
605
854
|
type: "background",
|
|
606
855
|
runId: body.run_id,
|
|
607
|
-
state: typeof body.state === "string" ? body.state : "running"
|
|
608
|
-
tunnels: Array.isArray(body.tunnels) ? body.tunnels : []
|
|
856
|
+
state: typeof body.state === "string" ? body.state : "running"
|
|
609
857
|
};
|
|
610
858
|
}
|
|
611
859
|
throw new ArkerError("internal", "unrecognized run response shape", 200);
|
|
@@ -669,6 +917,10 @@ function numberField(value, context) {
|
|
|
669
917
|
if (typeof value !== "number") throw new ArkerError("internal", `${context} must be a number`, 200);
|
|
670
918
|
return value;
|
|
671
919
|
}
|
|
920
|
+
function optionalNumberOrNull(value) {
|
|
921
|
+
if (value === null || typeof value === "number") return value;
|
|
922
|
+
return void 0;
|
|
923
|
+
}
|
|
672
924
|
function assertWriteComplete(result, context) {
|
|
673
925
|
if (result.complete && result.written) return;
|
|
674
926
|
throw new ArkerError("internal", `${context} did not complete`, 200);
|