@nimbus-sh/worker 0.2.3 → 0.3.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 (129) 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/facets/cirrus-real.js +1 -1
  5. package/dist/facets/manager.d.ts +40 -126
  6. package/dist/facets/manager.d.ts.map +1 -1
  7. package/dist/facets/manager.js +97 -313
  8. package/dist/facets/opencode-staging.d.ts +1 -1
  9. package/dist/facets/opencode-staging.d.ts.map +1 -1
  10. package/dist/facets/opencode-staging.js +4 -0
  11. package/dist/facets/vite-dev-server.d.ts +2 -2
  12. package/dist/facets/vite-dev-server.js +4 -4
  13. package/dist/git/commands.d.ts +8 -0
  14. package/dist/git/commands.d.ts.map +1 -1
  15. package/dist/git/commands.js +41 -9
  16. package/dist/git/network-facet.d.ts +1 -1
  17. package/dist/git/network-facet.d.ts.map +1 -1
  18. package/dist/git/network-facet.js +35 -12
  19. package/dist/git-bundle.generated.d.ts +2 -2
  20. package/dist/git-bundle.generated.d.ts.map +1 -1
  21. package/dist/git-bundle.generated.js +3 -3
  22. package/dist/index.js +1 -1
  23. package/dist/loaders/child-process/spawn-facet.js +1 -1
  24. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  25. package/dist/loaders/child-process/spawn-pool.js +2 -2
  26. package/dist/loaders/generated-workers.d.ts +1 -1
  27. package/dist/loaders/generated-workers.d.ts.map +1 -1
  28. package/dist/loaders/generated-workers.js +2 -2
  29. package/dist/loaders/npm-resolve-preamble.d.ts +3 -3
  30. package/dist/loaders/npm-resolve-preamble.js +3 -3
  31. package/dist/loaders/pre-bundle-preamble.d.ts +5 -5
  32. package/dist/loaders/pre-bundle-preamble.js +6 -6
  33. package/dist/loaders/process-host.d.ts +6 -107
  34. package/dist/loaders/process-host.d.ts.map +1 -1
  35. package/dist/loaders/process-host.js +6 -405
  36. package/dist/npm/install-batch-facet.js +1 -1
  37. package/dist/npm/installer.d.ts +4 -4
  38. package/dist/npm/installer.js +18 -18
  39. package/dist/npm/pre-bundle-facet.d.ts +2 -2
  40. package/dist/npm/pre-bundle-facet.js +5 -5
  41. package/dist/npm/resolve-facet.d.ts +1 -1
  42. package/dist/npm/resolve-facet.js +1 -1
  43. package/dist/npm/resolve-one-facet.d.ts +5 -5
  44. package/dist/npm/resolve-one-facet.js +5 -5
  45. package/dist/router/index.js +1 -1
  46. package/dist/router/remote-api.js +8 -0
  47. package/dist/runtime/bun-repl.d.ts +1 -1
  48. package/dist/runtime/bun-repl.js +3 -3
  49. package/dist/runtime/facet-loader-host.d.ts +5 -8
  50. package/dist/runtime/facet-loader-host.d.ts.map +1 -1
  51. package/dist/runtime/facet-loader-host.js +7 -11
  52. package/dist/runtime/node-repl.js +2 -2
  53. package/dist/runtime/python-repl.js +3 -3
  54. package/dist/runtime/ruby-repl.js +2 -2
  55. package/dist/runtime/ruby-resident.js +1 -1
  56. package/dist/session/hibernation.d.ts +18 -51
  57. package/dist/session/hibernation.d.ts.map +1 -1
  58. package/dist/session/hibernation.js +49 -186
  59. package/dist/session/init-phases.d.ts +2 -2
  60. package/dist/session/init-phases.d.ts.map +1 -1
  61. package/dist/session/init-phases.js +1 -1
  62. package/dist/session/init.d.ts.map +1 -1
  63. package/dist/session/init.js +6 -3
  64. package/dist/session/keys.d.ts +14 -37
  65. package/dist/session/keys.d.ts.map +1 -1
  66. package/dist/session/keys.js +17 -37
  67. package/dist/session/nimbus-session.d.ts +10 -4
  68. package/dist/session/nimbus-session.d.ts.map +1 -1
  69. package/dist/session/nimbus-session.js +20 -11
  70. package/dist/session/port-capability.d.ts +43 -0
  71. package/dist/session/port-capability.d.ts.map +1 -0
  72. package/dist/session/port-capability.js +49 -0
  73. package/dist/session/programmatic.d.ts +41 -5
  74. package/dist/session/programmatic.d.ts.map +1 -1
  75. package/dist/session/programmatic.js +147 -15
  76. package/dist/session/routes.d.ts +2 -0
  77. package/dist/session/routes.d.ts.map +1 -1
  78. package/dist/session/routes.js +91 -16
  79. package/dist/session/rpc.d.ts +35 -8
  80. package/dist/session/rpc.d.ts.map +1 -1
  81. package/dist/session/rpc.js +73 -14
  82. package/dist/session/start-real-vite.d.ts.map +1 -1
  83. package/dist/session/start-real-vite.js +2 -0
  84. package/dist/session/state-store.d.ts +3 -2
  85. package/dist/session/state-store.d.ts.map +1 -1
  86. package/dist/session/state-store.js +3 -2
  87. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  88. package/dist/session/supervisor-rpc.js +5 -0
  89. package/dist/session/ws.d.ts +2 -2
  90. package/dist/session/ws.d.ts.map +1 -1
  91. package/dist/session/ws.js +2 -2
  92. package/dist/wrangler/nimbus-wrangler.js +1 -1
  93. package/package.json +3 -2
  94. package/dist/facets/inner-do-registry.d.ts +0 -41
  95. package/dist/facets/inner-do-registry.d.ts.map +0 -1
  96. package/dist/facets/inner-do-registry.js +0 -51
  97. package/dist/facets/launch-pacer.d.ts +0 -111
  98. package/dist/facets/launch-pacer.d.ts.map +0 -1
  99. package/dist/facets/launch-pacer.js +0 -130
  100. package/dist/loaders/fanout-pool.d.ts +0 -207
  101. package/dist/loaders/fanout-pool.d.ts.map +0 -1
  102. package/dist/loaders/fanout-pool.js +0 -363
  103. package/dist/loaders/loader-pool.d.ts +0 -294
  104. package/dist/loaders/loader-pool.d.ts.map +0 -1
  105. package/dist/loaders/loader-pool.js +0 -642
  106. package/dist/loaders/process-fabric.d.ts +0 -509
  107. package/dist/loaders/process-fabric.d.ts.map +0 -1
  108. package/dist/loaders/process-fabric.js +0 -360
  109. package/dist/loaders/vendor/errors.d.ts +0 -24
  110. package/dist/loaders/vendor/errors.d.ts.map +0 -1
  111. package/dist/loaders/vendor/errors.js +0 -46
  112. package/dist/loaders/vendor/serialize.d.ts +0 -3
  113. package/dist/loaders/vendor/serialize.d.ts.map +0 -1
  114. package/dist/loaders/vendor/serialize.js +0 -25
  115. package/dist/loaders/vendor/types.d.ts +0 -69
  116. package/dist/loaders/vendor/types.d.ts.map +0 -1
  117. package/dist/loaders/vendor/types.js +0 -4
  118. package/dist/loaders/workerd-facet-host.d.ts +0 -141
  119. package/dist/loaders/workerd-facet-host.d.ts.map +0 -1
  120. package/dist/loaders/workerd-facet-host.js +0 -284
  121. package/dist/session/bindings.d.ts +0 -209
  122. package/dist/session/bindings.d.ts.map +0 -1
  123. package/dist/session/bindings.js +0 -680
  124. package/dist/session/ctx-exports.d.ts +0 -16
  125. package/dist/session/ctx-exports.d.ts.map +0 -1
  126. package/dist/session/ctx-exports.js +0 -22
  127. package/dist/session/ws-hibernation-config.d.ts +0 -64
  128. package/dist/session/ws-hibernation-config.d.ts.map +0 -1
  129. package/dist/session/ws-hibernation-config.js +0 -89
@@ -1,141 +0,0 @@
1
- /**
2
- * workerd-facet-host.ts — how a resident process is actually made, on workerd.
3
- *
4
- * `loaders/process-fabric.ts` says what a resident process IS, in terms no
5
- * runtime owns: a boot spec, a start contract, a handle that can be routed to
6
- * and released. This module is the one implementation of that on Cloudflare,
7
- * and everything here is a workerd mechanism rather than a Nimbus concept —
8
- * `ctx.facets`, the Worker Loader, `ctx.exports`, and the facet-index
9
- * arithmetic the slot book exists to satisfy.
10
- *
11
- * The split is what lets the contract be read without the platform: a host
12
- * that is not a Durable Object implements `ProcessHost` against the same
13
- * `HostedProcess` and never imports this file.
14
- */
15
- import { type OpencodeAssetsEnv, type OpencodeStageSpec } from '../facets/opencode-staging.js';
16
- import { type HostedProcess, type OneShotParams, type ProcessHostParams, type ResidentDiskReader, type ResidentSupervisorProps } from './process-fabric.js';
17
- /** Structural surface of a NimbusLoadedEntrypoint RPC stub. */
18
- export interface LoadedWorkerEntrypointStub {
19
- handleHttpRequest?: (request: Request) => Promise<Response>;
20
- fetch?(request: Request): Promise<Response>;
21
- }
22
- export interface NimbusCtxExports {
23
- SupervisorRPC?: (options: {
24
- props: {
25
- doId: string;
26
- pid: number;
27
- writerId: string;
28
- };
29
- }) => unknown;
30
- NimbusLoadedEntrypoint?: (options: {
31
- props: {
32
- key: string;
33
- name: string | null;
34
- depth: number;
35
- supervisor: {
36
- doId: string;
37
- pid: number;
38
- writerId: string;
39
- };
40
- stage?: OpencodeStageSpec;
41
- };
42
- }) => LoadedWorkerEntrypointStub;
43
- }
44
- export declare function getNimbusCtxExports(): NimbusCtxExports;
45
- /**
46
- * Mint a NimbusLoadedEntrypoint stub for a keyed dynamic worker. Used by the
47
- * one-shot runtime paths, which run a program to completion inside a single
48
- * request rather than leaving it resident: their module map is assembled in
49
- * that stateless entrypoint's own isolate, never in a session DO.
50
- */
51
- export declare function createLoadedWorkerEntrypoint(ctxExports: NimbusCtxExports, supervisor: {
52
- doId: string;
53
- pid: number;
54
- writerId: string;
55
- }, stage: OpencodeStageSpec, name?: string | null): Promise<LoadedWorkerEntrypointStub>;
56
- /**
57
- * Total bytes a dynamic Worker's module map may carry, across every member of
58
- * it. A hard platform limit, not a policy knob: 62 MiB lands and 64 MiB is
59
- * refused with "Dynamic Worker code size (N bytes) exceeds the maximum allowed
60
- * size of 67108864 bytes", confirmed at five sizes with two trials each. The
61
- * budget is shared, so a ruby process is already 34.3 MiB down before its disk
62
- * is counted.
63
- */
64
- export declare const DYNAMIC_WORKER_CODE_LIMIT_BYTES = 67108864;
65
- /** What an unkeyed `LOADER.load` hands back. */
66
- interface LoadedWorkerStub {
67
- getEntrypoint(): LoadedWorkerEntrypointStub;
68
- }
69
- /**
70
- * `env.LOADER` — the Worker Loader binding, as used from inside a DO.
71
- *
72
- * Both arms are here because both are the same platform affordance seen from
73
- * the two lifetimes Nimbus runs programs under: `get` is keyed and yields a
74
- * Durable Object class, so a resident process can be re-entered; `load` is
75
- * unkeyed and yields a stateless entrypoint, which is all a program that ends
76
- * with its call can ever need.
77
- */
78
- interface WorkerLoaderBinding {
79
- get(id: string, code: () => Promise<unknown>): {
80
- getDurableObjectClass(name: string): unknown;
81
- };
82
- load(code: unknown): LoadedWorkerStub;
83
- }
84
- /** The bindings `openResidentFacet` needs off whichever DO is hosting. */
85
- export interface ResidentFacetEnv extends Partial<OpencodeAssetsEnv> {
86
- LOADER?: WorkerLoaderBinding;
87
- }
88
- /**
89
- * The facet name for a slot. Reused, and that is the entire point.
90
- *
91
- * A Durable Object admits 65,536 facets over its LIFETIME: the IDs are
92
- * append-only and are never reclaimed, so the bound is on facets ever CREATED,
93
- * not facets alive at once. Naming a facet after its pid, when pids never
94
- * repeat, therefore burned one of those IDs on every spawn — a long-lived
95
- * session would eventually exhaust its facet index with no way back, and the
96
- * failure is unrecoverable rather than merely slow.
97
- *
98
- * Reusing a NAME costs no new ID. So the name comes from a free list and the
99
- * pid stays what it always was: the process identity in the ProcessTable. The
100
- * two were only ever conflated because one of them happened to be handy.
101
- */
102
- export declare function residentFacetName(slot: number): string;
103
- /**
104
- * What `openResidentFacet` hands back: a running process, minus its placement.
105
- *
106
- * `slot` rides along because the caller's `describe` needs the facet's real
107
- * name and the slot is not derivable from the pid — that indirection is the
108
- * whole point of the free list. Reading it back out of the book later would
109
- * also race the release that empties it.
110
- */
111
- export type ResidentFacet = Omit<HostedProcess, 'describe'> & {
112
- slot: number;
113
- };
114
- /**
115
- * Open a resident process as a facet of the actor whose `ctx` and `env` are
116
- * given, and start its runner.
117
- *
118
- * This is the ONE way a resident process comes into existence, and every
119
- * substrate goes through it: the facet host calls it with the coordinator's
120
- * own `ctx`, the peer host calls it — over one RPC — with a sibling session
121
- * DO's. Everything a substrate could plausibly want to special-case is a
122
- * PARAMETER here rather than a branch: which actor hosts the child, and how
123
- * the boot spec's by-path members are read.
124
- */
125
- export declare function openResidentFacet(ctx: DurableObjectState, env: ResidentFacetEnv, disk: () => ResidentDiskReader, supervisor: ResidentSupervisorProps, params: ProcessHostParams): ResidentFacet;
126
- /**
127
- * Run one program to completion as an UNKEYED dynamic worker.
128
- *
129
- * Unkeyed is the whole difference from `openResidentFacet`: nothing can
130
- * re-resolve this worker into a later request's context, so it can never be a
131
- * routeable target and never has to be released by name. It exists for the
132
- * duration of one call and its stubs are dropped as that call unwinds.
133
- *
134
- * Shared by both substrates on purpose. `peer` places processes that have a
135
- * residency to place; a one-shot has none, and shipping its fully-inline map
136
- * across a sibling hop would meet the 32 MiB RPC ceiling that by-path boot
137
- * specs exist to avoid — for a run that gains nothing by moving.
138
- */
139
- export declare function runOneShotWorker<T>(env: ResidentFacetEnv, supervisor: ResidentSupervisorProps, params: OneShotParams, consume: (response: Response) => Promise<T>): Promise<T>;
140
- export {};
141
- //# sourceMappingURL=workerd-facet-host.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workerd-facet-host.d.ts","sourceRoot":"","sources":["../../src/loaders/workerd-facet-host.ts"],"names":[],"mappings":"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"}
@@ -1,284 +0,0 @@
1
- /**
2
- * workerd-facet-host.ts — how a resident process is actually made, on workerd.
3
- *
4
- * `loaders/process-fabric.ts` says what a resident process IS, in terms no
5
- * runtime owns: a boot spec, a start contract, a handle that can be routed to
6
- * and released. This module is the one implementation of that on Cloudflare,
7
- * and everything here is a workerd mechanism rather than a Nimbus concept —
8
- * `ctx.facets`, the Worker Loader, `ctx.exports`, and the facet-index
9
- * arithmetic the slot book exists to satisfy.
10
- *
11
- * The split is what lets the contract be read without the platform: a host
12
- * that is not a Durable Object implements `ProcessHost` against the same
13
- * `HostedProcess` and never imports this file.
14
- */
15
- import { disposeRpcResource } from '@nimbus-sh/core/_shared/rpc-dispose.js';
16
- import { assembleOpencodeFacetConfig, } from '../facets/opencode-staging.js';
17
- import { getCtxExports } from '../session/ctx-exports.js';
18
- import { RESIDENT_PROCESS_CLASS, residentLoaderConfig, } from './process-fabric.js';
19
- export function getNimbusCtxExports() {
20
- const ctxExports = getCtxExports();
21
- if (!ctxExports || typeof ctxExports !== 'object') {
22
- throw new Error('Nimbus: ctx.exports unavailable');
23
- }
24
- return ctxExports;
25
- }
26
- /**
27
- * Mint a NimbusLoadedEntrypoint stub for a keyed dynamic worker. Used by the
28
- * one-shot runtime paths, which run a program to completion inside a single
29
- * request rather than leaving it resident: their module map is assembled in
30
- * that stateless entrypoint's own isolate, never in a session DO.
31
- */
32
- export async function createLoadedWorkerEntrypoint(ctxExports, supervisor, stage, name = null) {
33
- if (!ctxExports.NimbusLoadedEntrypoint) {
34
- throw new Error('Nimbus: ctx.exports.NimbusLoadedEntrypoint unavailable');
35
- }
36
- return await ctxExports.NimbusLoadedEntrypoint({
37
- props: {
38
- key: `nimbus-process:${supervisor.doId}:${supervisor.pid}`,
39
- name,
40
- depth: 0,
41
- supervisor,
42
- stage,
43
- },
44
- });
45
- }
46
- /**
47
- * Total bytes a dynamic Worker's module map may carry, across every member of
48
- * it. A hard platform limit, not a policy knob: 62 MiB lands and 64 MiB is
49
- * refused with "Dynamic Worker code size (N bytes) exceeds the maximum allowed
50
- * size of 67108864 bytes", confirmed at five sizes with two trials each. The
51
- * budget is shared, so a ruby process is already 34.3 MiB down before its disk
52
- * is counted.
53
- */
54
- export const DYNAMIC_WORKER_CODE_LIMIT_BYTES = 67_108_864;
55
- function facetContainer(ctx) {
56
- const facets = ctx.facets;
57
- if (!facets || typeof facets.get !== 'function') {
58
- throw new Error('Nimbus: ctx.facets is unavailable in this Durable Object; '
59
- + 'resident processes cannot be hosted');
60
- }
61
- return facets;
62
- }
63
- /**
64
- * The facet name for a slot. Reused, and that is the entire point.
65
- *
66
- * A Durable Object admits 65,536 facets over its LIFETIME: the IDs are
67
- * append-only and are never reclaimed, so the bound is on facets ever CREATED,
68
- * not facets alive at once. Naming a facet after its pid, when pids never
69
- * repeat, therefore burned one of those IDs on every spawn — a long-lived
70
- * session would eventually exhaust its facet index with no way back, and the
71
- * failure is unrecoverable rather than merely slow.
72
- *
73
- * Reusing a NAME costs no new ID. So the name comes from a free list and the
74
- * pid stays what it always was: the process identity in the ProcessTable. The
75
- * two were only ever conflated because one of them happened to be handy.
76
- */
77
- export function residentFacetName(slot) {
78
- return `proc-slot-${slot}`;
79
- }
80
- /**
81
- * Slot books, per hosting actor, because the facet index is per Durable
82
- * Object.
83
- *
84
- * Keyed weakly off `ctx`, and that is sound rather than lossy: a facet cannot
85
- * outlive the Durable Object hosting it, so a book that goes away with its
86
- * host describes nothing that still exists. A fresh incarnation restarts at
87
- * slot 0 and re-attaches to the SQLite a previous incarnation left there —
88
- * which is safe for the reason the store is sealed until it has reconciled.
89
- * Its persisted cursor is either datable against the current authority, in
90
- * which case the ACQUIRE delta brings it current, or it carries a different
91
- * VFS epoch, in which case `invalidatedSince` can only answer poison and the
92
- * whole store is dropped. A process therefore cannot boot onto a previous
93
- * tenant's filesystem even when release never ran.
94
- */
95
- const slotBooks = new WeakMap();
96
- function slotBook(ctx) {
97
- let book = slotBooks.get(ctx);
98
- if (!book) {
99
- book = { free: [], next: 0, held: new Map() };
100
- slotBooks.set(ctx, book);
101
- }
102
- return book;
103
- }
104
- /** Take a slot for `pid`, reusing a returned one before minting a new name. */
105
- function acquireSlot(ctx, pid) {
106
- const book = slotBook(ctx);
107
- const existing = book.held.get(pid);
108
- if (existing !== undefined)
109
- return existing;
110
- const slot = book.free.length > 0 ? book.free.shift() : book.next++;
111
- book.held.set(pid, slot);
112
- return slot;
113
- }
114
- /** Return `pid`'s slot to the free list. */
115
- function releaseSlot(ctx, pid) {
116
- const book = slotBook(ctx);
117
- const slot = book.held.get(pid);
118
- if (slot === undefined)
119
- return;
120
- book.held.delete(pid);
121
- book.free.push(slot);
122
- book.free.sort((a, b) => a - b);
123
- }
124
- /**
125
- * Open a resident process as a facet of the actor whose `ctx` and `env` are
126
- * given, and start its runner.
127
- *
128
- * This is the ONE way a resident process comes into existence, and every
129
- * substrate goes through it: the facet host calls it with the coordinator's
130
- * own `ctx`, the peer host calls it — over one RPC — with a sibling session
131
- * DO's. Everything a substrate could plausibly want to special-case is a
132
- * PARAMETER here rather than a branch: which actor hosts the child, and how
133
- * the boot spec's by-path members are read.
134
- */
135
- export function openResidentFacet(ctx, env, disk, supervisor, params) {
136
- const facets = facetContainer(ctx);
137
- const slot = acquireSlot(ctx, params.pid);
138
- const name = residentFacetName(slot);
139
- // The start callback is the ONLY way this facet is ever created, and it
140
- // fires AT MOST ONCE. Every later use goes through the stub below, so the
141
- // callback running a second time means the facet was released or died —
142
- // and re-running it would evaluate the user's program again, answering a
143
- // request from a process they never started while the one they did start
144
- // is gone. Both cases are reported instead.
145
- let evaluated = false;
146
- let released = false;
147
- const start = async () => {
148
- if (released) {
149
- throw new Error(`Nimbus: resident process ${params.pid} is no longer running`);
150
- }
151
- if (evaluated) {
152
- throw new Error(`Nimbus: resident process ${params.pid} is no longer loaded (its facet was lost); `
153
- + 'it is not restarted');
154
- }
155
- evaluated = true;
156
- return { class: residentProcessClass(env, disk, supervisor, params) };
157
- };
158
- const facet = facets.get(name, start);
159
- let disposed = false;
160
- const release = async () => {
161
- if (disposed)
162
- return;
163
- disposed = true;
164
- released = true;
165
- try {
166
- facets.abort(name, new Error('Nimbus: resident process released'));
167
- }
168
- catch { /* already gone */ }
169
- try {
170
- facets.delete(name);
171
- }
172
- catch { /* already gone */ }
173
- // Only after the facet is gone. A slot handed out while its previous
174
- // tenant were still being torn down would have two processes on one name.
175
- releaseSlot(ctx, params.pid);
176
- };
177
- let started;
178
- try {
179
- started = facet.startProcess(params.startArgs);
180
- }
181
- catch (error) {
182
- void release();
183
- throw error;
184
- }
185
- // A caller reads whichever of `started` and the lifecycle it needs, so keep
186
- // the runtime from reporting the other as an unhandled rejection.
187
- started.catch(() => { });
188
- return {
189
- started,
190
- // A facet cannot die without taking its Durable Object — and this object —
191
- // with it, so there is no independent death to report.
192
- lost: new Promise(() => { }),
193
- handleHttpRequest: (request) => facet.handleHttpRequest(request),
194
- release,
195
- slot,
196
- };
197
- }
198
- /**
199
- * The dynamic worker's Durable Object class, minted in the caller's request
200
- * context. `LOADER.get` runs its callback only on a cache miss, so a process
201
- * assembles its module map at most once and the bytes never stay resident in
202
- * the hosting DO's heap.
203
- */
204
- function residentProcessClass(env, disk, supervisor, params) {
205
- const loader = env.LOADER;
206
- if (!loader || typeof loader.get !== 'function') {
207
- throw new Error('Nimbus: env.LOADER binding missing or invalid. Resident processes require '
208
- + 'the Worker Loader binding; add it via worker_loaders in wrangler.jsonc.');
209
- }
210
- return loader
211
- .get(params.workerKey, () => residentWorkerConfig(env, disk, supervisor, params.boot))
212
- .getDurableObjectClass(RESIDENT_PROCESS_CLASS);
213
- }
214
- /**
215
- * Run one program to completion as an UNKEYED dynamic worker.
216
- *
217
- * Unkeyed is the whole difference from `openResidentFacet`: nothing can
218
- * re-resolve this worker into a later request's context, so it can never be a
219
- * routeable target and never has to be released by name. It exists for the
220
- * duration of one call and its stubs are dropped as that call unwinds.
221
- *
222
- * Shared by both substrates on purpose. `peer` places processes that have a
223
- * residency to place; a one-shot has none, and shipping its fully-inline map
224
- * across a sibling hop would meet the 32 MiB RPC ceiling that by-path boot
225
- * specs exist to avoid — for a run that gains nothing by moving.
226
- */
227
- export async function runOneShotWorker(env, supervisor, params, consume) {
228
- const loader = env.LOADER;
229
- if (!loader || typeof loader.load !== 'function') {
230
- throw new Error('Nimbus: env.LOADER binding missing or invalid. Running a program requires '
231
- + 'the Worker Loader binding; add it via worker_loaders in wrangler.jsonc.');
232
- }
233
- const ctxExports = getCtxExports();
234
- let supervisorBinding;
235
- let worker;
236
- let entrypoint;
237
- try {
238
- // Built before the capability is minted: nothing can write as this writer
239
- // until there is a program to do the writing, and a map that fails to
240
- // assemble should not have granted append authority on its way out.
241
- let spec = await params.code();
242
- if (ctxExports?.SupervisorRPC) {
243
- params.onWriterActivated(params.writerId);
244
- supervisorBinding = ctxExports.SupervisorRPC({ props: supervisor });
245
- }
246
- worker = loader.load({
247
- compatibilityDate: spec.compatibilityDate,
248
- compatibilityFlags: spec.compatibilityFlags,
249
- mainModule: spec.mainModule,
250
- modules: spec.modules,
251
- ...(supervisorBinding ? { env: { SUPERVISOR: supervisorBinding } } : {}),
252
- });
253
- // The loader has taken the map; holding it here would keep a second full
254
- // copy of the program alive for as long as the program runs.
255
- spec = undefined;
256
- entrypoint = worker.getEntrypoint();
257
- if (typeof entrypoint.fetch !== 'function') {
258
- throw new Error('Nimbus: one-shot runtime entrypoint has no fetch method');
259
- }
260
- params.onLoaded?.();
261
- const response = await entrypoint.fetch(params.request);
262
- try {
263
- return await consume(response);
264
- }
265
- finally {
266
- disposeRpcResource(response);
267
- }
268
- }
269
- finally {
270
- disposeRpcResource(entrypoint);
271
- disposeRpcResource(worker);
272
- disposeRpcResource(supervisorBinding);
273
- }
274
- }
275
- async function residentWorkerConfig(env, disk, supervisor, boot) {
276
- const config = boot.kind === 'staged'
277
- ? await assembleOpencodeFacetConfig(env, boot.stage)
278
- : await residentLoaderConfig(boot.code, disk());
279
- const ctxExports = getNimbusCtxExports();
280
- if (!ctxExports.SupervisorRPC) {
281
- throw new Error('Nimbus: ctx.exports.SupervisorRPC unavailable');
282
- }
283
- return { ...config, env: { SUPERVISOR: ctxExports.SupervisorRPC({ props: supervisor }) } };
284
- }
@@ -1,209 +0,0 @@
1
- /**
2
- * session/bindings.ts — Inner-Worker + assets binding shims (W10).
3
- *
4
- * `nimbus-wrangler dev` runs a USER worker as a child process. That
5
- * child needs working `env` bindings (env.ASSETS, env.LOADER, env.MY_DO,
6
- * etc.) but the DO's `env` belongs to the supervisor's contract — we
7
- * can't pass it through directly. Workerd's enable_ctx_exports
8
- * (compat date 2026-04-01+) auto-populates Service Bindings from
9
- * top-level WorkerEntrypoint classes; these classes ARE those entry
10
- * points. They forward each binding kind back to the supervisor DO via
11
- * RPC stub (`env.NIMBUS_SESSION.idFromString(doId).get()...`).
12
- *
13
- * The shims have NO interaction with NimbusSession internals except
14
- * through that RPC stub. Co-located here for grep-ability.
15
- *
16
- * Exports re-shipped from nimbus-session.ts so existing import paths work:
17
- * NimbusAssetsRPC, NimbusLoaderRPC, NimbusLoadedWorker,
18
- * NimbusLoadedEntrypoint, NimbusDurableObjectNamespace, NimbusDOStub.
19
- *
20
- * Bundle-graph note: these classes must remain reachable from `src/index.ts`
21
- * for Wrangler to bundle the WorkerEntrypoint exports.
22
- */
23
- import { WorkerEntrypoint } from 'cloudflare:workers';
24
- import { z } from 'zod/v4';
25
- /**
26
- * Assets binding shim. The inner Worker calls `env.ASSETS.fetch(request)`
27
- * and we serve the file from VFS under `<vfsRoot>/<assetsDir>/<pathname>`.
28
- *
29
- * Props (passed via ctx.props when this binding is constructed):
30
- * vfsRoot — project root in VFS (e.g. "home/user/myapp")
31
- * assetsDir — directory declared in wrangler.jsonc.assets.directory
32
- * (e.g. "./public" → we trim the leading ./)
33
- *
34
- * The hostname on the incoming Request is irrelevant (Workers Assets
35
- * convention); only pathname matters. Path traversal (`..`) is clamped.
36
- * Directories resolve to their `index.html` child; missing files fall
37
- * back to the assetsDir root `index.html` (SPA convention), then 404.
38
- *
39
- * The VFS is read from the supervisor DO via the class property
40
- * `_nimbusVfsResolver` set by NimbusSession at construction. WorkerEntrypoint
41
- * instances don't have direct access to the supervisor's SqliteVFS, so we
42
- * reach it through the supervisor stub (env.NIMBUS_SESSION.idFromString).
43
- * For Phase 1, we use a simpler approach: the props carry a supervisor
44
- * DO id so we can round-trip through an RPC method that reads the file.
45
- */
46
- export declare class NimbusAssetsRPC extends WorkerEntrypoint {
47
- /**
48
- * Fetch a static asset. Called by the inner Worker as
49
- * `env.ASSETS.fetch(request)`. The request URL's pathname is used to
50
- * resolve a file under the configured assets directory.
51
- */
52
- fetch(request: Request): Promise<Response>;
53
- }
54
- declare const NimbusLoadedEntrypointPropsSchema: z.ZodObject<{
55
- key: z.ZodString;
56
- name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
57
- depth: z.ZodOptional<z.ZodNumber>;
58
- supervisor: z.ZodOptional<z.ZodObject<{
59
- doId: z.ZodString;
60
- pid: z.ZodNumber;
61
- writerId: z.ZodString;
62
- }, z.core.$strip>>;
63
- stage: z.ZodOptional<z.ZodUnknown>;
64
- }, z.core.$loose>;
65
- type NimbusLoadedEntrypointProps = z.infer<typeof NimbusLoadedEntrypointPropsSchema>;
66
- /**
67
- * Diagnostic surface for /api/_diag/memory. Returns a snapshot of
68
- * the Map state — entry count, configured cap, eviction counter
69
- * since isolate boot. Pure read; no I/O.
70
- */
71
- export declare function getLoadedCodesStats(): {
72
- entries: number;
73
- maxEntries: number;
74
- evictions: number;
75
- };
76
- /** Hop 1: env.LOADER.{load,get} forwarded to the outer loader. */
77
- export declare class NimbusLoaderRPC extends WorkerEntrypoint {
78
- private _currentDepth;
79
- private _maxDepth;
80
- private _assertDepthOk;
81
- /**
82
- * Inner: env.LOADER.load(code). Stashes the CODE (not a stub — stubs
83
- * are I/O-bound to the calling request context) and returns a
84
- * NimbusLoadedWorker RPC stub. Each downstream call re-loads the
85
- * worker in its own request context via LOADER.get(key, cb).
86
- */
87
- load(code: any): any;
88
- /**
89
- * Inner: env.LOADER.get(id, callback). The inner's callback returns
90
- * a code object; we treat `id` as the outer cache key (prefixed so
91
- * it doesn't collide with load()-generated keys).
92
- */
93
- get(id: string, callback: () => any): Promise<any>;
94
- }
95
- /** Hop 2: the returned "worker" stub. Exposes .getEntrypoint(). */
96
- export declare class NimbusLoadedWorker extends WorkerEntrypoint {
97
- /**
98
- * Returns a NimbusLoadedEntrypoint stub that carries the code key +
99
- * entrypoint name forward. The actual outer-side load + fetch happens
100
- * inside NimbusLoadedEntrypoint.fetch() so all outer hops run in a
101
- * SINGLE outer request context (the cross-request-I/O limitation is
102
- * real — stubs created in one outer request can't be used by another).
103
- */
104
- getEntrypoint(name?: string): any;
105
- /**
106
- * Pass-through to outer worker.getDurableObjectClass(name). The
107
- * returned stub is tied to THIS method's outer request context; if
108
- * the caller (the inner worker) uses the class in a later request
109
- * it will fail the cross-request-I/O check. For Phase 3 DO binding
110
- * synthesis we resolve classes directly from nimbus-wrangler's own
111
- * request context (which is the build-time context), not through
112
- * this method.
113
- */
114
- getDurableObjectClass(name: string): any;
115
- }
116
- /** Hop 3: a named-or-default entrypoint. Exposes .fetch(). */
117
- export declare class NimbusLoadedEntrypoint extends WorkerEntrypoint {
118
- _props(): NimbusLoadedEntrypointProps;
119
- _supervisorBinding(props: NimbusLoadedEntrypointProps): Promise<unknown>;
120
- _resolveEntrypoint(): Promise<any>;
121
- /**
122
- * Relay the inner entrypoint's Response to the caller with a LIVE body.
123
- * The body streams through an identity pipe and the entrypoint stub is
124
- * disposed only once the body finishes — materializing (arrayBuffer) here
125
- * buffered every routed response to stream-end, which froze SSE/chunked
126
- * bodies (opencode's /event live-sync, `curl -N` loopback, external
127
- * preview) until the facet closed the stream.
128
- */
129
- private _relayNestedRpcResponse;
130
- /**
131
- * Invoke the facet's HTTP handler.
132
- *
133
- * The call must be written as `ep.method(request)`. An RPC stub's method is a
134
- * JsRpcProperty, whose every property access is a WILDCARD that extends a
135
- * pipelined path (`JSG_WILDCARD_PROPERTY`, workerd api/worker-rpc.h) — so
136
- * `method.call(ep, request)` does NOT reach Function.prototype.call. It builds
137
- * the path `handleHttpRequest.call` and invokes it remotely with `ep` as its
138
- * first ARGUMENT. Serializing `ep` — an entrypoint to a dynamically-loaded
139
- * worker — is what workerd refuses:
140
- *
141
- * DataCloneError: Entrypoints to dynamically-loaded workers cannot be
142
- * transferred to other Workers
143
- *
144
- * (server.c++ `requireAllowsTransfer` → `throwDynamicEntrypointTransferError`).
145
- * The facet is never entered, because the failure is in serializing the
146
- * arguments, before the call is delivered.
147
- */
148
- private _callHttpHandler;
149
- handleHttpRequest(request: Request): Promise<Response>;
150
- /**
151
- * Forward fetch() to the outer worker's entrypoint. All three outer
152
- * hops (load → getEntrypoint → fetch) run in the same outer request
153
- * context (this method's invocation), which sidesteps the
154
- * cross-request-I/O limitation.
155
- */
156
- fetch(request: Request): Promise<Response>;
157
- }
158
- /**
159
- * `env.MY_DO` shim — a DurableObjectNamespace-like WorkerEntrypoint.
160
- *
161
- * Usage from inner Worker:
162
- * const id = await env.MY_DO.idFromName('x'); // AWAIT required
163
- * const stub = env.MY_DO.get(id);
164
- * await stub.fetch(request);
165
- *
166
- * IMPORTANT: unlike the real DurableObjectNamespace, idFromName /
167
- * newUniqueId / idFromString here return **Promises**, because they're
168
- * RPC-backed WorkerEntrypoint methods. The inner caller MUST `await`
169
- * them before passing the result to `.get()`. Workers RPC pipelining
170
- * does not currently allow passing an RpcPromise as a method argument
171
- * — the no-await form fails with:
172
- * "Could not serialize object of type \"RpcPromise\"."
173
- *
174
- * Typical real-Worker code written for Cloudflare's synchronous
175
- * DurableObjectNamespace needs a one-word change (add `await`).
176
- *
177
- * idFromName produces prefix `name:` (deterministic FNV-style hash);
178
- * newUniqueId uses `uniq:` (random). The prefixes keep the two id
179
- * spaces distinct so a name-derived id can't collide with a random
180
- * one.
181
- */
182
- export declare class NimbusDurableObjectNamespace extends WorkerEntrypoint {
183
- /** Stable string id derived from a name. Hash is deterministic. */
184
- idFromName(name: string): string;
185
- /** Fresh random id (matches DurableObjectNamespace.newUniqueId()). */
186
- newUniqueId(): string;
187
- /** Accept-through for an already-formatted id. */
188
- idFromString(s: string): string;
189
- /** Return a stub bound to the given id. */
190
- get(id: string): any;
191
- }
192
- /**
193
- * A Durable-Object-namespace-stub for a specific id. Exposes fetch()
194
- * and will, if we later need it, forward RPC method calls through a
195
- * dispatch helper. The important invariant: EVERY call resolves the
196
- * inner DO class via getInnerDoClass() (./inner-do-registry.js) and
197
- * spins up / attaches to a facet via the supervisor's ctx.facets in
198
- * the SAME outer request context — never reusing stubs across requests.
199
- */
200
- export declare class NimbusDOStub extends WorkerEntrypoint {
201
- /**
202
- * Resolve the supervisor DO from env.NIMBUS_SESSION and route through
203
- * its _rpcInnerDoFetch RPC method, which runs ctx.facets.get(...) in
204
- * its own context and forwards the request.
205
- */
206
- fetch(request: Request): Promise<Response>;
207
- }
208
- export {};
209
- //# sourceMappingURL=bindings.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../src/session/bindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAmB3B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAgB,SAAQ,gBAAgB;IACnD;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CA2DjD;AA2FD,QAAA,MAAM,iCAAiC;;;;;;;;;;iBAgBvB,CAAC;AAEjB,KAAK,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AA4CrF;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAMhG;AAiBD,kEAAkE;AAClE,qBAAa,eAAgB,SAAQ,gBAAgB;IACnD,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,cAAc;IAWtB;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG;IAmBpB;;;;OAIG;IACG,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;CAiBzD;AAED,mEAAmE;AACnE,qBAAa,kBAAmB,SAAQ,gBAAgB;IACtD;;;;;;OAMG;IACH,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG;IAWjC;;;;;;;;OAQG;IACH,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;CAQzC;AAED,8DAA8D;AAC9D,qBAAa,sBAAuB,SAAQ,gBAAgB;IAC1D,MAAM,IAAI,2BAA2B;IAI/B,kBAAkB,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,OAAO,CAAC;IAUxE,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC;IAkCxC;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IAyB/B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,gBAAgB;IAMlB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAe5D;;;;;OAKG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAUjD;AAqBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,4BAA6B,SAAQ,gBAAgB;IAChE,mEAAmE;IACnE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAiBhC,sEAAsE;IACtE,WAAW,IAAI,MAAM;IAIrB,kDAAkD;IAClD,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI/B,2CAA2C;IAC3C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG;CAYrB;AAED;;;;;;;GAOG;AACH,qBAAa,YAAa,SAAQ,gBAAgB;IAChD;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAuCjD"}