@cloudflare/sandbox 0.9.4 → 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 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:20-slim AS pruner
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:20-slim AS builder
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 20 LTS from official Node image
130
- COPY --from=node:20-slim /usr/local/bin/node /usr/local/bin/node
131
- COPY --from=node:20-slim /usr/local/lib/node_modules /usr/local/lib/node_modules
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
 
@@ -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-CdWjEUHl.js";
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.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-CdWjEUHl.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-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 };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/opencode/types.ts","../../src/opencode/opencode.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAOiB,UAAA,eAAA,CAAe;EAcf;EAaA,IAAA,CAAA,EAAA,MAAA;EAAyB;EAEhC,SAAA,CAAA,EAAA,MAAA;EAEA;EAAc,MAAA,CAAA,EAzBb,MAyBa;EAMX;EAEc,GAAA,CAAA,EA/BnB,MA+BmB,CAAA,MAAA,EAAA,MAAA,CAAA;;;;;UAzBV,cAAA;;;ECsSK;EACX,GAAA,EAAA,MAAA;EACC;EACD,KAAA,EAAA,EDnSA,OCmSA,CAAA,IAAA,CAAA;;;AAqEX;;;AAEY,UDnWK,cCmWL,CAAA,UDnW8B,cCmW9B,CAAA,CAAA;EACc;EAAf,MAAA,EDlWD,OCkWC;EAAR;EAAO,MAAA,EDhWA,cCgWA;AA0BV;;;;AAIW,cDxXE,oBAAA,SAA6B,KAAA,CCwX/B;EAAR,SAAA,IAAA,EAAA,yBAAA;EAAO,SAAA,OAAA,EDtXiB,sBCsXjB;EAmDM,WAAA,CAAA,OAAe,EAAA,MAAA,EAAA,OAAA,EDralB,sBCqakB,EAAA,OAAA,CAAA,EDpajB,YCoaiB;;;;;;;ADhd/B;AAcA;AAaA;;;;;AAUA;;;;;;;;;AC+QA;;;;;;AAwEA;;;;;;;;AA6BA;;;;;;;AAuDA;;;;;;AAIc,iBAhKQ,oBAAA,CAgKR,OAAA,EA/JH,OA+JG,CAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EA9JF,eA8JE,CAAA,EA7JX,OA6JW,CA7JH,cA6JG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAxFQ,yBAAyB,yBACpC,4BACC,kBACT,QAAQ,eAAe;;;;;;;;iBA0BV,qBAAA,UACL,kBACA,0BACD,iBACP,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmDK,eAAA,UACL,kBACA,0BACD,iBACP,WAAW,QAAQ"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/opencode/types.ts","../../src/opencode/opencode.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAOiB,UAAA,eAAA,CAMN;EAQM;EAaA,IAAA,CAAA,EAAA,MAAA;EAAyB;EAEhC,SAAA,CAAA,EAAA,MAAA;EAEA;EAAc,MAAA,CAAA,EAzBb,MAyBa;EAMX;EAEc,GAAA,CAAA,EA/BnB,MA+BmB,CAAA,MAAA,EAAA,MAAA,CAAA;;;;;UAzBV,cAAA;;;ECsSK;EACX,GAAA,EAAA,MAAA;EACC;EACD,KAAA,EAAA,EDnSA,OCmSA,CAAA,IAAA,CAAA;;;AAqEX;;;AAEY,UDnWK,cCmWL,CAAA,UDnW8B,cCmW9B,CAAA,CAAA;EACc;EAAf,MAAA,EDlWD,OCkWC;EAAR;EAAO,MAAA,EDhWA,cCgWA;AA0BV;;;;AAIW,cDxXE,oBAAA,SAA6B,KAAA,CCwX/B;EAAR,SAAA,IAAA,EAAA,yBAAA;EAAO,SAAA,OAAA,EDtXiB,sBCsXjB;EAmDM,WAAA,CAAA,OAAe,EAAA,MAAA,EAAA,OAAA,EDralB,sBCqakB,EAAA,OAAA,CAAA,EDpajB,YCoaiB;;;;;;;ADhd/B;AAcA;AAaA;;;;;AAUA;;;;;;;;;AC+QA;;;;;;AAwEA;;;;;;;;AA6BA;;;;;;;AAuDA;;;;;;AAIc,iBAhKQ,oBAAA,CAgKR,OAAA,EA/JH,OA+JG,CAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EA9JF,eA8JE,CAAA,EA7JX,OA6JW,CA7JH,cA6JG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAxFQ,yBAAyB,yBACpC,4BACC,kBACT,QAAQ,eAAe;;;;;;;;iBA0BV,qBAAA,UACL,kBACA,0BACD,iBACP,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmDK,eAAA,UACL,kBACA,0BACD,iBACP,WAAW,QAAQ"}
@@ -4257,7 +4257,7 @@ function isLocalhostPattern(hostname) {
4257
4257
  * This file is auto-updated by .github/changeset-version.ts during releases
4258
4258
  * DO NOT EDIT MANUALLY - Changes will be overwritten on the next version bump
4259
4259
  */
4260
- const SDK_VERSION = "0.9.4";
4260
+ const SDK_VERSION = "0.10.0";
4261
4261
 
4262
4262
  //#endregion
4263
4263
  //#region src/sandbox.ts
@@ -7232,9 +7232,18 @@ var Sandbox = class Sandbox extends Container {
7232
7232
  sizeBytes = createResult.sizeBytes;
7233
7233
  const r2Key = `${BACKUP_STORAGE_PREFIX}/${backupId}/${BACKUP_ARCHIVE_OBJECT_NAME}`;
7234
7234
  const metaKey = `${BACKUP_STORAGE_PREFIX}/${backupId}/${BACKUP_METADATA_OBJECT_NAME}`;
7235
- const { content } = await collectFile(await this.client.files.readFileStream(archivePath, backupSession));
7236
- const archiveData = content instanceof Uint8Array ? content : new TextEncoder().encode(content);
7237
- await bucket.put(r2Key, archiveData);
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);
7238
7247
  const head = await bucket.head(r2Key);
7239
7248
  if (!head || head.size !== createResult.sizeBytes) throw new BackupCreateError({
7240
7249
  message: `Upload verification failed: expected ${createResult.sizeBytes} bytes, got ${head?.size ?? 0}`,
@@ -7512,20 +7521,35 @@ var Sandbox = class Sandbox extends Container {
7512
7521
  });
7513
7522
  backupSession = await this.ensureBackupSession();
7514
7523
  const archivePath = `${BACKUP_CONTAINER_DIR}/${id}.sqsh`;
7515
- const archiveBuffer = await archiveObject.arrayBuffer();
7516
- const base64Content = Buffer.from(archiveBuffer).toString("base64");
7517
7524
  await this.execWithSession(`mkdir -p ${BACKUP_CONTAINER_DIR}`, backupSession, { origin: "internal" });
7518
- const writeResult = await this.client.files.writeFile(archivePath, base64Content, backupSession, { encoding: "base64" });
7519
- if (!writeResult.success) throw new BackupRestoreError({
7520
- 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}'`}`,
7521
- code: ErrorCode.BACKUP_RESTORE_FAILED,
7522
- httpStatus: 500,
7523
- context: {
7524
- dir,
7525
- backupId: id
7526
- },
7527
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
7528
- });
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
+ }
7529
7553
  const extractResult = await this.execWithSession(`/usr/bin/unsquashfs -f -d ${shellEscape(dir)} ${shellEscape(archivePath)}`, backupSession, { origin: "internal" });
7530
7554
  if (extractResult.exitCode !== 0) throw new BackupRestoreError({
7531
7555
  message: `unsquashfs extraction failed (exit code ${extractResult.exitCode}): ${extractResult.stderr}`,
@@ -7568,4 +7592,4 @@ var Sandbox = class Sandbox extends Container {
7568
7592
 
7569
7593
  //#endregion
7570
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 };
7571
- //# sourceMappingURL=sandbox-CdWjEUHl.js.map
7595
+ //# sourceMappingURL=sandbox-2bHZZmy5.js.map