@droveragent/sandbox-cloudflare 0.0.0-stage → 0.3.0-next.1
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/LICENSE +21 -0
- package/dist/cloudflare-sandbox.d.ts +327 -0
- package/dist/cloudflare-sandbox.d.ts.map +1 -0
- package/dist/cloudflare-sandbox.js +428 -0
- package/dist/cloudflare-sandbox.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -4
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nik Cubrilovic
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { SandboxError } from "@droveragent/core";
|
|
2
|
+
import type { SandboxAdapter } from "@droveragent/sandbox";
|
|
3
|
+
import { Effect } from "effect";
|
|
4
|
+
/**
|
|
5
|
+
* Egress posture for the container.
|
|
6
|
+
*
|
|
7
|
+
* Unlike Vercel Sandbox — where the firewall is a `getOrCreate` parameter —
|
|
8
|
+
* Cloudflare's egress controls live on the `Sandbox` **Durable Object**
|
|
9
|
+
* (`@cloudflare/containers`' `enableInternet` field plus the runtime
|
|
10
|
+
* `setAllowedHosts` / `setDeniedHosts` RPCs). Three consequences:
|
|
11
|
+
*
|
|
12
|
+
* 1. `deny-all` is only *real* when the DO subclass declares
|
|
13
|
+
* `enableInternet = false`. The adapter cannot read that flag over RPC,
|
|
14
|
+
* so it cannot verify it — see {@link CloudflareSandboxOptions.networkPolicy}.
|
|
15
|
+
* 2. `allow-all` is likewise not something the adapter can switch on; it
|
|
16
|
+
* means "the adapter installs no host lists, the DO's own posture wins".
|
|
17
|
+
* 3. Installing either list flips the container into **intercept-all** mode
|
|
18
|
+
* for the rest of its life (`@cloudflare/containers` promotes as soon as
|
|
19
|
+
* the outbound config is mutated at runtime). Any catch-all `static
|
|
20
|
+
* outbound` handler on the DO then sees *every* allowed host, not just
|
|
21
|
+
* the one it was written for — so a credential-stamping handler must key
|
|
22
|
+
* off `new URL(request.url).hostname` (or live in `static outboundByHost`)
|
|
23
|
+
* rather than assume its target.
|
|
24
|
+
*
|
|
25
|
+
* Host patterns are matched by `@cloudflare/containers`' `simpleGlobMatch`:
|
|
26
|
+
* plain equality plus `*` wildcards, against the hostname only. As of
|
|
27
|
+
* `@cloudflare/containers@0.3.7` there is **no CIDR matching** despite what
|
|
28
|
+
* the docs suggest — a `"10.0.0.0/8"` entry matches nothing.
|
|
29
|
+
*/
|
|
30
|
+
export type CloudflareNetworkPolicy = "deny-all" | "allow-all" | {
|
|
31
|
+
/** Hostnames granted egress even when `enableInternet` is false. */
|
|
32
|
+
allow: readonly string[];
|
|
33
|
+
/** Hostnames blocked unconditionally, even when `enableInternet` is true. */
|
|
34
|
+
deny?: readonly string[];
|
|
35
|
+
};
|
|
36
|
+
/** Structural slice of the SDK's `ProcessOutput<string>`. */
|
|
37
|
+
export interface CloudflareProcessOutput {
|
|
38
|
+
stdout: string;
|
|
39
|
+
stderr: string;
|
|
40
|
+
exitCode: number;
|
|
41
|
+
signal?: number;
|
|
42
|
+
/** True when the container-side `ExecOptions.timeout` fired. */
|
|
43
|
+
timedOut: boolean;
|
|
44
|
+
/** True when `maxBytes` clipped the captured streams. */
|
|
45
|
+
truncated: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** Structural slice of the SDK's `SandboxProcess`. */
|
|
48
|
+
export interface CloudflareProcessHandle {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
output(options: {
|
|
51
|
+
encoding: "utf8";
|
|
52
|
+
maxBytes?: number;
|
|
53
|
+
timeout?: number;
|
|
54
|
+
}): Promise<CloudflareProcessOutput>;
|
|
55
|
+
/** POSIX signal *number* — 9 for SIGKILL. (The SDK takes no string form.) */
|
|
56
|
+
kill(signal?: number): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/** Structural slice of the SDK's `ExecOptions`. Note: no `signal`. */
|
|
59
|
+
export interface CloudflareExecOptions {
|
|
60
|
+
cwd?: string;
|
|
61
|
+
env?: Record<string, string>;
|
|
62
|
+
/** Container-side kill deadline, ms. */
|
|
63
|
+
timeout?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface CloudflareReadFileResult {
|
|
66
|
+
success: boolean;
|
|
67
|
+
content: string;
|
|
68
|
+
}
|
|
69
|
+
export interface CloudflareWriteFileResult {
|
|
70
|
+
success: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface CloudflareMkdirResult {
|
|
73
|
+
success: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface CloudflareFileInfo {
|
|
76
|
+
name: string;
|
|
77
|
+
}
|
|
78
|
+
export interface CloudflareListFilesResult {
|
|
79
|
+
success: boolean;
|
|
80
|
+
files: CloudflareFileInfo[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Structural slice of `SandboxClient<Sandbox>` — the stub `getSandbox()`
|
|
84
|
+
* returns. The optional members come from the `Container` base class rather
|
|
85
|
+
* than `ISandbox`; a real client has them, a hand-rolled test double need
|
|
86
|
+
* not (except where {@link CloudflareSandboxOptions.networkPolicy} requires
|
|
87
|
+
* the egress controls — see `createCloudflareSandbox`).
|
|
88
|
+
*/
|
|
89
|
+
export interface CloudflareSandboxHandle {
|
|
90
|
+
exec(command: readonly [string, ...string[]], options?: CloudflareExecOptions): Promise<CloudflareProcessHandle>;
|
|
91
|
+
readFile(path: string, options?: {
|
|
92
|
+
encoding?: "utf-8" | "utf8" | "base64";
|
|
93
|
+
}): Promise<CloudflareReadFileResult>;
|
|
94
|
+
writeFile(path: string, content: string, options?: {
|
|
95
|
+
encoding?: string;
|
|
96
|
+
}): Promise<CloudflareWriteFileResult>;
|
|
97
|
+
listFiles(path: string, options?: {
|
|
98
|
+
recursive?: boolean;
|
|
99
|
+
includeHidden?: boolean;
|
|
100
|
+
}): Promise<CloudflareListFilesResult>;
|
|
101
|
+
mkdir?(path: string, options?: {
|
|
102
|
+
recursive?: boolean;
|
|
103
|
+
}): Promise<CloudflareMkdirResult>;
|
|
104
|
+
setEnvVars?(envVars: Record<string, string | undefined>): Promise<void>;
|
|
105
|
+
setAllowedHosts?(hosts: string[]): Promise<void>;
|
|
106
|
+
setDeniedHosts?(hosts: string[]): Promise<void>;
|
|
107
|
+
/** Tear the container down. Not the same as "stop" — there is no snapshot. */
|
|
108
|
+
destroy?(): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
/** Structural slice of the SDK's `SandboxOptions`, forwarded to `getSandbox`. */
|
|
111
|
+
export interface CloudflareGetSandboxOptions {
|
|
112
|
+
/** Idle sleep window — `"10m"`, `"1h"`, or seconds. SDK default `"10m"`. */
|
|
113
|
+
sleepAfter?: string | number;
|
|
114
|
+
/** Never auto-sleep. Requires an explicit `destroy()`. SDK default false. */
|
|
115
|
+
keepAlive?: boolean;
|
|
116
|
+
/** Lowercase the DO id. Recommended — and required for preview URLs. */
|
|
117
|
+
normalizeId?: boolean;
|
|
118
|
+
containerTimeouts?: {
|
|
119
|
+
instanceGetTimeoutMS?: number;
|
|
120
|
+
portReadyTimeoutMS?: number;
|
|
121
|
+
waitIntervalMS?: number;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* SDK entry point, injectable for tests. In a Worker, build one with
|
|
126
|
+
* {@link cloudflareSdkClient}; the namespace binding is captured there so
|
|
127
|
+
* this interface stays free of Workers types.
|
|
128
|
+
*/
|
|
129
|
+
export interface CloudflareSandboxClient {
|
|
130
|
+
getSandbox(id: string, options?: CloudflareGetSandboxOptions): CloudflareSandboxHandle;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Bind `@cloudflare/sandbox`'s `getSandbox` to a Durable Object namespace,
|
|
134
|
+
* producing the adapter's structural client. This is the *only* place the
|
|
135
|
+
* real SDK types meet the adapter's, so it is also the only cast:
|
|
136
|
+
*
|
|
137
|
+
* ```ts
|
|
138
|
+
* import { getSandbox } from "@cloudflare/sandbox";
|
|
139
|
+
*
|
|
140
|
+
* const sandbox = createCloudflareSandbox({
|
|
141
|
+
* name: `conv-${conversationId}`,
|
|
142
|
+
* client: cloudflareSdkClient(getSandbox, env.Sandbox),
|
|
143
|
+
* networkPolicy: { allow: ["data.example.org"] },
|
|
144
|
+
* });
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* The adapter itself never imports `@cloudflare/sandbox`, so it type-checks
|
|
148
|
+
* and unit-tests in plain bun — the SDK only runs inside `workerd`.
|
|
149
|
+
*/
|
|
150
|
+
export declare function cloudflareSdkClient<NS, H>(getSandbox: (ns: NS, id: string, options?: CloudflareGetSandboxOptions) => H, namespace: NS): CloudflareSandboxClient;
|
|
151
|
+
export interface CloudflareSandboxOptions {
|
|
152
|
+
/**
|
|
153
|
+
* Durable Object id — the sandbox's identity *and* its persistence key.
|
|
154
|
+
* The same name reattaches to the same container (and its disk) across
|
|
155
|
+
* requests, isolates and sessions. This is Cloudflare's `getOrCreate`.
|
|
156
|
+
*/
|
|
157
|
+
name: string;
|
|
158
|
+
/** SDK entry point. See {@link cloudflareSdkClient}. */
|
|
159
|
+
client: CloudflareSandboxClient;
|
|
160
|
+
/**
|
|
161
|
+
* Egress firewall. Defaults to `"deny-all"` — drover sandboxes ship locked
|
|
162
|
+
* down.
|
|
163
|
+
*
|
|
164
|
+
* **Read this before trusting it.** Cloudflare's real deny-all switch is
|
|
165
|
+
* `enableInternet = false` on your `Sandbox` Durable Object subclass; the
|
|
166
|
+
* host lists this adapter installs are an *allowlist on top of that*. The
|
|
167
|
+
* adapter cannot read `enableInternet` over RPC, so it cannot assert the
|
|
168
|
+
* base posture. Declare it yourself:
|
|
169
|
+
*
|
|
170
|
+
* ```ts
|
|
171
|
+
* export class MySandbox extends Sandbox<Env> {
|
|
172
|
+
* override enableInternet = false;
|
|
173
|
+
* // Required to see (and therefore modify) HTTPS egress. Defaults to
|
|
174
|
+
* // false on Container; Sandbox does not override it. Left false, an
|
|
175
|
+
* // allowed HTTPS host is a transparent tunnel — outbound handlers
|
|
176
|
+
* // never run and no header can be added.
|
|
177
|
+
* override interceptHttps = true;
|
|
178
|
+
* }
|
|
179
|
+
* // Without this re-export the DO throws on the first list install:
|
|
180
|
+
* // "ctx.exports.ContainerProxy is undefined".
|
|
181
|
+
* export { ContainerProxy } from "@cloudflare/sandbox";
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* With `interceptHttps = true` the platform mints an ephemeral CA at
|
|
185
|
+
* `/etc/cloudflare/certs/cloudflare-containers-ca.crt` inside the
|
|
186
|
+
* container. The stock sandbox image trusts it; anything with its own
|
|
187
|
+
* trust store (python `certifi`, node, curl built against a pinned
|
|
188
|
+
* bundle) needs `SSL_CERT_FILE` / `REQUESTS_CA_BUNDLE` /
|
|
189
|
+
* `NODE_EXTRA_CA_CERTS` pointed at a bundle that includes it, or TLS
|
|
190
|
+
* verification fails for every intercepted host. The CA-free alternative
|
|
191
|
+
* (what the SDK's own git/s3/r2 credential proxies do): have the container
|
|
192
|
+
* speak plain `http://` to the host, and let the `outboundByHost` handler
|
|
193
|
+
* upgrade to `https://` and stamp the credential before forwarding.
|
|
194
|
+
*
|
|
195
|
+
* Anything other than `"allow-all"` requires the handle to expose
|
|
196
|
+
* `setAllowedHosts` / `setDeniedHosts`; the adapter fails closed with a
|
|
197
|
+
* `SandboxError` when they are missing rather than running wide open.
|
|
198
|
+
*/
|
|
199
|
+
networkPolicy?: CloudflareNetworkPolicy;
|
|
200
|
+
/** Options forwarded to `getSandbox`. `normalizeId` defaults to true. */
|
|
201
|
+
sandboxOptions?: CloudflareGetSandboxOptions;
|
|
202
|
+
/**
|
|
203
|
+
* Environment for everything this adapter runs.
|
|
204
|
+
*
|
|
205
|
+
* Applied two ways, deliberately:
|
|
206
|
+
*
|
|
207
|
+
* 1. `setEnvVars` once per acquire. **This only reaches a container that has
|
|
208
|
+
* not started yet** — the SDK's `setEnvVars` mutates the Durable Object's
|
|
209
|
+
* `envVars` record, and that record is handed to the container exactly
|
|
210
|
+
* once, in the `container.start()` config. Call it against a container
|
|
211
|
+
* that is already running (a warm sandbox reattached from a later
|
|
212
|
+
* isolate) and it is a silent no-op until the next cold start.
|
|
213
|
+
* 2. Merged under `ExecOptions.env` on **every** `run`, so it is in effect
|
|
214
|
+
* regardless of container warmth. Per-call `env` wins on key collisions.
|
|
215
|
+
*
|
|
216
|
+
* Secrets do not belong here either way: they would be visible to every
|
|
217
|
+
* process in the container. Inject them at the egress handler instead.
|
|
218
|
+
*/
|
|
219
|
+
env?: Record<string, string>;
|
|
220
|
+
/**
|
|
221
|
+
* Default cwd for `run` and the base for `resolvePath`. Default
|
|
222
|
+
* `"/workspace"` — the container's working root.
|
|
223
|
+
*/
|
|
224
|
+
cwd?: string;
|
|
225
|
+
/**
|
|
226
|
+
* Restrict `assertPathAllowed` to these prefixes. Omit (the default) to
|
|
227
|
+
* allow every path: the container is the isolation boundary, exactly as
|
|
228
|
+
* with the Vercel adapter. Set it when you also want intra-container
|
|
229
|
+
* confinement (e.g. `["/workspace"]`).
|
|
230
|
+
*/
|
|
231
|
+
allowedRoots?: readonly string[];
|
|
232
|
+
/**
|
|
233
|
+
* Ran once per adapter instance, right after the stub is acquired and the
|
|
234
|
+
* env/egress policy are applied. Note this is NOT "on container create" —
|
|
235
|
+
* the SDK gives no such signal — so it fires on every cold isolate. Make
|
|
236
|
+
* it idempotent (a marker file is the usual guard).
|
|
237
|
+
*/
|
|
238
|
+
onAcquire?: (sandbox: CloudflareSandboxHandle) => Promise<void>;
|
|
239
|
+
/** Per-call default exec timeout, ms. Default 30_000 (matches just-bash). */
|
|
240
|
+
timeoutMs?: number;
|
|
241
|
+
/**
|
|
242
|
+
* Tail cap per output stream, in bytes. Default 16 KiB. Longer output is
|
|
243
|
+
* truncated to its tail with a note, so a runaway `cat` cannot blow the
|
|
244
|
+
* transcript.
|
|
245
|
+
*/
|
|
246
|
+
maxOutputBytes?: number;
|
|
247
|
+
/**
|
|
248
|
+
* `maxBytes` handed to the SDK's `output()` — the cap on what crosses the
|
|
249
|
+
* RPC boundary at all, before the tail cap above. Default 1 MiB.
|
|
250
|
+
*/
|
|
251
|
+
transportMaxBytes?: number;
|
|
252
|
+
/** How long to wait after SIGKILL for exit code + output harvest, ms. Default 2_000. */
|
|
253
|
+
killGraceMs?: number;
|
|
254
|
+
/** Telemetry identifier. Default `"cloudflare-sandbox"`. */
|
|
255
|
+
id?: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* The SDK's "the container behind this stub was replaced" family.
|
|
259
|
+
*
|
|
260
|
+
* Matched on the SDK's error `code` first (`OPERATION_INTERRUPTED` with a
|
|
261
|
+
* `runtime_replaced` reason, `STALE_PROCESS_HANDLE`) and on its messages as a
|
|
262
|
+
* fallback, through up to eight `cause` links, because the SDK wraps DO
|
|
263
|
+
* transport failures before they reach the adapter. Also true for a
|
|
264
|
+
* `SandboxError` this adapter minted from one, so callers can classify the
|
|
265
|
+
* error they were handed without keeping the original.
|
|
266
|
+
*/
|
|
267
|
+
export declare function isRuntimeReplacedError(err: unknown): boolean;
|
|
268
|
+
/**
|
|
269
|
+
* Pure POSIX `normalize`. Hand-rolled rather than `node:path/posix` so the
|
|
270
|
+
* adapter needs no `nodejs_compat` flag in the consuming Worker. Trailing
|
|
271
|
+
* slashes are dropped (node keeps them); nothing else differs for the
|
|
272
|
+
* absolute paths a container deals in.
|
|
273
|
+
*/
|
|
274
|
+
export declare function normalizePosix(p: string): string;
|
|
275
|
+
/**
|
|
276
|
+
* Cloudflare Sandbox adapter: every op runs inside a Cloudflare **container**
|
|
277
|
+
* fronted by a `Sandbox` Durable Object. **A real isolation boundary** — the
|
|
278
|
+
* container is remote, has its own filesystem, and (with
|
|
279
|
+
* `enableInternet = false` on the DO) no egress — so `bash` is safe to
|
|
280
|
+
* compose by default and `capabilities.shell` is unconditionally `true`.
|
|
281
|
+
*
|
|
282
|
+
* ### Identity and persistence
|
|
283
|
+
* `getSandbox(ns, name)` *is* the getOrCreate: the name is the Durable Object
|
|
284
|
+
* id, so the same name reattaches to the same container and the same disk.
|
|
285
|
+
* There is no Vercel-style snapshot on stop — the container simply sleeps
|
|
286
|
+
* after `sleepAfter` and wakes with its disk intact. For durable, portable
|
|
287
|
+
* state use the SDK's `createBackup`/`restoreBackup` (R2) directly on the
|
|
288
|
+
* handle; the adapter does not wrap them.
|
|
289
|
+
*
|
|
290
|
+
* ### What differs from `@droveragent/sandbox-vercel`
|
|
291
|
+
* - **Egress is DO-side, not per-acquire.** See
|
|
292
|
+
* {@link CloudflareSandboxOptions.networkPolicy}.
|
|
293
|
+
* - **No `AbortSignal` on `exec`.** The SDK's `ExecOptions` has `cwd`, `env`
|
|
294
|
+
* and `timeout` only, so cancellation is a client-side race plus an
|
|
295
|
+
* explicit `kill(9)`, exactly as the Vercel adapter does for timeouts.
|
|
296
|
+
* - **`stop()` does not snapshot.** It drops the memoised handle so the next
|
|
297
|
+
* op re-acquires; the container sleeps on its own schedule. Use
|
|
298
|
+
* {@link CloudflareSandboxAdapter.destroy} to actually tear it down.
|
|
299
|
+
* - **No node builtins.** Path handling and byte counting use plain string
|
|
300
|
+
* ops and `TextEncoder`, so no `nodejs_compat` flag is needed.
|
|
301
|
+
*
|
|
302
|
+
* `run` enforces `timeoutMs`/`signal` with its own deadline race and
|
|
303
|
+
* SIGKILLs the container-side process on expiry, resolving with
|
|
304
|
+
* `killed: true` (matching just-bash) rather than failing, so the tool layer
|
|
305
|
+
* can report the partial result. `SandboxError` is reserved for
|
|
306
|
+
* SDK/transport failures, including failure to acquire within the deadline.
|
|
307
|
+
*/
|
|
308
|
+
export interface CloudflareSandboxAdapter extends SandboxAdapter {
|
|
309
|
+
/** List directory entry names inside the container (always implemented here). */
|
|
310
|
+
readdir(path: string): Effect.Effect<ReadonlyArray<string>, SandboxError, never>;
|
|
311
|
+
/** `mkdir -p` inside the container. */
|
|
312
|
+
mkdir(path: string): Effect.Effect<void, SandboxError, never>;
|
|
313
|
+
/**
|
|
314
|
+
* Drop the memoised handle. The container is left running and sleeps on
|
|
315
|
+
* its own `sleepAfter` schedule with its disk intact; the next operation
|
|
316
|
+
* re-acquires it. A no-op when nothing was acquired. Safe to call repeatedly.
|
|
317
|
+
*/
|
|
318
|
+
stop(): Effect.Effect<void, SandboxError, never>;
|
|
319
|
+
/**
|
|
320
|
+
* Tear the container down for good (`Sandbox.destroy()`), then drop the
|
|
321
|
+
* handle. Unlike {@link CloudflareSandboxAdapter.stop} this is destructive:
|
|
322
|
+
* the filesystem does not survive.
|
|
323
|
+
*/
|
|
324
|
+
destroy(): Effect.Effect<void, SandboxError, never>;
|
|
325
|
+
}
|
|
326
|
+
export declare function createCloudflareSandbox(opts: CloudflareSandboxOptions): CloudflareSandboxAdapter;
|
|
327
|
+
//# sourceMappingURL=cloudflare-sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare-sandbox.d.ts","sourceRoot":"","sources":["../src/cloudflare-sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { SandboxError } from "@droveragent/core";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
/**
|
|
4
|
+
* Bind `@cloudflare/sandbox`'s `getSandbox` to a Durable Object namespace,
|
|
5
|
+
* producing the adapter's structural client. This is the *only* place the
|
|
6
|
+
* real SDK types meet the adapter's, so it is also the only cast:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { getSandbox } from "@cloudflare/sandbox";
|
|
10
|
+
*
|
|
11
|
+
* const sandbox = createCloudflareSandbox({
|
|
12
|
+
* name: `conv-${conversationId}`,
|
|
13
|
+
* client: cloudflareSdkClient(getSandbox, env.Sandbox),
|
|
14
|
+
* networkPolicy: { allow: ["data.example.org"] },
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* The adapter itself never imports `@cloudflare/sandbox`, so it type-checks
|
|
19
|
+
* and unit-tests in plain bun — the SDK only runs inside `workerd`.
|
|
20
|
+
*/
|
|
21
|
+
export function cloudflareSdkClient(getSandbox, namespace) {
|
|
22
|
+
return {
|
|
23
|
+
getSandbox: (id, options) => getSandbox(namespace, id, options),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
27
|
+
const DEFAULT_MAX_OUTPUT_BYTES = 16 * 1024;
|
|
28
|
+
const DEFAULT_TRANSPORT_MAX_BYTES = 1024 * 1024;
|
|
29
|
+
const DEFAULT_KILL_GRACE_MS = 2_000;
|
|
30
|
+
const DEFAULT_CWD = "/workspace";
|
|
31
|
+
// The container-side timeout backstop trails the adapter's own deadline so
|
|
32
|
+
// the client-side race decides `killed` in the normal case.
|
|
33
|
+
const SDK_TIMEOUT_PAD_MS = 500;
|
|
34
|
+
const SIGKILL = 9;
|
|
35
|
+
const encoder = new TextEncoder();
|
|
36
|
+
const decoder = new TextDecoder("utf-8");
|
|
37
|
+
/**
|
|
38
|
+
* The SDK's "the container behind this stub was replaced" family.
|
|
39
|
+
*
|
|
40
|
+
* Matched on the SDK's error `code` first (`OPERATION_INTERRUPTED` with a
|
|
41
|
+
* `runtime_replaced` reason, `STALE_PROCESS_HANDLE`) and on its messages as a
|
|
42
|
+
* fallback, through up to eight `cause` links, because the SDK wraps DO
|
|
43
|
+
* transport failures before they reach the adapter. Also true for a
|
|
44
|
+
* `SandboxError` this adapter minted from one, so callers can classify the
|
|
45
|
+
* error they were handed without keeping the original.
|
|
46
|
+
*/
|
|
47
|
+
export function isRuntimeReplacedError(err) {
|
|
48
|
+
let current = err;
|
|
49
|
+
for (let depth = 0; depth < 8 && current != null; depth += 1) {
|
|
50
|
+
if (typeof current === "object") {
|
|
51
|
+
const { code, message, cause } = current;
|
|
52
|
+
if (code === "OPERATION_INTERRUPTED" || code === "STALE_PROCESS_HANDLE")
|
|
53
|
+
return true;
|
|
54
|
+
if (typeof message === "string" && RUNTIME_REPLACED_PATTERN.test(message))
|
|
55
|
+
return true;
|
|
56
|
+
current = cause;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
/** Appended to a wrapped message that was recognised by `code` alone. */
|
|
64
|
+
const RUNTIME_REPLACED_TAG = "(sandbox runtime replaced)";
|
|
65
|
+
const RUNTIME_REPLACED_PATTERN = /interrupted while the platform was updating the sandbox runtime|refers to a previous runtime incarnation|runtime incarnation does not match|\(sandbox runtime replaced\)/i;
|
|
66
|
+
const sandboxError = (op, err, path) => err instanceof SandboxError
|
|
67
|
+
? err
|
|
68
|
+
: new SandboxError({
|
|
69
|
+
runId: "(sandbox)",
|
|
70
|
+
op,
|
|
71
|
+
...(path !== undefined ? { path } : {}),
|
|
72
|
+
message: err instanceof Error ? err.message : String(err),
|
|
73
|
+
});
|
|
74
|
+
const startDeadline = (ms) => {
|
|
75
|
+
let timer;
|
|
76
|
+
const promise = new Promise((resolve) => {
|
|
77
|
+
timer = setTimeout(() => resolve({ kind: "timeout" }), ms);
|
|
78
|
+
});
|
|
79
|
+
return { promise, clear: () => clearTimeout(timer) };
|
|
80
|
+
};
|
|
81
|
+
const watchAbort = (signal) => {
|
|
82
|
+
let cleanup = () => { };
|
|
83
|
+
const promise = new Promise((resolve) => {
|
|
84
|
+
if (!signal)
|
|
85
|
+
return; // never resolves; the deadline branch always does
|
|
86
|
+
if (signal.aborted) {
|
|
87
|
+
resolve({ kind: "abort" });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const onAbort = () => resolve({ kind: "abort" });
|
|
91
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
92
|
+
cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
93
|
+
});
|
|
94
|
+
return { promise, cleanup };
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Pure POSIX `normalize`. Hand-rolled rather than `node:path/posix` so the
|
|
98
|
+
* adapter needs no `nodejs_compat` flag in the consuming Worker. Trailing
|
|
99
|
+
* slashes are dropped (node keeps them); nothing else differs for the
|
|
100
|
+
* absolute paths a container deals in.
|
|
101
|
+
*/
|
|
102
|
+
export function normalizePosix(p) {
|
|
103
|
+
const absolute = p.startsWith("/");
|
|
104
|
+
const parts = [];
|
|
105
|
+
for (const seg of p.split("/")) {
|
|
106
|
+
if (seg === "" || seg === ".")
|
|
107
|
+
continue;
|
|
108
|
+
if (seg === "..") {
|
|
109
|
+
const last = parts[parts.length - 1];
|
|
110
|
+
if (parts.length > 0 && last !== "..")
|
|
111
|
+
parts.pop();
|
|
112
|
+
else if (!absolute)
|
|
113
|
+
parts.push("..");
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
parts.push(seg);
|
|
117
|
+
}
|
|
118
|
+
const joined = parts.join("/");
|
|
119
|
+
if (absolute)
|
|
120
|
+
return `/${joined}`;
|
|
121
|
+
return joined === "" ? "." : joined;
|
|
122
|
+
}
|
|
123
|
+
export function createCloudflareSandbox(opts) {
|
|
124
|
+
const id = opts.id ?? "cloudflare-sandbox";
|
|
125
|
+
const defaultTimeout = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
126
|
+
const maxOutputBytes = opts.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
|
|
127
|
+
const transportMaxBytes = opts.transportMaxBytes ?? DEFAULT_TRANSPORT_MAX_BYTES;
|
|
128
|
+
const killGraceMs = opts.killGraceMs ?? DEFAULT_KILL_GRACE_MS;
|
|
129
|
+
const baseCwd = normalizePosix(opts.cwd ?? DEFAULT_CWD);
|
|
130
|
+
const policy = opts.networkPolicy ?? "deny-all";
|
|
131
|
+
const allowedRoots = opts.allowedRoots?.map((r) => normalizePosix(r));
|
|
132
|
+
const getSandboxOptions = {
|
|
133
|
+
normalizeId: true,
|
|
134
|
+
...opts.sandboxOptions,
|
|
135
|
+
};
|
|
136
|
+
const applyNetworkPolicy = async (sandbox) => {
|
|
137
|
+
if (policy === "allow-all")
|
|
138
|
+
return; // the DO's own posture stands
|
|
139
|
+
const allow = policy === "deny-all" ? [] : [...policy.allow];
|
|
140
|
+
const deny = policy === "deny-all" ? [] : [...(policy.deny ?? [])];
|
|
141
|
+
if (!sandbox.setAllowedHosts || !sandbox.setDeniedHosts) {
|
|
142
|
+
// Fail closed: silently skipping the lists would leave the container
|
|
143
|
+
// on whatever posture the DO happens to have.
|
|
144
|
+
throw new SandboxError({
|
|
145
|
+
runId: "(sandbox)",
|
|
146
|
+
op: "exec",
|
|
147
|
+
message: `network policy "${policy === "deny-all" ? "deny-all" : "allowlist"}" requires the sandbox handle to expose ` +
|
|
148
|
+
"setAllowedHosts/setDeniedHosts (the @cloudflare/containers egress controls). " +
|
|
149
|
+
'Pass networkPolicy: "allow-all" to opt out of adapter-managed egress.',
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
await sandbox.setAllowedHosts(allow);
|
|
153
|
+
await sandbox.setDeniedHosts(deny);
|
|
154
|
+
};
|
|
155
|
+
// Lazy, memoised acquisition. `getSandbox` itself is synchronous (it just
|
|
156
|
+
// builds a DO stub), but the one-time setup around it is not, so the same
|
|
157
|
+
// memoisation shape as the Vercel adapter applies: concurrent first ops
|
|
158
|
+
// share one setup; a failure resets so the next op can retry.
|
|
159
|
+
let sandboxP = null;
|
|
160
|
+
const acquire = () => {
|
|
161
|
+
sandboxP ??= (async () => {
|
|
162
|
+
const sandbox = opts.client.getSandbox(opts.name, getSandboxOptions);
|
|
163
|
+
if (opts.env && sandbox.setEnvVars)
|
|
164
|
+
await sandbox.setEnvVars({ ...opts.env });
|
|
165
|
+
await applyNetworkPolicy(sandbox);
|
|
166
|
+
if (opts.onAcquire)
|
|
167
|
+
await opts.onAcquire(sandbox);
|
|
168
|
+
return sandbox;
|
|
169
|
+
})().catch((err) => {
|
|
170
|
+
sandboxP = null;
|
|
171
|
+
throw err;
|
|
172
|
+
});
|
|
173
|
+
return sandboxP;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Wrap an SDK failure, and drop the memoised handle when the SDK reports
|
|
177
|
+
* that the container behind it was REPLACED.
|
|
178
|
+
*
|
|
179
|
+
* When the container restarts under a live stub — the platform killed it
|
|
180
|
+
* (out of memory is the usual reason), it crashed, or the runtime was
|
|
181
|
+
* updated — the SDK fails the in-flight op with `OPERATION_INTERRUPTED`
|
|
182
|
+
* ("interrupted while the platform was updating the sandbox runtime") and
|
|
183
|
+
* every later op on the SAME stub with the same error, or with
|
|
184
|
+
* `STALE_PROCESS_HANDLE` ("Process handle refers to a previous runtime
|
|
185
|
+
* incarnation"). Those are not retryable in place, but a FRESH acquire is:
|
|
186
|
+
* `getSandbox` addresses the same Durable Object, whose new runtime
|
|
187
|
+
* incarnation accepts work. Without this reset one container restart wedged
|
|
188
|
+
* every remaining tool call of the turn.
|
|
189
|
+
*
|
|
190
|
+
* The disk did not survive the restart. The error is returned unchanged so
|
|
191
|
+
* the caller can recognise it (see {@link isRuntimeReplacedError}) and
|
|
192
|
+
* re-stage whatever it had written.
|
|
193
|
+
*/
|
|
194
|
+
const failed = (op, err, path) => {
|
|
195
|
+
if (!isRuntimeReplacedError(err))
|
|
196
|
+
return sandboxError(op, err, path);
|
|
197
|
+
sandboxP = null;
|
|
198
|
+
const wrapped = sandboxError(op, err, path);
|
|
199
|
+
// `SandboxError` carries only a message, so an SDK error recognised by its
|
|
200
|
+
// `code` alone would stop being recognisable once wrapped. Tag it.
|
|
201
|
+
return RUNTIME_REPLACED_PATTERN.test(wrapped.message)
|
|
202
|
+
? wrapped
|
|
203
|
+
: new SandboxError({
|
|
204
|
+
runId: wrapped.runId,
|
|
205
|
+
op: wrapped.op,
|
|
206
|
+
...(wrapped.path !== undefined ? { path: wrapped.path } : {}),
|
|
207
|
+
message: `${wrapped.message} ${RUNTIME_REPLACED_TAG}`,
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
const capTail = (text) => {
|
|
211
|
+
const bytes = encoder.encode(text);
|
|
212
|
+
if (bytes.length <= maxOutputBytes)
|
|
213
|
+
return text;
|
|
214
|
+
const tail = decoder
|
|
215
|
+
.decode(bytes.subarray(bytes.length - maxOutputBytes))
|
|
216
|
+
// drop the partial code point a byte-boundary slice can leave behind
|
|
217
|
+
.replace(/^�+/, "");
|
|
218
|
+
return `[truncated: showing last ${maxOutputBytes} of ${bytes.length} bytes]\n${tail}`;
|
|
219
|
+
};
|
|
220
|
+
const interruptedResult = (kind, timeoutMs, stdout, stderr, exitCode = -1) => {
|
|
221
|
+
const note = kind === "timeout"
|
|
222
|
+
? `[command timed out after ${timeoutMs}ms and was killed]`
|
|
223
|
+
: "[command aborted and was killed]";
|
|
224
|
+
const capped = capTail(stderr);
|
|
225
|
+
return {
|
|
226
|
+
exitCode,
|
|
227
|
+
stdout: capTail(stdout),
|
|
228
|
+
stderr: capped === "" ? note : `${capped}\n${note}`,
|
|
229
|
+
killed: true,
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
const execRun = async (cmd, args, runOpts) => {
|
|
233
|
+
const timeoutMs = runOpts?.timeoutMs ?? defaultTimeout;
|
|
234
|
+
// Already-aborted: report killed without ever touching the container
|
|
235
|
+
// (matches just-bash).
|
|
236
|
+
if (runOpts?.signal?.aborted)
|
|
237
|
+
return interruptedResult("abort", timeoutMs, "", "");
|
|
238
|
+
const deadline = startDeadline(timeoutMs);
|
|
239
|
+
const abort = watchAbort(runOpts?.signal);
|
|
240
|
+
try {
|
|
241
|
+
// Acquisition counts against the exec deadline — a cold container can
|
|
242
|
+
// take minutes to provision and must not hang the tool call. No process
|
|
243
|
+
// exists yet, so an expiry here is infra failure (SandboxError), not a
|
|
244
|
+
// killed result.
|
|
245
|
+
const acquireP = acquire().then((sandbox) => ({ kind: "acquired", sandbox }), (error) => ({ kind: "acquire-error", error }));
|
|
246
|
+
const acquired = await Promise.race([acquireP, deadline.promise, abort.promise]);
|
|
247
|
+
if (acquired.kind === "acquire-error")
|
|
248
|
+
throw acquired.error;
|
|
249
|
+
if (acquired.kind !== "acquired") {
|
|
250
|
+
throw new SandboxError({
|
|
251
|
+
runId: "(sandbox)",
|
|
252
|
+
op: "exec",
|
|
253
|
+
message: acquired.kind === "timeout"
|
|
254
|
+
? `sandbox acquisition timed out after ${timeoutMs}ms`
|
|
255
|
+
: "sandbox acquisition aborted",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
// `setEnvVars` only lands on a container that has yet to start, so the
|
|
259
|
+
// adapter-wide env rides on every exec too. Per-call env wins.
|
|
260
|
+
const execEnv = opts.env !== undefined || runOpts?.env !== undefined
|
|
261
|
+
? { ...opts.env, ...runOpts?.env }
|
|
262
|
+
: undefined;
|
|
263
|
+
const startP = acquired.sandbox
|
|
264
|
+
.exec([cmd, ...args], {
|
|
265
|
+
cwd: runOpts?.cwd ?? baseCwd,
|
|
266
|
+
// Container-side backstop; the client-side race is the primary.
|
|
267
|
+
timeout: timeoutMs + SDK_TIMEOUT_PAD_MS,
|
|
268
|
+
...(execEnv !== undefined ? { env: execEnv } : {}),
|
|
269
|
+
})
|
|
270
|
+
.then((process) => ({ kind: "started", process }), (error) => ({ kind: "start-error", error }));
|
|
271
|
+
const started = await Promise.race([startP, deadline.promise, abort.promise]);
|
|
272
|
+
if (started.kind === "start-error")
|
|
273
|
+
throw started.error;
|
|
274
|
+
if (started.kind !== "started") {
|
|
275
|
+
// Reap the orphan if the spawn ever completes.
|
|
276
|
+
void startP.then((s) => {
|
|
277
|
+
if (s.kind === "started")
|
|
278
|
+
void s.process.kill(SIGKILL).catch(() => { });
|
|
279
|
+
});
|
|
280
|
+
return interruptedResult(started.kind, timeoutMs, "", "");
|
|
281
|
+
}
|
|
282
|
+
// One `output()` call, raced — a second call after the kill would be a
|
|
283
|
+
// second log replay, so the grace window reuses this same promise.
|
|
284
|
+
const outputP = started.process
|
|
285
|
+
.output({ encoding: "utf8", maxBytes: transportMaxBytes })
|
|
286
|
+
.then((out) => ({ kind: "finished", out }), (error) => ({ kind: "output-error", error }));
|
|
287
|
+
const first = await Promise.race([outputP, deadline.promise, abort.promise]);
|
|
288
|
+
if (first.kind === "output-error")
|
|
289
|
+
throw first.error;
|
|
290
|
+
if (first.kind === "finished") {
|
|
291
|
+
return {
|
|
292
|
+
exitCode: first.out.exitCode,
|
|
293
|
+
stdout: capTail(first.out.stdout),
|
|
294
|
+
stderr: capTail(first.out.stderr),
|
|
295
|
+
// The container's own `timeout` can fire just before ours does.
|
|
296
|
+
killed: first.out.timedOut,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
// Deadline or abort: kill, then a bounded grace to harvest the exit
|
|
300
|
+
// code and any partial output.
|
|
301
|
+
await started.process.kill(SIGKILL).catch(() => { });
|
|
302
|
+
const grace = startDeadline(killGraceMs);
|
|
303
|
+
const graced = await Promise.race([outputP, grace.promise]);
|
|
304
|
+
grace.clear();
|
|
305
|
+
if (graced.kind === "finished") {
|
|
306
|
+
return interruptedResult(first.kind, timeoutMs, graced.out.stdout, graced.out.stderr, graced.out.exitCode);
|
|
307
|
+
}
|
|
308
|
+
return interruptedResult(first.kind, timeoutMs, "", "");
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
deadline.clear();
|
|
312
|
+
abort.cleanup();
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const run = (cmd, args, runOpts) => Effect.tryPromise({
|
|
316
|
+
try: () => execRun(cmd, args, runOpts),
|
|
317
|
+
catch: (err) => failed("exec", err),
|
|
318
|
+
});
|
|
319
|
+
const readFile = (p) => Effect.tryPromise({
|
|
320
|
+
try: async () => {
|
|
321
|
+
const sandbox = await acquire();
|
|
322
|
+
// Force utf-8: the default auto-detects and hands back base64 for
|
|
323
|
+
// anything it thinks is binary, which the adapter contract (a
|
|
324
|
+
// `string` of file contents) cannot express.
|
|
325
|
+
const result = await sandbox.readFile(p, { encoding: "utf-8" });
|
|
326
|
+
if (!result.success)
|
|
327
|
+
throw new Error(`readFile failed for '${p}'`);
|
|
328
|
+
return result.content;
|
|
329
|
+
},
|
|
330
|
+
catch: (err) => failed("read", err, p),
|
|
331
|
+
});
|
|
332
|
+
const writeFile = (p, contents) => Effect.tryPromise({
|
|
333
|
+
try: async () => {
|
|
334
|
+
const sandbox = await acquire();
|
|
335
|
+
const write = async () => {
|
|
336
|
+
const result = await sandbox.writeFile(p, contents);
|
|
337
|
+
if (!result.success)
|
|
338
|
+
throw new Error(`writeFile failed for '${p}'`);
|
|
339
|
+
};
|
|
340
|
+
try {
|
|
341
|
+
await write();
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
// `writeFile` must create missing parents (the SandboxAdapter conformance suite
|
|
345
|
+
// checks it). A backend that refuses to write into a missing directory gets the
|
|
346
|
+
// parent made with `mkdir -p` and one retry.
|
|
347
|
+
const parent = normalizePosix(`${p}/..`);
|
|
348
|
+
if (!sandbox.mkdir || parent === normalizePosix(p))
|
|
349
|
+
throw err;
|
|
350
|
+
const made = await sandbox.mkdir(parent, { recursive: true });
|
|
351
|
+
if (!made.success)
|
|
352
|
+
throw err;
|
|
353
|
+
await write();
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
catch: (err) => failed("write", err, p),
|
|
357
|
+
});
|
|
358
|
+
const readdir = (p) => Effect.tryPromise({
|
|
359
|
+
try: async () => {
|
|
360
|
+
const sandbox = await acquire();
|
|
361
|
+
const result = await sandbox.listFiles(p);
|
|
362
|
+
if (!result.success)
|
|
363
|
+
throw new Error(`listFiles failed for '${p}'`);
|
|
364
|
+
return result.files.map((f) => f.name);
|
|
365
|
+
},
|
|
366
|
+
catch: (err) => failed("read", err, p),
|
|
367
|
+
});
|
|
368
|
+
const mkdir = (p) => Effect.tryPromise({
|
|
369
|
+
try: async () => {
|
|
370
|
+
const sandbox = await acquire();
|
|
371
|
+
if (!sandbox.mkdir)
|
|
372
|
+
throw new Error("sandbox handle does not implement mkdir");
|
|
373
|
+
const result = await sandbox.mkdir(p, { recursive: true });
|
|
374
|
+
if (!result.success)
|
|
375
|
+
throw new Error(`mkdir failed for '${p}'`);
|
|
376
|
+
},
|
|
377
|
+
catch: (err) => failed("write", err, p),
|
|
378
|
+
});
|
|
379
|
+
const resolvePath = (p, cwd) => p.startsWith("/") ? normalizePosix(p) : normalizePosix(`${cwd || baseCwd}/${p}`);
|
|
380
|
+
const assertPathAllowed = (p) => {
|
|
381
|
+
// No roots configured: the container *is* the boundary, and there is
|
|
382
|
+
// nothing of the host's to escape to — same structural argument as the
|
|
383
|
+
// Vercel adapter and just-bash's mount namespace.
|
|
384
|
+
if (!allowedRoots || allowedRoots.length === 0)
|
|
385
|
+
return Effect.void;
|
|
386
|
+
const target = resolvePath(p, baseCwd);
|
|
387
|
+
const ok = allowedRoots.some((root) => target === root || target.startsWith(root.endsWith("/") ? root : `${root}/`));
|
|
388
|
+
return ok
|
|
389
|
+
? Effect.void
|
|
390
|
+
: Effect.fail(new SandboxError({
|
|
391
|
+
runId: "(sandbox)",
|
|
392
|
+
op: "read",
|
|
393
|
+
path: target,
|
|
394
|
+
message: `path '${target}' is outside the sandbox's allowed roots (${allowedRoots.join(", ")})`,
|
|
395
|
+
}));
|
|
396
|
+
};
|
|
397
|
+
const release = (op) => Effect.tryPromise({
|
|
398
|
+
try: async () => {
|
|
399
|
+
const pending = sandboxP;
|
|
400
|
+
if (!pending)
|
|
401
|
+
return;
|
|
402
|
+
// Reset first: the next op re-acquires.
|
|
403
|
+
sandboxP = null;
|
|
404
|
+
const sandbox = await pending.catch(() => null);
|
|
405
|
+
if (sandbox)
|
|
406
|
+
await op(sandbox);
|
|
407
|
+
},
|
|
408
|
+
catch: (err) => failed("exec", err),
|
|
409
|
+
});
|
|
410
|
+
return {
|
|
411
|
+
id,
|
|
412
|
+
// The container is a real isolation boundary, so `bash` composes safely.
|
|
413
|
+
capabilities: { shell: true },
|
|
414
|
+
run,
|
|
415
|
+
readFile,
|
|
416
|
+
writeFile,
|
|
417
|
+
readdir,
|
|
418
|
+
mkdir,
|
|
419
|
+
resolvePath,
|
|
420
|
+
assertPathAllowed,
|
|
421
|
+
stop: () => release(async () => { }),
|
|
422
|
+
destroy: () => release(async (sandbox) => {
|
|
423
|
+
if (sandbox.destroy)
|
|
424
|
+
await sandbox.destroy();
|
|
425
|
+
}),
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
//# sourceMappingURL=cloudflare-sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare-sandbox.js","sourceRoot":"","sources":["../src/cloudflare-sandbox.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@droveragent/sandbox-cloudflare",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0-next.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"homepage": "https://nc9.github.io/drover/",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/nc9/drover/issues"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Nik Cubrilovic",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/nc9/drover.git",
|
|
14
|
+
"directory": "packages/sandbox-cloudflare"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"typecheck": "tsgo --noEmit",
|
|
35
|
+
"test": "bun test",
|
|
36
|
+
"build": "tsc -p tsconfig.build.json && bun run ../../scripts/postbuild-dts.ts",
|
|
37
|
+
"prepublishOnly": "tsc -p tsconfig.build.json && bun run ../../scripts/postbuild-dts.ts"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@droveragent/core": "0.3.0-next.1",
|
|
41
|
+
"@droveragent/sandbox": "0.3.0-next.1",
|
|
42
|
+
"effect": "^3.10.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/README.md
DELETED