@cloudflare/sandbox 0.13.0-next.632.1 → 0.13.0-next.649.1
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-B0_bcx9f.d.ts → contexts-DPFhc2nR.d.ts} +8 -2
- package/dist/contexts-DPFhc2nR.d.ts.map +1 -0
- package/dist/{errors-aRUdk9K8.js → errors-CpoDEfUZ.js} +8 -1
- package/dist/errors-CpoDEfUZ.js.map +1 -0
- package/dist/index.d.ts +6 -3
- 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-Cz8DRoAm.d.ts → sandbox-44kEJjAc.d.ts} +3 -1
- package/dist/{sandbox-Cz8DRoAm.d.ts.map → sandbox-44kEJjAc.d.ts.map} +1 -1
- package/dist/{sandbox-B7ewRruX.js → sandbox-B-FLGbkP.js} +80 -21
- package/dist/sandbox-B-FLGbkP.js.map +1 -0
- package/package.json +3 -3
- package/dist/contexts-B0_bcx9f.d.ts.map +0 -1
- package/dist/errors-aRUdk9K8.js.map +0 -1
- package/dist/sandbox-B7ewRruX.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as shellEscape, c as TraceContext, d as ResultImpl, f as filterEnvVars, i as parseSSEFrames, l as logCanonicalEvent, m as partitionEnvVars, o as createLogger, p as getEnvString, s as createNoOpLogger, u as Execution } from "./dist-mAH_7Ui7.js";
|
|
2
|
-
import { n as getHttpStatus, r as ErrorCode, t as getSuggestion } from "./errors-
|
|
2
|
+
import { n as getHttpStatus, r as ErrorCode, t as getSuggestion } from "./errors-CpoDEfUZ.js";
|
|
3
3
|
import { Container, ContainerProxy, getContainer, switchPort } from "@cloudflare/containers";
|
|
4
4
|
import { AwsClient } from "aws4fetch";
|
|
5
5
|
import { RpcSession, RpcTarget } from "capnweb";
|
|
@@ -629,6 +629,12 @@ var BackupRestoreError = class extends SandboxError {
|
|
|
629
629
|
return this.context.backupId;
|
|
630
630
|
}
|
|
631
631
|
};
|
|
632
|
+
var ContainerUnavailableError = class extends SandboxError {
|
|
633
|
+
constructor(errorResponse) {
|
|
634
|
+
super(errorResponse);
|
|
635
|
+
this.name = "ContainerUnavailableError";
|
|
636
|
+
}
|
|
637
|
+
};
|
|
632
638
|
/**
|
|
633
639
|
* Raised when the capnweb WebSocket session itself fails on the SDK side.
|
|
634
640
|
* Unlike the rest of the SandboxError tree, the container never produces
|
|
@@ -710,6 +716,7 @@ function createErrorFromResponse(errorResponse, options) {
|
|
|
710
716
|
case ErrorCode.INTERPRETER_NOT_READY: return new InterpreterNotReadyError(errorResponse);
|
|
711
717
|
case ErrorCode.CONTEXT_NOT_FOUND: return new ContextNotFoundError(errorResponse);
|
|
712
718
|
case ErrorCode.CODE_EXECUTION_ERROR: return new CodeExecutionError(errorResponse);
|
|
719
|
+
case ErrorCode.CONTAINER_UNAVAILABLE: return new ContainerUnavailableError(errorResponse);
|
|
713
720
|
case ErrorCode.RPC_TRANSPORT_ERROR: return new RPCTransportError(errorResponse, options);
|
|
714
721
|
case ErrorCode.VALIDATION_FAILED: return new ValidationFailedError(errorResponse);
|
|
715
722
|
case ErrorCode.INVALID_JSON_RESPONSE:
|
|
@@ -1126,6 +1133,11 @@ async function fetchWithResponseRetry(fetchResponse, options) {
|
|
|
1126
1133
|
const DEFAULT_CONNECT_TIMEOUT_MS = 3e4;
|
|
1127
1134
|
const DEFAULT_RETRY_TIMEOUT_MS = 12e4;
|
|
1128
1135
|
const MIN_TIME_FOR_RETRY_MS = 15e3;
|
|
1136
|
+
function isErrorResponse(value) {
|
|
1137
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1138
|
+
const candidate = value;
|
|
1139
|
+
return typeof candidate.code === "string" && Object.values(ErrorCode).includes(candidate.code) && typeof candidate.message === "string" && typeof candidate.httpStatus === "number" && typeof candidate.timestamp === "string" && typeof candidate.context === "object" && candidate.context !== null;
|
|
1140
|
+
}
|
|
1129
1141
|
/**
|
|
1130
1142
|
* Manages a capnweb WebSocket RPC session to the container.
|
|
1131
1143
|
*
|
|
@@ -1249,7 +1261,19 @@ var ContainerControlConnection = class {
|
|
|
1249
1261
|
async doConnect() {
|
|
1250
1262
|
try {
|
|
1251
1263
|
const response = await this.fetchUpgradeWithRetry();
|
|
1252
|
-
if (response.status !== 101)
|
|
1264
|
+
if (response.status !== 101) {
|
|
1265
|
+
const structuredError = await this.parseStructuredUpgradeError(response);
|
|
1266
|
+
if (structuredError) throw createErrorFromResponse(structuredError);
|
|
1267
|
+
if (isRetryableWebSocketUpgradeResponse(response)) throw createErrorFromResponse({
|
|
1268
|
+
code: ErrorCode.CONTAINER_UNAVAILABLE,
|
|
1269
|
+
message: "Container is starting. Please retry in a moment.",
|
|
1270
|
+
context: { reason: "startup" },
|
|
1271
|
+
httpStatus: 503,
|
|
1272
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1273
|
+
suggestion: "The container is not ready yet. Retry the operation in a moment."
|
|
1274
|
+
});
|
|
1275
|
+
throw new Error(`WebSocket upgrade failed: ${response.status} ${response.statusText}`);
|
|
1276
|
+
}
|
|
1253
1277
|
const ws = response.webSocket;
|
|
1254
1278
|
if (!ws) throw new Error("No WebSocket in upgrade response");
|
|
1255
1279
|
ws.accept();
|
|
@@ -1267,6 +1291,17 @@ var ContainerControlConnection = class {
|
|
|
1267
1291
|
throw error;
|
|
1268
1292
|
}
|
|
1269
1293
|
}
|
|
1294
|
+
async parseStructuredUpgradeError(response) {
|
|
1295
|
+
if (!(response.headers.get("Content-Type") ?? "").includes("application/json")) return null;
|
|
1296
|
+
let body;
|
|
1297
|
+
try {
|
|
1298
|
+
body = await response.clone().json();
|
|
1299
|
+
} catch {
|
|
1300
|
+
return null;
|
|
1301
|
+
}
|
|
1302
|
+
if (!isErrorResponse(body)) return null;
|
|
1303
|
+
return body;
|
|
1304
|
+
}
|
|
1270
1305
|
/**
|
|
1271
1306
|
* Issue WebSocket upgrade fetches, retrying transient control-plane
|
|
1272
1307
|
* unavailability responses until either the upgrade succeeds, a
|
|
@@ -1395,6 +1430,11 @@ const BUSY_POLL_INTERVAL_MS = 1e3;
|
|
|
1395
1430
|
*/
|
|
1396
1431
|
const IDLE_IMPORT_THRESHOLD = 1;
|
|
1397
1432
|
const IDLE_EXPORT_THRESHOLD = 1;
|
|
1433
|
+
function isLocalSandboxError(error) {
|
|
1434
|
+
if (!("errorResponse" in error)) return false;
|
|
1435
|
+
const response = error.errorResponse;
|
|
1436
|
+
return typeof response?.code === "string" && Object.hasOwn(ErrorCode, response.code) && typeof response.message === "string" && typeof response.httpStatus === "number" && typeof response.timestamp === "string" && typeof response.context === "object" && response.context !== null;
|
|
1437
|
+
}
|
|
1398
1438
|
/**
|
|
1399
1439
|
* Translate a capnweb-propagated error into a typed SandboxError.
|
|
1400
1440
|
*
|
|
@@ -1413,6 +1453,7 @@ const IDLE_EXPORT_THRESHOLD = 1;
|
|
|
1413
1453
|
*/
|
|
1414
1454
|
function translateRPCError(error) {
|
|
1415
1455
|
if (error instanceof Error) {
|
|
1456
|
+
if (isLocalSandboxError(error)) throw error;
|
|
1416
1457
|
const propagated = error;
|
|
1417
1458
|
if (typeof propagated.code === "string" && Object.hasOwn(ErrorCode, propagated.code)) {
|
|
1418
1459
|
const code = propagated.code;
|
|
@@ -4144,7 +4185,7 @@ async function pruneTunnelsForRestart(storage) {
|
|
|
4144
4185
|
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
4145
4186
|
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
4146
4187
|
*/
|
|
4147
|
-
const SDK_VERSION = "0.13.0-next.
|
|
4188
|
+
const SDK_VERSION = "0.13.0-next.649.1";
|
|
4148
4189
|
|
|
4149
4190
|
//#endregion
|
|
4150
4191
|
//#region src/sandbox.ts
|
|
@@ -4211,6 +4252,8 @@ const BACKUP_MULTIPART_MAX_PARTS = 64;
|
|
|
4211
4252
|
const BACKUP_DOWNLOAD_PARALLEL_PARTS = 8;
|
|
4212
4253
|
const BACKUP_DOWNLOAD_PARALLEL_MIN_SIZE = 10 * 1024 * 1024;
|
|
4213
4254
|
const BACKUP_DOWNLOAD_MAX_PARTS = 64;
|
|
4255
|
+
const DEFAULT_SESSION_INIT_MAX_ATTEMPTS = 2;
|
|
4256
|
+
const DEFAULT_SESSION_RESTART_SETTLE_MS = 100;
|
|
4214
4257
|
/**
|
|
4215
4258
|
* Calculate the optimal number of parts for multipart upload/download
|
|
4216
4259
|
* based on archive size. Larger archives benefit from more parallelism.
|
|
@@ -5512,12 +5555,12 @@ var Sandbox = class Sandbox extends Container {
|
|
|
5512
5555
|
} catch (e) {
|
|
5513
5556
|
if (this.isNoInstanceError(e)) {
|
|
5514
5557
|
const errorBody$1 = {
|
|
5515
|
-
code: ErrorCode.
|
|
5558
|
+
code: ErrorCode.CONTAINER_UNAVAILABLE,
|
|
5516
5559
|
message: "Container is currently provisioning. This can take several minutes on first deployment.",
|
|
5517
|
-
context: {
|
|
5560
|
+
context: { reason: "provisioning" },
|
|
5518
5561
|
httpStatus: 503,
|
|
5519
5562
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5520
|
-
suggestion: "
|
|
5563
|
+
suggestion: "The container is still being provisioned. Retry the operation in a moment."
|
|
5521
5564
|
};
|
|
5522
5565
|
return new Response(JSON.stringify(errorBody$1), {
|
|
5523
5566
|
status: 503,
|
|
@@ -5559,15 +5602,12 @@ var Sandbox = class Sandbox extends Container {
|
|
|
5559
5602
|
error: e instanceof Error ? e.message : String(e)
|
|
5560
5603
|
});
|
|
5561
5604
|
const errorBody$1 = {
|
|
5562
|
-
code: ErrorCode.
|
|
5605
|
+
code: ErrorCode.CONTAINER_UNAVAILABLE,
|
|
5563
5606
|
message: "Container is starting. Please retry in a moment.",
|
|
5564
|
-
context: {
|
|
5565
|
-
phase: "startup",
|
|
5566
|
-
error: e instanceof Error ? e.message : String(e)
|
|
5567
|
-
},
|
|
5607
|
+
context: { reason: "startup" },
|
|
5568
5608
|
httpStatus: 503,
|
|
5569
5609
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5570
|
-
suggestion: "The container is
|
|
5610
|
+
suggestion: "The container is not ready yet. Retry the operation in a moment."
|
|
5571
5611
|
};
|
|
5572
5612
|
return new Response(JSON.stringify(errorBody$1), {
|
|
5573
5613
|
status: 503,
|
|
@@ -5583,15 +5623,12 @@ var Sandbox = class Sandbox extends Container {
|
|
|
5583
5623
|
error: e instanceof Error ? e.message : String(e)
|
|
5584
5624
|
});
|
|
5585
5625
|
const errorBody = {
|
|
5586
|
-
code: ErrorCode.
|
|
5626
|
+
code: ErrorCode.CONTAINER_UNAVAILABLE,
|
|
5587
5627
|
message: "Container is starting. Please retry in a moment.",
|
|
5588
|
-
context: {
|
|
5589
|
-
phase: "startup",
|
|
5590
|
-
error: e instanceof Error ? e.message : String(e)
|
|
5591
|
-
},
|
|
5628
|
+
context: { reason: "startup" },
|
|
5592
5629
|
httpStatus: 503,
|
|
5593
5630
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5594
|
-
suggestion: "The
|
|
5631
|
+
suggestion: "The container is not ready yet. Retry the operation in a moment."
|
|
5595
5632
|
};
|
|
5596
5633
|
return new Response(JSON.stringify(errorBody), {
|
|
5597
5634
|
status: 503,
|
|
@@ -5837,6 +5874,15 @@ var Sandbox = class Sandbox extends Container {
|
|
|
5837
5874
|
*/
|
|
5838
5875
|
async ensureDefaultSession() {
|
|
5839
5876
|
const sessionId = `sandbox-${this.sandboxName || "default"}`;
|
|
5877
|
+
for (let attempt = 1; attempt <= DEFAULT_SESSION_INIT_MAX_ATTEMPTS; attempt++) try {
|
|
5878
|
+
return await this.getOrInitializeDefaultSession(sessionId);
|
|
5879
|
+
} catch (error) {
|
|
5880
|
+
if (!this.isDefaultSessionInitContainerRestart(error) || attempt === DEFAULT_SESSION_INIT_MAX_ATTEMPTS) throw error;
|
|
5881
|
+
await new Promise((resolve) => setTimeout(resolve, DEFAULT_SESSION_RESTART_SETTLE_MS));
|
|
5882
|
+
}
|
|
5883
|
+
throw new Error("Default session initialization failed unexpectedly");
|
|
5884
|
+
}
|
|
5885
|
+
async getOrInitializeDefaultSession(sessionId) {
|
|
5840
5886
|
if (this.defaultSession === sessionId) return this.defaultSession;
|
|
5841
5887
|
const generation = this.containerGeneration;
|
|
5842
5888
|
const pending = this.defaultSessionInit;
|
|
@@ -5854,6 +5900,9 @@ var Sandbox = class Sandbox extends Container {
|
|
|
5854
5900
|
if (this.defaultSessionInit === init) this.defaultSessionInit = null;
|
|
5855
5901
|
}
|
|
5856
5902
|
}
|
|
5903
|
+
isDefaultSessionInitContainerRestart(error) {
|
|
5904
|
+
return error instanceof ContainerUnavailableError && error.context.reason === "container_restarted";
|
|
5905
|
+
}
|
|
5857
5906
|
async initializeDefaultSession(sessionId, generation) {
|
|
5858
5907
|
let placementId;
|
|
5859
5908
|
try {
|
|
@@ -5867,7 +5916,17 @@ var Sandbox = class Sandbox extends Container {
|
|
|
5867
5916
|
placementId = error.containerPlacementId;
|
|
5868
5917
|
this.logger.debug("Session exists in container but not in DO state, syncing", { sessionId });
|
|
5869
5918
|
}
|
|
5870
|
-
if (generation !== this.containerGeneration) throw new
|
|
5919
|
+
if (generation !== this.containerGeneration) throw new ContainerUnavailableError({
|
|
5920
|
+
code: ErrorCode.CONTAINER_UNAVAILABLE,
|
|
5921
|
+
message: "Container restarted while the default session was being initialized.",
|
|
5922
|
+
context: {
|
|
5923
|
+
reason: "container_restarted",
|
|
5924
|
+
sessionId
|
|
5925
|
+
},
|
|
5926
|
+
httpStatus: 503,
|
|
5927
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5928
|
+
suggestion: "The container restarted while the SDK was preparing the default session. Retry the operation to use the new container."
|
|
5929
|
+
});
|
|
5871
5930
|
await this.ctx.storage.put("defaultSession", sessionId);
|
|
5872
5931
|
await this.capturePlacementId(placementId);
|
|
5873
5932
|
this.defaultSession = sessionId;
|
|
@@ -8207,5 +8266,5 @@ var Sandbox = class Sandbox extends Container {
|
|
|
8207
8266
|
};
|
|
8208
8267
|
|
|
8209
8268
|
//#endregion
|
|
8210
|
-
export {
|
|
8211
|
-
//# sourceMappingURL=sandbox-
|
|
8269
|
+
export { InvalidBackupConfigError as A, collectFile as C, BackupNotFoundError as D, BackupExpiredError as E, ProcessReadyTimeoutError as M, RPCTransportError as N, BackupRestoreError as O, SessionTerminatedError as P, validateTunnelName as S, BackupCreateError as T, proxyTerminal as _, BucketUnmountError as a, sanitizeSandboxId as b, S3FSMountError as c, responseToAsyncIterable as d, PREVIEW_PROXY_HEADER as f, PREVIEW_PROXY_TOKEN_HEADER as g, PREVIEW_PROXY_SANDBOX_ID_HEADER as h, BucketMountError as i, ProcessExitedBeforeReadyError as j, ContainerUnavailableError as k, asyncIterableToSSEStream as l, PREVIEW_PROXY_PORT_HEADER as m, Sandbox as n, InvalidMountConfigError as o, PREVIEW_PROXY_HEADERS as p, getSandbox as r, MissingCredentialsError as s, ContainerProxy$1 as t, parseSSEStream as u, CodeInterpreter as v, streamFile as w, validatePort as x, SandboxSecurityError as y };
|
|
8270
|
+
//# sourceMappingURL=sandbox-B-FLGbkP.js.map
|