@cloudflare/sandbox 0.0.0-0b4cc05 → 0.0.0-104f455
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/CHANGELOG.md +34 -0
- package/Dockerfile +12 -48
- package/README.md +0 -2
- package/dist/{chunk-U2M5GSMU.js → chunk-2P3MDMNJ.js} +178 -31
- package/dist/chunk-2P3MDMNJ.js.map +1 -0
- package/dist/chunk-JXZMAU2C.js +559 -0
- package/dist/chunk-JXZMAU2C.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +22 -11
- package/dist/index.js.map +1 -1
- package/dist/interpreter.d.ts +1 -1
- package/dist/interpreter.js +1 -1
- package/dist/request-handler.d.ts +1 -1
- package/dist/request-handler.js +2 -2
- package/dist/{sandbox-Cyuj5F-M.d.ts → sandbox-CZTMzV2R.d.ts} +9 -1
- package/dist/sandbox.d.ts +1 -1
- package/dist/sandbox.js +2 -2
- package/package.json +4 -2
- package/src/sandbox.ts +50 -11
- package/dist/chunk-BCJ7SF3Q.js +0 -117
- package/dist/chunk-BCJ7SF3Q.js.map +0 -1
- package/dist/chunk-U2M5GSMU.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @cloudflare/sandbox
|
|
2
2
|
|
|
3
|
+
## 0.4.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#125](https://github.com/cloudflare/sandbox-sdk/pull/125) [`fddccfd`](https://github.com/cloudflare/sandbox-sdk/commit/fddccfdce8204ce2aa7dadc0ad9fb2acbdeaec51) Thanks [@whoiskatrin](https://github.com/whoiskatrin)! - add docker image to pkg workflow
|
|
8
|
+
|
|
9
|
+
## 0.4.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#114](https://github.com/cloudflare/sandbox-sdk/pull/114) [`8c1f440`](https://github.com/cloudflare/sandbox-sdk/commit/8c1f440ad6fd89a5c69f9ca9d055ad9b183dd1c3) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Debloat base docker image (2.63GB → 1.03GB)
|
|
14
|
+
|
|
15
|
+
## 0.4.2
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [`e53d7e7`](https://github.com/cloudflare/sandbox-sdk/commit/e53d7e7ce185f79bdd899029bb532e9651ae7ba5) Thanks [@threepointone](https://github.com/threepointone)! - fix build by inlining repo/shared
|
|
20
|
+
|
|
21
|
+
## 0.4.1
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [#111](https://github.com/cloudflare/sandbox-sdk/pull/111) [`1b5496b`](https://github.com/cloudflare/sandbox-sdk/commit/1b5496bfceaee53c31911b409476ea87bebffe4c) Thanks [@threepointone](https://github.com/threepointone)! - trigger a release
|
|
26
|
+
|
|
27
|
+
## 0.4.0
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- [#95](https://github.com/cloudflare/sandbox-sdk/pull/95) [`7aee736`](https://github.com/cloudflare/sandbox-sdk/commit/7aee736bf07a4bf9020e2109bdaaa70214d52a01) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Rewrite SDK with cleaner design patterns and tests. Remove the unnecessary isolation cruft and fix foundational issues with streaming, sessions, validations and error handling. Cover the SDK with unit & e2e tests.
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- [#106](https://github.com/cloudflare/sandbox-sdk/pull/106) [`da947cd`](https://github.com/cloudflare/sandbox-sdk/commit/da947cd9543fc99831eefb1e8741fc905cb8fa42) Thanks [@jahands](https://github.com/jahands)! - fix examples failing to deploy and prevent committing node_modules
|
|
36
|
+
|
|
3
37
|
## 0.3.3
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
package/Dockerfile
CHANGED
|
@@ -56,46 +56,27 @@ COPY --from=builder /app/tooling ./tooling
|
|
|
56
56
|
RUN npm ci --production
|
|
57
57
|
|
|
58
58
|
# ============================================================================
|
|
59
|
-
# Stage 4: Runtime - Ubuntu 22.04 with
|
|
59
|
+
# Stage 4: Runtime - Ubuntu 22.04 with only runtime dependencies
|
|
60
60
|
# ============================================================================
|
|
61
61
|
FROM ubuntu:22.04 AS runtime
|
|
62
62
|
|
|
63
63
|
# Prevent interactive prompts during package installation
|
|
64
64
|
ENV DEBIAN_FRONTEND=noninteractive
|
|
65
65
|
|
|
66
|
-
# Install essential
|
|
67
|
-
RUN apt-get update && apt-get install -y \
|
|
68
|
-
# Basic utilities
|
|
66
|
+
# Install essential runtime packages
|
|
67
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
69
68
|
curl \
|
|
70
69
|
wget \
|
|
70
|
+
ca-certificates \
|
|
71
|
+
python3.11 \
|
|
72
|
+
python3-pip \
|
|
73
|
+
python3.11-venv \
|
|
74
|
+
procps \
|
|
71
75
|
git \
|
|
72
76
|
unzip \
|
|
73
77
|
zip \
|
|
74
|
-
file \
|
|
75
|
-
# Process management
|
|
76
|
-
procps \
|
|
77
|
-
htop \
|
|
78
|
-
# Build tools
|
|
79
|
-
build-essential \
|
|
80
|
-
pkg-config \
|
|
81
|
-
# Network tools
|
|
82
|
-
net-tools \
|
|
83
|
-
iputils-ping \
|
|
84
|
-
dnsutils \
|
|
85
|
-
# Text processing
|
|
86
78
|
jq \
|
|
87
|
-
|
|
88
|
-
nano \
|
|
89
|
-
# Python dependencies
|
|
90
|
-
python3.11 \
|
|
91
|
-
python3.11-dev \
|
|
92
|
-
python3-pip \
|
|
93
|
-
python3.11-venv \
|
|
94
|
-
# Other useful tools
|
|
95
|
-
ca-certificates \
|
|
96
|
-
gnupg \
|
|
97
|
-
lsb-release \
|
|
98
|
-
strace \
|
|
79
|
+
file \
|
|
99
80
|
&& rm -rf /var/lib/apt/lists/*
|
|
100
81
|
|
|
101
82
|
# Set Python 3.11 as default python3
|
|
@@ -108,13 +89,6 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
|
108
89
|
|
|
109
90
|
# Install Bun runtime from official image
|
|
110
91
|
COPY --from=oven/bun:1 /usr/local/bin/bun /usr/local/bin/bun
|
|
111
|
-
COPY --from=oven/bun:1 /usr/local/bin/bunx /usr/local/bin/bunx
|
|
112
|
-
|
|
113
|
-
# Install development tools globally
|
|
114
|
-
RUN npm install -g \
|
|
115
|
-
wrangler \
|
|
116
|
-
vite \
|
|
117
|
-
opencode-ai
|
|
118
92
|
|
|
119
93
|
# Install essential Python packages for code execution
|
|
120
94
|
RUN pip3 install --no-cache-dir \
|
|
@@ -123,12 +97,6 @@ RUN pip3 install --no-cache-dir \
|
|
|
123
97
|
pandas \
|
|
124
98
|
ipython
|
|
125
99
|
|
|
126
|
-
# Verify installations
|
|
127
|
-
RUN python3 --version && \
|
|
128
|
-
node --version && \
|
|
129
|
-
npm --version && \
|
|
130
|
-
bun --version
|
|
131
|
-
|
|
132
100
|
# Set up runtime container server directory
|
|
133
101
|
WORKDIR /container-server
|
|
134
102
|
|
|
@@ -143,10 +111,9 @@ COPY --from=builder /app/packages/sandbox-container/src/runtime/executors/python
|
|
|
143
111
|
# Includes: @repo/shared, zod, esbuild (runtime dependencies)
|
|
144
112
|
COPY --from=prod-deps /app/node_modules ./node_modules
|
|
145
113
|
|
|
146
|
-
# Copy workspace packages
|
|
147
|
-
|
|
148
|
-
COPY --from=prod-deps /app/packages/shared ./packages/shared
|
|
149
|
-
COPY --from=prod-deps /app/tooling/typescript-config ./tooling/typescript-config
|
|
114
|
+
# Copy workspace packages
|
|
115
|
+
COPY --from=prod-deps /app/packages/shared/dist ./packages/shared/dist
|
|
116
|
+
COPY --from=prod-deps /app/packages/shared/package.json ./packages/shared/package.json
|
|
150
117
|
|
|
151
118
|
# Configure process pool sizes (can be overridden at runtime)
|
|
152
119
|
ENV PYTHON_POOL_MIN_SIZE=3
|
|
@@ -157,9 +124,6 @@ ENV TYPESCRIPT_POOL_MIN_SIZE=3
|
|
|
157
124
|
ENV TYPESCRIPT_POOL_MAX_SIZE=10
|
|
158
125
|
|
|
159
126
|
# Create clean workspace directory for user code
|
|
160
|
-
# Architecture:
|
|
161
|
-
# /container-server/ - SDK infrastructure (server, executors, dependencies)
|
|
162
|
-
# /workspace/ - User's clean workspace for their code
|
|
163
127
|
RUN mkdir -p /workspace
|
|
164
128
|
|
|
165
129
|
# Expose the application port (3000 for control)
|
package/README.md
CHANGED
|
@@ -10,8 +10,6 @@ The Sandbox SDK lets you run untrusted code safely in isolated containers. Execu
|
|
|
10
10
|
|
|
11
11
|
Perfect for AI code execution, interactive development environments, data analysis platforms, CI/CD systems, and any application that needs secure code execution at the edge.
|
|
12
12
|
|
|
13
|
-
> **Note:** The latest published version of the SDK is on the [v03 branch](https://github.com/cloudflare/sandbox-sdk/tree/v03). This main branch is currently the development version and is not yet published.
|
|
14
|
-
|
|
15
13
|
## Getting Started
|
|
16
14
|
|
|
17
15
|
### Prerequisites
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
CodeInterpreter
|
|
3
|
-
|
|
2
|
+
CodeInterpreter,
|
|
3
|
+
ResultImpl,
|
|
4
|
+
TraceContext,
|
|
5
|
+
createLogger,
|
|
6
|
+
createNoOpLogger,
|
|
7
|
+
runWithLogger
|
|
8
|
+
} from "./chunk-JXZMAU2C.js";
|
|
4
9
|
import {
|
|
5
10
|
SecurityError,
|
|
6
11
|
sanitizeSandboxId,
|
|
@@ -10,21 +15,135 @@ import {
|
|
|
10
15
|
parseSSEStream
|
|
11
16
|
} from "./chunk-EKSWCBCA.js";
|
|
12
17
|
|
|
13
|
-
// src/request-handler.ts
|
|
14
|
-
import { createLogger as createLogger2, TraceContext as TraceContext2 } from "@repo/shared";
|
|
15
|
-
|
|
16
18
|
// src/sandbox.ts
|
|
17
19
|
import { Container, getContainer } from "@cloudflare/containers";
|
|
18
|
-
import { createLogger, runWithLogger, TraceContext } from "@repo/shared";
|
|
19
|
-
|
|
20
|
-
// src/clients/base-client.ts
|
|
21
|
-
import { createNoOpLogger } from "@repo/shared";
|
|
22
20
|
|
|
23
|
-
//
|
|
24
|
-
|
|
21
|
+
// ../shared/dist/errors/codes.js
|
|
22
|
+
var ErrorCode = {
|
|
23
|
+
// File System Errors (404)
|
|
24
|
+
FILE_NOT_FOUND: "FILE_NOT_FOUND",
|
|
25
|
+
// Permission Errors (403)
|
|
26
|
+
PERMISSION_DENIED: "PERMISSION_DENIED",
|
|
27
|
+
// File System Errors (409)
|
|
28
|
+
FILE_EXISTS: "FILE_EXISTS",
|
|
29
|
+
// File System Errors (400)
|
|
30
|
+
IS_DIRECTORY: "IS_DIRECTORY",
|
|
31
|
+
NOT_DIRECTORY: "NOT_DIRECTORY",
|
|
32
|
+
// File System Errors (500)
|
|
33
|
+
NO_SPACE: "NO_SPACE",
|
|
34
|
+
TOO_MANY_FILES: "TOO_MANY_FILES",
|
|
35
|
+
RESOURCE_BUSY: "RESOURCE_BUSY",
|
|
36
|
+
READ_ONLY: "READ_ONLY",
|
|
37
|
+
NAME_TOO_LONG: "NAME_TOO_LONG",
|
|
38
|
+
TOO_MANY_LINKS: "TOO_MANY_LINKS",
|
|
39
|
+
FILESYSTEM_ERROR: "FILESYSTEM_ERROR",
|
|
40
|
+
// Command Errors (404)
|
|
41
|
+
COMMAND_NOT_FOUND: "COMMAND_NOT_FOUND",
|
|
42
|
+
// Command Errors (403/400)
|
|
43
|
+
COMMAND_PERMISSION_DENIED: "COMMAND_PERMISSION_DENIED",
|
|
44
|
+
INVALID_COMMAND: "INVALID_COMMAND",
|
|
45
|
+
// Command Errors (500)
|
|
46
|
+
COMMAND_EXECUTION_ERROR: "COMMAND_EXECUTION_ERROR",
|
|
47
|
+
STREAM_START_ERROR: "STREAM_START_ERROR",
|
|
48
|
+
// Process Errors (404)
|
|
49
|
+
PROCESS_NOT_FOUND: "PROCESS_NOT_FOUND",
|
|
50
|
+
// Process Errors (403/500)
|
|
51
|
+
PROCESS_PERMISSION_DENIED: "PROCESS_PERMISSION_DENIED",
|
|
52
|
+
PROCESS_ERROR: "PROCESS_ERROR",
|
|
53
|
+
// Port Errors (409)
|
|
54
|
+
PORT_ALREADY_EXPOSED: "PORT_ALREADY_EXPOSED",
|
|
55
|
+
PORT_IN_USE: "PORT_IN_USE",
|
|
56
|
+
// Port Errors (404)
|
|
57
|
+
PORT_NOT_EXPOSED: "PORT_NOT_EXPOSED",
|
|
58
|
+
// Port Errors (400)
|
|
59
|
+
INVALID_PORT_NUMBER: "INVALID_PORT_NUMBER",
|
|
60
|
+
INVALID_PORT: "INVALID_PORT",
|
|
61
|
+
// Port Errors (502/500)
|
|
62
|
+
SERVICE_NOT_RESPONDING: "SERVICE_NOT_RESPONDING",
|
|
63
|
+
PORT_OPERATION_ERROR: "PORT_OPERATION_ERROR",
|
|
64
|
+
// Port Errors (400)
|
|
65
|
+
CUSTOM_DOMAIN_REQUIRED: "CUSTOM_DOMAIN_REQUIRED",
|
|
66
|
+
// Git Errors (404)
|
|
67
|
+
GIT_REPOSITORY_NOT_FOUND: "GIT_REPOSITORY_NOT_FOUND",
|
|
68
|
+
GIT_BRANCH_NOT_FOUND: "GIT_BRANCH_NOT_FOUND",
|
|
69
|
+
// Git Errors (401)
|
|
70
|
+
GIT_AUTH_FAILED: "GIT_AUTH_FAILED",
|
|
71
|
+
// Git Errors (502)
|
|
72
|
+
GIT_NETWORK_ERROR: "GIT_NETWORK_ERROR",
|
|
73
|
+
// Git Errors (400)
|
|
74
|
+
INVALID_GIT_URL: "INVALID_GIT_URL",
|
|
75
|
+
// Git Errors (500)
|
|
76
|
+
GIT_CLONE_FAILED: "GIT_CLONE_FAILED",
|
|
77
|
+
GIT_CHECKOUT_FAILED: "GIT_CHECKOUT_FAILED",
|
|
78
|
+
GIT_OPERATION_FAILED: "GIT_OPERATION_FAILED",
|
|
79
|
+
// Code Interpreter Errors (503)
|
|
80
|
+
INTERPRETER_NOT_READY: "INTERPRETER_NOT_READY",
|
|
81
|
+
// Code Interpreter Errors (404)
|
|
82
|
+
CONTEXT_NOT_FOUND: "CONTEXT_NOT_FOUND",
|
|
83
|
+
// Code Interpreter Errors (500)
|
|
84
|
+
CODE_EXECUTION_ERROR: "CODE_EXECUTION_ERROR",
|
|
85
|
+
// Validation Errors (400)
|
|
86
|
+
VALIDATION_FAILED: "VALIDATION_FAILED",
|
|
87
|
+
// Generic Errors (400/500)
|
|
88
|
+
INVALID_JSON_RESPONSE: "INVALID_JSON_RESPONSE",
|
|
89
|
+
UNKNOWN_ERROR: "UNKNOWN_ERROR",
|
|
90
|
+
INTERNAL_ERROR: "INTERNAL_ERROR"
|
|
91
|
+
};
|
|
25
92
|
|
|
26
|
-
//
|
|
27
|
-
|
|
93
|
+
// ../shared/dist/errors/status-map.js
|
|
94
|
+
var ERROR_STATUS_MAP = {
|
|
95
|
+
// 404 Not Found
|
|
96
|
+
[ErrorCode.FILE_NOT_FOUND]: 404,
|
|
97
|
+
[ErrorCode.COMMAND_NOT_FOUND]: 404,
|
|
98
|
+
[ErrorCode.PROCESS_NOT_FOUND]: 404,
|
|
99
|
+
[ErrorCode.PORT_NOT_EXPOSED]: 404,
|
|
100
|
+
[ErrorCode.GIT_REPOSITORY_NOT_FOUND]: 404,
|
|
101
|
+
[ErrorCode.GIT_BRANCH_NOT_FOUND]: 404,
|
|
102
|
+
[ErrorCode.CONTEXT_NOT_FOUND]: 404,
|
|
103
|
+
// 400 Bad Request
|
|
104
|
+
[ErrorCode.IS_DIRECTORY]: 400,
|
|
105
|
+
[ErrorCode.NOT_DIRECTORY]: 400,
|
|
106
|
+
[ErrorCode.INVALID_COMMAND]: 400,
|
|
107
|
+
[ErrorCode.INVALID_PORT_NUMBER]: 400,
|
|
108
|
+
[ErrorCode.INVALID_PORT]: 400,
|
|
109
|
+
[ErrorCode.INVALID_GIT_URL]: 400,
|
|
110
|
+
[ErrorCode.CUSTOM_DOMAIN_REQUIRED]: 400,
|
|
111
|
+
[ErrorCode.INVALID_JSON_RESPONSE]: 400,
|
|
112
|
+
[ErrorCode.NAME_TOO_LONG]: 400,
|
|
113
|
+
[ErrorCode.VALIDATION_FAILED]: 400,
|
|
114
|
+
// 401 Unauthorized
|
|
115
|
+
[ErrorCode.GIT_AUTH_FAILED]: 401,
|
|
116
|
+
// 403 Forbidden
|
|
117
|
+
[ErrorCode.PERMISSION_DENIED]: 403,
|
|
118
|
+
[ErrorCode.COMMAND_PERMISSION_DENIED]: 403,
|
|
119
|
+
[ErrorCode.PROCESS_PERMISSION_DENIED]: 403,
|
|
120
|
+
[ErrorCode.READ_ONLY]: 403,
|
|
121
|
+
// 409 Conflict
|
|
122
|
+
[ErrorCode.FILE_EXISTS]: 409,
|
|
123
|
+
[ErrorCode.PORT_ALREADY_EXPOSED]: 409,
|
|
124
|
+
[ErrorCode.PORT_IN_USE]: 409,
|
|
125
|
+
[ErrorCode.RESOURCE_BUSY]: 409,
|
|
126
|
+
// 502 Bad Gateway
|
|
127
|
+
[ErrorCode.SERVICE_NOT_RESPONDING]: 502,
|
|
128
|
+
[ErrorCode.GIT_NETWORK_ERROR]: 502,
|
|
129
|
+
// 503 Service Unavailable
|
|
130
|
+
[ErrorCode.INTERPRETER_NOT_READY]: 503,
|
|
131
|
+
// 500 Internal Server Error
|
|
132
|
+
[ErrorCode.NO_SPACE]: 500,
|
|
133
|
+
[ErrorCode.TOO_MANY_FILES]: 500,
|
|
134
|
+
[ErrorCode.TOO_MANY_LINKS]: 500,
|
|
135
|
+
[ErrorCode.FILESYSTEM_ERROR]: 500,
|
|
136
|
+
[ErrorCode.COMMAND_EXECUTION_ERROR]: 500,
|
|
137
|
+
[ErrorCode.STREAM_START_ERROR]: 500,
|
|
138
|
+
[ErrorCode.PROCESS_ERROR]: 500,
|
|
139
|
+
[ErrorCode.PORT_OPERATION_ERROR]: 500,
|
|
140
|
+
[ErrorCode.GIT_CLONE_FAILED]: 500,
|
|
141
|
+
[ErrorCode.GIT_CHECKOUT_FAILED]: 500,
|
|
142
|
+
[ErrorCode.GIT_OPERATION_FAILED]: 500,
|
|
143
|
+
[ErrorCode.CODE_EXECUTION_ERROR]: 500,
|
|
144
|
+
[ErrorCode.UNKNOWN_ERROR]: 500,
|
|
145
|
+
[ErrorCode.INTERNAL_ERROR]: 500
|
|
146
|
+
};
|
|
28
147
|
|
|
29
148
|
// src/errors/classes.ts
|
|
30
149
|
var SandboxError = class extends Error {
|
|
@@ -600,7 +719,7 @@ var BaseHttpClient = class {
|
|
|
600
719
|
return await response.json();
|
|
601
720
|
} catch (error) {
|
|
602
721
|
const errorResponse = {
|
|
603
|
-
code:
|
|
722
|
+
code: ErrorCode.INVALID_JSON_RESPONSE,
|
|
604
723
|
message: `Invalid JSON response: ${error instanceof Error ? error.message : "Unknown parsing error"}`,
|
|
605
724
|
context: {},
|
|
606
725
|
httpStatus: response.status,
|
|
@@ -618,7 +737,7 @@ var BaseHttpClient = class {
|
|
|
618
737
|
errorData = await response.json();
|
|
619
738
|
} catch {
|
|
620
739
|
errorData = {
|
|
621
|
-
code:
|
|
740
|
+
code: ErrorCode.INTERNAL_ERROR,
|
|
622
741
|
message: `HTTP error! status: ${response.status}`,
|
|
623
742
|
context: { statusText: response.statusText },
|
|
624
743
|
httpStatus: response.status,
|
|
@@ -995,9 +1114,6 @@ var GitClient = class extends BaseHttpClient {
|
|
|
995
1114
|
};
|
|
996
1115
|
|
|
997
1116
|
// src/clients/interpreter-client.ts
|
|
998
|
-
import {
|
|
999
|
-
ResultImpl
|
|
1000
|
-
} from "@repo/shared";
|
|
1001
1117
|
var InterpreterClient = class extends BaseHttpClient {
|
|
1002
1118
|
maxRetries = 3;
|
|
1003
1119
|
retryDelayMs = 1e3;
|
|
@@ -1129,7 +1245,7 @@ var InterpreterClient = class extends BaseHttpClient {
|
|
|
1129
1245
|
return createErrorFromResponse(errorData);
|
|
1130
1246
|
} catch {
|
|
1131
1247
|
const errorResponse = {
|
|
1132
|
-
code:
|
|
1248
|
+
code: ErrorCode.INTERNAL_ERROR,
|
|
1133
1249
|
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
1134
1250
|
context: {},
|
|
1135
1251
|
httpStatus: response.status,
|
|
@@ -1473,9 +1589,12 @@ var SandboxClient = class {
|
|
|
1473
1589
|
};
|
|
1474
1590
|
|
|
1475
1591
|
// src/sandbox.ts
|
|
1476
|
-
function getSandbox(ns, id) {
|
|
1592
|
+
function getSandbox(ns, id, options) {
|
|
1477
1593
|
const stub = getContainer(ns, id);
|
|
1478
1594
|
stub.setSandboxName?.(id);
|
|
1595
|
+
if (options?.baseUrl) {
|
|
1596
|
+
stub.setBaseUrl(options.baseUrl);
|
|
1597
|
+
}
|
|
1479
1598
|
return stub;
|
|
1480
1599
|
}
|
|
1481
1600
|
var Sandbox = class extends Container {
|
|
@@ -1486,6 +1605,7 @@ var Sandbox = class extends Container {
|
|
|
1486
1605
|
client;
|
|
1487
1606
|
codeInterpreter;
|
|
1488
1607
|
sandboxName = null;
|
|
1608
|
+
baseUrl = null;
|
|
1489
1609
|
portTokens = /* @__PURE__ */ new Map();
|
|
1490
1610
|
defaultSession = null;
|
|
1491
1611
|
envVars = {};
|
|
@@ -1512,6 +1632,7 @@ var Sandbox = class extends Container {
|
|
|
1512
1632
|
this.codeInterpreter = new CodeInterpreter(this);
|
|
1513
1633
|
this.ctx.blockConcurrencyWhile(async () => {
|
|
1514
1634
|
this.sandboxName = await this.ctx.storage.get("sandboxName") || null;
|
|
1635
|
+
this.defaultSession = await this.ctx.storage.get("defaultSession") || null;
|
|
1515
1636
|
const storedTokens = await this.ctx.storage.get("portTokens") || {};
|
|
1516
1637
|
this.portTokens = /* @__PURE__ */ new Map();
|
|
1517
1638
|
for (const [portStr, token] of Object.entries(storedTokens)) {
|
|
@@ -1526,6 +1647,17 @@ var Sandbox = class extends Container {
|
|
|
1526
1647
|
await this.ctx.storage.put("sandboxName", name);
|
|
1527
1648
|
}
|
|
1528
1649
|
}
|
|
1650
|
+
// RPC method to set the base URL
|
|
1651
|
+
async setBaseUrl(baseUrl) {
|
|
1652
|
+
if (!this.baseUrl) {
|
|
1653
|
+
this.baseUrl = baseUrl;
|
|
1654
|
+
await this.ctx.storage.put("baseUrl", baseUrl);
|
|
1655
|
+
} else {
|
|
1656
|
+
if (this.baseUrl !== baseUrl) {
|
|
1657
|
+
throw new Error("Base URL already set and different from one previously provided");
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1529
1661
|
// RPC method to set environment variables
|
|
1530
1662
|
async setEnvVars(envVars) {
|
|
1531
1663
|
this.envVars = { ...this.envVars, ...envVars };
|
|
@@ -1581,17 +1713,32 @@ var Sandbox = class extends Container {
|
|
|
1581
1713
|
/**
|
|
1582
1714
|
* Ensure default session exists - lazy initialization
|
|
1583
1715
|
* This is called automatically by all public methods that need a session
|
|
1716
|
+
*
|
|
1717
|
+
* The session is persisted to Durable Object storage to survive hot reloads
|
|
1718
|
+
* during development. If a session already exists in the container after reload,
|
|
1719
|
+
* we reuse it instead of trying to create a new one.
|
|
1584
1720
|
*/
|
|
1585
1721
|
async ensureDefaultSession() {
|
|
1586
1722
|
if (!this.defaultSession) {
|
|
1587
1723
|
const sessionId = `sandbox-${this.sandboxName || "default"}`;
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1724
|
+
try {
|
|
1725
|
+
await this.client.utils.createSession({
|
|
1726
|
+
id: sessionId,
|
|
1727
|
+
env: this.envVars || {},
|
|
1728
|
+
cwd: "/workspace"
|
|
1729
|
+
});
|
|
1730
|
+
this.defaultSession = sessionId;
|
|
1731
|
+
await this.ctx.storage.put("defaultSession", sessionId);
|
|
1732
|
+
this.logger.debug("Default session initialized", { sessionId });
|
|
1733
|
+
} catch (error) {
|
|
1734
|
+
if (error?.message?.includes("already exists") || error?.message?.includes("Session")) {
|
|
1735
|
+
this.logger.debug("Reusing existing session after reload", { sessionId });
|
|
1736
|
+
this.defaultSession = sessionId;
|
|
1737
|
+
await this.ctx.storage.put("defaultSession", sessionId);
|
|
1738
|
+
} else {
|
|
1739
|
+
throw error;
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1595
1742
|
}
|
|
1596
1743
|
return this.defaultSession;
|
|
1597
1744
|
}
|
|
@@ -1869,7 +2016,7 @@ var Sandbox = class extends Container {
|
|
|
1869
2016
|
async exposePort(port, options) {
|
|
1870
2017
|
if (options.hostname.endsWith(".workers.dev")) {
|
|
1871
2018
|
const errorResponse = {
|
|
1872
|
-
code:
|
|
2019
|
+
code: ErrorCode.CUSTOM_DOMAIN_REQUIRED,
|
|
1873
2020
|
message: `Port exposure requires a custom domain. .workers.dev domains do not support wildcard subdomains required for port proxying.`,
|
|
1874
2021
|
context: { originalError: options.hostname },
|
|
1875
2022
|
httpStatus: 400,
|
|
@@ -2093,8 +2240,8 @@ var Sandbox = class extends Container {
|
|
|
2093
2240
|
|
|
2094
2241
|
// src/request-handler.ts
|
|
2095
2242
|
async function proxyToSandbox(request, env) {
|
|
2096
|
-
const traceId =
|
|
2097
|
-
const logger =
|
|
2243
|
+
const traceId = TraceContext.fromHeaders(request.headers) || TraceContext.generate();
|
|
2244
|
+
const logger = createLogger({
|
|
2098
2245
|
component: "sandbox-do",
|
|
2099
2246
|
traceId,
|
|
2100
2247
|
operation: "proxy"
|
|
@@ -2217,4 +2364,4 @@ export {
|
|
|
2217
2364
|
getSandbox,
|
|
2218
2365
|
Sandbox
|
|
2219
2366
|
};
|
|
2220
|
-
//# sourceMappingURL=chunk-
|
|
2367
|
+
//# sourceMappingURL=chunk-2P3MDMNJ.js.map
|