sandboxedjs 0.1.72 → 0.1.74

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 CHANGED
@@ -22,6 +22,27 @@ await box.exec("python3 -c 'print(2**64)'"); // → 18446744073709551616
22
22
  box.dispose();
23
23
  ```
24
24
 
25
+ ## Python packages with compiled extensions
26
+
27
+ `pip install` works for packages with C, Cython, Rust or Meson extensions. A
28
+ wheel built for this runtime is used when one exists; otherwise one is built
29
+ from source, from a recipe generated out of what PyPI and the package already
30
+ state.
31
+
32
+ ```js
33
+ configurePython({ buildFromSource: true }); // build here (Node)
34
+ configurePython({ buildFromSource: "http://localhost:4180/build" }); // ask a builder
35
+ ```
36
+
37
+ Browsers have no compiler, so they ask a machine that does:
38
+
39
+ ```bash
40
+ npx sandboxedjs-build-wheels 4180
41
+ ```
42
+
43
+ See `docs/python/build-on-miss.md`, and `docs/python/compatibility.md` for what
44
+ has been built and tested.
45
+
25
46
  ## Why
26
47
 
27
48
  Sometimes you need to run untrusted or generated code, give an AI agent a shell, build a
@@ -144,6 +165,17 @@ await session.run("echo $TOKEN in $(pwd)"); // → abc in /app
144
165
 
145
166
  ### Long-running processes
146
167
 
168
+ A job put in the background with `&` keeps running after the command that started it returns,
169
+ even from a stateless `exec`, and stops with `kill %N` in a session or when the container is
170
+ disposed:
171
+
172
+ ```ts
173
+ await box.exec("node server.js > /tmp/server.log 2>&1 &", { cwd: "/app" });
174
+ await box.waitForPort(3000);
175
+ ```
176
+
177
+ To hold the process yourself, spawn it:
178
+
147
179
  ```ts
148
180
  const proc = box.spawn("node server.js", { cwd: "/app" });
149
181
 
@@ -524,7 +556,10 @@ The container has no access to your filesystem, environment, or network unless y
524
556
  - The filesystem is entirely in memory. Code inside cannot read or write a host path — there is
525
557
  no `/Users`, no `/home/you`, no way to reach one.
526
558
  - Outbound network access is **off by default**; `curl https://…` fails until you pass
527
- `network: { allowOutbound: true }`, optionally narrowed with `allowedHosts`.
559
+ `network: { allowOutbound: true }`, optionally narrowed with `allowedHosts`. The same policy
560
+ binds a program's own `fetch`, `http`, `https` and `WebSocket`: a refused request fails with
561
+ `ENETUNREACH`. `localhost` and `127.0.0.1` always mean the container's own servers — never the
562
+ host's.
528
563
  - Host files enter only through `files`, `mount()` or `copyIn()`, and leave only through
529
564
  `copyOut()` or `fs.readFile()`.
530
565
  - `timeoutMs` bounds runaway commands, and `exec` settles even when a process ignores its kill
@@ -979,7 +1014,16 @@ Honest list of what does not work:
979
1014
  through is to answer **No** to a prompt like `npm create vite`'s "Install with npm and start
980
1015
  now?" and run `npm install && npm run dev` from the shell instead.
981
1016
  - **No `net`, `tls`, `worker_threads` or `vm`.** `http` and `https` are served by a virtual stack
982
- that `request()` talks to directly, so servers work; raw sockets do not.
1017
+ that `request()` talks to directly, so servers work; raw sockets do not. A program can reach
1018
+ servers anywhere in the container over HTTP (`http.get`, `fetch`), but not open a `WebSocket` to
1019
+ one.
1020
+ - **`node:test` covers what test files use** — `test`/`it`, `describe`, hooks, subtests, `skip`,
1021
+ `todo`, `only`, `mock.fn` and `mock.method`, with `spec` and `tap` reports — and `node --test`
1022
+ finds and runs test files as Node 22 does. `run()`, coverage and mock timers are not
1023
+ implemented. A test file exits when its tests finish, as under `--test-force-exit`.
1024
+ - **On the in-realm runtime, programs share one global object.** A global one program sets is
1025
+ visible to the next. The worker runtime (the default where shared memory is available) gives
1026
+ each program its own.
983
1027
  - **Python is source-built CPython/WASM.** Each program gets its own interpreter
984
1028
  process worker. Pure-Python wheels install normally; native extensions must
985
1029
  be linked or published for Emscripten. The bundled wheel index includes the
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * A wheel index that builds what it does not have.
4
+ *
5
+ * A browser cannot compile a C extension and never will, so "build it from
6
+ * source" there can only mean "ask a machine that can". This is that machine,
7
+ * reduced to the smallest thing that works: it serves the wheel index over
8
+ * HTTP, and it builds a package on request using the same pipeline and the
9
+ * same ABI contract as everything else.
10
+ *
11
+ * sandboxedjs-build-wheels [port=4180]
12
+ *
13
+ * Point a host at it:
14
+ *
15
+ * configurePython({
16
+ * wheelIndex: "http://localhost:4180",
17
+ * buildFromSource: "http://localhost:4180/build",
18
+ * });
19
+ *
20
+ * It binds loopback only. Building runs a package's own build system, which is
21
+ * arbitrary code execution by design, so exposing this to a network would be
22
+ * handing that to whoever can reach it.
23
+ */
24
+
25
+ import { createServer } from "node:http";
26
+ import { existsSync, readFileSync } from "node:fs";
27
+ import { dirname, join, resolve } from "node:path";
28
+ import { fileURLToPath } from "node:url";
29
+ import { spawn } from "node:child_process";
30
+
31
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "../python-runtime");
32
+ const wheels = join(root, "out/wheels");
33
+
34
+ if (!existsSync(join(root, "scripts/build_extension.py"))) {
35
+ console.error("sandboxedjs-build-wheels: the build pipeline is only present in a checkout");
36
+ process.exit(1);
37
+ }
38
+
39
+ const port = Number(process.argv[2] ?? 4180);
40
+ const building = new Map();
41
+ const finished = new Map();
42
+
43
+ const run = (args) => new Promise((done) => {
44
+ const child = spawn("python3", args, { cwd: root });
45
+ let stdout = "", stderr = "";
46
+ child.stdout.on("data", (c) => { stdout += String(c); });
47
+ child.stderr.on("data", (c) => { stderr += String(c); });
48
+ child.on("error", (e) => done({ code: -1, stdout, stderr: String(e) }));
49
+ child.on("close", (code) => done({ code: code ?? -1, stdout, stderr }));
50
+ });
51
+
52
+ async function build(requirement) {
53
+ const recipe = await run(["scripts/auto_recipe.py", requirement]);
54
+ if (recipe.code !== 0) {
55
+ let reported = {};
56
+ try { reported = JSON.parse(recipe.stdout.trim().split("\n").at(-1) ?? "{}"); } catch {}
57
+ return {
58
+ built: false,
59
+ classification: reported.classification ?? "blocked-toolchain",
60
+ reason: reported.reason ?? recipe.stderr.trim().slice(-400),
61
+ };
62
+ }
63
+ const path = recipe.stdout.trim().split("\n").at(-1);
64
+ const made = await run(["scripts/build_extension.py", path]);
65
+ if (made.code !== 0) {
66
+ return {
67
+ built: false, classification: "blocked-toolchain",
68
+ reason: `${made.stdout}\n${made.stderr}`.trim().split("\n").slice(-12).join("\n"),
69
+ };
70
+ }
71
+ const indexed = await run(["scripts/build_index.py"]);
72
+ if (indexed.code !== 0) {
73
+ return { built: false, classification: "blocked-toolchain", reason: indexed.stderr.slice(-300) };
74
+ }
75
+ return { built: true, classification: "supported-generic" };
76
+ }
77
+
78
+ const server = createServer(async (request, response) => {
79
+ const cors = {
80
+ "access-control-allow-origin": request.headers.origin ?? "*",
81
+ "access-control-allow-headers": "content-type",
82
+ "access-control-allow-methods": "GET,POST,OPTIONS",
83
+ };
84
+ if (request.method === "OPTIONS") { response.writeHead(204, cors).end(); return; }
85
+
86
+ const path = decodeURIComponent(new URL(request.url ?? "/", "http://localhost").pathname);
87
+
88
+ if (request.method === "POST" && path === "/build") {
89
+ const body = await new Promise((done) => {
90
+ let text = ""; request.on("data", (c) => { text += c; }); request.on("end", () => done(text));
91
+ });
92
+ let requirement = "";
93
+ try { requirement = String(JSON.parse(body || "{}").requirement ?? ""); } catch {}
94
+ /* Only a package name and optional pin. Anything else would be handed to a
95
+ * shell-adjacent build as an argument. */
96
+ if (!/^[A-Za-z0-9._-]+(==[A-Za-z0-9._+-]+)?$/.test(requirement)) {
97
+ response.writeHead(400, { ...cors, "content-type": "application/json" })
98
+ .end(JSON.stringify({ built: false, reason: "invalid requirement" }));
99
+ return;
100
+ }
101
+ /* Submit and poll, never one long request. A build takes minutes and an
102
+ * HTTP client -- especially one inside a sandboxed worker -- will drop a
103
+ * connection held open that long, which looks to the caller like the
104
+ * service being unreachable while it is in fact working. This is why the
105
+ * protocol in docs/python/build-on-miss.md has states rather than a single
106
+ * blocking call.
107
+ *
108
+ * One build per package: two identical requests are the same build. */
109
+ if (!building.has(requirement) && !finished.has(requirement)) {
110
+ console.log(`building ${requirement}`);
111
+ building.set(requirement, build(requirement).then((verdict) => {
112
+ console.log(` ${requirement}: ${verdict.built ? "built" : verdict.classification}`);
113
+ finished.set(requirement, verdict);
114
+ building.delete(requirement);
115
+ return verdict;
116
+ }));
117
+ }
118
+ const done = finished.get(requirement);
119
+ const verdict = done
120
+ ? { ...done, state: done.built ? "published" : "failed" }
121
+ : { state: "building-wheel" };
122
+ response.writeHead(200, { ...cors, "content-type": "application/json" })
123
+ .end(JSON.stringify(verdict));
124
+ return;
125
+ }
126
+
127
+ const name = path === "/" ? "/index.json" : path;
128
+ const file = join(wheels, name);
129
+ if (!file.startsWith(wheels) || !existsSync(file)) {
130
+ response.writeHead(404, cors).end("not found");
131
+ return;
132
+ }
133
+ response.writeHead(200, {
134
+ ...cors,
135
+ "content-type": name.endsWith(".json") ? "application/json" : "application/octet-stream",
136
+ }).end(readFileSync(file));
137
+ });
138
+
139
+ server.listen(port, "127.0.0.1", () => {
140
+ console.log(`SandboxedJs wheel builder: http://127.0.0.1:${port}`);
141
+ console.log(` index http://127.0.0.1:${port}/index.json`);
142
+ console.log(` build POST http://127.0.0.1:${port}/build {"requirement":"numpy"}`);
143
+ });
package/dist/agent.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Container } from './container-BwXE2J26.cjs';
2
- import './contracts-CVgctitO.cjs';
1
+ import { C as Container } from './container-DAWPIkGG.cjs';
2
+ import './contracts-C2_dTgk3.cjs';
3
3
 
4
4
  /**
5
5
  * Structural copies of the LangChain Deep Agents backend contract.
package/dist/agent.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Container } from './container-WPf_A76-.js';
2
- import './contracts-CVgctitO.js';
1
+ import { C as Container } from './container-CsLNpeyi.js';
2
+ import './contracts-C2_dTgk3.js';
3
3
 
4
4
  /**
5
5
  * Structural copies of the LangChain Deep Agents backend contract.
@@ -1,4 +1,4 @@
1
- import { V as Vfs, C as Cred, f as RuntimePod, D as DirEntry, p as Stats } from './contracts-CVgctitO.cjs';
1
+ import { V as Vfs, C as Cred, f as RuntimePod, O as OutboundPolicy, D as DirEntry, p as Stats } from './contracts-C2_dTgk3.js';
2
2
 
3
3
  /**
4
4
  * Byte streams for stdin/stdout/stderr, pipelines and redirections.
@@ -487,6 +487,8 @@ declare class NetworkStack {
487
487
  timeoutMs?: number;
488
488
  intervalMs?: number;
489
489
  }): Promise<boolean>;
490
+ /** The policy every way out of the container applies, not only the shell's. */
491
+ get policy(): OutboundPolicy;
490
492
  outboundAllowed(url: string): boolean;
491
493
  procNetDev(): string;
492
494
  procNetRoute(): string;
@@ -979,8 +981,13 @@ declare class Shell {
979
981
  captureSubshell(command: string): Promise<string>;
980
982
  /** `<(cmd)` — run the command now and hand back a path holding its output. */
981
983
  private makeProcessSubstitution;
982
- /** A copy that shares nothing mutable with this shell. */
983
- fork(): Shell;
984
+ /**
985
+ * A copy that shares nothing mutable with this shell.
986
+ *
987
+ * Subshells and pipeline stages run as part of this shell's process. A
988
+ * background job passes a process of its own, the way fork(2) gives one.
989
+ */
990
+ fork(proc?: Process): Shell;
984
991
  private currentIO;
985
992
  run(node: Node, io: ShellIO): Promise<number>;
986
993
  private runList;
@@ -1238,6 +1245,14 @@ interface PythonOptions {
1238
1245
  * no published wheel targets wasm32-emscripten.
1239
1246
  */
1240
1247
  wheelIndex?: WheelIndex | string | null;
1248
+ /**
1249
+ * Build a missing wheel instead of reporting it.
1250
+ *
1251
+ * `true` builds locally, which needs Node and the build pipeline. A URL asks
1252
+ * a build service -- which is how a browser gets a wheel built, having no
1253
+ * compiler of its own. See docs/python/build-on-miss.md.
1254
+ */
1255
+ buildFromSource?: boolean | string;
1241
1256
  }
1242
1257
  declare function configurePython(options?: PythonOptions): void;
1243
1258
  declare const isPythonAvailable: typeof isCPythonAvailable;
@@ -1535,6 +1550,14 @@ declare class Container {
1535
1550
  }): Session;
1536
1551
  /** The container-wide session used by `shell()` shorthand helpers. */
1537
1552
  get shell(): Session;
1553
+ /**
1554
+ * The streams one call collects into.
1555
+ *
1556
+ * They are detachable because a background job started by the command keeps
1557
+ * writing after the call has returned. Nothing reads the result any more by
1558
+ * then, so without `detach` a chatty server would grow the buffer for as long
1559
+ * as it ran; afterwards its output still reaches the container-wide taps.
1560
+ */
1538
1561
  private makeStdio;
1539
1562
  /** Send an HTTP request to a server running inside the container. */
1540
1563
  request(port: number, init?: {
@@ -1,4 +1,4 @@
1
- import { V as Vfs, C as Cred, f as RuntimePod, D as DirEntry, p as Stats } from './contracts-CVgctitO.js';
1
+ import { V as Vfs, C as Cred, f as RuntimePod, O as OutboundPolicy, D as DirEntry, p as Stats } from './contracts-C2_dTgk3.cjs';
2
2
 
3
3
  /**
4
4
  * Byte streams for stdin/stdout/stderr, pipelines and redirections.
@@ -487,6 +487,8 @@ declare class NetworkStack {
487
487
  timeoutMs?: number;
488
488
  intervalMs?: number;
489
489
  }): Promise<boolean>;
490
+ /** The policy every way out of the container applies, not only the shell's. */
491
+ get policy(): OutboundPolicy;
490
492
  outboundAllowed(url: string): boolean;
491
493
  procNetDev(): string;
492
494
  procNetRoute(): string;
@@ -979,8 +981,13 @@ declare class Shell {
979
981
  captureSubshell(command: string): Promise<string>;
980
982
  /** `<(cmd)` — run the command now and hand back a path holding its output. */
981
983
  private makeProcessSubstitution;
982
- /** A copy that shares nothing mutable with this shell. */
983
- fork(): Shell;
984
+ /**
985
+ * A copy that shares nothing mutable with this shell.
986
+ *
987
+ * Subshells and pipeline stages run as part of this shell's process. A
988
+ * background job passes a process of its own, the way fork(2) gives one.
989
+ */
990
+ fork(proc?: Process): Shell;
984
991
  private currentIO;
985
992
  run(node: Node, io: ShellIO): Promise<number>;
986
993
  private runList;
@@ -1238,6 +1245,14 @@ interface PythonOptions {
1238
1245
  * no published wheel targets wasm32-emscripten.
1239
1246
  */
1240
1247
  wheelIndex?: WheelIndex | string | null;
1248
+ /**
1249
+ * Build a missing wheel instead of reporting it.
1250
+ *
1251
+ * `true` builds locally, which needs Node and the build pipeline. A URL asks
1252
+ * a build service -- which is how a browser gets a wheel built, having no
1253
+ * compiler of its own. See docs/python/build-on-miss.md.
1254
+ */
1255
+ buildFromSource?: boolean | string;
1241
1256
  }
1242
1257
  declare function configurePython(options?: PythonOptions): void;
1243
1258
  declare const isPythonAvailable: typeof isCPythonAvailable;
@@ -1535,6 +1550,14 @@ declare class Container {
1535
1550
  }): Session;
1536
1551
  /** The container-wide session used by `shell()` shorthand helpers. */
1537
1552
  get shell(): Session;
1553
+ /**
1554
+ * The streams one call collects into.
1555
+ *
1556
+ * They are detachable because a background job started by the command keeps
1557
+ * writing after the call has returned. Nothing reads the result any more by
1558
+ * then, so without `detach` a chatty server would grow the buffer for as long
1559
+ * as it ran; afterwards its output still reaches the container-wide taps.
1560
+ */
1538
1561
  private makeStdio;
1539
1562
  /** Send an HTTP request to a server running inside the container. */
1540
1563
  request(port: number, init?: {
@@ -347,6 +347,27 @@ declare class VirtualTcpNetwork {
347
347
  closeAll(): void;
348
348
  }
349
349
 
350
+ /**
351
+ * The outbound network policy, as plain functions every client consults.
352
+ *
353
+ * The container has several ways out — `curl` and `wget` in the shell, `http`,
354
+ * `https`, `fetch` and `WebSocket` in a Node program, sockets in Python — and
355
+ * they used to decide separately. Only the shell asked: a Node program's
356
+ * `fetch("https://…")` reached the internet from a container booted with
357
+ * outbound access off. One policy, applied at each exit, is what makes
358
+ * `network: { allowOutbound: false }` mean what it says.
359
+ *
360
+ * Loopback is not "outbound" at all. `127.0.0.1` inside the container is the
361
+ * container, so those requests are routed to its own servers and never handed
362
+ * to the host's network stack, whatever the policy allows.
363
+ */
364
+ interface OutboundPolicy {
365
+ /** Whether requests may leave the container at all. */
366
+ allowOutbound: boolean;
367
+ /** When outbound is on, the hosts it may reach (subdomains included). `null` means any. */
368
+ allowedHosts: string[] | null;
369
+ }
370
+
350
371
  /**
351
372
  * Clean-room contracts between SandboxedJS and its JavaScript runtime.
352
373
  *
@@ -479,9 +500,17 @@ interface RuntimePod {
479
500
  headers: Record<string, string>;
480
501
  body: Uint8Array;
481
502
  }) => Promise<RuntimeHttpResponse>): () => void;
503
+ /**
504
+ * Apply the container's outbound policy to programs this pod runs.
505
+ *
506
+ * Optional so a pod written elsewhere still satisfies the contract, but a pod
507
+ * without it cannot keep a program's own `fetch` inside the policy — only
508
+ * the shell's `curl` would honour it.
509
+ */
510
+ setNetworkPolicy?(policy: OutboundPolicy): void;
482
511
  snapshot(options?: Record<string, unknown>): unknown;
483
512
  restore(snapshot: unknown, options?: Record<string, unknown>): Promise<void>;
484
513
  teardown(): void;
485
514
  }
486
515
 
487
- export { type Cred as C, type DirEntry as D, type RuntimeVolume as R, type SpawnChild as S, Vfs as V, type WriteOptions as W, VirtualTcpNetwork as a, type RuntimeHttpResponse as b, type SyncSpawn as c, type VolumeStat as d, type VolumeStats as e, type RuntimePod as f, type RuntimePackageInstaller as g, type ChildSpawnConfig as h, type ChildHandle as i, type RuntimeProcess as j, type RuntimeSocketPeer as k, type RuntimeConnection as l, ROOT_CRED as m, type RuntimeProcessManager as n, type RuntimeProcessResult as o, Stats as p, type VirtualNode as q, type VirtualProvider as r, applyChmod as s, createChildProcessModule as t, formatMode as u, makeCred as v, octalMode as w, parseUmask as x };
516
+ export { type Cred as C, type DirEntry as D, type OutboundPolicy as O, type RuntimeVolume as R, type SpawnChild as S, Vfs as V, type WriteOptions as W, VirtualTcpNetwork as a, type RuntimeHttpResponse as b, type SyncSpawn as c, type VolumeStat as d, type VolumeStats as e, type RuntimePod as f, type RuntimePackageInstaller as g, type ChildSpawnConfig as h, type ChildHandle as i, type RuntimeProcess as j, type RuntimeSocketPeer as k, type RuntimeConnection as l, ROOT_CRED as m, type RuntimeProcessManager as n, type RuntimeProcessResult as o, Stats as p, type VirtualNode as q, type VirtualProvider as r, applyChmod as s, createChildProcessModule as t, formatMode as u, makeCred as v, octalMode as w, parseUmask as x };
@@ -347,6 +347,27 @@ declare class VirtualTcpNetwork {
347
347
  closeAll(): void;
348
348
  }
349
349
 
350
+ /**
351
+ * The outbound network policy, as plain functions every client consults.
352
+ *
353
+ * The container has several ways out — `curl` and `wget` in the shell, `http`,
354
+ * `https`, `fetch` and `WebSocket` in a Node program, sockets in Python — and
355
+ * they used to decide separately. Only the shell asked: a Node program's
356
+ * `fetch("https://…")` reached the internet from a container booted with
357
+ * outbound access off. One policy, applied at each exit, is what makes
358
+ * `network: { allowOutbound: false }` mean what it says.
359
+ *
360
+ * Loopback is not "outbound" at all. `127.0.0.1` inside the container is the
361
+ * container, so those requests are routed to its own servers and never handed
362
+ * to the host's network stack, whatever the policy allows.
363
+ */
364
+ interface OutboundPolicy {
365
+ /** Whether requests may leave the container at all. */
366
+ allowOutbound: boolean;
367
+ /** When outbound is on, the hosts it may reach (subdomains included). `null` means any. */
368
+ allowedHosts: string[] | null;
369
+ }
370
+
350
371
  /**
351
372
  * Clean-room contracts between SandboxedJS and its JavaScript runtime.
352
373
  *
@@ -479,9 +500,17 @@ interface RuntimePod {
479
500
  headers: Record<string, string>;
480
501
  body: Uint8Array;
481
502
  }) => Promise<RuntimeHttpResponse>): () => void;
503
+ /**
504
+ * Apply the container's outbound policy to programs this pod runs.
505
+ *
506
+ * Optional so a pod written elsewhere still satisfies the contract, but a pod
507
+ * without it cannot keep a program's own `fetch` inside the policy — only
508
+ * the shell's `curl` would honour it.
509
+ */
510
+ setNetworkPolicy?(policy: OutboundPolicy): void;
482
511
  snapshot(options?: Record<string, unknown>): unknown;
483
512
  restore(snapshot: unknown, options?: Record<string, unknown>): Promise<void>;
484
513
  teardown(): void;
485
514
  }
486
515
 
487
- export { type Cred as C, type DirEntry as D, type RuntimeVolume as R, type SpawnChild as S, Vfs as V, type WriteOptions as W, VirtualTcpNetwork as a, type RuntimeHttpResponse as b, type SyncSpawn as c, type VolumeStat as d, type VolumeStats as e, type RuntimePod as f, type RuntimePackageInstaller as g, type ChildSpawnConfig as h, type ChildHandle as i, type RuntimeProcess as j, type RuntimeSocketPeer as k, type RuntimeConnection as l, ROOT_CRED as m, type RuntimeProcessManager as n, type RuntimeProcessResult as o, Stats as p, type VirtualNode as q, type VirtualProvider as r, applyChmod as s, createChildProcessModule as t, formatMode as u, makeCred as v, octalMode as w, parseUmask as x };
516
+ export { type Cred as C, type DirEntry as D, type OutboundPolicy as O, type RuntimeVolume as R, type SpawnChild as S, Vfs as V, type WriteOptions as W, VirtualTcpNetwork as a, type RuntimeHttpResponse as b, type SyncSpawn as c, type VolumeStat as d, type VolumeStats as e, type RuntimePod as f, type RuntimePackageInstaller as g, type ChildSpawnConfig as h, type ChildHandle as i, type RuntimeProcess as j, type RuntimeSocketPeer as k, type RuntimeConnection as l, ROOT_CRED as m, type RuntimeProcessManager as n, type RuntimeProcessResult as o, Stats as p, type VirtualNode as q, type VirtualProvider as r, applyChmod as s, createChildProcessModule as t, formatMode as u, makeCred as v, octalMode as w, parseUmask as x };