@cloudflare/sandbox 0.9.1 → 0.9.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/bridge/index.js +2 -2
- package/dist/{contexts-D6kt6WyG.d.ts → contexts-D_shbnJs.d.ts} +32 -2
- package/dist/contexts-D_shbnJs.d.ts.map +1 -0
- package/dist/errors-CBi-O-pF.js +227 -0
- package/dist/errors-CBi-O-pF.js.map +1 -0
- package/dist/index.d.ts +25 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/openai/index.d.ts +1 -1
- package/dist/opencode/index.d.ts +2 -2
- package/dist/opencode/index.d.ts.map +1 -1
- package/dist/opencode/index.js +1 -1
- package/dist/{sandbox-PAYx1CcU.js → sandbox-CReFGUtF.js} +114 -16
- package/dist/sandbox-CReFGUtF.js.map +1 -0
- package/dist/{sandbox-Bb3n0SeC.d.ts → sandbox-YMrVC62F.d.ts} +2 -1
- package/dist/{sandbox-Bb3n0SeC.d.ts.map → sandbox-YMrVC62F.d.ts.map} +1 -1
- package/package.json +1 -1
- package/dist/contexts-D6kt6WyG.d.ts.map +0 -1
- package/dist/errors-LE3HHcRb.js +0 -169
- package/dist/errors-LE3HHcRb.js.map +0 -1
- package/dist/sandbox-PAYx1CcU.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _ as GitLogger, b as getEnvString, c as parseSSEFrames, d as createNoOpLogger, f as TraceContext, g as DEFAULT_GIT_CLONE_TIMEOUT_MS, h as ResultImpl, i as isWSStreamChunk, l as shellEscape, m as Execution, n as isWSError, p as logCanonicalEvent, r as isWSResponse, t as generateRequestId, u as createLogger, v as extractRepoName, x as partitionEnvVars, y as filterEnvVars } from "./dist-B_eXrP83.js";
|
|
2
|
-
import { n as ErrorCode, t as
|
|
2
|
+
import { n as getHttpStatus, r as ErrorCode, t as getSuggestion } from "./errors-CBi-O-pF.js";
|
|
3
3
|
import { Container, getContainer, switchPort } from "@cloudflare/containers";
|
|
4
4
|
import { AwsClient } from "aws4fetch";
|
|
5
5
|
import { RpcSession } from "capnweb";
|
|
@@ -11,8 +11,8 @@ import path from "node:path/posix";
|
|
|
11
11
|
* Preserves all error information from container
|
|
12
12
|
*/
|
|
13
13
|
var SandboxError = class extends Error {
|
|
14
|
-
constructor(errorResponse) {
|
|
15
|
-
super(errorResponse.message);
|
|
14
|
+
constructor(errorResponse, options) {
|
|
15
|
+
super(errorResponse.message, options);
|
|
16
16
|
this.errorResponse = errorResponse;
|
|
17
17
|
this.name = "SandboxError";
|
|
18
18
|
}
|
|
@@ -664,6 +664,30 @@ var DesktopInvalidCoordinatesError = class extends SandboxError {
|
|
|
664
664
|
this.name = "DesktopInvalidCoordinatesError";
|
|
665
665
|
}
|
|
666
666
|
};
|
|
667
|
+
/**
|
|
668
|
+
* Raised when the capnweb WebSocket session itself fails on the SDK side.
|
|
669
|
+
* Unlike the rest of the SandboxError tree, the container never produces
|
|
670
|
+
* this error — it is synthesised by `translateRPCError` from the plain
|
|
671
|
+
* Errors capnweb / DeferredTransport raise when the connection dies.
|
|
672
|
+
*
|
|
673
|
+
* `kind` distinguishes the failure mode (peer close, upgrade failed, etc.)
|
|
674
|
+
* so callers can branch on a structured code instead of substring-matching
|
|
675
|
+
* on the message.
|
|
676
|
+
*
|
|
677
|
+
* Always retryable: the SDK opens a fresh connection on the next call.
|
|
678
|
+
*/
|
|
679
|
+
var RPCTransportError = class extends SandboxError {
|
|
680
|
+
constructor(errorResponse, options) {
|
|
681
|
+
super(errorResponse, options);
|
|
682
|
+
this.name = "RPCTransportError";
|
|
683
|
+
}
|
|
684
|
+
get kind() {
|
|
685
|
+
return this.errorResponse.context.kind;
|
|
686
|
+
}
|
|
687
|
+
get originalMessage() {
|
|
688
|
+
return this.errorResponse.context.originalMessage;
|
|
689
|
+
}
|
|
690
|
+
};
|
|
667
691
|
|
|
668
692
|
//#endregion
|
|
669
693
|
//#region src/errors/adapter.ts
|
|
@@ -671,7 +695,7 @@ var DesktopInvalidCoordinatesError = class extends SandboxError {
|
|
|
671
695
|
* Convert ErrorResponse to appropriate Error class
|
|
672
696
|
* Simple switch statement - we trust the container sends correct context
|
|
673
697
|
*/
|
|
674
|
-
function createErrorFromResponse(errorResponse) {
|
|
698
|
+
function createErrorFromResponse(errorResponse, options) {
|
|
675
699
|
switch (errorResponse.code) {
|
|
676
700
|
case ErrorCode.FILE_NOT_FOUND: return new FileNotFoundError(errorResponse);
|
|
677
701
|
case ErrorCode.FILE_EXISTS: return new FileExistsError(errorResponse);
|
|
@@ -727,6 +751,7 @@ function createErrorFromResponse(errorResponse) {
|
|
|
727
751
|
case ErrorCode.DESKTOP_PROCESS_CRASHED: return new DesktopProcessCrashedError(errorResponse);
|
|
728
752
|
case ErrorCode.DESKTOP_INVALID_OPTIONS: return new DesktopInvalidOptionsError(errorResponse);
|
|
729
753
|
case ErrorCode.DESKTOP_INVALID_COORDINATES: return new DesktopInvalidCoordinatesError(errorResponse);
|
|
754
|
+
case ErrorCode.RPC_TRANSPORT_ERROR: return new RPCTransportError(errorResponse, options);
|
|
730
755
|
case ErrorCode.VALIDATION_FAILED: return new ValidationFailedError(errorResponse);
|
|
731
756
|
case ErrorCode.INVALID_JSON_RESPONSE:
|
|
732
757
|
case ErrorCode.UNKNOWN_ERROR:
|
|
@@ -2712,6 +2737,14 @@ const BACKUP_ALLOWED_PREFIXES = [
|
|
|
2712
2737
|
"/var/tmp",
|
|
2713
2738
|
"/app"
|
|
2714
2739
|
];
|
|
2740
|
+
function normalizeBackupExcludePattern(pattern) {
|
|
2741
|
+
let normalized = pattern;
|
|
2742
|
+
while (normalized.startsWith("**/")) normalized = normalized.slice(3);
|
|
2743
|
+
while (normalized.includes("/**/")) normalized = normalized.replace(/\/\*\*\//g, "/");
|
|
2744
|
+
if (normalized.endsWith("/**")) normalized = normalized.slice(0, -3);
|
|
2745
|
+
if (!normalized || normalized === "**") return null;
|
|
2746
|
+
return normalized;
|
|
2747
|
+
}
|
|
2715
2748
|
|
|
2716
2749
|
//#endregion
|
|
2717
2750
|
//#region src/container-connection.ts
|
|
@@ -2847,12 +2880,13 @@ var DeferredTransport = class {
|
|
|
2847
2880
|
this.#receiveResolver = void 0;
|
|
2848
2881
|
this.#receiveRejecter = void 0;
|
|
2849
2882
|
} else this.#receiveQueue.push(event.data);
|
|
2883
|
+
else this.#fail(/* @__PURE__ */ new TypeError("Received non-string message from WebSocket."));
|
|
2850
2884
|
});
|
|
2851
2885
|
ws.addEventListener("close", (event) => {
|
|
2852
2886
|
this.#fail(/* @__PURE__ */ new Error(`Peer closed WebSocket: ${event.code} ${event.reason}`));
|
|
2853
2887
|
});
|
|
2854
2888
|
ws.addEventListener("error", () => {
|
|
2855
|
-
this.#fail(/* @__PURE__ */ new Error("WebSocket connection failed"));
|
|
2889
|
+
this.#fail(/* @__PURE__ */ new Error("WebSocket connection failed."));
|
|
2856
2890
|
});
|
|
2857
2891
|
for (const msg of this.#sendQueue) ws.send(msg);
|
|
2858
2892
|
this.#sendQueue = [];
|
|
@@ -2924,19 +2958,65 @@ const IDLE_EXPORT_THRESHOLD = 1;
|
|
|
2924
2958
|
* string: `{"code":"...","message":"...","context":{...}}`.
|
|
2925
2959
|
*/
|
|
2926
2960
|
function translateRPCError(error) {
|
|
2927
|
-
if (error instanceof Error)
|
|
2928
|
-
|
|
2929
|
-
|
|
2961
|
+
if (error instanceof Error) {
|
|
2962
|
+
let payload;
|
|
2963
|
+
try {
|
|
2964
|
+
payload = JSON.parse(error.message);
|
|
2965
|
+
} catch {}
|
|
2966
|
+
if (payload && typeof payload.code === "string" && typeof payload.message === "string") throw createErrorFromResponse({
|
|
2930
2967
|
code: payload.code,
|
|
2931
2968
|
message: payload.message,
|
|
2932
2969
|
context: payload.context ?? {},
|
|
2933
2970
|
httpStatus: getHttpStatus(payload.code),
|
|
2934
2971
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2935
2972
|
});
|
|
2936
|
-
|
|
2937
|
-
if (e instanceof Error && e !== error) throw e;
|
|
2973
|
+
throw createErrorFromResponse(buildTransportErrorResponse(error), { cause: error });
|
|
2938
2974
|
}
|
|
2939
|
-
throw error;
|
|
2975
|
+
throw createErrorFromResponse(buildTransportErrorResponse(new Error(String(error))), { cause: error });
|
|
2976
|
+
}
|
|
2977
|
+
/**
|
|
2978
|
+
* Inspect a transport-level Error's message and produce the ErrorResponse
|
|
2979
|
+
* that becomes an RPCTransportError. Pattern strings are pinned to the exact
|
|
2980
|
+
* messages emitted by capnweb's WebSocketTransport (see capnweb's
|
|
2981
|
+
* src/websocket.ts) and our DeferredTransport in container-connection.ts —
|
|
2982
|
+
* notably the trailing period in `WebSocket connection failed.` matches
|
|
2983
|
+
* capnweb verbatim. The DeferredTransport tests in
|
|
2984
|
+
* tests/container-connection.test.ts pin the literal strings.
|
|
2985
|
+
*/
|
|
2986
|
+
function buildTransportErrorResponse(error) {
|
|
2987
|
+
const message = error.message;
|
|
2988
|
+
const errorName = error.name;
|
|
2989
|
+
let kind = "unknown";
|
|
2990
|
+
let closeCode;
|
|
2991
|
+
let closeReason;
|
|
2992
|
+
if (errorName === "TypeError") kind = "invalid_frame";
|
|
2993
|
+
else if (errorName === "SyntaxError") kind = "protocol_error";
|
|
2994
|
+
else {
|
|
2995
|
+
const peerCloseMatch = message.match(/^Peer closed WebSocket: (\d+) ?(.*)$/);
|
|
2996
|
+
if (peerCloseMatch) {
|
|
2997
|
+
kind = "peer_closed";
|
|
2998
|
+
closeCode = Number(peerCloseMatch[1]);
|
|
2999
|
+
closeReason = peerCloseMatch[2] || void 0;
|
|
3000
|
+
} else if (message === "WebSocket connection failed.") kind = "connection_failed";
|
|
3001
|
+
else if (message.startsWith("WebSocket upgrade failed")) kind = "upgrade_failed";
|
|
3002
|
+
else if (message === "No WebSocket in upgrade response") kind = "upgrade_failed";
|
|
3003
|
+
else if (message === "RPC session was shut down by disposing the main stub" || message === "RPC was canceled because the RpcPromise was disposed.") kind = "session_disposed";
|
|
3004
|
+
}
|
|
3005
|
+
const context = {
|
|
3006
|
+
kind,
|
|
3007
|
+
originalMessage: message,
|
|
3008
|
+
errorName,
|
|
3009
|
+
...closeCode !== void 0 ? { closeCode } : {},
|
|
3010
|
+
...closeReason !== void 0 ? { closeReason } : {}
|
|
3011
|
+
};
|
|
3012
|
+
return {
|
|
3013
|
+
code: ErrorCode.RPC_TRANSPORT_ERROR,
|
|
3014
|
+
message,
|
|
3015
|
+
context,
|
|
3016
|
+
httpStatus: getHttpStatus(ErrorCode.RPC_TRANSPORT_ERROR),
|
|
3017
|
+
suggestion: getSuggestion(ErrorCode.RPC_TRANSPORT_ERROR, context),
|
|
3018
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3019
|
+
};
|
|
2940
3020
|
}
|
|
2941
3021
|
/**
|
|
2942
3022
|
* Wrap a capnweb RPC stub so that every method call translates errors
|
|
@@ -4111,7 +4191,7 @@ function isLocalhostPattern(hostname) {
|
|
|
4111
4191
|
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
4112
4192
|
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
4113
4193
|
*/
|
|
4114
|
-
const SDK_VERSION = "0.9.
|
|
4194
|
+
const SDK_VERSION = "0.9.2";
|
|
4115
4195
|
|
|
4116
4196
|
//#endregion
|
|
4117
4197
|
//#region src/sandbox.ts
|
|
@@ -6362,6 +6442,22 @@ var Sandbox = class Sandbox extends Container {
|
|
|
6362
6442
|
});
|
|
6363
6443
|
return this.backupBucket;
|
|
6364
6444
|
}
|
|
6445
|
+
normalizeBackupExcludes(excludes) {
|
|
6446
|
+
const normalizedExcludes = [];
|
|
6447
|
+
for (const pattern of excludes) {
|
|
6448
|
+
const normalized = normalizeBackupExcludePattern(pattern);
|
|
6449
|
+
if (normalized === null) {
|
|
6450
|
+
this.logger.warn("Exclude pattern reduced to empty after globstar normalization; skipping", { original: pattern });
|
|
6451
|
+
continue;
|
|
6452
|
+
}
|
|
6453
|
+
if (normalized !== pattern) this.logger.warn("Exclude pattern contained ** (globstar) which mksquashfs does not support; normalized automatically", {
|
|
6454
|
+
original: pattern,
|
|
6455
|
+
normalized
|
|
6456
|
+
});
|
|
6457
|
+
normalizedExcludes.push(normalized);
|
|
6458
|
+
}
|
|
6459
|
+
return normalizedExcludes;
|
|
6460
|
+
}
|
|
6365
6461
|
static PRESIGNED_URL_EXPIRY_SECONDS = 3600;
|
|
6366
6462
|
/**
|
|
6367
6463
|
* Create a unique, dedicated session for a single backup operation.
|
|
@@ -6592,12 +6688,13 @@ var Sandbox = class Sandbox extends Container {
|
|
|
6592
6688
|
context: { reason: "excludes must be an array of strings" },
|
|
6593
6689
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6594
6690
|
});
|
|
6691
|
+
const normalizedExcludes = this.normalizeBackupExcludes(excludes);
|
|
6595
6692
|
backupSession = await this.ensureBackupSession();
|
|
6596
6693
|
backupId = crypto.randomUUID();
|
|
6597
6694
|
const archivePath = `${BACKUP_CONTAINER_DIR}/${backupId}.sqsh`;
|
|
6598
6695
|
const createResult = await this.client.backup.createArchive(dir, archivePath, backupSession, {
|
|
6599
6696
|
gitignore,
|
|
6600
|
-
excludes
|
|
6697
|
+
excludes: normalizedExcludes
|
|
6601
6698
|
});
|
|
6602
6699
|
if (!createResult.success) throw new BackupCreateError({
|
|
6603
6700
|
message: "Container failed to create backup archive",
|
|
@@ -6713,12 +6810,13 @@ var Sandbox = class Sandbox extends Container {
|
|
|
6713
6810
|
context: { reason: "excludes must be an array of strings" },
|
|
6714
6811
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6715
6812
|
});
|
|
6813
|
+
const normalizedExcludes = this.normalizeBackupExcludes(excludes);
|
|
6716
6814
|
backupSession = await this.ensureBackupSession();
|
|
6717
6815
|
backupId = crypto.randomUUID();
|
|
6718
6816
|
const archivePath = `${BACKUP_CONTAINER_DIR}/${backupId}.sqsh`;
|
|
6719
6817
|
const createResult = await this.client.backup.createArchive(dir, archivePath, backupSession, {
|
|
6720
6818
|
gitignore,
|
|
6721
|
-
excludes
|
|
6819
|
+
excludes: normalizedExcludes
|
|
6722
6820
|
});
|
|
6723
6821
|
if (!createResult.success) throw new BackupCreateError({
|
|
6724
6822
|
message: "Container failed to create backup archive",
|
|
@@ -7070,5 +7168,5 @@ var Sandbox = class Sandbox extends Container {
|
|
|
7070
7168
|
};
|
|
7071
7169
|
|
|
7072
7170
|
//#endregion
|
|
7073
|
-
export { DesktopInvalidOptionsError as A, CommandClient as C, BackupNotFoundError as D, BackupExpiredError as E, InvalidBackupConfigError as F, ProcessExitedBeforeReadyError as I, ProcessReadyTimeoutError as L, DesktopProcessCrashedError as M, DesktopStartFailedError as N, BackupRestoreError as O, DesktopUnavailableError as P,
|
|
7074
|
-
//# sourceMappingURL=sandbox-
|
|
7171
|
+
export { DesktopInvalidOptionsError as A, CommandClient as C, BackupNotFoundError as D, BackupExpiredError as E, InvalidBackupConfigError as F, ProcessExitedBeforeReadyError as I, ProcessReadyTimeoutError as L, DesktopProcessCrashedError as M, DesktopStartFailedError as N, BackupRestoreError as O, DesktopUnavailableError as P, RPCTransportError as R, DesktopClient as S, BackupCreateError as T, UtilityClient as _, BucketMountError as a, GitClient as b, MissingCredentialsError as c, parseSSEStream as d, responseToAsyncIterable as f, SandboxClient as g, streamFile as h, proxyTerminal as i, DesktopNotStartedError as j, DesktopInvalidCoordinatesError as k, S3FSMountError as l, collectFile as m, getSandbox as n, BucketUnmountError as o, CodeInterpreter as p, proxyToSandbox as r, InvalidMountConfigError as s, Sandbox as t, asyncIterableToSSEStream as u, ProcessClient as v, BackupClient as w, FileClient as x, PortClient as y, SessionTerminatedError as z };
|
|
7172
|
+
//# sourceMappingURL=sandbox-CReFGUtF.js.map
|