@aerol-ai/aerolvm-sdk 0.1.2 → 0.1.3
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/internal/client.js +58 -8
- package/package.json +1 -1
package/dist/internal/client.js
CHANGED
|
@@ -442,6 +442,35 @@ async function decodeError(response) {
|
|
|
442
442
|
}
|
|
443
443
|
const STREAM_PREFIX_STDOUT = 0x01;
|
|
444
444
|
const STREAM_PREFIX_STDERR = 0x02;
|
|
445
|
+
// Pull whatever diagnostic detail the runtime gave us off a WebSocket "error"
|
|
446
|
+
// event. Node 22's native WebSocket fires an ErrorEvent with `.error` /
|
|
447
|
+
// `.message`; browsers' base WebSocket fires a bare Event. Returns "" when
|
|
448
|
+
// nothing useful is there so callers can fall back to a generic label.
|
|
449
|
+
function describeWSError(event) {
|
|
450
|
+
if (!event || typeof event !== "object")
|
|
451
|
+
return "";
|
|
452
|
+
const e = event;
|
|
453
|
+
if (e.error instanceof Error && e.error.message)
|
|
454
|
+
return e.error.message;
|
|
455
|
+
if (typeof e.error === "string" && e.error !== "")
|
|
456
|
+
return e.error;
|
|
457
|
+
if (typeof e.message === "string" && e.message !== "")
|
|
458
|
+
return e.message;
|
|
459
|
+
return "";
|
|
460
|
+
}
|
|
461
|
+
function describeWSClose(event) {
|
|
462
|
+
if (!event || typeof event !== "object")
|
|
463
|
+
return "";
|
|
464
|
+
const e = event;
|
|
465
|
+
const parts = [];
|
|
466
|
+
if (typeof e.code === "number")
|
|
467
|
+
parts.push(`code=${e.code}`);
|
|
468
|
+
if (typeof e.reason === "string" && e.reason !== "")
|
|
469
|
+
parts.push(`reason=${JSON.stringify(e.reason)}`);
|
|
470
|
+
if (typeof e.wasClean === "boolean")
|
|
471
|
+
parts.push(`wasClean=${e.wasClean}`);
|
|
472
|
+
return parts.join(" ");
|
|
473
|
+
}
|
|
445
474
|
function openExecStream(baseURL, patToken, sandboxID, options) {
|
|
446
475
|
const wsURL = baseURL.replace(/^http/, "ws") + `/v1/sandboxes/${encodeURIComponent(sandboxID)}/toolbox/process/exec/stream`;
|
|
447
476
|
const WS = globalThis.WebSocket;
|
|
@@ -453,6 +482,10 @@ function openExecStream(baseURL, patToken, sandboxID, options) {
|
|
|
453
482
|
// `sandbox.bearer, <token>`.
|
|
454
483
|
const ws = new WS(wsURL, ["sandbox.bearer", patToken]);
|
|
455
484
|
ws.binaryType = "arraybuffer";
|
|
485
|
+
// Captured by the "error" listener and consumed by "close" so we report the
|
|
486
|
+
// root cause (e.g. "Unexpected server response: 502") rather than the
|
|
487
|
+
// generic "stream closed before exit" that would otherwise win the race.
|
|
488
|
+
let lastErrorDetail = "";
|
|
456
489
|
let exitResolve;
|
|
457
490
|
let exitReject;
|
|
458
491
|
const done = new Promise((resolve, reject) => {
|
|
@@ -513,11 +546,19 @@ function openExecStream(baseURL, patToken, sandboxID, options) {
|
|
|
513
546
|
options.onStderr?.(payload);
|
|
514
547
|
}
|
|
515
548
|
});
|
|
516
|
-
ws.addEventListener("close", () => {
|
|
517
|
-
|
|
549
|
+
ws.addEventListener("close", (event) => {
|
|
550
|
+
const closeDetail = describeWSClose(event);
|
|
551
|
+
const parts = [lastErrorDetail, closeDetail].filter((s) => s !== "");
|
|
552
|
+
const suffix = parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
553
|
+
failWith(`stream closed before exit${suffix}`);
|
|
518
554
|
});
|
|
519
|
-
ws.addEventListener("error", () => {
|
|
520
|
-
|
|
555
|
+
ws.addEventListener("error", (event) => {
|
|
556
|
+
const detail = describeWSError(event);
|
|
557
|
+
if (detail !== "") {
|
|
558
|
+
lastErrorDetail = detail;
|
|
559
|
+
}
|
|
560
|
+
options.onError?.(detail !== "" ? detail : "websocket error");
|
|
561
|
+
failWith(detail !== "" ? `websocket error: ${detail}` : "websocket error");
|
|
521
562
|
});
|
|
522
563
|
const sendBinary = (data) => {
|
|
523
564
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
@@ -552,6 +593,7 @@ function openSessionAttach(baseURL, patToken, sandboxID, sessionID, options) {
|
|
|
552
593
|
exitReject = reject;
|
|
553
594
|
});
|
|
554
595
|
let settled = false;
|
|
596
|
+
let lastErrorDetail = "";
|
|
555
597
|
const finishWith = (info) => {
|
|
556
598
|
if (settled)
|
|
557
599
|
return;
|
|
@@ -602,13 +644,21 @@ function openSessionAttach(baseURL, patToken, sandboxID, sessionID, options) {
|
|
|
602
644
|
options.onStderr?.(payload);
|
|
603
645
|
}
|
|
604
646
|
});
|
|
605
|
-
ws.addEventListener("close", () => {
|
|
647
|
+
ws.addEventListener("close", (event) => {
|
|
606
648
|
if (!settled) {
|
|
607
|
-
|
|
649
|
+
const closeDetail = describeWSClose(event);
|
|
650
|
+
const parts = [lastErrorDetail, closeDetail].filter((s) => s !== "");
|
|
651
|
+
const suffix = parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
652
|
+
failWith(`session stream closed before exit${suffix}`);
|
|
608
653
|
}
|
|
609
654
|
});
|
|
610
|
-
ws.addEventListener("error", () => {
|
|
611
|
-
|
|
655
|
+
ws.addEventListener("error", (event) => {
|
|
656
|
+
const detail = describeWSError(event);
|
|
657
|
+
if (detail !== "") {
|
|
658
|
+
lastErrorDetail = detail;
|
|
659
|
+
}
|
|
660
|
+
options.onError?.(detail !== "" ? detail : "websocket error");
|
|
661
|
+
failWith(detail !== "" ? `websocket error: ${detail}` : "websocket error");
|
|
612
662
|
});
|
|
613
663
|
const sendBinary = (data) => {
|
|
614
664
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|