@nimbus-sh/worker 0.2.3 → 0.4.0

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.
Files changed (146) hide show
  1. package/dist/_shared/session-router.d.ts +8 -0
  2. package/dist/_shared/session-router.d.ts.map +1 -1
  3. package/dist/_shared/session-router.js +8 -0
  4. package/dist/esbuild-wasm-bundle.generated.d.ts +1 -1
  5. package/dist/esbuild-wasm-bundle.generated.js +1 -1
  6. package/dist/facets/cirrus-real.js +1 -1
  7. package/dist/facets/manager.d.ts +43 -129
  8. package/dist/facets/manager.d.ts.map +1 -1
  9. package/dist/facets/manager.js +107 -318
  10. package/dist/facets/opencode-staging.d.ts +1 -1
  11. package/dist/facets/opencode-staging.d.ts.map +1 -1
  12. package/dist/facets/opencode-staging.js +3 -0
  13. package/dist/facets/real-vite-hmr.js +1 -1
  14. package/dist/facets/vite-dev-server.d.ts +4 -4
  15. package/dist/facets/vite-dev-server.js +5 -5
  16. package/dist/git/commands.d.ts +8 -0
  17. package/dist/git/commands.d.ts.map +1 -1
  18. package/dist/git/commands.js +41 -9
  19. package/dist/git/network-facet.d.ts +1 -1
  20. package/dist/git/network-facet.d.ts.map +1 -1
  21. package/dist/git/network-facet.js +39 -15
  22. package/dist/git-bundle.generated.d.ts +2 -2
  23. package/dist/git-bundle.generated.d.ts.map +1 -1
  24. package/dist/git-bundle.generated.js +3 -3
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +9 -1
  27. package/dist/loaders/child-process/spawn-facet.js +1 -1
  28. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  29. package/dist/loaders/child-process/spawn-pool.js +2 -2
  30. package/dist/loaders/generated-workers.d.ts +2 -2
  31. package/dist/loaders/generated-workers.d.ts.map +1 -1
  32. package/dist/loaders/generated-workers.js +3 -3
  33. package/dist/loaders/npm-resolve-preamble.d.ts +3 -3
  34. package/dist/loaders/npm-resolve-preamble.js +3 -3
  35. package/dist/loaders/pre-bundle-preamble.d.ts +5 -5
  36. package/dist/loaders/pre-bundle-preamble.js +6 -6
  37. package/dist/loaders/process-host.d.ts +6 -107
  38. package/dist/loaders/process-host.d.ts.map +1 -1
  39. package/dist/loaders/process-host.js +6 -405
  40. package/dist/npm/install-batch-facet.d.ts +1 -1
  41. package/dist/npm/install-batch-facet.js +1 -1
  42. package/dist/npm/installer.d.ts +6 -6
  43. package/dist/npm/installer.d.ts.map +1 -1
  44. package/dist/npm/installer.js +28 -27
  45. package/dist/npm/pre-bundle-facet.d.ts +2 -2
  46. package/dist/npm/pre-bundle-facet.js +5 -5
  47. package/dist/npm/r2-cache.d.ts +1 -1
  48. package/dist/npm/resolve-facet.d.ts +1 -1
  49. package/dist/npm/resolve-facet.js +1 -1
  50. package/dist/npm/resolve-one-facet.d.ts +5 -5
  51. package/dist/npm/resolve-one-facet.js +5 -5
  52. package/dist/router/index.js +2 -2
  53. package/dist/router/remote-api.js +9 -1
  54. package/dist/runtime/bun-repl.d.ts +1 -1
  55. package/dist/runtime/bun-repl.js +3 -3
  56. package/dist/runtime/esbuild-wasm-bytes.js +1 -1
  57. package/dist/runtime/facet-loader-host.d.ts +5 -8
  58. package/dist/runtime/facet-loader-host.d.ts.map +1 -1
  59. package/dist/runtime/facet-loader-host.js +7 -11
  60. package/dist/runtime/node-repl.js +2 -2
  61. package/dist/runtime/node-shims-artifact.js +1 -1
  62. package/dist/runtime/node-shims.js +2 -1
  63. package/dist/runtime/opencode-artifact.js +1 -1
  64. package/dist/runtime/opentui-wasm-bytes.js +1 -1
  65. package/dist/runtime/python-repl.js +3 -3
  66. package/dist/runtime/ruby-repl.js +2 -2
  67. package/dist/runtime/ruby-resident.js +1 -1
  68. package/dist/runtime/sqlite-wasm-bytes.js +1 -1
  69. package/dist/session/diag.js +1 -1
  70. package/dist/session/hibernation.d.ts +20 -53
  71. package/dist/session/hibernation.d.ts.map +1 -1
  72. package/dist/session/hibernation.js +57 -194
  73. package/dist/session/init-phases.d.ts +2 -3
  74. package/dist/session/init-phases.d.ts.map +1 -1
  75. package/dist/session/init-phases.js +3 -2
  76. package/dist/session/init.d.ts.map +1 -1
  77. package/dist/session/init.js +8 -4
  78. package/dist/session/keys.d.ts +14 -37
  79. package/dist/session/keys.d.ts.map +1 -1
  80. package/dist/session/keys.js +18 -37
  81. package/dist/session/nimbus-session.d.ts +10 -15
  82. package/dist/session/nimbus-session.d.ts.map +1 -1
  83. package/dist/session/nimbus-session.js +28 -31
  84. package/dist/session/port-capability.d.ts +43 -0
  85. package/dist/session/port-capability.d.ts.map +1 -0
  86. package/dist/session/port-capability.js +49 -0
  87. package/dist/session/programmatic.d.ts +39 -5
  88. package/dist/session/programmatic.d.ts.map +1 -1
  89. package/dist/session/programmatic.js +150 -19
  90. package/dist/session/routes.d.ts +2 -0
  91. package/dist/session/routes.d.ts.map +1 -1
  92. package/dist/session/routes.js +96 -20
  93. package/dist/session/rpc.d.ts +36 -9
  94. package/dist/session/rpc.d.ts.map +1 -1
  95. package/dist/session/rpc.js +84 -24
  96. package/dist/session/start-real-vite.d.ts.map +1 -1
  97. package/dist/session/start-real-vite.js +3 -1
  98. package/dist/session/state-store.d.ts +3 -2
  99. package/dist/session/state-store.d.ts.map +1 -1
  100. package/dist/session/state-store.js +3 -2
  101. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  102. package/dist/session/supervisor-rpc.js +7 -4
  103. package/dist/session/ws.d.ts +1 -3
  104. package/dist/session/ws.d.ts.map +1 -1
  105. package/dist/session/ws.js +4 -3
  106. package/dist/wrangler/nimbus-wrangler.js +1 -1
  107. package/package.json +4 -2
  108. package/scripts/bundle-esbuild-wasm.mjs +2 -2
  109. package/scripts/bundle-facet-workers.mjs +5 -7
  110. package/scripts/bundle-sqlite-wasm.mjs +1 -1
  111. package/dist/facets/inner-do-registry.d.ts +0 -41
  112. package/dist/facets/inner-do-registry.d.ts.map +0 -1
  113. package/dist/facets/inner-do-registry.js +0 -51
  114. package/dist/facets/launch-pacer.d.ts +0 -111
  115. package/dist/facets/launch-pacer.d.ts.map +0 -1
  116. package/dist/facets/launch-pacer.js +0 -130
  117. package/dist/loaders/fanout-pool.d.ts +0 -207
  118. package/dist/loaders/fanout-pool.d.ts.map +0 -1
  119. package/dist/loaders/fanout-pool.js +0 -363
  120. package/dist/loaders/loader-pool.d.ts +0 -294
  121. package/dist/loaders/loader-pool.d.ts.map +0 -1
  122. package/dist/loaders/loader-pool.js +0 -642
  123. package/dist/loaders/process-fabric.d.ts +0 -509
  124. package/dist/loaders/process-fabric.d.ts.map +0 -1
  125. package/dist/loaders/process-fabric.js +0 -360
  126. package/dist/loaders/vendor/errors.d.ts +0 -24
  127. package/dist/loaders/vendor/errors.d.ts.map +0 -1
  128. package/dist/loaders/vendor/errors.js +0 -46
  129. package/dist/loaders/vendor/serialize.d.ts +0 -3
  130. package/dist/loaders/vendor/serialize.d.ts.map +0 -1
  131. package/dist/loaders/vendor/serialize.js +0 -25
  132. package/dist/loaders/vendor/types.d.ts +0 -69
  133. package/dist/loaders/vendor/types.d.ts.map +0 -1
  134. package/dist/loaders/vendor/types.js +0 -4
  135. package/dist/loaders/workerd-facet-host.d.ts +0 -141
  136. package/dist/loaders/workerd-facet-host.d.ts.map +0 -1
  137. package/dist/loaders/workerd-facet-host.js +0 -284
  138. package/dist/session/bindings.d.ts +0 -209
  139. package/dist/session/bindings.d.ts.map +0 -1
  140. package/dist/session/bindings.js +0 -680
  141. package/dist/session/ctx-exports.d.ts +0 -16
  142. package/dist/session/ctx-exports.d.ts.map +0 -1
  143. package/dist/session/ctx-exports.js +0 -22
  144. package/dist/session/ws-hibernation-config.d.ts +0 -64
  145. package/dist/session/ws-hibernation-config.d.ts.map +0 -1
  146. package/dist/session/ws-hibernation-config.js +0 -89
@@ -1,360 +0,0 @@
1
- /**
2
- * process-fabric.ts — the resident-process scheduler, and the process half of
3
- * the substrate it runs on.
4
- *
5
- * Every long-lived process Nimbus runs — node servers, python/ruby socket
6
- * servers, the opencode TUI and its headless server — runs as a **DO Facet**:
7
- * a named child actor whose class comes from a dynamic worker, opened by
8
- * `openResidentFacet` in `loaders/workerd-facet-host.ts`.
9
- *
10
- * ctx.facets.get(`proc-${pid}`, () => ({
11
- * class: env.LOADER.get(workerKey, buildConfig)
12
- * .getDurableObjectClass('NimbusProcess'),
13
- * }))
14
- *
15
- * There is ONE process implementation. What varies is WHOSE `ctx` and `env`
16
- * that call runs against — the user's own session DO, or a sibling DO acting
17
- * as a host — and that choice is a single deployment-wide config value read in
18
- * `loaders/process-host.ts`. Nothing here, and nothing above here, branches on
19
- * which program is running: no spawn site picks its own substrate, and no
20
- * program name, mode or payload size reaches the selection.
21
- *
22
- * What each substrate costs, all of it measured on the production
23
- * compatibility shape (see `loaders/process-host.ts` for the operator-facing
24
- * version of this table):
25
- *
26
- * facet — spawn 8-16 ms warm. Memory independent: its OWN ~208 MiB
27
- * envelope, identical whether the coordinator holds 0 or 128 MiB,
28
- * with 1,664 MiB live across 8 facets + parent. CPU SHARED with
29
- * its siblings, because facets are separate isolates inside one
30
- * actor thread: awaiting I/O yields that thread completely (a
31
- * sibling's RPC latency while a facet parks on a socket, on stdin
32
- * or on an outbound call is indistinguishable from idle) but
33
- * sustained CPU stalls every sibling for its full duration —
34
- * a python HTTP server at 32-way saturation held siblings under
35
- * 1.06 s (p50 231 ms), the opencode attach TUI held them at the
36
- * 77 ms idle baseline, and a deliberate 9,956 ms CPU burn stalled
37
- * them for 9,966 ms.
38
- * peer — spawn 242-359 ms, because every spawn pays a DO create plus a
39
- * SQLite open. Memory AND CPU both independent: the process runs
40
- * in a different workerd process, verified per placement rather
41
- * than assumed (see `_place` in `loaders/process-host.ts`).
42
- *
43
- * Both give the process its own SQLite. Neither changes what the process is:
44
- * the runner, the boot spec, the class name, the writer handshake and the
45
- * lifecycle contract are the same code either way.
46
- *
47
- * The facet's SUPERVISOR binding is minted for the COORDINATOR's doId, so
48
- * every syscall — VFS read/write, stdout/stderr frames, stdin pump,
49
- * registerPort, loopback HTTP — lands on the user's session DO wherever the
50
- * process runs. Because that binding is minted by an actor rather than by a
51
- * stateless entrypoint, it lives as long as the process does; nothing has to
52
- * hold a call open to keep it alive.
53
- *
54
- * Boot specs
55
- * ──────────
56
- * A resident process boots from one of two specs, and in both cases the module
57
- * map is assembled LAZILY inside the loader's cache-miss callback — so the
58
- * artifact sources are materialized only when the facet actually starts, and
59
- * only for as long as the load takes:
60
- *
61
- * staged — an OpencodeStageSpec; `assembleOpencodeFacetConfig` fetches the
62
- * artifact sources from ASSETS.
63
- * code — a generated module map (node / python / ruby runners). Fixed-size
64
- * module text rides inline; anything sized by the user's disk is
65
- * named BY VFS PATH and read through the injected disk reader. A
66
- * ruby server's `ruby+stdlib.wasm` alone is 34.3 MiB and a node
67
- * facet's disk snapshot reached 44 MB for pi.
68
- *
69
- * By-path is what lets a boot spec reach EITHER substrate. Inline, pi's node
70
- * snapshot serialized to 44,252,709 bytes and died at workerd's 32 MiB RPC
71
- * ceiling the moment it had to cross to a peer; named by path it sends zero
72
- * bytes, and the host reads them off the coordinator's own disk through the
73
- * `ResidentDiskReader` it was given.
74
- */
75
- import { z } from 'zod/v4';
76
- import { OpencodeStageSpecSchema } from '../facets/opencode-staging.js';
77
- /**
78
- * The class every generated resident runner exports. One name for every
79
- * runtime: the fabric names it unconditionally, so nothing about which program
80
- * is running reaches this module.
81
- */
82
- export const RESIDENT_PROCESS_CLASS = 'NimbusProcess';
83
- /**
84
- * A generated module map. Only bounded, fixed-size module text rides inline;
85
- * anything whose size is a function of the user's disk is named by VFS path
86
- * and read when the facet loads, so the bytes are transient rather than
87
- * resident in the coordinator's heap.
88
- */
89
- export const ResidentCodeSpecSchema = z.object({
90
- compatibilityDate: z.string().min(1),
91
- compatibilityFlags: z.array(z.string()),
92
- mainModule: z.string().min(1),
93
- /**
94
- * Inline modules: fixed-size generated source, plus small wasm sidecars that
95
- * come from the worker's own ASSETS rather than the user's disk.
96
- */
97
- modules: z.record(z.string(), z.union([z.string(), z.object({ wasm: z.instanceof(ArrayBuffer) })])),
98
- /**
99
- * Module name → absolute VFS path of a wasm image to materialize at load.
100
- * This is how the big user-installed runtimes travel: ruby's
101
- * interpreter+stdlib image alone is 34.3 MiB.
102
- */
103
- vfsWasmModules: z.record(z.string(), z.string()).optional(),
104
- /**
105
- * Module name → absolute VFS path of a GENERATED module source, read as
106
- * UTF-8 at load. The same by-path posture as `vfsWasmModules`, for module
107
- * text whose size is a function of the user's disk.
108
- *
109
- * A node facet carries a snapshot of that disk, and it is the largest thing
110
- * Nimbus generates: pi's is 3096 cells and inline it serialized to
111
- * 44,252,709 bytes. That text cannot be rebuilt from the user's files at
112
- * load time either — two thirds of the cells are esbuild ESM→CJS output, and
113
- * the manifest and metadata members are walks of the tree rather than files
114
- * in it. So the generator materializes its output in the content-addressed
115
- * image store below and the spec names it.
116
- */
117
- vfsTextModules: z.record(z.string(), z.string()).optional(),
118
- });
119
- export const ResidentBootSpecSchema = z.discriminatedUnion('kind', [
120
- z.object({ kind: z.literal('staged'), stage: OpencodeStageSpecSchema }),
121
- z.object({ kind: z.literal('code'), code: ResidentCodeSpecSchema }),
122
- ]);
123
- // ── Boot-image store ────────────────────────────────────────────────────────
124
- /**
125
- * Where a generated module source is materialized so a boot spec can name it.
126
- *
127
- * Outside any user working tree on purpose. The passes that build a node
128
- * facet's snapshot enumerate the process's cwd, so an image written under one
129
- * would be swept into the next snapshot — and that snapshot is what produced
130
- * the image, so each spawn would grow the thing it just wrote.
131
- *
132
- * Kernel-owned and world-readable: the generator writes as CRED_KERNEL, and
133
- * every process reads through a supervisor binding that enforces its own
134
- * credential. Mode 0644 is what makes the read succeed for any process by
135
- * construction rather than by a privilege carve-out in the permission layer,
136
- * and leaves the bytes beyond reach of the user whose program they encode.
137
- */
138
- export const FACET_IMAGE_DIR = 'var/lib/nimbus/facet-images';
139
- /**
140
- * An image is named by the SHA-256 of its own bytes, so its name IS its
141
- * integrity check and a stale image is not something to invalidate but
142
- * something that cannot be addressed: different generated text is a different
143
- * path.
144
- *
145
- * What that actually dedups, measured on a deployed worker rather than
146
- * assumed: a RESTART resolves to the image already there, because the fabric
147
- * replays one unchanged boot spec. Two separate spawns of the same tool do
148
- * NOT, whenever the generated text carries anything per-process: an
149
- * attached-TTY spawn bakes `NIMBUS_CP_CHILD_PID` into `__NIMBUS_ARGS`, so `pi`
150
- * twice wrote two images (2c3a90ad… then c5b74f1a…). A spawn with no attached
151
- * TTY has no pid in its args and does dedup. Lifting argv/env/pid out of the
152
- * generated text into `startArgs` would make every image per-PROGRAM and
153
- * shareable across spawns and sessions; the sweep bounds the store either way.
154
- */
155
- export async function facetImageDigest(source) {
156
- const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(source));
157
- return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('');
158
- }
159
- export function facetImagePath(digest) {
160
- return `/${FACET_IMAGE_DIR}/${digest}.js`;
161
- }
162
- /**
163
- * The digest an image path claims, for the reader's verify-on-read. Content
164
- * addressing only holds if the bytes are checked against the name they were
165
- * fetched under; without that a truncated or overwritten image boots as
166
- * silently-wrong code, which in a facet surfaces as an unattributable
167
- * "Cannot find module" a long way from the corruption.
168
- */
169
- export function facetImagePathDigest(path) {
170
- const match = /(?:^|\/)([0-9a-f]{64})\.js$/.exec(path);
171
- return match ? match[1] : null;
172
- }
173
- /**
174
- * Complete a resident-process module map: read every member the spec named by
175
- * path, verifying each generated image against the digest its own path claims.
176
- * Runs inside the loader's cache-miss callback, so the bytes exist only for
177
- * the duration of the load.
178
- */
179
- export async function residentLoaderConfig(spec, disk) {
180
- const resolved = {};
181
- for (const [moduleName, path] of Object.entries(spec.vfsWasmModules ?? {})) {
182
- const bytes = await disk.readFile(path);
183
- resolved[moduleName] = {
184
- wasm: bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength),
185
- };
186
- }
187
- for (const [moduleName, path] of Object.entries(spec.vfsTextModules ?? {})) {
188
- resolved[moduleName] = await readFacetImage(disk, path);
189
- }
190
- return {
191
- compatibilityDate: spec.compatibilityDate,
192
- compatibilityFlags: spec.compatibilityFlags,
193
- mainModule: spec.mainModule,
194
- modules: { ...spec.modules, ...resolved },
195
- };
196
- }
197
- /**
198
- * Read one content-addressed facet image and verify it against the digest its
199
- * path claims. Content addressing is only a guarantee if the bytes are checked
200
- * against the name they arrived under: an image that was truncated, or
201
- * replaced by something the generator never wrote, would otherwise be loaded
202
- * as the program and fail somewhere inside it with no way back to the cause.
203
- */
204
- async function readFacetImage(disk, path) {
205
- const expected = facetImagePathDigest(path);
206
- if (!expected) {
207
- throw new Error(`Nimbus: '${path}' is not a content-addressed facet image path`);
208
- }
209
- const source = new TextDecoder().decode(await disk.readFile(path));
210
- const actual = await facetImageDigest(source);
211
- if (actual !== expected) {
212
- throw new Error(`Nimbus: facet image '${path}' does not match its digest (read ${actual}); `
213
- + 'the image store is corrupt and the process cannot boot from it');
214
- }
215
- return source;
216
- }
217
- // ── Handle ──────────────────────────────────────────────────────────────────
218
- /**
219
- * Resource handle for one resident process — the whole surface the kernel
220
- * above this module sees: `booted()` for the boot payload, `done` for death,
221
- * `kill()` for teardown, `routeTarget` for inbound HTTP. Substrate-free: the
222
- * kernel cannot tell from it where the process is running, and never asks.
223
- *
224
- * `done` settles when the process ends: for a `lifetime` runner that is its
225
- * held-open startProcess settling (resolve on exit, reject on host death);
226
- * for a `boot` runner it is the kill that releases the host.
227
- *
228
- * The handle is disposable so FacetManager's existing per-pid resource
229
- * tracking tears a process down exactly the way it releases any other
230
- * per-process resource.
231
- */
232
- export class ResidentProcessHandle {
233
- done;
234
- /**
235
- * Inbound-HTTP target for PortRegistry: the running facet's own stub. A
236
- * facet is a child actor, so its stub stays usable in request contexts long
237
- * after the one that created it — which is the whole reason a resident
238
- * process can serve a port at all.
239
- */
240
- routeTarget;
241
- #booted;
242
- #kill;
243
- #killed = false;
244
- #describe;
245
- constructor(init) {
246
- this.done = init.done;
247
- this.#booted = init.booted;
248
- this.routeTarget = init.routeTarget;
249
- this.#kill = init.kill;
250
- this.#describe = init.describe;
251
- // Symbol.dispose may be absent from older lib targets; wire defensively
252
- // so disposeRpcResource() (which probes for it) finds the disposer.
253
- const disposeSym = Symbol.dispose;
254
- if (disposeSym) {
255
- Object.defineProperty(this, disposeSym, { value: () => this.kill() });
256
- }
257
- }
258
- /**
259
- * The runner's startProcess payload. The runner is started as part of the
260
- * spawn, so this is a handle on that one boot — awaiting it twice is safe
261
- * and never re-starts anything. For a `lifetime` runner it settles at exit.
262
- */
263
- booted() {
264
- return this.#booted();
265
- }
266
- get killed() {
267
- return this.#killed;
268
- }
269
- /** Human-readable placement, for the NIMBUS_DEBUG process-log line. */
270
- describePlacement() {
271
- return this.#describe();
272
- }
273
- /** Idempotent: abort the facet and release its isolate. */
274
- kill() {
275
- if (this.#killed)
276
- return;
277
- this.#killed = true;
278
- try {
279
- this.#kill();
280
- }
281
- catch { /* best-effort teardown */ }
282
- }
283
- }
284
- /** A promise that settles only when the process is killed. */
285
- function heldUntilKilled() {
286
- let release = () => { };
287
- const promise = new Promise((resolve) => { release = resolve; });
288
- return { promise, release };
289
- }
290
- export class ProcessFabric {
291
- host;
292
- constructor(host) {
293
- this.host = host;
294
- }
295
- /**
296
- * Boot a resident process on this deployment's substrate and return its
297
- * handle. Resolves once the process is up and its runner has been started;
298
- * rejects on boot failure.
299
- *
300
- * There is no decision in here. The substrate was chosen once, for the
301
- * deployment, and the only thing this method knows about it is the
302
- * `ProcessHost` interface.
303
- */
304
- async startResidentProcess(spawn) {
305
- // The facet-local append sequence starts at one when its module evaluates.
306
- // Bind that sequence to this concrete incarnation, then retire it only
307
- // after the host is released; a later incarnation must use a fresh one.
308
- const writerId = crypto.randomUUID();
309
- spawn.onWriterActivated(writerId);
310
- let hosted;
311
- try {
312
- hosted = await this.host.open({
313
- pid: spawn.pid,
314
- workerKey: spawn.workerKey,
315
- boot: spawn.boot,
316
- writerId,
317
- startArgs: spawn.startArgs,
318
- });
319
- }
320
- catch (error) {
321
- spawn.onWriterRetired(writerId);
322
- throw error;
323
- }
324
- const held = heldUntilKilled();
325
- // Runs at most once, however it is reached — the lifecycle ending, a kill,
326
- // or both. Retiring the writer twice would revoke an identity a later
327
- // incarnation had already been granted.
328
- let releasing = null;
329
- const release = () => {
330
- if (!releasing) {
331
- releasing = (async () => {
332
- try {
333
- await hosted.release();
334
- }
335
- finally {
336
- spawn.onWriterRetired(writerId);
337
- }
338
- })();
339
- releasing.catch(() => { });
340
- }
341
- return releasing;
342
- };
343
- // `lifetime`: the runner's startProcess IS the process, so its settlement
344
- // is the lifecycle — a host that dies under it rejects `started`.
345
- // `boot`: the runner returns once it is up and the process stays resident
346
- // on its host, so residency ends at a kill — or at the host dying, which
347
- // is the same thing happening to the process without anyone asking for it.
348
- const done = (spawn.startContract === 'lifetime'
349
- ? hosted.started.then(() => undefined)
350
- : hosted.started.then(() => Promise.race([held.promise, hosted.lost]))).finally(() => release());
351
- done.catch(() => { });
352
- return new ResidentProcessHandle({
353
- done,
354
- booted: () => hosted.started,
355
- routeTarget: { handleHttpRequest: (request) => hosted.handleHttpRequest(request) },
356
- kill: () => { held.release(); void release(); },
357
- describe: () => hosted.describe(),
358
- });
359
- }
360
- }
@@ -1,24 +0,0 @@
1
- export declare class ParallelError extends Error {
2
- constructor(message: string);
3
- }
4
- export declare class SerializationError extends ParallelError {
5
- constructor(message: string);
6
- }
7
- export declare class ExecutionError extends ParallelError {
8
- readonly remoteMessage: string;
9
- readonly remoteStack?: string;
10
- constructor(message: string, remoteStack?: string);
11
- }
12
- export declare class TimeoutError extends ParallelError {
13
- readonly deadlineMs: number;
14
- constructor(deadlineMs: number);
15
- }
16
- export declare class RetryExhaustedError extends ParallelError {
17
- readonly lastError: Error;
18
- readonly attempts: number;
19
- constructor(attempts: number, lastError: Error);
20
- }
21
- export declare class BindingError extends ParallelError {
22
- constructor(message: string);
23
- }
24
- //# sourceMappingURL=errors.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/loaders/vendor/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,aAAa;gBACvC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,cAAe,SAAQ,aAAa;IAC/C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;CAMlD;AAED,qBAAa,YAAa,SAAQ,aAAa;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM;CAK/B;AAED,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK;CAQ/C;AAED,qBAAa,YAAa,SAAQ,aAAa;gBACjC,OAAO,EAAE,MAAM;CAI5B"}
@@ -1,46 +0,0 @@
1
- export class ParallelError extends Error {
2
- constructor(message) {
3
- super(message);
4
- this.name = 'ParallelError';
5
- }
6
- }
7
- export class SerializationError extends ParallelError {
8
- constructor(message) {
9
- super(message);
10
- this.name = 'SerializationError';
11
- }
12
- }
13
- export class ExecutionError extends ParallelError {
14
- remoteMessage;
15
- remoteStack;
16
- constructor(message, remoteStack) {
17
- super(message);
18
- this.name = 'ExecutionError';
19
- this.remoteMessage = message;
20
- this.remoteStack = remoteStack;
21
- }
22
- }
23
- export class TimeoutError extends ParallelError {
24
- deadlineMs;
25
- constructor(deadlineMs) {
26
- super(`Task exceeded ${deadlineMs}ms deadline`);
27
- this.name = 'TimeoutError';
28
- this.deadlineMs = deadlineMs;
29
- }
30
- }
31
- export class RetryExhaustedError extends ParallelError {
32
- lastError;
33
- attempts;
34
- constructor(attempts, lastError) {
35
- super(`Task failed after ${attempts} attempt(s): ${lastError.message}`);
36
- this.name = 'RetryExhaustedError';
37
- this.attempts = attempts;
38
- this.lastError = lastError;
39
- }
40
- }
41
- export class BindingError extends ParallelError {
42
- constructor(message) {
43
- super(message);
44
- this.name = 'BindingError';
45
- }
46
- }
@@ -1,3 +0,0 @@
1
- export declare function serializeFunction(fn: Function): string;
2
- export declare function hashSource(source: string): string;
3
- //# sourceMappingURL=serialize.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../../src/loaders/vendor/serialize.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAyBtD;AAGD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMjD"}
@@ -1,25 +0,0 @@
1
- import { SerializationError } from './errors.js';
2
- export function serializeFunction(fn) {
3
- if (typeof fn !== 'function') {
4
- throw new SerializationError(`Expected a function, got ${typeof fn}`);
5
- }
6
- const source = fn.toString();
7
- if (source.includes('[native code]')) {
8
- throw new SerializationError(`Cannot serialize native function: ${fn.name || '(anonymous)'}. ` +
9
- 'Only user-defined functions can be dispatched to remote isolates.');
10
- }
11
- // `this` has no receiver in the remote isolate — reject it early.
12
- if (/\bthis\b/.test(source)) {
13
- throw new SerializationError(`Function "${fn.name || '(anonymous)'}" references \`this\`, which is ` +
14
- 'not available in a remote isolate. Pass values as explicit arguments instead.');
15
- }
16
- return source;
17
- }
18
- // djb2 hash — fast, deterministic, not cryptographic. Used only for loader cache key differentiation.
19
- export function hashSource(source) {
20
- let hash = 5381;
21
- for (let i = 0; i < source.length; i++) {
22
- hash = ((hash << 5) + hash + source.charCodeAt(i)) | 0;
23
- }
24
- return (hash >>> 0).toString(36);
25
- }
@@ -1,69 +0,0 @@
1
- export interface JsModule {
2
- js: string;
3
- }
4
- export interface CjsModule {
5
- cjs: string;
6
- }
7
- export interface PyModule {
8
- py: string;
9
- }
10
- export interface TextModule {
11
- text: string;
12
- }
13
- export interface DataModule {
14
- data: ArrayBuffer;
15
- }
16
- export interface JsonModule {
17
- json: unknown;
18
- }
19
- /**
20
- * A compiled WebAssembly module, importable from a facet by module name.
21
- * Nimbus ships these on every path — sql.js for node:sqlite, the interpreter
22
- * images for python and ruby — so the omission here was the type lagging the
23
- * API, not a kind the loader lacks.
24
- */
25
- export interface WasmModule {
26
- wasm: ArrayBuffer;
27
- }
28
- /** Plain string = type inferred from file extension (.js or .py). */
29
- export type ModuleContent = string | JsModule | CjsModule | PyModule | TextModule | DataModule | JsonModule | WasmModule;
30
- export interface WorkerCode {
31
- compatibilityDate: string;
32
- compatibilityFlags?: string[];
33
- allowExperimental?: boolean;
34
- mainModule: string;
35
- modules: Record<string, ModuleContent>;
36
- env?: Record<string, unknown>;
37
- /**
38
- * Network access control:
39
- * - `undefined`: inherit parent's network access.
40
- * - `null`: block all outbound (fetch/connect throw).
41
- * - A service stub: redirect outbound through that binding.
42
- */
43
- globalOutbound?: ServiceStub | null;
44
- tails?: ServiceStub[];
45
- }
46
- export interface ServiceStub {
47
- fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
48
- }
49
- export interface EntrypointOptions {
50
- props?: Record<string, unknown>;
51
- }
52
- export interface WorkerStub {
53
- getEntrypoint(): EntrypointStub;
54
- getEntrypoint(name: string, opts?: EntrypointOptions): EntrypointStub;
55
- }
56
- export interface EntrypointStub {
57
- fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
58
- execute(...args: unknown[]): Promise<unknown>;
59
- }
60
- export type GetCodeCallback = () => Promise<WorkerCode>;
61
- export interface WorkerLoader {
62
- /**
63
- * Load or reuse an isolate by ID. Same ID + same code may reuse an isolate;
64
- * different IDs always get fresh isolates. `getCodeCallback` must return
65
- * the same content for the same ID.
66
- */
67
- get(id: string, getCodeCallback: GetCodeCallback): WorkerStub;
68
- }
69
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/loaders/vendor/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AACxC,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,MAAM,CAAA;CAAE;AAC1C,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AACxC,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAA;CAAE;AAC5C,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,WAAW,CAAA;CAAE;AACjD,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,OAAO,CAAA;CAAE;AAC7C;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,WAAW,CAAA;CAAE;AAEjD,qEAAqE;AACrE,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,UAAU;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE9B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,IAAI,cAAc,CAAC;IAChC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,cAAc,CAAC;CACvE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/C;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,GAAG,UAAU,CAAC;CAC/D"}
@@ -1,4 +0,0 @@
1
- // Types for the Cloudflare Worker Loader API (closed beta).
2
- // Not yet in @cloudflare/workers-types. Remove this file when they ship.
3
- // https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/
4
- export {};