@cloudflare/sandbox 0.0.0-603d05f → 0.0.0-66cc85b
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 +36 -0
- package/Dockerfile +23 -24
- package/README.md +59 -6
- package/container_src/bun.lock +31 -77
- package/container_src/control-process.ts +1 -1
- package/container_src/handler/exec.ts +2 -2
- package/container_src/handler/file.ts +51 -0
- package/container_src/handler/session.ts +2 -2
- package/container_src/index.ts +43 -43
- package/container_src/interpreter-service.ts +276 -0
- package/container_src/isolation.ts +207 -33
- package/container_src/mime-processor.ts +1 -1
- package/container_src/package.json +4 -4
- package/container_src/runtime/executors/javascript/node_executor.ts +123 -0
- package/container_src/runtime/executors/python/ipython_executor.py +338 -0
- package/container_src/runtime/executors/typescript/ts_executor.ts +138 -0
- package/container_src/runtime/process-pool.ts +464 -0
- package/container_src/startup.sh +6 -79
- package/package.json +2 -2
- package/src/client.ts +39 -0
- package/src/errors.ts +15 -14
- package/src/file-stream.ts +162 -0
- package/src/index.ts +22 -5
- package/src/{jupyter-client.ts → interpreter-client.ts} +6 -3
- package/src/interpreter-types.ts +102 -95
- package/src/interpreter.ts +8 -8
- package/src/sandbox.ts +18 -5
- package/src/types.ts +69 -0
- package/container_src/jupyter-server.ts +0 -579
- package/container_src/jupyter-service.ts +0 -461
- package/container_src/jupyter_config.py +0 -48
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @cloudflare/sandbox
|
|
2
2
|
|
|
3
|
+
## 0.3.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#88](https://github.com/cloudflare/sandbox-sdk/pull/88) [`46eb4e6`](https://github.com/cloudflare/sandbox-sdk/commit/46eb4e6b6c671b682fc74f83563ccf5f316011cb) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Add binary file support with automatic MIME detection and streaming
|
|
8
|
+
|
|
9
|
+
## 0.3.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#86](https://github.com/cloudflare/sandbox-sdk/pull/86) [`feafd32`](https://github.com/cloudflare/sandbox-sdk/commit/feafd32a51f50dfaf4994bddcbfb56d46cada622) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Fix session reuse to reuse existing healthy session
|
|
14
|
+
|
|
15
|
+
## 0.3.3
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#83](https://github.com/cloudflare/sandbox-sdk/pull/83) [`eec5bb6`](https://github.com/cloudflare/sandbox-sdk/commit/eec5bb6203dd5d775b4b54e91c26de25eeb767ce) Thanks [@mikenomitch](https://github.com/mikenomitch)! - Bump containers package version
|
|
20
|
+
|
|
21
|
+
## 0.3.2
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [#76](https://github.com/cloudflare/sandbox-sdk/pull/76) [`ef9e320`](https://github.com/cloudflare/sandbox-sdk/commit/ef9e320dcef30e57797fef6ebd9a9383fa9720d9) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Replace Jupyter with lightweight interpreters for >90% faster cold starts for `.runCode` calls, while maintaining full code execution capabilities and rich output support.
|
|
26
|
+
|
|
27
|
+
## 0.3.1
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- [#71](https://github.com/cloudflare/sandbox-sdk/pull/71) [`fb3c9c2`](https://github.com/cloudflare/sandbox-sdk/commit/fb3c9c22242d9d4f157c26f547f1e697ef7875f9) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Bump containers package version
|
|
32
|
+
|
|
33
|
+
- [#70](https://github.com/cloudflare/sandbox-sdk/pull/70) [`e1fa354`](https://github.com/cloudflare/sandbox-sdk/commit/e1fa354ab1bc7b0e89db4901b67028ebf1a93d0a) Thanks [@ghostwriternr](https://github.com/ghostwriternr)! - Fix escaped quotes in file write operations
|
|
34
|
+
|
|
35
|
+
- [#68](https://github.com/cloudflare/sandbox-sdk/pull/68) [`69b91d1`](https://github.com/cloudflare/sandbox-sdk/commit/69b91d1a8f6afb63262cc381ea93e94a033ed5e8) Thanks [@CyrusNuevoDia](https://github.com/CyrusNuevoDia)! - Configurable timeouts via environment variables in isolation.ts
|
|
36
|
+
|
|
37
|
+
- [#66](https://github.com/cloudflare/sandbox-sdk/pull/66) [`eca93b9`](https://github.com/cloudflare/sandbox-sdk/commit/eca93b97e40fa0d3bd9dc27af2cc214ec355b696) Thanks [@peterp](https://github.com/peterp)! - Determine if the port is specified in the URL.
|
|
38
|
+
|
|
3
39
|
## 0.3.0
|
|
4
40
|
|
|
5
41
|
### Minor Changes
|
package/Dockerfile
CHANGED
|
@@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y \
|
|
|
13
13
|
git \
|
|
14
14
|
unzip \
|
|
15
15
|
zip \
|
|
16
|
+
file \
|
|
16
17
|
# Process management
|
|
17
18
|
procps \
|
|
18
19
|
htop \
|
|
@@ -51,24 +52,12 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
|
51
52
|
COPY --from=bun-source /usr/local/bin/bun /usr/local/bin/bun
|
|
52
53
|
COPY --from=bun-source /usr/local/bin/bunx /usr/local/bin/bunx
|
|
53
54
|
|
|
54
|
-
# Install
|
|
55
|
-
RUN pip3 install --no-cache-dir \
|
|
56
|
-
jupyter-server \
|
|
57
|
-
jupyter-client \
|
|
58
|
-
ipykernel \
|
|
59
|
-
orjson \
|
|
60
|
-
&& python3 -m ipykernel install --user --name python3
|
|
61
|
-
|
|
62
|
-
# Install scientific packages
|
|
55
|
+
# Install essential Python packages for code execution
|
|
63
56
|
RUN pip3 install --no-cache-dir \
|
|
64
57
|
matplotlib \
|
|
65
58
|
numpy \
|
|
66
59
|
pandas \
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# Install JavaScript kernel (ijavascript) - using E2B's fork
|
|
70
|
-
RUN npm install -g git+https://github.com/e2b-dev/ijavascript.git \
|
|
71
|
-
&& ijsinstall --install=global
|
|
60
|
+
ipython
|
|
72
61
|
|
|
73
62
|
# Set up container server directory
|
|
74
63
|
WORKDIR /container-server
|
|
@@ -77,9 +66,7 @@ WORKDIR /container-server
|
|
|
77
66
|
RUN python3 --version && \
|
|
78
67
|
node --version && \
|
|
79
68
|
npm --version && \
|
|
80
|
-
bun --version
|
|
81
|
-
jupyter --version && \
|
|
82
|
-
jupyter kernelspec list
|
|
69
|
+
bun --version
|
|
83
70
|
|
|
84
71
|
# Copy container source files to server directory
|
|
85
72
|
COPY container_src/package.json container_src/bun.lock ./
|
|
@@ -87,15 +74,27 @@ RUN bun install --frozen-lockfile
|
|
|
87
74
|
|
|
88
75
|
COPY container_src/ ./
|
|
89
76
|
|
|
90
|
-
# Compile TypeScript
|
|
91
|
-
|
|
92
|
-
RUN
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
# Compile TypeScript files using the locally installed TypeScript
|
|
78
|
+
RUN npx tsc control-process.ts --outDir . --module commonjs --target es2020 --esModuleInterop --skipLibCheck
|
|
79
|
+
RUN cd runtime/executors/javascript && npx tsc node_executor.ts --module commonjs --target es2020 --esModuleInterop --skipLibCheck
|
|
80
|
+
RUN cd runtime/executors/typescript && npx tsc ts_executor.ts --module commonjs --target es2020 --esModuleInterop --skipLibCheck
|
|
81
|
+
|
|
82
|
+
# Configure process pool sizes (can be overridden at runtime)
|
|
83
|
+
ENV PYTHON_POOL_MIN_SIZE=3
|
|
84
|
+
ENV PYTHON_POOL_MAX_SIZE=15
|
|
85
|
+
ENV JAVASCRIPT_POOL_MIN_SIZE=3
|
|
86
|
+
ENV JAVASCRIPT_POOL_MAX_SIZE=10
|
|
87
|
+
ENV TYPESCRIPT_POOL_MIN_SIZE=3
|
|
88
|
+
ENV TYPESCRIPT_POOL_MAX_SIZE=10
|
|
89
|
+
|
|
90
|
+
# Create clean workspace directory for user code
|
|
91
|
+
# Architecture:
|
|
92
|
+
# /container-server/ - SDK infrastructure (server, executors, dependencies)
|
|
93
|
+
# /workspace/ - User's clean workspace for their code
|
|
95
94
|
RUN mkdir -p /workspace
|
|
96
95
|
|
|
97
|
-
# Expose the application port (3000 for control
|
|
98
|
-
EXPOSE 3000
|
|
96
|
+
# Expose the application port (3000 for control)
|
|
97
|
+
EXPOSE 3000
|
|
99
98
|
|
|
100
99
|
# Make startup script executable
|
|
101
100
|
RUN chmod +x startup.sh
|
package/README.md
CHANGED
|
@@ -50,10 +50,11 @@ The Cloudflare Sandbox SDK enables you to run isolated code environments directl
|
|
|
50
50
|
- **🔒 Secure Isolation**: Each sandbox runs in its own container with full process isolation
|
|
51
51
|
- **⚡ Edge-Native**: Runs on Cloudflare's global network for low latency worldwide
|
|
52
52
|
- **📁 File System Access**: Read, write, and manage files within the sandbox
|
|
53
|
+
- **🖼️ Binary File Support**: Automatic MIME type detection and base64 encoding for images, PDFs, and other binary files
|
|
53
54
|
- **🔧 Command Execution**: Run any command or process inside the container
|
|
54
55
|
- **🌐 Preview URLs**: Expose services running in your sandbox via public URLs
|
|
55
56
|
- **🔄 Git Integration**: Clone repositories directly into sandboxes
|
|
56
|
-
- **🚀 Streaming Support**: Real-time output streaming for long-running commands
|
|
57
|
+
- **🚀 Streaming Support**: Real-time output streaming for long-running commands and file transfers
|
|
57
58
|
- **🎮 Session Management**: Maintain state across multiple operations
|
|
58
59
|
- **🧪 Code Interpreter**: Execute Python and JavaScript with rich outputs (charts, tables, formatted data)
|
|
59
60
|
- **📊 Multi-Language Support**: Persistent execution contexts for Python and JavaScript/TypeScript
|
|
@@ -72,7 +73,7 @@ npm install @cloudflare/sandbox
|
|
|
72
73
|
1. **Create a Dockerfile** (temporary requirement, will be removed in future releases):
|
|
73
74
|
|
|
74
75
|
```dockerfile
|
|
75
|
-
FROM docker.io/cloudflare/sandbox:0.3.
|
|
76
|
+
FROM docker.io/cloudflare/sandbox:0.3.5
|
|
76
77
|
|
|
77
78
|
# Expose the ports you want to expose
|
|
78
79
|
EXPOSE 3000
|
|
@@ -89,7 +90,7 @@ EXPOSE 3000
|
|
|
89
90
|
{
|
|
90
91
|
"class_name": "Sandbox",
|
|
91
92
|
"image": "./Dockerfile",
|
|
92
|
-
"max_instances":
|
|
93
|
+
"max_instances": 20
|
|
93
94
|
}
|
|
94
95
|
],
|
|
95
96
|
"durable_objects": {
|
|
@@ -189,11 +190,57 @@ await sandbox.writeFile("/workspace/app.js", "console.log('Hello!');");
|
|
|
189
190
|
|
|
190
191
|
#### `readFile(path, options?)`
|
|
191
192
|
|
|
192
|
-
Read a file from the sandbox.
|
|
193
|
+
Read a file from the sandbox with automatic binary detection.
|
|
193
194
|
|
|
194
195
|
```typescript
|
|
196
|
+
// Read text files
|
|
195
197
|
const file = await sandbox.readFile("/package.json");
|
|
196
|
-
console.log(file.content);
|
|
198
|
+
console.log(file.content); // UTF-8 text content
|
|
199
|
+
|
|
200
|
+
// Read binary files - automatically detected and base64 encoded
|
|
201
|
+
const image = await sandbox.readFile("/workspace/chart.png");
|
|
202
|
+
console.log(image.mimeType); // "image/png"
|
|
203
|
+
console.log(image.isBinary); // true
|
|
204
|
+
console.log(image.encoding); // "base64"
|
|
205
|
+
console.log(image.size); // File size in bytes
|
|
206
|
+
|
|
207
|
+
// Use the base64 content directly in data URLs
|
|
208
|
+
const dataUrl = `data:${image.mimeType};base64,${image.content}`;
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### `readFileStream(path)`
|
|
212
|
+
|
|
213
|
+
Stream large files efficiently with automatic chunking and encoding.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { streamFile, collectFile } from '@cloudflare/sandbox';
|
|
217
|
+
|
|
218
|
+
// Stream a large file
|
|
219
|
+
const stream = await sandbox.readFileStream("/large-video.mp4");
|
|
220
|
+
|
|
221
|
+
// Option 1: Process chunks as they arrive
|
|
222
|
+
for await (const chunk of streamFile(stream)) {
|
|
223
|
+
if (chunk instanceof Uint8Array) {
|
|
224
|
+
// Binary chunk - already decoded from base64
|
|
225
|
+
console.log(`Received ${chunk.byteLength} bytes`);
|
|
226
|
+
// Process binary data...
|
|
227
|
+
} else {
|
|
228
|
+
// Text chunk
|
|
229
|
+
console.log('Text:', chunk);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Option 2: Collect entire file into memory
|
|
234
|
+
const { content, metadata } = await collectFile(stream);
|
|
235
|
+
console.log(`MIME: ${metadata.mimeType}, Size: ${metadata.size} bytes`);
|
|
236
|
+
|
|
237
|
+
if (content instanceof Uint8Array) {
|
|
238
|
+
// Binary file - ready to save or process
|
|
239
|
+
await writeToStorage(content);
|
|
240
|
+
} else {
|
|
241
|
+
// Text file
|
|
242
|
+
console.log('Content:', content);
|
|
243
|
+
}
|
|
197
244
|
```
|
|
198
245
|
|
|
199
246
|
#### `gitCheckout(repoUrl, options?)`
|
|
@@ -241,7 +288,8 @@ console.log(result.stdout); // "production"
|
|
|
241
288
|
#### File System Methods
|
|
242
289
|
|
|
243
290
|
- `writeFile(path, content, options?)` - Write content to a file
|
|
244
|
-
- `readFile(path, options?)` - Read a file
|
|
291
|
+
- `readFile(path, options?)` - Read a file with automatic binary detection and base64 encoding
|
|
292
|
+
- `readFileStream(path)` - Stream large files efficiently with chunking
|
|
245
293
|
- `mkdir(path, options?)` - Create a directory
|
|
246
294
|
- `deleteFile(path)` - Delete a file
|
|
247
295
|
- `renameFile(oldPath, newPath)` - Rename a file
|
|
@@ -665,10 +713,15 @@ for await (const event of parseSSEStream<ExecEvent>(stream)) {
|
|
|
665
713
|
|
|
666
714
|
The SDK exports utilities for working with Server-Sent Event streams:
|
|
667
715
|
|
|
716
|
+
**Command Execution:**
|
|
668
717
|
- **`parseSSEStream<T>(stream)`** - Convert ReadableStream to typed AsyncIterable
|
|
669
718
|
- **`responseToAsyncIterable<T>(response)`** - Convert SSE Response to AsyncIterable
|
|
670
719
|
- **`asyncIterableToSSEStream<T>(iterable)`** - Convert AsyncIterable back to SSE stream
|
|
671
720
|
|
|
721
|
+
**File Streaming:**
|
|
722
|
+
- **`streamFile(stream, signal?)`** - Convert file SSE stream to AsyncIterable with automatic base64 decoding
|
|
723
|
+
- **`collectFile(stream, signal?)`** - Collect entire file from stream into memory
|
|
724
|
+
|
|
672
725
|
#### Advanced Streaming Examples
|
|
673
726
|
|
|
674
727
|
**CI/CD Build System:**
|
package/container_src/bun.lock
CHANGED
|
@@ -4,119 +4,73 @@
|
|
|
4
4
|
"": {
|
|
5
5
|
"name": "sandbox-server",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"
|
|
7
|
+
"esbuild": "^0.21.5",
|
|
8
8
|
"uuid": "^9.0.1",
|
|
9
|
-
"ws": "^8.16.0",
|
|
10
9
|
},
|
|
11
10
|
"devDependencies": {
|
|
11
|
+
"@types/node": "^20.0.0",
|
|
12
12
|
"@types/uuid": "^9.0.7",
|
|
13
|
-
"
|
|
13
|
+
"typescript": "^5.3.0",
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
"packages": {
|
|
18
|
-
"@
|
|
18
|
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
|
19
19
|
|
|
20
|
-
"@
|
|
20
|
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
|
21
21
|
|
|
22
|
-
"@
|
|
22
|
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
|
|
23
23
|
|
|
24
|
-
"@
|
|
24
|
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
|
|
25
25
|
|
|
26
|
-
"@
|
|
26
|
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
|
|
27
27
|
|
|
28
|
-
"@
|
|
28
|
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
|
|
29
29
|
|
|
30
|
-
"@
|
|
30
|
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
|
|
31
31
|
|
|
32
|
-
"@
|
|
32
|
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
|
|
33
33
|
|
|
34
|
-
"@
|
|
34
|
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
|
|
35
35
|
|
|
36
|
-
"@
|
|
36
|
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
|
|
37
37
|
|
|
38
|
-
"@
|
|
38
|
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
|
|
39
39
|
|
|
40
|
-
"@
|
|
40
|
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
|
|
41
41
|
|
|
42
|
-
"@
|
|
42
|
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
|
|
43
43
|
|
|
44
|
-
"@
|
|
44
|
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
|
|
45
45
|
|
|
46
|
-
"@
|
|
46
|
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
|
|
47
47
|
|
|
48
|
-
"@
|
|
48
|
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
|
|
49
49
|
|
|
50
|
-
"@
|
|
50
|
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
|
|
51
51
|
|
|
52
|
-
"@
|
|
52
|
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
|
|
53
53
|
|
|
54
|
-
"@
|
|
55
|
-
|
|
56
|
-
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
|
57
|
-
|
|
58
|
-
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
|
59
|
-
|
|
60
|
-
"compute-gcd": ["compute-gcd@1.2.1", "", { "dependencies": { "validate.io-array": "^1.0.3", "validate.io-function": "^1.0.2", "validate.io-integer-array": "^1.0.0" } }, "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg=="],
|
|
61
|
-
|
|
62
|
-
"compute-lcm": ["compute-lcm@1.1.2", "", { "dependencies": { "compute-gcd": "^1.2.1", "validate.io-array": "^1.0.3", "validate.io-function": "^1.0.2", "validate.io-integer-array": "^1.0.0" } }, "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ=="],
|
|
63
|
-
|
|
64
|
-
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
|
65
|
-
|
|
66
|
-
"fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="],
|
|
67
|
-
|
|
68
|
-
"isomorphic.js": ["isomorphic.js@0.2.5", "", {}, "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw=="],
|
|
69
|
-
|
|
70
|
-
"json-schema-compare": ["json-schema-compare@0.2.2", "", { "dependencies": { "lodash": "^4.17.4" } }, "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ=="],
|
|
71
|
-
|
|
72
|
-
"json-schema-merge-allof": ["json-schema-merge-allof@0.8.1", "", { "dependencies": { "compute-lcm": "^1.1.2", "json-schema-compare": "^0.2.2", "lodash": "^4.17.20" } }, "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w=="],
|
|
73
|
-
|
|
74
|
-
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
|
75
|
-
|
|
76
|
-
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
|
77
|
-
|
|
78
|
-
"jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="],
|
|
54
|
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
|
|
79
55
|
|
|
80
|
-
"
|
|
56
|
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
|
|
81
57
|
|
|
82
|
-
"
|
|
58
|
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
|
|
83
59
|
|
|
84
|
-
"
|
|
60
|
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
|
|
85
61
|
|
|
86
|
-
"
|
|
62
|
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
|
|
87
63
|
|
|
88
|
-
"
|
|
64
|
+
"@types/node": ["@types/node@20.19.16", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-VS6TTONVdgwJwtJr7U+ghEjpfmQdqehLLpg/iMYGOd1+ilaFjdBJwFuPggJ4EAYPDCzWfDUHoIxyVnu+tOWVuQ=="],
|
|
89
65
|
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
"react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="],
|
|
93
|
-
|
|
94
|
-
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
|
95
|
-
|
|
96
|
-
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
|
66
|
+
"@types/uuid": ["@types/uuid@9.0.8", "", {}, "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="],
|
|
97
67
|
|
|
98
|
-
"
|
|
68
|
+
"esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
|
|
99
69
|
|
|
100
|
-
"
|
|
70
|
+
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
|
101
71
|
|
|
102
|
-
"
|
|
72
|
+
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
|
103
73
|
|
|
104
74
|
"uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
|
|
105
|
-
|
|
106
|
-
"validate.io-array": ["validate.io-array@1.0.6", "", {}, "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg=="],
|
|
107
|
-
|
|
108
|
-
"validate.io-function": ["validate.io-function@1.0.2", "", {}, "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ=="],
|
|
109
|
-
|
|
110
|
-
"validate.io-integer": ["validate.io-integer@1.0.5", "", { "dependencies": { "validate.io-number": "^1.0.3" } }, "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ=="],
|
|
111
|
-
|
|
112
|
-
"validate.io-integer-array": ["validate.io-integer-array@1.0.0", "", { "dependencies": { "validate.io-array": "^1.0.3", "validate.io-integer": "^1.0.4" } }, "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA=="],
|
|
113
|
-
|
|
114
|
-
"validate.io-number": ["validate.io-number@1.0.3", "", {}, "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg=="],
|
|
115
|
-
|
|
116
|
-
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
|
117
|
-
|
|
118
|
-
"y-protocols": ["y-protocols@1.0.6", "", { "dependencies": { "lib0": "^0.2.85" }, "peerDependencies": { "yjs": "^13.0.0" } }, "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q=="],
|
|
119
|
-
|
|
120
|
-
"yjs": ["yjs@13.6.27", "", { "dependencies": { "lib0": "^0.2.99" } }, "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw=="],
|
|
121
75
|
}
|
|
122
76
|
}
|
|
@@ -654,7 +654,7 @@ async function handleControlMessage(msg: ControlMessage): Promise<void> {
|
|
|
654
654
|
*
|
|
655
655
|
* Creates either an isolated shell using 'unshare' or a regular bash shell.
|
|
656
656
|
* Isolation uses Linux namespaces (PID) to prevent the shell from:
|
|
657
|
-
* - Seeing control plane processes (
|
|
657
|
+
* - Seeing control plane processes (Bun server)
|
|
658
658
|
* - Accessing platform secrets in /proc/1/environ
|
|
659
659
|
* - Hijacking control plane ports
|
|
660
660
|
*/
|
|
@@ -204,6 +204,11 @@ export async function handleReadFileRequest(
|
|
|
204
204
|
path,
|
|
205
205
|
success: result.success,
|
|
206
206
|
timestamp: new Date().toISOString(),
|
|
207
|
+
// New metadata fields for binary file support
|
|
208
|
+
encoding: result.encoding,
|
|
209
|
+
isBinary: result.isBinary,
|
|
210
|
+
mimeType: result.mimeType,
|
|
211
|
+
size: result.size,
|
|
207
212
|
}),
|
|
208
213
|
{
|
|
209
214
|
headers: {
|
|
@@ -403,4 +408,50 @@ export async function handleListFilesRequest(
|
|
|
403
408
|
} catch (error) {
|
|
404
409
|
return createServerErrorResponse("handleListFilesRequest", error, corsHeaders);
|
|
405
410
|
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export async function handleReadFileStreamRequest(
|
|
414
|
+
req: Request,
|
|
415
|
+
corsHeaders: Record<string, string>,
|
|
416
|
+
sessionManager: SessionManager
|
|
417
|
+
): Promise<Response> {
|
|
418
|
+
try {
|
|
419
|
+
const body = (await req.json()) as ReadFileRequest;
|
|
420
|
+
const { path, sessionId } = body;
|
|
421
|
+
|
|
422
|
+
// Validate path
|
|
423
|
+
const pathError = validatePath(path);
|
|
424
|
+
if (pathError) {
|
|
425
|
+
return createPathErrorResponse(pathError, corsHeaders);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
console.log(`[Server] Streaming file: ${path}${sessionId ? ` in session: ${sessionId}` : ''}`);
|
|
429
|
+
|
|
430
|
+
// Get the appropriate session
|
|
431
|
+
const session = sessionId
|
|
432
|
+
? sessionManager.getSession(sessionId)
|
|
433
|
+
: await sessionManager.getOrCreateDefaultSession();
|
|
434
|
+
|
|
435
|
+
if (!session) {
|
|
436
|
+
return createServerErrorResponse(
|
|
437
|
+
"handleReadFileStreamRequest",
|
|
438
|
+
new Error(`Session '${sessionId}' not found`),
|
|
439
|
+
corsHeaders
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Create SSE stream
|
|
444
|
+
const stream = await session.readFileStreamOperation(path);
|
|
445
|
+
|
|
446
|
+
return new Response(stream, {
|
|
447
|
+
headers: {
|
|
448
|
+
"Content-Type": "text/event-stream",
|
|
449
|
+
"Cache-Control": "no-cache",
|
|
450
|
+
"Connection": "keep-alive",
|
|
451
|
+
...corsHeaders,
|
|
452
|
+
},
|
|
453
|
+
});
|
|
454
|
+
} catch (error) {
|
|
455
|
+
return createServerErrorResponse("handleReadFileStreamRequest", error, corsHeaders);
|
|
456
|
+
}
|
|
406
457
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SessionManager } from "../isolation";
|
|
2
|
-
import { CreateSessionRequest } from "../types";
|
|
1
|
+
import type { SessionManager } from "../isolation";
|
|
2
|
+
import type { CreateSessionRequest } from "../types";
|
|
3
3
|
|
|
4
4
|
export async function handleCreateSession(
|
|
5
5
|
req: Request,
|