@nimbus-sh/worker 0.12.0 → 0.13.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 (198) hide show
  1. package/dist/esbuild-cli-artifact.generated.d.ts +1 -1
  2. package/dist/esbuild-cli-artifact.generated.js +4 -4
  3. package/dist/esbuild-wasm-bundle.generated.d.ts +11 -10
  4. package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -1
  5. package/dist/esbuild-wasm-bundle.generated.js +11 -10
  6. package/dist/facets/build-facet.d.ts +53 -0
  7. package/dist/facets/build-facet.d.ts.map +1 -0
  8. package/dist/facets/build-facet.js +346 -0
  9. package/dist/facets/cirrus-real.d.ts +3 -0
  10. package/dist/facets/cirrus-real.d.ts.map +1 -1
  11. package/dist/facets/cirrus-real.js +1 -2
  12. package/dist/facets/compose.d.ts +1 -0
  13. package/dist/facets/compose.d.ts.map +1 -1
  14. package/dist/facets/compose.js +3 -0
  15. package/dist/facets/data-plan.d.ts +14 -30
  16. package/dist/facets/data-plan.d.ts.map +1 -1
  17. package/dist/facets/data-plan.js +153 -13
  18. package/dist/facets/dev-stylesheet.d.ts +27 -0
  19. package/dist/facets/dev-stylesheet.d.ts.map +1 -0
  20. package/dist/facets/dev-stylesheet.js +65 -0
  21. package/dist/facets/esbuild-transform.d.ts +23 -18
  22. package/dist/facets/esbuild-transform.d.ts.map +1 -1
  23. package/dist/facets/esbuild-transform.js +63 -109
  24. package/dist/facets/manager.d.ts +49 -9
  25. package/dist/facets/manager.d.ts.map +1 -1
  26. package/dist/facets/manager.js +238 -69
  27. package/dist/facets/oxc-transform.d.ts +29 -0
  28. package/dist/facets/oxc-transform.d.ts.map +1 -0
  29. package/dist/facets/oxc-transform.js +198 -0
  30. package/dist/facets/prebundle-pool.d.ts +23 -0
  31. package/dist/facets/prebundle-pool.d.ts.map +1 -0
  32. package/dist/facets/prebundle-pool.js +55 -0
  33. package/dist/facets/process.d.ts +13 -6
  34. package/dist/facets/process.d.ts.map +1 -1
  35. package/dist/facets/process.js +37 -31
  36. package/dist/facets/transform-store.d.ts +4 -4
  37. package/dist/facets/transform-store.js +4 -4
  38. package/dist/facets/vite-dev-server.d.ts +89 -12
  39. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  40. package/dist/facets/vite-dev-server.js +66 -43
  41. package/dist/hosted/commands.d.ts.map +1 -1
  42. package/dist/hosted/commands.js +20 -4
  43. package/dist/hosted/runtime.d.ts.map +1 -1
  44. package/dist/hosted/runtime.js +7 -2
  45. package/dist/hosted/services.d.ts +3 -3
  46. package/dist/hosted/services.d.ts.map +1 -1
  47. package/dist/hosted/services.js +102 -95
  48. package/dist/hosted/session.d.ts +1 -0
  49. package/dist/hosted/session.d.ts.map +1 -1
  50. package/dist/loaders/generated-workers.d.ts +3 -0
  51. package/dist/loaders/generated-workers.d.ts.map +1 -1
  52. package/dist/loaders/generated-workers.js +3 -0
  53. package/dist/napi-wasm-artifacts.generated.js +2 -2
  54. package/dist/node-shims-artifact.generated.d.ts +14 -1
  55. package/dist/node-shims-artifact.generated.d.ts.map +1 -1
  56. package/dist/node-shims-artifact.generated.js +23 -10
  57. package/dist/npm/bin-links.d.ts +7 -4
  58. package/dist/npm/bin-links.d.ts.map +1 -1
  59. package/dist/npm/bin-links.js +14 -55
  60. package/dist/npm/cache.d.ts +6 -0
  61. package/dist/npm/cache.d.ts.map +1 -1
  62. package/dist/npm/cache.js +26 -4
  63. package/dist/npm/installer.d.ts +1 -1
  64. package/dist/npm/installer.d.ts.map +1 -1
  65. package/dist/npm/installer.js +26 -52
  66. package/dist/npm/pre-bundle-facet.d.ts +15 -117
  67. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  68. package/dist/npm/pre-bundle-facet.js +13 -511
  69. package/dist/oxc-facet-artifact.generated.d.ts +18 -0
  70. package/dist/oxc-facet-artifact.generated.d.ts.map +1 -0
  71. package/dist/oxc-facet-artifact.generated.js +17 -0
  72. package/dist/oxc-wasm-artifact.generated.d.ts +20 -0
  73. package/dist/oxc-wasm-artifact.generated.d.ts.map +1 -0
  74. package/dist/oxc-wasm-artifact.generated.js +19 -0
  75. package/dist/rolldown-facet-artifact.generated.d.ts +18 -0
  76. package/dist/rolldown-facet-artifact.generated.d.ts.map +1 -0
  77. package/dist/rolldown-facet-artifact.generated.js +17 -0
  78. package/dist/router/remote-api.d.ts.map +1 -1
  79. package/dist/router/remote-api.js +9 -0
  80. package/dist/runtime/bash-repl.d.ts.map +1 -1
  81. package/dist/runtime/bash-repl.js +1 -4
  82. package/dist/runtime/cpython-resident.d.ts.map +1 -1
  83. package/dist/runtime/cpython-resident.js +1 -0
  84. package/dist/runtime/esbuild-wasm-bytes.d.ts +25 -23
  85. package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
  86. package/dist/runtime/esbuild-wasm-bytes.js +30 -25
  87. package/dist/runtime/facet-loader-host.d.ts +5 -4
  88. package/dist/runtime/facet-loader-host.d.ts.map +1 -1
  89. package/dist/runtime/facet-loader-host.js +5 -4
  90. package/dist/runtime/node-runner.d.ts +2 -0
  91. package/dist/runtime/node-runner.d.ts.map +1 -1
  92. package/dist/runtime/node-runner.js +1 -0
  93. package/dist/runtime/node-shims-artifact.d.ts +8 -1
  94. package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
  95. package/dist/runtime/node-shims-artifact.js +32 -4
  96. package/dist/runtime/node-shims.d.ts.map +1 -1
  97. package/dist/runtime/node-shims.js +145 -109
  98. package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
  99. package/dist/runtime/opencode-facet-runner.js +6 -2
  100. package/dist/runtime/oxc-wasm-bytes.d.ts +19 -0
  101. package/dist/runtime/oxc-wasm-bytes.d.ts.map +1 -0
  102. package/dist/runtime/oxc-wasm-bytes.js +39 -0
  103. package/dist/runtime/package-manager.js +1 -1
  104. package/dist/runtime/process-logs-api.d.ts.map +1 -1
  105. package/dist/runtime/process-logs-api.js +2 -0
  106. package/dist/runtime/project-fs.d.ts +8 -1
  107. package/dist/runtime/project-fs.d.ts.map +1 -1
  108. package/dist/runtime/project-fs.js +15 -1
  109. package/dist/runtime/python-repl.d.ts +40 -1
  110. package/dist/runtime/python-repl.d.ts.map +1 -1
  111. package/dist/runtime/python-repl.js +19 -11
  112. package/dist/runtime/ruby-repl.d.ts +38 -0
  113. package/dist/runtime/ruby-repl.d.ts.map +1 -1
  114. package/dist/runtime/ruby-repl.js +24 -5
  115. package/dist/runtime/ruby-resident.d.ts.map +1 -1
  116. package/dist/runtime/ruby-resident.js +2 -0
  117. package/dist/session/nimbus-session.d.ts +13 -8
  118. package/dist/session/nimbus-session.d.ts.map +1 -1
  119. package/dist/session/nimbus-session.js +11 -5
  120. package/dist/session/programmatic.d.ts +25 -30
  121. package/dist/session/programmatic.d.ts.map +1 -1
  122. package/dist/session/programmatic.js +65 -93
  123. package/dist/session/routes.d.ts.map +1 -1
  124. package/dist/session/routes.js +23 -7
  125. package/dist/session/rpc.d.ts +16 -6
  126. package/dist/session/rpc.d.ts.map +1 -1
  127. package/dist/session/rpc.js +53 -13
  128. package/dist/session/start-real-vite.d.ts +24 -9
  129. package/dist/session/start-real-vite.d.ts.map +1 -1
  130. package/dist/session/start-real-vite.js +40 -4
  131. package/dist/session/supervisor-op.d.ts +14 -0
  132. package/dist/session/supervisor-op.d.ts.map +1 -1
  133. package/dist/session/supervisor-op.js +49 -0
  134. package/dist/session/supervisor-rpc.d.ts +11 -0
  135. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  136. package/dist/session/supervisor-rpc.js +18 -0
  137. package/dist/session/vite-command.d.ts.map +1 -1
  138. package/dist/session/vite-command.js +23 -19
  139. package/dist/session/ws-relay.d.ts.map +1 -1
  140. package/dist/session/ws-relay.js +13 -1
  141. package/dist/shell/npm-bin-entrypoints.d.ts +3 -1
  142. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  143. package/dist/shell/npm-bin-entrypoints.js +53 -25
  144. package/dist/vfs/facet-resident-store.d.ts.map +1 -1
  145. package/dist/vfs/facet-resident-store.js +11 -5
  146. package/dist/wrangler/nimbus-wrangler.d.ts +8 -0
  147. package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
  148. package/dist/wrangler/nimbus-wrangler.js +54 -57
  149. package/package.json +6 -4
  150. package/public/_assets/esbuild-0.24.2.wasm +0 -0
  151. package/public/_assets/napi-wasm/loader/{99efae93dd1dcc2b → ab7e57fe9e8750c2}/napi-wasm-loader.mjs +4 -4
  152. package/public/_assets/napi-wasm/loader/{99efae93dd1dcc2b → ab7e57fe9e8750c2}/provenance.json +2 -2
  153. package/public/_assets/oxc/nimbus-oxc-1aa8c4c7057c6c28.provenance.json +72 -0
  154. package/public/_assets/oxc/nimbus-oxc-1aa8c4c7057c6c28.wasm +0 -0
  155. package/public/_assets/runtime/esbuild-cli-f13e6a112b03ac07.js +1143 -0
  156. package/public/_assets/runtime/js-interpreter-3c37c48024f0f651.js +23 -0
  157. package/public/_assets/runtime/js-interpreter-ops-2f4dfec6798e70fc.js +290 -0
  158. package/public/_assets/runtime/js-interpreter-primordials-e620a61b7e9800fa.js +1 -0
  159. package/public/_assets/runtime/{node-shims-f92f16c7d7c532e9.js → node-shims-e3adc4576da31e6e.js} +651 -103
  160. package/public/_assets/runtime/{esbuild-cli-b7aecffd4c6a36fe.js → oxc-facet-fd86fefcdf16bf9c.js} +217 -1047
  161. package/public/_assets/runtime/{resident-store-92386265e8b306dc.js → resident-store-009f39539ac989fc.js} +11 -5
  162. package/public/_assets/runtime/rolldown-facet-09983434e2dbe93e.js +15165 -0
  163. package/public/_assets/runtime/{vfs-write-ledger-d33ee0034446c3e0.js → vfs-write-ledger-9e9594591425a9b8.js} +4 -1
  164. package/scripts/acorn-primordials.mjs +637 -0
  165. package/scripts/bundle-esbuild-wasm.mjs +42 -50
  166. package/scripts/bundle-facet-workers.mjs +247 -18
  167. package/scripts/bundle-node-shims.mjs +29 -2
  168. package/scripts/bundle-oxc-wasm.mjs +105 -0
  169. package/scripts/interpreter-bundle.mjs +105 -0
  170. package/scripts/napi-wasm/build.mjs +4 -1
  171. package/scripts/napi-wasm/loader/napi-wasm-loader.ts +38 -3
  172. package/scripts/oxc-wasm/Cargo.lock +1246 -0
  173. package/scripts/oxc-wasm/Cargo.toml +30 -0
  174. package/scripts/oxc-wasm/build.mjs +249 -0
  175. package/scripts/oxc-wasm/examples/memory.rs +51 -0
  176. package/scripts/oxc-wasm/examples/transform.rs +20 -0
  177. package/scripts/oxc-wasm/inputs.mjs +32 -0
  178. package/scripts/oxc-wasm/rust-toolchain.toml +5 -0
  179. package/scripts/oxc-wasm/src/abi.rs +136 -0
  180. package/scripts/oxc-wasm/src/diagnostics.rs +49 -0
  181. package/scripts/oxc-wasm/src/helpers.rs +139 -0
  182. package/scripts/oxc-wasm/src/lib.rs +247 -0
  183. package/scripts/oxc-wasm/src/module.rs +978 -0
  184. package/scripts/oxc-wasm/src/names.rs +175 -0
  185. package/scripts/oxc-wasm/src/options.rs +154 -0
  186. package/scripts/parser-audit.mjs +492 -0
  187. package/scripts/rolldown-facet/entry.mjs +21 -0
  188. package/scripts/rolldown-facet/shims.mjs +64 -0
  189. package/dist/facets/esbuild-bundle-pool.d.ts +0 -43
  190. package/dist/facets/esbuild-bundle-pool.d.ts.map +0 -1
  191. package/dist/facets/esbuild-bundle-pool.js +0 -80
  192. package/dist/loaders/pre-bundle-preamble.d.ts +0 -44
  193. package/dist/loaders/pre-bundle-preamble.d.ts.map +0 -1
  194. package/dist/loaders/pre-bundle-preamble.js +0 -116
  195. package/dist/runtime/host-wasm.d.ts +0 -8
  196. package/dist/runtime/host-wasm.d.ts.map +0 -1
  197. package/dist/runtime/host-wasm.js +0 -33
  198. /package/public/_assets/napi-wasm/loader/{99efae93dd1dcc2b → ab7e57fe9e8750c2}/wasi-trampoline.wasm +0 -0
@@ -16,15 +16,16 @@ import { normalizeVfsPath, parentVfsPath, resolveVfsPath, stripLeadingSlashes }
16
16
  import { errorText } from '@nimbus-sh/core/_shared/error-text.js';
17
17
  import { CRED_KERNEL, requireVfsCred } from '@nimbus-sh/core/runtime/os-contracts.js';
18
18
  import { engineKey } from '@nimbus-sh/core/runtime/process-files.js';
19
+ import { execIdField } from '@nimbus-sh/core/runtime/process-table.js';
19
20
  import { parseViteConfigSource, parseViteConfigTypeScript, viteBuildBlockingPlugins, unhandledVitePlugins } from '@nimbus-sh/core/runtime/vite-config-parser.js';
20
21
  import { findHtmlScriptEntrypoint, rewriteViteBuildHtml } from '../runtime/html-entrypoint.js';
21
- import { handKernelArtifact, projectFs as viewFs } from '../runtime/project-fs.js';
22
+ import { handKernelArtifact, projectEntryType, projectFs as viewFs } from '../runtime/project-fs.js';
22
23
  import { supervisorEsbuildService } from '../facets/esbuild-transform.js';
23
24
  import { ViteDevServer } from '../facets/vite-dev-server.js';
24
25
  import { shouldUseRealVite } from '../facets/cirrus-real.js';
25
26
  import { makeLongRunningPortStub, resolveLongRunningPort, expandArgvShellDefaults, } from '@nimbus-sh/core/runtime/long-running-handle.js';
26
27
  import { checkNodeModulesGuard, withLoudTimeout, VITE_BUILD_TIMEOUT_MS, } from './helpers.js';
27
- import { startRealVite } from './start-real-vite.js';
28
+ import { devServerIdentity, startRealVite } from './start-real-vite.js';
28
29
  import { notifyTerminalEvent } from '../runtime/process-logs-api.js';
29
30
  import { VITE_CONFIG_KEY } from './keys.js';
30
31
  import { registerServingPort } from './serving-port.js';
@@ -124,7 +125,7 @@ export function createViteCommand(self) {
124
125
  return 1;
125
126
  }
126
127
  ctx.stdout.write('Building for production...\n');
127
- ctx.stdout.write(' Entry: ' + entryPoint + '\n');
128
+ ctx.stdout.write(' Entry: /' + entryPoint + '\n');
128
129
  const t0 = Date.now();
129
130
  try {
130
131
  // Vite parity: build writes to the resolved outDir wherever it
@@ -162,7 +163,7 @@ export function createViteCommand(self) {
162
163
  // Bounded (G5): an esbuild stall must surface as a loud timeout
163
164
  // naming the entry, never a silent hang. The existing catch below
164
165
  // renders the timeout as `Build error: …`.
165
- ctx.stdout.write(' Bundling ' + entryPoint + ' …\n');
166
+ ctx.stdout.write(' Bundling /' + entryPoint + ' …\n');
166
167
  const result = await withLoudTimeout(self.esbuildService.build([entryPoint], {
167
168
  bundle: true, format: 'esm', target: 'es2020', platform: 'browser',
168
169
  minify: true, outdir: distDir,
@@ -173,7 +174,7 @@ export function createViteCommand(self) {
173
174
  viteAssets: true,
174
175
  vitePublicDir: hasPublic ? publicDir : undefined,
175
176
  fs: projectFs,
176
- }), VITE_BUILD_TIMEOUT_MS, `vite build of ${entryPoint}`);
177
+ }), VITE_BUILD_TIMEOUT_MS, `vite build of /${entryPoint}`);
177
178
  if (result.errors?.length) {
178
179
  for (const e of result.errors)
179
180
  ctx.stderr.write(' error: ' + e.text + '\n');
@@ -220,7 +221,7 @@ export function createViteCommand(self) {
220
221
  try {
221
222
  for (const e of await projectFs.readdir(dir)) {
222
223
  const fp = dir + '/' + e.name;
223
- if (e.type === 'directory')
224
+ if ((await projectEntryType(projectFs, dir, e)) === 'directory')
224
225
  await collectCss(fp);
225
226
  else if (e.name.endsWith('.css')) {
226
227
  try {
@@ -262,7 +263,7 @@ export function createViteCommand(self) {
262
263
  for (const e of await projectFs.readdir(src)) {
263
264
  const s = src + '/' + e.name;
264
265
  const d = dst + '/' + e.name;
265
- if (e.type === 'directory') {
266
+ if ((await projectEntryType(projectFs, src, e)) === 'directory') {
266
267
  await copyTree(s, d);
267
268
  }
268
269
  else {
@@ -323,9 +324,11 @@ export function createViteCommand(self) {
323
324
  // process metadata support: same long-running treatment as the
324
325
  // dev path, just on the dist/ directory.
325
326
  const previewPort = viteConfig.port || 4173; // vite preview default
326
- const previewProcEntry = self.processes.spawn('vite preview (' + distRoot + ')', ['vite', ...args], distRoot, { longRunning: true });
327
+ // A child of the command, under its credential: the server reads the
328
+ // build as the principal who ran it.
329
+ const previewProcEntry = self.processes.spawn('vite preview (' + distRoot + ')', ['vite', ...args], distRoot, { longRunning: true, parentPid: ctx.pid });
327
330
  self.viteDevServer = new ViteDevServer({
328
- vfs: self.sqliteFs, esbuild: self.esbuildService, root: servedDist,
331
+ vfs: self.sqliteFs, cred: previewProcEntry.cred, esbuild: self.esbuildService, root: servedDist,
329
332
  onHmrMessage: () => { },
330
333
  sql: self.ctx.storage.sql,
331
334
  basePath: previewBasePath,
@@ -348,7 +351,7 @@ export function createViteCommand(self) {
348
351
  try {
349
352
  await self.ctx.storage.put(VITE_CONFIG_KEY, {
350
353
  root: servedDist, basePath: previewBasePath, port: previewPort,
351
- identity: { cwd: previewProcEntry.cwd, argv: previewProcEntry.argv },
354
+ identity: devServerIdentity(previewProcEntry),
352
355
  });
353
356
  }
354
357
  catch { }
@@ -469,8 +472,8 @@ export function createViteCommand(self) {
469
472
  : undefined;
470
473
  const handedOff = adoptedEntry != null;
471
474
  const identity = adoptedEntry
472
- ? { cwd: adoptedEntry.cwd, argv: adoptedEntry.argv }
473
- : { cwd: vfsRoot, argv: expandedArgs };
475
+ ? devServerIdentity(adoptedEntry)
476
+ : { cwd: vfsRoot, argv: expandedArgs, cred: requireVfsCred(ctx.cred, 'vite'), ...execIdField(self.processes.get(ctx.pid)) };
474
477
  if (useReal) {
475
478
  const vitePort = resolvedPort;
476
479
  const previewBasePath = self.viteBasePath;
@@ -496,7 +499,7 @@ export function createViteCommand(self) {
496
499
  ctx.stdout.write('\n\x1b[1;36m Nimbus: real-vite mode\x1b[0m \x1b[2m(experimental, Phase 1-4)\x1b[0m\n\n');
497
500
  ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Preview: \x1b[36m' + previewBasePath + '/\x1b[0m\n');
498
501
  ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Vite: ' + cirrusReal.stats.viteVersion + ' (bundled)\n');
499
- ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Root: ' + vfsRoot + '\n');
502
+ ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Root: /' + vfsRoot + '\n');
500
503
  ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Port: ' + vitePort + ' \x1b[2m(virtual routing key)\x1b[0m\n');
501
504
  if (snap) {
502
505
  const kb = (snap.totalBytes / 1024).toFixed(1);
@@ -506,7 +509,7 @@ export function createViteCommand(self) {
506
509
  (pkgJson ? '\x1b[2m(incl. ' + pkgJson + ' package.json, rest lazy)\x1b[0m' : '') + '\n');
507
510
  }
508
511
  if (userConfigBundle) {
509
- ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Config: ' + cfgPath + ' \x1b[2m(' +
512
+ ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Config: /' + cfgPath + ' \x1b[2m(' +
510
513
  (userConfigBundle.length / 1024).toFixed(0) + ' KB bundled)\x1b[0m\n');
511
514
  }
512
515
  ctx.stdout.write('\n \x1b[2mWorks:\x1b[0m @vitejs/plugin-react, JSX/TSX transforms, SPA fallback, HMR.\n');
@@ -546,11 +549,13 @@ export function createViteCommand(self) {
546
549
  //
547
550
  // The adopted wrapper pid stays `running` in /api/processes with this
548
551
  // port; a fresh spawn carries the identity inputs computed above.
549
- const viteProcEntry = adoptedEntry ?? self.processes.spawn('vite (' + vfsRoot + ')', identity.argv, identity.cwd, { longRunning: true });
552
+ const viteProcEntry = adoptedEntry ?? self.processes.spawn('vite (' + vfsRoot + ')', identity.argv, identity.cwd, { longRunning: true, cred: identity.cred, execId: identity.execId });
550
553
  if (handedOff)
551
554
  self.processes.setLongRunning(viteProcEntry.pid);
552
555
  self.viteDevServer = new ViteDevServer({
553
556
  vfs: self.sqliteFs,
557
+ // The server reads and writes as the principal who ran the command.
558
+ cred: viteProcEntry.cred,
554
559
  esbuild: self.esbuildService,
555
560
  root: servedRoot,
556
561
  port: resolvedPort,
@@ -569,8 +574,7 @@ export function createViteCommand(self) {
569
574
  env: self.env,
570
575
  ctx: self.ctx,
571
576
  // The shared bundle pool puts cold /@modules/ misses on the facet
572
- // path. This site never passed it before, so `vite` served every
573
- // cold miss through in-supervisor esbuild-wasm.
577
+ // path, from a slice.
574
578
  bundlePool: self.ensureBundlePool(),
575
579
  // Process diagnostics support: wire dev-server diagnostics into the
576
580
  // supervisor's per-PID log store so the Process tab is not silent
@@ -584,7 +588,7 @@ export function createViteCommand(self) {
584
588
  root: servedRoot, aliases: viteConfig.alias, define: viteDefine,
585
589
  injectBasename: viteConfig.injectBasename, basePath: previewBasePath,
586
590
  port: resolvedPort,
587
- identity: { cwd: viteProcEntry.cwd, argv: viteProcEntry.argv },
591
+ identity: devServerIdentity(viteProcEntry),
588
592
  });
589
593
  }
590
594
  catch { }
@@ -623,7 +627,7 @@ export function createViteCommand(self) {
623
627
  ctx.stdout.write(' \x1b[2m(also: ' + previewBasePath + '/?port=' + resolvedPort + ')\x1b[0m');
624
628
  }
625
629
  ctx.stdout.write('\n');
626
- ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Root: ' + vfsRoot + '\n');
630
+ ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Root: /' + vfsRoot + '\n');
627
631
  ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Port: ' + resolvedPort + ' \x1b[2m(pid=' + viteProcEntry.pid + ')\x1b[0m\n');
628
632
  ctx.stdout.write(' \x1b[32m\u279C\x1b[0m Transforms: .ts .tsx .jsx (React JSX automatic)\n');
629
633
  if (viteConfig.alias)
@@ -1 +1 @@
1
- {"version":3,"file":"ws-relay.d.ts","sourceRoot":"","sources":["../../src/session/ws-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAWvC;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,QAAkB,CAAC;AAW1D,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,MAAM,CAAK;IAEnB;;;;;;;;OAQG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAoCpG;;;;OAIG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAgB5E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAMlF,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IASpE,kDAAkD;IAClD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAM9B,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,OAAO;CAmBhB"}
1
+ {"version":3,"file":"ws-relay.d.ts","sourceRoot":"","sources":["../../src/session/ws-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAWvC;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,QAAkB,CAAC;AAwB1D,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,MAAM,CAAK;IAEnB;;;;;;;;OAQG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAoCpG;;;;OAIG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAgB5E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAMlF,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IASpE,kDAAkD;IAClD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAM9B,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,OAAO;CAmBhB"}
@@ -48,6 +48,18 @@ function eventBytes(event) {
48
48
  return event.bytes.byteLength;
49
49
  return event.text ? event.text.length * 2 : 0;
50
50
  }
51
+ /**
52
+ * The URL a socket's upgrade is fetched from: workerd's fetch takes http(s)
53
+ * only ("Fetch API cannot load: wss://..."), so ws: is http: and wss: is
54
+ * https:, the rest of the address as given. A fragment never reaches a
55
+ * server, in a WebSocket handshake or an HTTP request.
56
+ */
57
+ function upgradeUrl(url) {
58
+ const target = new URL(url);
59
+ target.protocol = target.protocol === 'wss:' ? 'https:' : 'http:';
60
+ target.hash = '';
61
+ return target.href;
62
+ }
51
63
  export class WebSocketRelay {
52
64
  entries = new Map();
53
65
  nextId = 1;
@@ -64,7 +76,7 @@ export class WebSocketRelay {
64
76
  const headers = { Upgrade: 'websocket' };
65
77
  if (protocols.length > 0)
66
78
  headers['Sec-WebSocket-Protocol'] = protocols.join(', ');
67
- const response = await fetch(url, { headers });
79
+ const response = await fetch(upgradeUrl(url), { headers });
68
80
  const socket = response.webSocket;
69
81
  if (!socket) {
70
82
  throw new Error(`websocket relay: ${url} did not upgrade (HTTP ${response.status}); ` +
@@ -1,10 +1,12 @@
1
1
  import { type ProcessFiles } from '@nimbus-sh/core/runtime/process-files.js';
2
2
  import type { SessionProcessSupervisor } from '@nimbus-sh/core/runtime/session-process-supervisor.js';
3
3
  import type { FacetManager } from '../facets/manager.js';
4
- import type { ResolveContext } from '@nimbus-sh/core/substrate/lifo/commands/registry.js';
4
+ import { type ResolveContext } from '@nimbus-sh/core/substrate/lifo/commands/registry.js';
5
5
  type Output = {
6
6
  write(data: string): void;
7
7
  };
8
+ /** Whether `command` is the stub a known runtime that is not installed resolves to: no registered command. */
9
+ export declare function isRuntimeInstallHint(command: object): boolean;
8
10
  type RegistryLike = {
9
11
  resolve(name: string, from?: ResolveContext): Promise<unknown> | unknown;
10
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"npm-bin-entrypoints.d.ts","sourceRoot":"","sources":["../../src/shell/npm-bin-entrypoints.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAE1F,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,sBAAsB,CAAC;AASnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qDAAqD,CAAC;AAI1F,KAAK,MAAM,GAAG;IAAE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAoB5C,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC1E,CAAC;AAEF,KAAK,kBAAkB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAezD,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE;IACJ,2FAA2F;IAC3F,UAAU,EAAE,YAAY,CAAC;IACzB,MAAM,IAAI,MAAM,CAAC;IACjB,SAAS,EAAE,wBAAwB,CAAC;IACpC,eAAe,IAAI,YAAY,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mBAAmB,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACxJ,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC9D,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7F,GACA,IAAI,CAgKN;AAqFD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAEnF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EAAE,GACb,yBAAyB,CAS3B;AAiGD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAS/E"}
1
+ {"version":3,"file":"npm-bin-entrypoints.d.ts","sourceRoot":"","sources":["../../src/shell/npm-bin-entrypoints.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAEhG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,KAAK,EAAE,YAAY,EAA4B,MAAM,sBAAsB,CAAC;AASnF,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,qDAAqD,CAAC;AAI1G,KAAK,MAAM,GAAG;IAAE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAoB5C,8GAA8G;AAC9G,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC1E,CAAC;AAEF,KAAK,kBAAkB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAezD,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE;IACJ,2FAA2F;IAC3F,UAAU,EAAE,YAAY,CAAC;IACzB,MAAM,IAAI,MAAM,CAAC;IACjB,SAAS,EAAE,wBAAwB,CAAC;IACpC,eAAe,IAAI,YAAY,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mBAAmB,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACxJ,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC9D,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7F,GACA,IAAI,CAoLN;AA4ED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAEnF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EAAE,GACb,yBAAyB,CAS3B;AAiGD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAS/E"}
@@ -1,12 +1,17 @@
1
1
  import { CRED_KERNEL } from '@nimbus-sh/core/runtime/os-contracts.js';
2
- import { ProcessView } from '@nimbus-sh/core/runtime/process-files.js';
2
+ import { ProcessView, X_OK } from '@nimbus-sh/core/runtime/process-files.js';
3
3
  import { projectFs } from '../runtime/project-fs.js';
4
- import { resolveNpmBin, resolveNpmBinFromPath, resolveNpmBinPath, isStagedArtifactTarget, stagedArtifactId, } from '../npm/bin-links.js';
4
+ import { resolveNpmBin, resolveNpmBinPath, isStagedArtifactTarget, stagedArtifactId, } from '../npm/bin-links.js';
5
5
  import { bundleProfileForNpmBin } from '@nimbus-sh/core/runtime/bundle-profile.js';
6
6
  import { OPENCODE_TREE_SITTER_DIAG_ARG } from '../runtime/opencode-facet-runner.js';
7
7
  import { normalizeVfsPath } from '@nimbus-sh/core/vfs/path.js';
8
- import { DEFAULT_PATH } from '@nimbus-sh/core/constants.js';
8
+ import { resolveContext } from '@nimbus-sh/core/substrate/lifo/commands/registry.js';
9
+ import { isVfsError } from '@nimbus-sh/core/vfs/vfs-error.js';
9
10
  import { z } from 'zod/v4';
11
+ /** Whether `command` is the stub a known runtime that is not installed resolves to: no registered command. */
12
+ export function isRuntimeInstallHint(command) {
13
+ return '__nimbusRuntimeInstallHint' in command && command.__nimbusRuntimeInstallHint === true;
14
+ }
10
15
  const NpmBinPackageMetadataSchema = z.object({
11
16
  name: z.string().optional(),
12
17
  keywords: z.array(z.string()).optional(),
@@ -19,10 +24,10 @@ const NpmBinPackageMetadataSchema = z.object({
19
24
  }).passthrough();
20
25
  export function installNpmBinFallbackResolver(registry, deps) {
21
26
  const upstreamResolve = registry.resolve.bind(registry);
22
- // What `registry.resolve` probes a name with before any command runs (it
23
- // has no caller): the namespace as the kernel, for the registry's life.
24
- // The command that then runs looks its bin up again through its own view.
25
- const inspector = projectFs(new ProcessView(deps.filesystem.openHost(CRED_KERNEL).fs));
27
+ // Bins are probed through the caller's view, the one the command that
28
+ // runs looks its bin up again through; a resolution without a caller sees
29
+ // the namespace as the kernel.
30
+ const kernelView = new ProcessView(deps.filesystem.openHost(CRED_KERNEL).fs);
26
31
  // A lookup the namespace cannot answer (a mount that fails under the cwd)
27
32
  // finds no bin: the name resolves as it would with none, and only the
28
33
  // command it names fails.
@@ -35,19 +40,25 @@ export function installNpmBinFallbackResolver(registry, deps) {
35
40
  }
36
41
  };
37
42
  registry.resolve = async function resolveWithNpmBins(name, from) {
38
- const cwd = from?.cwd || deps.getCwd() || '/home/user';
39
- // `<dir>/node_modules/.bin/<bin>` by path (a launcher's `exec`) is the
40
- // same program as the bare name: same runtime choice, TTY and lifecycle.
43
+ const context = from ?? resolveContext(deps.getCwd() || '/home/user', undefined, kernelView);
44
+ const cwd = context.cwd;
45
+ const inspector = projectFs(context.view);
46
+ // An npm bin shim by path (a launcher's `exec`, or the file a search of
47
+ // PATH found for a bare name) is the same program as the bare name: same
48
+ // runtime choice, TTY and lifecycle. The command that runs looks the
49
+ // shim up again through its own view, at the same path.
41
50
  if (name.startsWith('/') || name.startsWith('./') || name.startsWith('../')) {
42
51
  const bin = await probe(() => resolveNpmBinPath(inspector, cwd, name));
43
52
  if (!bin)
44
- return await upstreamResolve(name, from);
45
- return binHandler(bin.name, async (ctx, vfs) => await resolveNpmBinPath(vfs, ctx.cwd || '/home/user', name));
53
+ return await upstreamResolve(name, context);
54
+ return binHandler(bin.name, async (vfs) => await resolveNpmBinPath(vfs, cwd, name), true);
46
55
  }
47
- const upstream = await upstreamResolve(name, from);
56
+ // Registered commands, then PATH (searched upstream), then the bins of
57
+ // the node_modules directories from the cwd up.
58
+ const upstream = await upstreamResolve(name, context);
48
59
  if (upstream)
49
60
  return upstream;
50
- if (!await probe(() => resolveNpmBinForInvocation(inspector, cwd, DEFAULT_PATH, name))) {
61
+ if (!context.search || !await probe(() => resolveNpmBin(inspector, cwd, name))) {
51
62
  let hint = null;
52
63
  try {
53
64
  hint = await deps.runtimeCommandHint(name);
@@ -65,16 +76,25 @@ export function installNpmBinFallbackResolver(registry, deps) {
65
76
  hintHandler.__nimbusRuntimeInstallHint = true;
66
77
  return hintHandler;
67
78
  }
68
- return binHandler(name, async (ctx, vfs) => await resolveNpmBinForInvocation(vfs, ctx.cwd || '/home/user', ctx.env?.PATH || DEFAULT_PATH, name));
79
+ return binHandler(name, async (vfs) => await resolveNpmBin(vfs, cwd, name), false);
69
80
  };
70
- function binHandler(name, lookup) {
81
+ /**
82
+ * The command that runs an npm bin. `executesShim`: the shim file is what
83
+ * was invoked (by its path, or found on PATH), so the caller must be
84
+ * allowed to execute it, as execve checks; a bare name found in the cwd's
85
+ * node_modules/.bin runs the package's program, as npm's own lookup does,
86
+ * whatever mode an older install left its shim with.
87
+ */
88
+ function binHandler(name, lookup, executesShim) {
71
89
  return async (ctx) => {
72
90
  const invocationCwd = ctx.cwd || '/home/user';
73
- // The bin as this command sees it, through its own view.
91
+ // The bin as this command sees it, through its own view; what it runs
92
+ // is resolved through that view too.
74
93
  const vfs = projectFs(ctx.vfs);
94
+ const from = resolveContext(invocationCwd, ctx.env, ctx.vfs);
75
95
  let bin;
76
96
  try {
77
- bin = await lookup(ctx, vfs);
97
+ bin = await lookup(vfs);
78
98
  }
79
99
  catch (error) {
80
100
  ctx.stderr.write(`${name}: ${error instanceof Error ? error.message : String(error)}\n`);
@@ -84,6 +104,17 @@ export function installNpmBinFallbackResolver(registry, deps) {
84
104
  ctx.stderr.write(`${name}: command not found\n`);
85
105
  return 127;
86
106
  }
107
+ if (executesShim) {
108
+ try {
109
+ await ctx.vfs.access('/' + bin.shimPath, X_OK);
110
+ }
111
+ catch (error) {
112
+ if (!isVfsError(error, 'EACCES') && !isVfsError(error, 'EPERM'))
113
+ throw error;
114
+ ctx.stderr.write(`/${bin.shimPath}: Permission denied\n`);
115
+ return 126;
116
+ }
117
+ }
87
118
  const argv = Array.isArray(ctx.args) ? ctx.args.map(String) : [];
88
119
  // Staged-artifact sentinel (e.g. opencode): the runnable bundle lives in
89
120
  // the static-assets layer, not the VFS. Dispatch it through the
@@ -97,7 +128,7 @@ export function installNpmBinFallbackResolver(registry, deps) {
97
128
  // program: run it the way a path-shaped invocation of it runs.
98
129
  const runtimeName = await npmBinRuntimeForTarget(vfs, bin.targetPath);
99
130
  if (runtimeName === null) {
100
- const execCmd = await upstreamResolve('/' + bin.shimPath);
131
+ const execCmd = await upstreamResolve('/' + bin.shimPath, from);
101
132
  if (typeof execCmd !== 'function') {
102
133
  ctx.stderr.write(`${name}: command not found\n`);
103
134
  return 127;
@@ -108,7 +139,7 @@ export function installNpmBinFallbackResolver(registry, deps) {
108
139
  const metadata = await readNpmBinPackageMetadata(vfs, bin.packagePath);
109
140
  const attachedTty = looksAttachedTtyNpmBin(metadata, argv, ctx.env);
110
141
  const longRunning = attachedTty || looksLongRunningNpmBin(name, argv);
111
- const runtimeCmd = await upstreamResolve(runtimeName);
142
+ const runtimeCmd = await upstreamResolve(runtimeName, from);
112
143
  if (typeof runtimeCmd !== 'function') {
113
144
  ctx.stderr.write(`${name}: ${runtimeName} command unavailable\n`);
114
145
  return 1;
@@ -180,17 +211,14 @@ export function installNpmBinFallbackResolver(registry, deps) {
180
211
  };
181
212
  }
182
213
  }
183
- async function resolveNpmBinForInvocation(vfs, cwd, envPath, name) {
184
- return await resolveNpmBinFromPath(vfs, cwd, envPath, name)
185
- ?? await resolveNpmBin(vfs, cwd, name);
186
- }
187
214
  async function runStagedArtifact(deps, name, artifact, argv, cwd, ctx, disposition) {
188
215
  const shellLine = `${name} ${argv.join(' ')}`.trim();
189
216
  const startedAt = Date.now();
190
217
  const fm = deps.getFacetManager();
191
218
  // Piped stdin is not yet wired for staged artifacts; the interactive TUI reads
192
219
  // keystrokes from the live ProcessInputStore via the attached-TTY stdin pump.
193
- const base = { argv, env: ctx.env ?? {}, cwd, command: shellLine };
220
+ // The program carries the exec id of the command that runs it.
221
+ const base = { argv, env: ctx.env ?? {}, cwd, command: shellLine, invokerPid: ctx.pid };
194
222
  let result;
195
223
  try {
196
224
  // Same contract as the node-bin path: a user-invoked program runs to
@@ -1 +1 @@
1
- {"version":3,"file":"facet-resident-store.d.ts","sourceRoot":"","sources":["../../src/vfs/facet-resident-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoLG;AAUH;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,OAA2B,CAAC;AAClE,eAAO,MAAM,yBAAyB,QAA8B,CAAC;AAErE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,2BAA2B,QAozEhC,CAAC;AAET,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE"}
1
+ {"version":3,"file":"facet-resident-store.d.ts","sourceRoot":"","sources":["../../src/vfs/facet-resident-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoLG;AAUH;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,OAA2B,CAAC;AAClE,eAAO,MAAM,yBAAyB,QAA8B,CAAC;AAErE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,2BAA2B,QA0zEhC,CAAC;AAET,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE"}
@@ -629,7 +629,7 @@ function __residentTablesOnSql(sql) {
629
629
  nsOfKind(kind) { return [...sql.exec("SELECT parent, name FROM ns WHERE kind = ?", kind)]; },
630
630
  // Directories whose entries the listing did not name (__nsUnlisted): their target is the mount point.
631
631
  nsUnlisted() { return [...sql.exec("SELECT parent, name, target FROM ns WHERE kind = ? AND target IS NOT NULL", __NS_DIR)]; },
632
- nsChildren(parent) { return [...sql.exec("SELECT name, kind FROM ns WHERE parent = ?", parent)]; },
632
+ nsChildren(parent) { return [...sql.exec("SELECT name, kind, mode FROM ns WHERE parent = ?", parent)]; },
633
633
  nsCount() { const row = first(sql.exec("SELECT count(*) AS n FROM ns")); return row === undefined ? 0 : Number(row.n); },
634
634
  };
635
635
  }
@@ -874,7 +874,7 @@ function __residentTablesInMemory() {
874
874
  nsChildren(parent) {
875
875
  const dir = ns.get(parent);
876
876
  if (!dir) return [];
877
- return [...dir.keys()].sort(byName).map((name) => ({ name, kind: dir.get(name).kind }));
877
+ return [...dir.keys()].sort(byName).map((name) => ({ name, kind: dir.get(name).kind, mode: dir.get(name).mode }));
878
878
  },
879
879
  nsCount() { return names; },
880
880
  };
@@ -1454,13 +1454,19 @@ function __nsLoadLinks(t) {
1454
1454
 
1455
1455
  /**
1456
1456
  * The mount a lookup of \`k\` lands on unlisted: the mount point of the
1457
- * nearest unlisted directory at \`k\` (when \`self\`) or above it, or null.
1457
+ * nearest directory the namespace holds at \`k\` (when \`self\`) or above
1458
+ * it, when that directory is unlisted, or null. A listed directory is known
1459
+ * whatever is above it: a device mount that resolves its own paths can show
1460
+ * a directory whose parents it will not list.
1458
1461
  */
1459
1462
  function __nsUnlistedOver(k, self) {
1460
1463
  if (__nsUnlisted.size === 0) return null;
1464
+ const t = __residentRequire();
1461
1465
  for (let at = self ? k : __nsSplit(k)[0]; at !== ""; at = __nsSplit(at)[0]) {
1462
1466
  const mount = __nsUnlisted.get(at);
1463
1467
  if (mount !== undefined) return mount;
1468
+ const row = __nsRowAt(t, at);
1469
+ if (row && Number(row.kind) === __NS_DIR) return null;
1464
1470
  }
1465
1471
  return null;
1466
1472
  }
@@ -1624,9 +1630,9 @@ function __nsUnknown(k, followLeaf, listing) {
1624
1630
  return listing ? __nsUnlistedOver(found.path, true) : null;
1625
1631
  }
1626
1632
 
1627
- /** The entries directly under directory \`k\` (already resolved): [{ name, kind }]. */
1633
+ /** The entries directly under directory \`k\` (already resolved): [{ name, kind, mode }]; the mode says what a file kind is. */
1628
1634
  function __nsChildren(k) {
1629
- return __residentRequire().nsChildren(k).map((row) => ({ name: String(row.name), kind: Number(row.kind) }));
1635
+ return __residentRequire().nsChildren(k).map((row) => ({ name: String(row.name), kind: Number(row.kind), mode: Number(row.mode) }));
1630
1636
  }
1631
1637
 
1632
1638
  /** Whether the credential may search directory \`row\` (POSIX x). */
@@ -100,6 +100,14 @@ export declare class NimbusWrangler {
100
100
  */
101
101
  private resolveEntryPath;
102
102
  private buildAndLoad;
103
+ /**
104
+ * Checks that `worker` (the inner Worker, loaded) exports each binding's
105
+ * class, asking its own isolate once through its `classesEntrypoint`
106
+ * (which also runs its module code, so an error there is the build's),
107
+ * then registers each class for the session's facets to run. False,
108
+ * logged, when one is missing.
109
+ */
110
+ private registerDoClasses;
103
111
  private buildInnerEnv;
104
112
  private handleVfsEvents;
105
113
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"nimbus-wrangler.d.ts","sourceRoot":"","sources":["../../src/wrangler/nimbus-wrangler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,KAAK,EAAY,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAsD/E,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,eAAe,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,EAAE,GAAG,CAAC;IACT;;;;OAIG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;CAClC;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,GACxB,MAAM,CA+BR;AAyDD,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,YAAY,CAAqB;IAEzC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAAa;IACjC,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAA+B;gBAErC,IAAI,EAAE,qBAAqB;IAWvC,qCAAqC;IAC/B,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAqB/B,oCAAoC;IACpC,IAAI,IAAI,IAAI;IAaZ,IAAI,SAAS,YAA2B;IAIxC,OAAO,CAAC,UAAU;IAiDlB,oFAAoF;IACpF,OAAO,CAAC,gBAAgB;IAqBxB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,gBAAgB;YAIV,YAAY;IA2L1B,OAAO,CAAC,aAAa;IAoOrB,OAAO,CAAC,eAAe;IAkCvB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,aAAa,CACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM;IAChB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,QAAQ,CAAC;IAsFpB,IAAI,KAAK;;;;;;MAQR;IAYD,8FAA8F;IAC9F,kBAAkB,IAAI,OAAO;IAK7B,+EAA+E;IAC/E,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI5C;;;;;gCAK4B;IAC5B,uBAAuB,IAAI,IAAI;CA4BhC"}
1
+ {"version":3,"file":"nimbus-wrangler.d.ts","sourceRoot":"","sources":["../../src/wrangler/nimbus-wrangler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,KAAK,EAAY,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAuD/E,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,eAAe,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,EAAE,GAAG,CAAC;IACT;;;;OAIG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;CAClC;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,GACxB,MAAM,CA+BR;AAyDD,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,YAAY,CAAqB;IAEzC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAAa;IACjC,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAA+B;gBAErC,IAAI,EAAE,qBAAqB;IAWvC,qCAAqC;IAC/B,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAqB/B,oCAAoC;IACpC,IAAI,IAAI,IAAI;IAaZ,IAAI,SAAS,YAA2B;IAIxC,OAAO,CAAC,UAAU;IAiDlB,oFAAoF;IACpF,OAAO,CAAC,gBAAgB;IAqBxB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,gBAAgB;YAIV,YAAY;IA8J1B;;;;;;OAMG;YACW,iBAAiB;IAyB/B,OAAO,CAAC,aAAa;IAiOrB,OAAO,CAAC,eAAe;IAkCvB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,aAAa,CACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM;IAChB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,QAAQ,CAAC;IAsFpB,IAAI,KAAK;;;;;;MAQR;IAYD,8FAA8F;IAC9F,kBAAkB,IAAI,OAAO;IAK7B,+EAA+E;IAC/E,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI5C;;;;;gCAK4B;IAC5B,uBAAuB,IAAI,IAAI;CA4BhC"}
@@ -16,6 +16,7 @@
16
16
  import { normalizeVfsPath } from '@nimbus-sh/core/vfs/path.js';
17
17
  import { CF_COMPAT_DATE } from '@nimbus-sh/core/constants.js';
18
18
  import { registerInnerDoClass, clearInnerDoClasses, abortInnerDoFacets } from '@nimbus-sh/fabric/inner-do-registry.js';
19
+ import { innerWorkerModules } from '@nimbus-sh/fabric/inner-do-env.js';
19
20
  import { KvEmulator } from '../bindings/kv.js';
20
21
  import { D1Emulator } from '../bindings/d1.js';
21
22
  import { R2Emulator } from '../bindings/r2.js';
@@ -321,7 +322,7 @@ export class NimbusWrangler {
321
322
  this.onLog(`\x1b[31mEntry point not found: ${entryPoint}\x1b[0m\n`);
322
323
  return false;
323
324
  }
324
- // Bundle via esbuild
325
+ // Bundle (EsbuildService.build: the build facet, rolldown)
325
326
  this.onLog(' Building Worker...\n');
326
327
  try {
327
328
  // [WRANGLER-DEV-HANG P0b] Time-bound the bundle. Pre-fix,
@@ -391,16 +392,7 @@ export class NimbusWrangler {
391
392
  if (this.supervisorCtx) {
392
393
  abortInnerDoFacets(this.supervisorCtx, this.doClassMap.keys(), new Error('nimbus-wrangler rebuilding'));
393
394
  }
394
- // Two-pass load to break the chicken-and-egg:
395
- // Pass 1: load with NO env to extract any durable_objects classes.
396
- // buildInnerEnv needs this.doClassMap to synthesize DO
397
- // namespace bindings, but getDurableObjectClass() needs a
398
- // worker stub, which we get only by loading.
399
- // Pass 2: re-load with FULL env (including DO namespace shims)
400
- // that the inner Worker actually uses.
401
- //
402
- // workerd caches by content hash, so the second load is cheap —
403
- // it reuses the same compiled isolate and just swaps env.
395
+ this.doClassMap.clear();
404
396
  const wrangCompatDate = this.config.compatibility_date || CF_COMPAT_DATE;
405
397
  // Filter flags that workerd refuses on dynamic-worker LOADER.load().
406
398
  // `experimental` gates behind the parent process's --experimental
@@ -419,46 +411,27 @@ export class NimbusWrangler {
419
411
  if (rawFlags.length !== wrangCompatFlags.length) {
420
412
  this.onLog(` \x1b[2mnote: stripped 'experimental' from inner compat_flags (not propagatable via LOADER.load)\x1b[0m\n`);
421
413
  }
422
- const baseWorkerCode = {
423
- compatibilityDate: wrangCompatDate,
424
- compatibilityFlags: wrangCompatFlags,
425
- mainModule: 'worker.js',
426
- modules: { 'worker.js': bundledCode },
427
- };
428
- // Pass 1: class extraction (no env, no DO shims).
429
- this.doClassMap.clear();
430
414
  const doBindings = this.config.durable_objects?.bindings || [];
431
- if (doBindings.length > 0) {
432
- let probeWorker;
433
- try {
434
- probeWorker = this.loaderEnv.LOADER.load(baseWorkerCode);
435
- }
436
- catch (e) {
437
- this.onLog(` \x1b[31mBuild error (probe load): ${e?.message || e}\x1b[0m\n`);
415
+ for (const b of doBindings) {
416
+ if (b.script_name && b.script_name !== this.config.name) {
417
+ this.onLog(` \x1b[31merror: durable_objects binding '${b.name}' references external script '${b.script_name}'. nimbus-wrangler cannot load external Workers by name.\x1b[0m\n`);
438
418
  return false;
439
419
  }
440
- for (const b of doBindings) {
441
- if (b.script_name && b.script_name !== this.config.name) {
442
- this.onLog(` \x1b[31merror: durable_objects binding '${b.name}' references external script '${b.script_name}'. nimbus-wrangler cannot load external Workers by name.\x1b[0m\n`);
443
- return false;
444
- }
445
- try {
446
- const cls = probeWorker.getDurableObjectClass(b.class_name);
447
- this.doClassMap.set(b.name, cls);
448
- }
449
- catch (e) {
450
- this.onLog(` \x1b[31merror: durable_objects binding '${b.name}' => class '${b.class_name}' not found in bundle: ${e?.message || e}\x1b[0m\n`);
451
- return false;
452
- }
453
- }
454
420
  }
455
- // Pass 2: real load with the full synthesized env. buildInnerEnv
456
- // reads this.doClassMap populated above.
457
- const innerEnv = this.buildInnerEnv();
421
+ // One load, with the full env. A Durable Object binding is a local
422
+ // namespace in the inner isolate, over the binding the loader passes
423
+ // (inner-do-env.ts): the bundle's first import replaces it in the env
424
+ // every handler, entrypoint and object of the isolate sees.
425
+ const { mainModule, modules, classesEntrypoint } = innerWorkerModules(bundledCode, doBindings.map((b) => b.name));
458
426
  const worker = this.loaderEnv.LOADER.load({
459
- ...baseWorkerCode,
460
- env: innerEnv,
427
+ compatibilityDate: wrangCompatDate,
428
+ compatibilityFlags: wrangCompatFlags,
429
+ mainModule,
430
+ modules,
431
+ env: this.buildInnerEnv(),
461
432
  });
433
+ if (classesEntrypoint !== null && !(await this.registerDoClasses(worker, classesEntrypoint, doBindings)))
434
+ return false;
462
435
  this.workerStub = worker.getEntrypoint();
463
436
  for (const w of result.warnings || []) {
464
437
  this.onLog(` \x1b[33mwarning: ${w.text}\x1b[0m\n`);
@@ -486,6 +459,33 @@ export class NimbusWrangler {
486
459
  // At the end of each phase the inner Worker has one more kind of binding
487
460
  // it can access by name. Phase 0 is the plumbing: adding the `env` field
488
461
  // to LOADER.load() at all, plus forwarding plain string vars.
462
+ /**
463
+ * Checks that `worker` (the inner Worker, loaded) exports each binding's
464
+ * class, asking its own isolate once through its `classesEntrypoint`
465
+ * (which also runs its module code, so an error there is the build's),
466
+ * then registers each class for the session's facets to run. False,
467
+ * logged, when one is missing.
468
+ */
469
+ async registerDoClasses(worker, classesEntrypoint, bindings) {
470
+ const missing = new Set(await worker.getEntrypoint(classesEntrypoint).missing(bindings.map((b) => b.class_name)));
471
+ for (const b of bindings) {
472
+ if (missing.has(b.class_name)) {
473
+ this.onLog(` \x1b[31merror: durable_objects binding '${b.name}' => class '${b.class_name}' is not exported by the Worker\x1b[0m\n`);
474
+ }
475
+ }
476
+ if (missing.size > 0)
477
+ return false;
478
+ const doId = this.supervisorCtx?.id?.toString?.() || '';
479
+ if (doId)
480
+ clearInnerDoClasses(doId);
481
+ for (const b of bindings) {
482
+ const cls = worker.getDurableObjectClass(b.class_name);
483
+ this.doClassMap.set(b.name, cls);
484
+ if (doId)
485
+ registerInnerDoClass(doId, b.name, cls);
486
+ }
487
+ return true;
488
+ }
489
489
  buildInnerEnv() {
490
490
  const env = {};
491
491
  // ── vars ──
@@ -584,29 +584,26 @@ export class NimbusWrangler {
584
584
  }
585
585
  }
586
586
  // ── durable_objects ──
587
- // Inner worker: env[binding].idFromName(name) + env[binding].get(id).fetch(req).
588
- // The class list was resolved and stored in this.doClassMap during
589
- // buildAndLoad(); register each class into the module-level
590
- // registry consulted by _rpcInnerDoFetch, then synthesize the
591
- // namespace stub via ctx.exports.NimbusDurableObjectNamespace(...).
592
- if (this.doClassMap.size > 0) {
587
+ // Inner worker: env[binding] is a local namespace (inner-do-env.ts) over
588
+ // the binding made here, whose fetchOn, callOn and getOn each stub
589
+ // relays to. buildAndLoad registers the classes, from the load this env
590
+ // goes into, in the registry _rpcInnerDoFetch and _rpcInnerDoCall read.
591
+ const doBindingNames = (this.config?.durable_objects?.bindings || []).map((b) => b.name);
592
+ if (doBindingNames.length > 0) {
593
593
  const ctxExports = this.supervisorCtx?.exports;
594
594
  const doId = this.supervisorCtx?.id?.toString?.() || '';
595
595
  if (!ctxExports?.NimbusDurableObjectNamespace) {
596
- for (const [bindingName] of this.doClassMap) {
596
+ for (const bindingName of doBindingNames) {
597
597
  this.onLog(` \x1b[33mwarning: ctx.exports.NimbusDurableObjectNamespace unavailable; env.${bindingName} will not work\x1b[0m\n`);
598
598
  }
599
599
  }
600
600
  else if (!doId) {
601
- for (const [bindingName] of this.doClassMap) {
601
+ for (const bindingName of doBindingNames) {
602
602
  this.onLog(` \x1b[33mwarning: supervisor DO id unavailable; env.${bindingName} will not work\x1b[0m\n`);
603
603
  }
604
604
  }
605
605
  else {
606
- // Clear + repopulate the registry for this supervisor DO id.
607
- clearInnerDoClasses(doId);
608
- for (const [bindingName, cls] of this.doClassMap) {
609
- registerInnerDoClass(doId, bindingName, cls);
606
+ for (const bindingName of doBindingNames) {
610
607
  if (bindingName in env) {
611
608
  this.onLog(` \x1b[33mwarning: durable_objects binding '${bindingName}' overwrites a previous key\x1b[0m\n`);
612
609
  }