@cloudflare/sandbox 0.9.3 → 0.10.0
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/Dockerfile +9 -5
- package/dist/bridge/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/opencode/index.d.ts +1 -1
- package/dist/{sandbox-BAuU-2a0.js → sandbox-2bHZZmy5.js} +123 -37
- package/dist/sandbox-2bHZZmy5.js.map +1 -0
- package/dist/{sandbox-CW4QeITP.d.ts → sandbox-C-AzrX_L.d.ts} +13 -2
- package/dist/{sandbox-CW4QeITP.d.ts.map → sandbox-C-AzrX_L.d.ts.map} +1 -1
- package/package.json +1 -1
- package/dist/sandbox-BAuU-2a0.js.map +0 -1
package/Dockerfile
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Bun version — override via --build-arg BUN_VERSION=$(cat .bun-version)
|
|
2
2
|
ARG BUN_VERSION=1
|
|
3
|
+
# Node version — override via --build-arg NODE_VERSION=24
|
|
4
|
+
ARG NODE_VERSION=24
|
|
3
5
|
FROM oven/bun:${BUN_VERSION} AS bun-binary
|
|
6
|
+
FROM node:${NODE_VERSION}-slim AS node-runtime
|
|
4
7
|
|
|
5
8
|
# Sandbox container images (default and python variants)
|
|
6
9
|
# Multi-stage build optimized for Turborepo monorepo
|
|
@@ -8,7 +11,7 @@ FROM oven/bun:${BUN_VERSION} AS bun-binary
|
|
|
8
11
|
# ============================================================================
|
|
9
12
|
# Stage 1: Prune monorepo to only include necessary packages
|
|
10
13
|
# ============================================================================
|
|
11
|
-
FROM node
|
|
14
|
+
FROM node-runtime AS pruner
|
|
12
15
|
|
|
13
16
|
WORKDIR /app
|
|
14
17
|
|
|
@@ -25,7 +28,7 @@ RUN turbo prune @repo/sandbox-container --docker
|
|
|
25
28
|
# Using glibc-based images (not Alpine) so the standalone binary works on
|
|
26
29
|
# standard Linux distributions (Debian, Ubuntu, RHEL, etc.)
|
|
27
30
|
# ============================================================================
|
|
28
|
-
FROM node
|
|
31
|
+
FROM node-runtime AS builder
|
|
29
32
|
|
|
30
33
|
WORKDIR /app
|
|
31
34
|
|
|
@@ -126,9 +129,10 @@ RUN sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
|
|
|
126
129
|
# fusermount requires /etc/mtab to locate active mounts
|
|
127
130
|
RUN ln -sf /proc/mounts /etc/mtab
|
|
128
131
|
|
|
129
|
-
# Install Node.js
|
|
130
|
-
|
|
131
|
-
COPY --from=node
|
|
132
|
+
# Install Node.js from official Node image (defaults to 24 LTS,
|
|
133
|
+
# override via --build-arg NODE_VERSION=<version>)
|
|
134
|
+
COPY --from=node-runtime /usr/local/bin/node /usr/local/bin/node
|
|
135
|
+
COPY --from=node-runtime /usr/local/lib/node_modules /usr/local/lib/node_modules
|
|
132
136
|
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
|
|
133
137
|
ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
|
|
134
138
|
|
package/dist/bridge/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../dist-B_eXrP83.js";
|
|
2
2
|
import "../errors-CBi-O-pF.js";
|
|
3
|
-
import { h as streamFile, n as getSandbox } from "../sandbox-
|
|
3
|
+
import { h as streamFile, n as getSandbox } from "../sandbox-2bHZZmy5.js";
|
|
4
4
|
import { DurableObject, env } from "cloudflare:workers";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as BackupOptions, A as DesktopStopResponse, At as ProcessStartResult, B as ExecuteResponse, Bt as WatchOptions, C as ClickOptions, Ct as Process, D as DesktopStartOptions, Dt as ProcessListResult, E as DesktopClient, Et as ProcessKillResult, F as ScreenshotRegion, Ft as SandboxTransport, G as HttpClientOptions, Gt as CodeContext, H as BaseApiResponse, Ht as isProcess, I as ScreenshotResponse, It as SessionOptions, J as SessionRequest, Jt as ExecutionResult, K as RequestConfig, Kt as CreateContextOptions, L as ScrollDirection, Lt as StreamOptions, M as ScreenSizeResponse, Mt as RemoteMountBucketOptions, N as ScreenshotBytesResponse, Nt as RestoreBackupResult, O as DesktopStartResponse, Ot as ProcessLogsResult, P as ScreenshotOptions, Pt as SandboxOptions, Q as StartProcessRequest, R as TypeOptions, Rt as WaitForLogResult, S as WriteFileRequest, St as PortListResult, T as Desktop, Tt as ProcessInfoResult, U as ContainerStub, Ut as isProcessStatus, V as BackupClient, Vt as isExecResult, W as ErrorResponse, Wt as PtyOptions, X as ExecuteRequest, Y as SandboxInterpreterAPI, Yt as RunCodeOptions, Z as ExposePortRequest, _ as GitClient, _t as LocalMountBucketOptions, a as CreateSessionRequest, at as DirectoryBackup, b as MkdirRequest, bt as PortCloseResult, c as DeleteSessionResponse, ct as ExecResult, d as ProcessClient, dt as FileMetadata, et as BaseExecOptions, f as PortClient, ft as FileStreamEvent, g as GitCheckoutRequest, gt as ListFilesOptions, h as InterpreterClient, ht as ISandbox, i as CommandsResponse, it as CheckChangesResult, j as KeyInput, jt as ProcessStatus, k as DesktopStatusResponse, kt as ProcessOptions, l as PingResponse, lt as ExecutionSession, m as ExecutionCallbacks, mt as GitCheckoutResult, n as getSandbox, nt as BucketProvider, o as CreateSessionResponse, ot as ExecEvent, p as UnexposePortRequest, pt as FileWatchSSEEvent, q as ResponseHandler, qt as Execution, r as SandboxClient, rt as CheckChangesOptions, s as DeleteSessionRequest, st as ExecOptions, t as Sandbox, tt as BucketCredentials, u as UtilityClient, ut as FileChunk, v as FileClient, vt as LogEvent, w as CursorPositionResponse, wt as ProcessCleanupResult, x as ReadFileRequest, xt as PortExposeResult, y as FileOperationRequest, yt as MountBucketOptions, z as CommandClient, zt as WaitForPortOptions } from "./sandbox-
|
|
1
|
+
import { $ as BackupOptions, A as DesktopStopResponse, At as ProcessStartResult, B as ExecuteResponse, Bt as WatchOptions, C as ClickOptions, Ct as Process, D as DesktopStartOptions, Dt as ProcessListResult, E as DesktopClient, Et as ProcessKillResult, F as ScreenshotRegion, Ft as SandboxTransport, G as HttpClientOptions, Gt as CodeContext, H as BaseApiResponse, Ht as isProcess, I as ScreenshotResponse, It as SessionOptions, J as SessionRequest, Jt as ExecutionResult, K as RequestConfig, Kt as CreateContextOptions, L as ScrollDirection, Lt as StreamOptions, M as ScreenSizeResponse, Mt as RemoteMountBucketOptions, N as ScreenshotBytesResponse, Nt as RestoreBackupResult, O as DesktopStartResponse, Ot as ProcessLogsResult, P as ScreenshotOptions, Pt as SandboxOptions, Q as StartProcessRequest, R as TypeOptions, Rt as WaitForLogResult, S as WriteFileRequest, St as PortListResult, T as Desktop, Tt as ProcessInfoResult, U as ContainerStub, Ut as isProcessStatus, V as BackupClient, Vt as isExecResult, W as ErrorResponse, Wt as PtyOptions, X as ExecuteRequest, Y as SandboxInterpreterAPI, Yt as RunCodeOptions, Z as ExposePortRequest, _ as GitClient, _t as LocalMountBucketOptions, a as CreateSessionRequest, at as DirectoryBackup, b as MkdirRequest, bt as PortCloseResult, c as DeleteSessionResponse, ct as ExecResult, d as ProcessClient, dt as FileMetadata, et as BaseExecOptions, f as PortClient, ft as FileStreamEvent, g as GitCheckoutRequest, gt as ListFilesOptions, h as InterpreterClient, ht as ISandbox, i as CommandsResponse, it as CheckChangesResult, j as KeyInput, jt as ProcessStatus, k as DesktopStatusResponse, kt as ProcessOptions, l as PingResponse, lt as ExecutionSession, m as ExecutionCallbacks, mt as GitCheckoutResult, n as getSandbox, nt as BucketProvider, o as CreateSessionResponse, ot as ExecEvent, p as UnexposePortRequest, pt as FileWatchSSEEvent, q as ResponseHandler, qt as Execution, r as SandboxClient, rt as CheckChangesOptions, s as DeleteSessionRequest, st as ExecOptions, t as Sandbox, tt as BucketCredentials, u as UtilityClient, ut as FileChunk, v as FileClient, vt as LogEvent, w as CursorPositionResponse, wt as ProcessCleanupResult, x as ReadFileRequest, xt as PortExposeResult, y as FileOperationRequest, yt as MountBucketOptions, z as CommandClient, zt as WaitForPortOptions } from "./sandbox-C-AzrX_L.js";
|
|
2
2
|
import { a as DesktopCoordinateErrorContext, d as RPCTransportContext, f as RPCTransportErrorKind, g as ErrorCode, h as OperationType, i as BackupRestoreContext, l as ProcessExitedBeforeReadyContext, m as ErrorResponse$1, n as BackupExpiredContext, o as DesktopErrorContext, p as SessionTerminatedContext, r as BackupNotFoundContext, s as InvalidBackupConfigContext, t as BackupCreateContext, u as ProcessReadyTimeoutContext } from "./contexts-D_shbnJs.js";
|
|
3
3
|
import { ContainerProxy } from "@cloudflare/containers";
|
|
4
4
|
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as isExecResult, o as isProcess, s as isProcessStatus } from "./dist-B_eXrP83.js";
|
|
2
2
|
import "./errors-CBi-O-pF.js";
|
|
3
|
-
import { A as DesktopInvalidOptionsError, C as CommandClient, D as BackupNotFoundError, E as BackupExpiredError, F as InvalidBackupConfigError, I as ProcessExitedBeforeReadyError, L as ProcessReadyTimeoutError, M as DesktopProcessCrashedError, N as DesktopStartFailedError, O as BackupRestoreError, P as DesktopUnavailableError, R as RPCTransportError, S as DesktopClient, T as BackupCreateError, _ as UtilityClient, a as BucketMountError, b as GitClient, c as MissingCredentialsError, d as parseSSEStream, f as responseToAsyncIterable, g as SandboxClient, h as streamFile, i as proxyTerminal, j as DesktopNotStartedError, k as DesktopInvalidCoordinatesError, l as S3FSMountError, m as collectFile, n as getSandbox, o as BucketUnmountError, p as CodeInterpreter, r as proxyToSandbox, s as InvalidMountConfigError, t as Sandbox, u as asyncIterableToSSEStream, v as ProcessClient, w as BackupClient, x as FileClient, y as PortClient, z as SessionTerminatedError } from "./sandbox-
|
|
3
|
+
import { A as DesktopInvalidOptionsError, C as CommandClient, D as BackupNotFoundError, E as BackupExpiredError, F as InvalidBackupConfigError, I as ProcessExitedBeforeReadyError, L as ProcessReadyTimeoutError, M as DesktopProcessCrashedError, N as DesktopStartFailedError, O as BackupRestoreError, P as DesktopUnavailableError, R as RPCTransportError, S as DesktopClient, T as BackupCreateError, _ as UtilityClient, a as BucketMountError, b as GitClient, c as MissingCredentialsError, d as parseSSEStream, f as responseToAsyncIterable, g as SandboxClient, h as streamFile, i as proxyTerminal, j as DesktopNotStartedError, k as DesktopInvalidCoordinatesError, l as S3FSMountError, m as collectFile, n as getSandbox, o as BucketUnmountError, p as CodeInterpreter, r as proxyToSandbox, s as InvalidMountConfigError, t as Sandbox, u as asyncIterableToSSEStream, v as ProcessClient, w as BackupClient, x as FileClient, y as PortClient, z as SessionTerminatedError } from "./sandbox-2bHZZmy5.js";
|
|
4
4
|
import { ContainerProxy } from "@cloudflare/containers";
|
|
5
5
|
|
|
6
6
|
export { BackupClient, BackupCreateError, BackupExpiredError, BackupNotFoundError, BackupRestoreError, BucketMountError, BucketUnmountError, CodeInterpreter, CommandClient, ContainerProxy, DesktopClient, DesktopInvalidCoordinatesError, DesktopInvalidOptionsError, DesktopNotStartedError, DesktopProcessCrashedError, DesktopStartFailedError, DesktopUnavailableError, FileClient, GitClient, InvalidBackupConfigError, InvalidMountConfigError, MissingCredentialsError, PortClient, ProcessClient, ProcessExitedBeforeReadyError, ProcessReadyTimeoutError, RPCTransportError, S3FSMountError, Sandbox, SandboxClient, SessionTerminatedError, UtilityClient, asyncIterableToSSEStream, collectFile, getSandbox, isExecResult, isProcess, isProcessStatus, parseSSEStream, proxyTerminal, proxyToSandbox, responseToAsyncIterable, streamFile };
|
package/dist/openai/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Sandbox } from "../sandbox-
|
|
1
|
+
import { t as Sandbox } from "../sandbox-C-AzrX_L.js";
|
|
2
2
|
import { ApplyPatchOperation, ApplyPatchResult, Editor as Editor$1, Shell as Shell$1, ShellAction, ShellResult } from "@openai/agents";
|
|
3
3
|
|
|
4
4
|
//#region src/openai/index.d.ts
|
package/dist/opencode/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Sandbox } from "../sandbox-
|
|
1
|
+
import { t as Sandbox } from "../sandbox-C-AzrX_L.js";
|
|
2
2
|
import { c as OpencodeStartupContext } from "../contexts-D_shbnJs.js";
|
|
3
3
|
import { OpencodeClient } from "@opencode-ai/sdk/v2/client";
|
|
4
4
|
import { Config } from "@opencode-ai/sdk/v2";
|
|
@@ -765,8 +765,8 @@ function createErrorFromResponse(errorResponse, options) {
|
|
|
765
765
|
/**
|
|
766
766
|
* Container startup retry configuration
|
|
767
767
|
*/
|
|
768
|
-
const DEFAULT_RETRY_TIMEOUT_MS = 12e4;
|
|
769
|
-
const MIN_TIME_FOR_RETRY_MS = 15e3;
|
|
768
|
+
const DEFAULT_RETRY_TIMEOUT_MS$1 = 12e4;
|
|
769
|
+
const MIN_TIME_FOR_RETRY_MS$1 = 15e3;
|
|
770
770
|
/**
|
|
771
771
|
* Abstract base transport with shared retry logic
|
|
772
772
|
*
|
|
@@ -780,7 +780,7 @@ var BaseTransport = class {
|
|
|
780
780
|
constructor(config) {
|
|
781
781
|
this.config = config;
|
|
782
782
|
this.logger = config.logger ?? createNoOpLogger();
|
|
783
|
-
this.retryTimeoutMs = config.retryTimeoutMs ?? DEFAULT_RETRY_TIMEOUT_MS;
|
|
783
|
+
this.retryTimeoutMs = config.retryTimeoutMs ?? DEFAULT_RETRY_TIMEOUT_MS$1;
|
|
784
784
|
}
|
|
785
785
|
setRetryTimeoutMs(ms) {
|
|
786
786
|
this.retryTimeoutMs = ms;
|
|
@@ -802,7 +802,7 @@ var BaseTransport = class {
|
|
|
802
802
|
if (response.status === 503) {
|
|
803
803
|
const elapsed = Date.now() - startTime;
|
|
804
804
|
const remaining = this.retryTimeoutMs - elapsed;
|
|
805
|
-
if (remaining > MIN_TIME_FOR_RETRY_MS) {
|
|
805
|
+
if (remaining > MIN_TIME_FOR_RETRY_MS$1) {
|
|
806
806
|
const delay = Math.min(3e3 * 2 ** attempt, 3e4);
|
|
807
807
|
this.logger.info("Container not ready, retrying", {
|
|
808
808
|
status: response.status,
|
|
@@ -2756,6 +2756,9 @@ function normalizeBackupExcludePattern(pattern) {
|
|
|
2756
2756
|
//#endregion
|
|
2757
2757
|
//#region src/container-control/connection.ts
|
|
2758
2758
|
const DEFAULT_CONNECT_TIMEOUT_MS = 3e4;
|
|
2759
|
+
const DEFAULT_RETRY_TIMEOUT_MS = 12e4;
|
|
2760
|
+
const MIN_TIME_FOR_RETRY_MS = 15e3;
|
|
2761
|
+
const MAX_RETRY_BACKOFF_MS = 3e4;
|
|
2759
2762
|
/**
|
|
2760
2763
|
* Manages a capnweb WebSocket RPC session to the container.
|
|
2761
2764
|
*
|
|
@@ -2773,10 +2776,12 @@ var ContainerControlConnection = class {
|
|
|
2773
2776
|
containerStub;
|
|
2774
2777
|
port;
|
|
2775
2778
|
logger;
|
|
2779
|
+
retryTimeoutMs;
|
|
2776
2780
|
constructor(options) {
|
|
2777
2781
|
this.containerStub = options.stub;
|
|
2778
2782
|
this.port = options.port ?? 3e3;
|
|
2779
2783
|
this.logger = options.logger ?? createNoOpLogger();
|
|
2784
|
+
this.retryTimeoutMs = options.retryTimeoutMs ?? DEFAULT_RETRY_TIMEOUT_MS;
|
|
2780
2785
|
this.transport = new DeferredTransport();
|
|
2781
2786
|
this.session = new RpcSession(this.transport);
|
|
2782
2787
|
this.stub = this.session.getRemoteMain();
|
|
@@ -2826,20 +2831,17 @@ var ContainerControlConnection = class {
|
|
|
2826
2831
|
this.connected = false;
|
|
2827
2832
|
this.connectPromise = null;
|
|
2828
2833
|
}
|
|
2834
|
+
/**
|
|
2835
|
+
* Update the 503 retry budget without recreating the connection. Takes
|
|
2836
|
+
* effect on the next `connect()`; an in-flight connect uses the value
|
|
2837
|
+
* captured at start. Mirrors `WebSocketTransport.setRetryTimeoutMs`.
|
|
2838
|
+
*/
|
|
2839
|
+
setRetryTimeoutMs(ms) {
|
|
2840
|
+
this.retryTimeoutMs = ms;
|
|
2841
|
+
}
|
|
2829
2842
|
async doConnect() {
|
|
2830
|
-
const controller = new AbortController();
|
|
2831
|
-
const timeout = setTimeout(() => controller.abort(), DEFAULT_CONNECT_TIMEOUT_MS);
|
|
2832
2843
|
try {
|
|
2833
|
-
const
|
|
2834
|
-
const request = new Request(url, {
|
|
2835
|
-
headers: {
|
|
2836
|
-
Upgrade: "websocket",
|
|
2837
|
-
Connection: "Upgrade"
|
|
2838
|
-
},
|
|
2839
|
-
signal: controller.signal
|
|
2840
|
-
});
|
|
2841
|
-
const response = await this.containerStub.fetch(request);
|
|
2842
|
-
clearTimeout(timeout);
|
|
2844
|
+
const response = await this.fetchUpgradeWithRetry();
|
|
2843
2845
|
if (response.status !== 101) throw new Error(`WebSocket upgrade failed: ${response.status} ${response.statusText}`);
|
|
2844
2846
|
const ws = response.webSocket;
|
|
2845
2847
|
if (!ws) throw new Error("No WebSocket in upgrade response");
|
|
@@ -2858,13 +2860,63 @@ var ContainerControlConnection = class {
|
|
|
2858
2860
|
this.connected = true;
|
|
2859
2861
|
this.logger.debug("ContainerControlConnection established", { port: this.port });
|
|
2860
2862
|
} catch (error) {
|
|
2861
|
-
clearTimeout(timeout);
|
|
2862
2863
|
this.connected = false;
|
|
2863
2864
|
this.transport.abort(error);
|
|
2864
2865
|
this.logger.error("ContainerControlConnection failed", error instanceof Error ? error : new Error(String(error)));
|
|
2865
2866
|
throw error;
|
|
2866
2867
|
}
|
|
2867
2868
|
}
|
|
2869
|
+
/**
|
|
2870
|
+
* Issue WebSocket upgrade fetches, retrying transient 503 responses with
|
|
2871
|
+
* exponential backoff (3s → 6s → 12s → … capped at 30s) until either
|
|
2872
|
+
* the upgrade succeeds, a non-503 status is returned, or the retry budget
|
|
2873
|
+
* runs out. Mirrors `WebSocketTransport.fetchUpgradeWithRetry` so both
|
|
2874
|
+
* transports behave the same way during container startup.
|
|
2875
|
+
*/
|
|
2876
|
+
async fetchUpgradeWithRetry() {
|
|
2877
|
+
const retryTimeoutMs = this.retryTimeoutMs;
|
|
2878
|
+
const startTime = Date.now();
|
|
2879
|
+
let attempt = 0;
|
|
2880
|
+
while (true) {
|
|
2881
|
+
const response = await this.fetchUpgradeAttempt();
|
|
2882
|
+
if (response.status !== 503) return response;
|
|
2883
|
+
const remaining = retryTimeoutMs - (Date.now() - startTime);
|
|
2884
|
+
if (remaining <= MIN_TIME_FOR_RETRY_MS) return response;
|
|
2885
|
+
const delay = Math.min(3e3 * 2 ** attempt, MAX_RETRY_BACKOFF_MS);
|
|
2886
|
+
this.logger.info("ContainerControlConnection upgrade returned 503, retrying", {
|
|
2887
|
+
attempt: attempt + 1,
|
|
2888
|
+
delayMs: delay,
|
|
2889
|
+
remainingSec: Math.floor(remaining / 1e3)
|
|
2890
|
+
});
|
|
2891
|
+
await this.sleep(delay);
|
|
2892
|
+
attempt++;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
/**
|
|
2896
|
+
* Single WebSocket-upgrade fetch attempt. Owns its own AbortController so
|
|
2897
|
+
* each retry gets a fresh per-attempt connect timeout independent of the
|
|
2898
|
+
* total retry budget.
|
|
2899
|
+
*/
|
|
2900
|
+
async fetchUpgradeAttempt() {
|
|
2901
|
+
const controller = new AbortController();
|
|
2902
|
+
const timeout = setTimeout(() => controller.abort(), DEFAULT_CONNECT_TIMEOUT_MS);
|
|
2903
|
+
try {
|
|
2904
|
+
const url = `http://localhost:${this.port}/rpc`;
|
|
2905
|
+
const request = new Request(url, {
|
|
2906
|
+
headers: {
|
|
2907
|
+
Upgrade: "websocket",
|
|
2908
|
+
Connection: "Upgrade"
|
|
2909
|
+
},
|
|
2910
|
+
signal: controller.signal
|
|
2911
|
+
});
|
|
2912
|
+
return await this.containerStub.fetch(request);
|
|
2913
|
+
} finally {
|
|
2914
|
+
clearTimeout(timeout);
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
sleep(ms) {
|
|
2918
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2919
|
+
}
|
|
2868
2920
|
};
|
|
2869
2921
|
/**
|
|
2870
2922
|
* RPC transport that queues sends and blocks receives until a WebSocket
|
|
@@ -3093,7 +3145,8 @@ var ContainerControlClient = class {
|
|
|
3093
3145
|
this.connOptions = {
|
|
3094
3146
|
stub: options.stub,
|
|
3095
3147
|
port: options.port,
|
|
3096
|
-
logger: options.logger
|
|
3148
|
+
logger: options.logger,
|
|
3149
|
+
retryTimeoutMs: options.retryTimeoutMs
|
|
3097
3150
|
};
|
|
3098
3151
|
this.idleDisconnectMs = options.idleDisconnectMs ?? DEFAULT_IDLE_DISCONNECT_MS;
|
|
3099
3152
|
this.busyPollIntervalMs = options.busyPollIntervalMs ?? BUSY_POLL_INTERVAL_MS;
|
|
@@ -3226,7 +3279,15 @@ var ContainerControlClient = class {
|
|
|
3226
3279
|
get interpreter() {
|
|
3227
3280
|
return wrapStub(this.getConnection().rpc().interpreter, this.renewActivity);
|
|
3228
3281
|
}
|
|
3229
|
-
|
|
3282
|
+
/**
|
|
3283
|
+
* Update the 503 upgrade-retry budget. Applies to the current connection
|
|
3284
|
+
* (if any) and is remembered for any future connections created after the
|
|
3285
|
+
* client is torn down and reconnected.
|
|
3286
|
+
*/
|
|
3287
|
+
setRetryTimeoutMs(ms) {
|
|
3288
|
+
this.connOptions.retryTimeoutMs = ms;
|
|
3289
|
+
this.conn?.setRetryTimeoutMs(ms);
|
|
3290
|
+
}
|
|
3230
3291
|
getTransportMode() {
|
|
3231
3292
|
return "rpc";
|
|
3232
3293
|
}
|
|
@@ -4196,7 +4257,7 @@ function isLocalhostPattern(hostname) {
|
|
|
4196
4257
|
* This file is auto-updated by .github/changeset-version.ts during releases
|
|
4197
4258
|
* DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
|
|
4198
4259
|
*/
|
|
4199
|
-
const SDK_VERSION = "0.
|
|
4260
|
+
const SDK_VERSION = "0.10.0";
|
|
4200
4261
|
|
|
4201
4262
|
//#endregion
|
|
4202
4263
|
//#region src/sandbox.ts
|
|
@@ -4528,6 +4589,7 @@ var Sandbox = class Sandbox extends Container {
|
|
|
4528
4589
|
stub: this,
|
|
4529
4590
|
port: 3e3,
|
|
4530
4591
|
logger: this.logger,
|
|
4592
|
+
retryTimeoutMs: this.computeRetryTimeoutMs(),
|
|
4531
4593
|
onActivity: () => {
|
|
4532
4594
|
this.renewActivityTimeout();
|
|
4533
4595
|
},
|
|
@@ -7170,9 +7232,18 @@ var Sandbox = class Sandbox extends Container {
|
|
|
7170
7232
|
sizeBytes = createResult.sizeBytes;
|
|
7171
7233
|
const r2Key = `${BACKUP_STORAGE_PREFIX}/${backupId}/${BACKUP_ARCHIVE_OBJECT_NAME}`;
|
|
7172
7234
|
const metaKey = `${BACKUP_STORAGE_PREFIX}/${backupId}/${BACKUP_METADATA_OBJECT_NAME}`;
|
|
7173
|
-
const
|
|
7174
|
-
const
|
|
7175
|
-
|
|
7235
|
+
const archiveStream = await this.client.files.readFileStream(archivePath, backupSession);
|
|
7236
|
+
const sseDecoded = new ReadableStream({ async start(controller) {
|
|
7237
|
+
try {
|
|
7238
|
+
for await (const chunk of streamFile(archiveStream)) if (chunk instanceof Uint8Array) controller.enqueue(chunk);
|
|
7239
|
+
controller.close();
|
|
7240
|
+
} catch (err) {
|
|
7241
|
+
controller.error(err);
|
|
7242
|
+
}
|
|
7243
|
+
} });
|
|
7244
|
+
const fixedStream = new FixedLengthStream(createResult.sizeBytes);
|
|
7245
|
+
sseDecoded.pipeTo(fixedStream.writable).catch(() => {});
|
|
7246
|
+
await bucket.put(r2Key, fixedStream.readable);
|
|
7176
7247
|
const head = await bucket.head(r2Key);
|
|
7177
7248
|
if (!head || head.size !== createResult.sizeBytes) throw new BackupCreateError({
|
|
7178
7249
|
message: `Upload verification failed: expected ${createResult.sizeBytes} bytes, got ${head?.size ?? 0}`,
|
|
@@ -7450,20 +7521,35 @@ var Sandbox = class Sandbox extends Container {
|
|
|
7450
7521
|
});
|
|
7451
7522
|
backupSession = await this.ensureBackupSession();
|
|
7452
7523
|
const archivePath = `${BACKUP_CONTAINER_DIR}/${id}.sqsh`;
|
|
7453
|
-
const archiveBuffer = await archiveObject.arrayBuffer();
|
|
7454
|
-
const base64Content = Buffer.from(archiveBuffer).toString("base64");
|
|
7455
7524
|
await this.execWithSession(`mkdir -p ${BACKUP_CONTAINER_DIR}`, backupSession, { origin: "internal" });
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7525
|
+
if (this.transport === "rpc") {
|
|
7526
|
+
const body = archiveObject.body;
|
|
7527
|
+
if (!body) throw new BackupRestoreError({
|
|
7528
|
+
message: `R2 archive object has no body stream for backup ${id}`,
|
|
7529
|
+
code: ErrorCode.BACKUP_RESTORE_FAILED,
|
|
7530
|
+
httpStatus: 500,
|
|
7531
|
+
context: {
|
|
7532
|
+
dir,
|
|
7533
|
+
backupId: id
|
|
7534
|
+
},
|
|
7535
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
7536
|
+
});
|
|
7537
|
+
await this.client.writeFileStream(archivePath, body, backupSession);
|
|
7538
|
+
} else {
|
|
7539
|
+
const archiveBuffer = await archiveObject.arrayBuffer();
|
|
7540
|
+
const base64Content = Buffer.from(archiveBuffer).toString("base64");
|
|
7541
|
+
const writeResult = await this.client.files.writeFile(archivePath, base64Content, backupSession, { encoding: "base64" });
|
|
7542
|
+
if (!writeResult.success) throw new BackupRestoreError({
|
|
7543
|
+
message: `Failed to write backup archive to ${archivePath}: ${"error" in writeResult && typeof writeResult.error === "object" && writeResult.error !== null && "message" in writeResult.error && typeof writeResult.error.message === "string" ? writeResult.error.message : `File write returned success: false for '${archivePath}'`}`,
|
|
7544
|
+
code: ErrorCode.BACKUP_RESTORE_FAILED,
|
|
7545
|
+
httpStatus: 500,
|
|
7546
|
+
context: {
|
|
7547
|
+
dir,
|
|
7548
|
+
backupId: id
|
|
7549
|
+
},
|
|
7550
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
7551
|
+
});
|
|
7552
|
+
}
|
|
7467
7553
|
const extractResult = await this.execWithSession(`/usr/bin/unsquashfs -f -d ${shellEscape(dir)} ${shellEscape(archivePath)}`, backupSession, { origin: "internal" });
|
|
7468
7554
|
if (extractResult.exitCode !== 0) throw new BackupRestoreError({
|
|
7469
7555
|
message: `unsquashfs extraction failed (exit code ${extractResult.exitCode}): ${extractResult.stderr}`,
|
|
@@ -7506,4 +7592,4 @@ var Sandbox = class Sandbox extends Container {
|
|
|
7506
7592
|
|
|
7507
7593
|
//#endregion
|
|
7508
7594
|
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 };
|
|
7509
|
-
//# sourceMappingURL=sandbox-
|
|
7595
|
+
//# sourceMappingURL=sandbox-2bHZZmy5.js.map
|