@cloudflare/sandbox 0.12.0 → 0.12.2
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/README.md +1 -0
- package/dist/bridge/index.js +21 -17
- package/dist/bridge/index.js.map +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-Duj2gvUC.js → sandbox-BXMrasVs.js} +79 -78
- package/dist/sandbox-BXMrasVs.js.map +1 -0
- package/dist/{sandbox-D3N9M5EI.d.ts → sandbox-C8l-pMlL.d.ts} +9 -8
- package/dist/{sandbox-D3N9M5EI.d.ts.map → sandbox-C8l-pMlL.d.ts.map} +1 -1
- package/package.json +3 -3
- package/dist/sandbox-Duj2gvUC.js.map +0 -1
package/README.md
CHANGED
|
@@ -200,6 +200,7 @@ See the [examples directory](./examples) for complete working examples:
|
|
|
200
200
|
- [Claude Code](./examples/claude-code) - Run [Claude Code](https://claude.ai/code) headless on any repo
|
|
201
201
|
- [OpenAI Agents](./examples/openai-agents) - `Shell` and `Editor` tools for [OpenAI Agents SDK](https://openai.github.io/openai-agents-js/)
|
|
202
202
|
- [OpenCode](./examples/opencode) - [OpenCode](https://github.com/sst/opencode) web UI or [SDK](https://opencode.ai/docs/sdk/) in a sandbox
|
|
203
|
+
- [Git Repo Per Sandbox](./examples/git-repo-per-sandbox) - One Artifacts Git repo per sandbox
|
|
203
204
|
- [TypeScript Validator](./examples/typescript-validator) - Build with npm in sandbox, execute in [isolates](https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/)
|
|
204
205
|
|
|
205
206
|
## Status
|
package/dist/bridge/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../dist-B_eXrP83.js";
|
|
2
2
|
import "../errors-aRUdk9K8.js";
|
|
3
|
-
import { S as validateTunnelName, r as getSandbox, w as streamFile, x as validatePort, y as SandboxSecurityError } from "../sandbox-
|
|
3
|
+
import { S as validateTunnelName, r as getSandbox, w as streamFile, x as validatePort, y as SandboxSecurityError } from "../sandbox-BXMrasVs.js";
|
|
4
4
|
import { DurableObject, env } from "cloudflare:workers";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
|
|
@@ -454,7 +454,7 @@ const OPENAPI_SCHEMA = {
|
|
|
454
454
|
type: "string",
|
|
455
455
|
pattern: "^[a-zA-Z0-9._-]{1,128}$"
|
|
456
456
|
},
|
|
457
|
-
description: "Scope this operation to a specific session.
|
|
457
|
+
description: "Scope this operation to a specific session. If omitted, the operation runs without reusing shell state."
|
|
458
458
|
}],
|
|
459
459
|
requestBody: {
|
|
460
460
|
required: true,
|
|
@@ -618,7 +618,7 @@ const OPENAPI_SCHEMA = {
|
|
|
618
618
|
type: "string",
|
|
619
619
|
pattern: "^[a-zA-Z0-9._-]{1,128}$"
|
|
620
620
|
},
|
|
621
|
-
description: "Scope this operation to a specific session.
|
|
621
|
+
description: "Scope this operation to a specific session. If omitted, the operation runs without reusing shell state."
|
|
622
622
|
}
|
|
623
623
|
],
|
|
624
624
|
responses: {
|
|
@@ -694,7 +694,7 @@ const OPENAPI_SCHEMA = {
|
|
|
694
694
|
type: "string",
|
|
695
695
|
pattern: "^[a-zA-Z0-9._-]{1,128}$"
|
|
696
696
|
},
|
|
697
|
-
description: "Scope this operation to a specific session.
|
|
697
|
+
description: "Scope this operation to a specific session. If omitted, the operation runs without reusing shell state."
|
|
698
698
|
}
|
|
699
699
|
],
|
|
700
700
|
requestBody: {
|
|
@@ -794,7 +794,7 @@ const OPENAPI_SCHEMA = {
|
|
|
794
794
|
type: "string",
|
|
795
795
|
pattern: "^[a-zA-Z0-9._-]{1,128}$"
|
|
796
796
|
},
|
|
797
|
-
description: "Scope this
|
|
797
|
+
description: "Scope this PTY to a specific session."
|
|
798
798
|
}
|
|
799
799
|
],
|
|
800
800
|
responses: {
|
|
@@ -1767,6 +1767,10 @@ function esc(s) {
|
|
|
1767
1767
|
function getSandbox$1(ns, containerUUID) {
|
|
1768
1768
|
return getSandbox(ns, containerUUID);
|
|
1769
1769
|
}
|
|
1770
|
+
/** Bridge routes should not implicitly reuse the SDK's default shell session. */
|
|
1771
|
+
function getSandboxWithoutDefaultSession(ns, containerUUID) {
|
|
1772
|
+
return getSandbox(ns, containerUUID, { enableDefaultSession: false });
|
|
1773
|
+
}
|
|
1770
1774
|
function hasEndpoint(options) {
|
|
1771
1775
|
return "endpoint" in options && typeof options.endpoint === "string";
|
|
1772
1776
|
}
|
|
@@ -1910,7 +1914,7 @@ function createBridgeApp(config) {
|
|
|
1910
1914
|
return errorJson("Invalid JSON body", "invalid_request", 400);
|
|
1911
1915
|
}
|
|
1912
1916
|
if (!Array.isArray(body.argv) || body.argv.length === 0) return errorJson("argv must be a non-empty array", "invalid_request", 400);
|
|
1913
|
-
const sandbox =
|
|
1917
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
1914
1918
|
const rawSessionId = c.req.header("Session-Id");
|
|
1915
1919
|
let executor = sandbox;
|
|
1916
1920
|
if (rawSessionId) {
|
|
@@ -1983,7 +1987,7 @@ function createBridgeApp(config) {
|
|
|
1983
1987
|
if (!relativePath) return errorJson("file path must not be empty", "invalid_request", 400);
|
|
1984
1988
|
const resolvedPath = resolveWorkspacePath(`/${relativePath}`);
|
|
1985
1989
|
if (!resolvedPath) return errorJson("path must resolve to a location within /workspace", "invalid_request", 403);
|
|
1986
|
-
const sandbox =
|
|
1990
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
1987
1991
|
const rawSessionId = c.req.header("Session-Id");
|
|
1988
1992
|
let executor = sandbox;
|
|
1989
1993
|
if (rawSessionId) {
|
|
@@ -2010,7 +2014,7 @@ function createBridgeApp(config) {
|
|
|
2010
2014
|
if (!relativePath) return errorJson("file path must not be empty", "invalid_request", 400);
|
|
2011
2015
|
const resolvedPath = resolveWorkspacePath(`/${relativePath}`);
|
|
2012
2016
|
if (!resolvedPath) return errorJson("path must resolve to a location within /workspace", "invalid_request", 403);
|
|
2013
|
-
const sandbox =
|
|
2017
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2014
2018
|
const rawSessionId = c.req.header("Session-Id");
|
|
2015
2019
|
let executor = sandbox;
|
|
2016
2020
|
if (rawSessionId) {
|
|
@@ -2037,7 +2041,7 @@ function createBridgeApp(config) {
|
|
|
2037
2041
|
if (!validatePort(port)) return errorJson("Invalid port", "invalid_request", 400);
|
|
2038
2042
|
const options = parseTunnelOptions(await c.req.text());
|
|
2039
2043
|
if (options instanceof Response) return options;
|
|
2040
|
-
const sandbox =
|
|
2044
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2041
2045
|
try {
|
|
2042
2046
|
const tunnel = await sandbox.tunnels.get(port, options);
|
|
2043
2047
|
return c.json(tunnel);
|
|
@@ -2048,7 +2052,7 @@ function createBridgeApp(config) {
|
|
|
2048
2052
|
app.delete(`${apiPrefix}/sandbox/:id/tunnel/:port`, async (c) => {
|
|
2049
2053
|
const port = Number(c.req.param("port"));
|
|
2050
2054
|
if (!validatePort(port)) return errorJson("Invalid port", "invalid_request", 400);
|
|
2051
|
-
const sandbox =
|
|
2055
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2052
2056
|
try {
|
|
2053
2057
|
await sandbox.tunnels.destroy(port);
|
|
2054
2058
|
return c.body(null, 204);
|
|
@@ -2057,7 +2061,7 @@ function createBridgeApp(config) {
|
|
|
2057
2061
|
}
|
|
2058
2062
|
});
|
|
2059
2063
|
app.get(`${apiPrefix}/sandbox/:id/running`, async (c) => {
|
|
2060
|
-
const sandbox =
|
|
2064
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2061
2065
|
try {
|
|
2062
2066
|
await sandbox.exec("true");
|
|
2063
2067
|
return c.json({ running: true });
|
|
@@ -2068,7 +2072,7 @@ function createBridgeApp(config) {
|
|
|
2068
2072
|
app.get(`${apiPrefix}/sandbox/:id/pty`, async (c) => {
|
|
2069
2073
|
const upgrade = c.req.header("Upgrade");
|
|
2070
2074
|
if (!upgrade || upgrade.toLowerCase() !== "websocket") return errorJson("WebSocket upgrade required", "invalid_request", 400);
|
|
2071
|
-
const sandbox =
|
|
2075
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2072
2076
|
const colsParam = c.req.query("cols");
|
|
2073
2077
|
const rowsParam = c.req.query("rows");
|
|
2074
2078
|
const shell = c.req.query("shell");
|
|
@@ -2097,7 +2101,7 @@ function createBridgeApp(config) {
|
|
|
2097
2101
|
const excludesParam = c.req.query("excludes") ?? "";
|
|
2098
2102
|
const excludes = excludesParam ? excludesParam.split(",").filter((s) => s.length > 0) : [];
|
|
2099
2103
|
for (const ex of excludes) if (ex.includes("..")) return errorJson("exclude paths must not contain \"..\"", "invalid_request", 400);
|
|
2100
|
-
const sandbox =
|
|
2104
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2101
2105
|
const tmpPath = `/tmp/sandbox-persist-${Date.now()}.tar`;
|
|
2102
2106
|
const excludeArgs = excludes.map((rel) => `--exclude ${shellQuote(`./${rel.replace(/^\.\//, "")}`)}`).join(" ");
|
|
2103
2107
|
const tarCmd = excludeArgs ? `tar cf ${shellQuote(tmpPath)} ${excludeArgs} -C ${shellQuote(root)} .` : `tar cf ${shellQuote(tmpPath)} -C ${shellQuote(root)} .`;
|
|
@@ -2116,7 +2120,7 @@ function createBridgeApp(config) {
|
|
|
2116
2120
|
});
|
|
2117
2121
|
app.post(`${apiPrefix}/sandbox/:id/hydrate`, async (c) => {
|
|
2118
2122
|
const root = "/workspace";
|
|
2119
|
-
const sandbox =
|
|
2123
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2120
2124
|
let tarBytes;
|
|
2121
2125
|
try {
|
|
2122
2126
|
const buffer = await c.req.arrayBuffer();
|
|
@@ -2156,7 +2160,7 @@ function createBridgeApp(config) {
|
|
|
2156
2160
|
if (optionsError) return optionsError;
|
|
2157
2161
|
const bucketName = resolveMountBucketName(body);
|
|
2158
2162
|
if (bucketName instanceof Response) return bucketName;
|
|
2159
|
-
const sandbox =
|
|
2163
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2160
2164
|
const sdkOptions = toSDKMountOptions(body.options);
|
|
2161
2165
|
try {
|
|
2162
2166
|
await sandbox.mountBucket(bucketName, body.mountPath, sdkOptions);
|
|
@@ -2176,7 +2180,7 @@ function createBridgeApp(config) {
|
|
|
2176
2180
|
if (!body.mountPath.startsWith("/")) return errorJson("mountPath must be an absolute path (start with /)", "invalid_request", 400);
|
|
2177
2181
|
const normalizedPath = new URL(body.mountPath, "file:///").pathname;
|
|
2178
2182
|
if (normalizedPath === "/") return errorJson("mountPath must not resolve to / (filesystem root)", "invalid_request", 400);
|
|
2179
|
-
const sandbox =
|
|
2183
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), c.get("containerUUID"));
|
|
2180
2184
|
try {
|
|
2181
2185
|
await sandbox.unmountBucket(normalizedPath);
|
|
2182
2186
|
const quoted = shellQuote(normalizedPath);
|
|
@@ -2213,7 +2217,7 @@ function createBridgeApp(config) {
|
|
|
2213
2217
|
});
|
|
2214
2218
|
app.delete(`${apiPrefix}/sandbox/:id`, async (c) => {
|
|
2215
2219
|
const containerUUID = c.get("containerUUID");
|
|
2216
|
-
const sandbox =
|
|
2220
|
+
const sandbox = getSandboxWithoutDefaultSession(getSandboxNs(c.env), containerUUID);
|
|
2217
2221
|
try {
|
|
2218
2222
|
await sandbox.destroy();
|
|
2219
2223
|
} catch {}
|