@nimbus-sh/worker 0.6.0 → 0.7.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 (133) hide show
  1. package/README.md +2 -2
  2. package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
  3. package/dist/cirrus-npm-cjs.generated.js +1 -1
  4. package/dist/facets/cirrus-real.d.ts.map +1 -1
  5. package/dist/facets/cirrus-real.js +6 -5
  6. package/dist/facets/compose.d.ts +148 -0
  7. package/dist/facets/compose.d.ts.map +1 -0
  8. package/dist/facets/compose.js +146 -0
  9. package/dist/facets/durable-images.d.ts +9 -5
  10. package/dist/facets/durable-images.d.ts.map +1 -1
  11. package/dist/facets/durable-images.js +17 -7
  12. package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
  13. package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
  14. package/dist/facets/esbuild-bundle-pool.js +122 -0
  15. package/dist/facets/exec-telemetry.d.ts +8 -0
  16. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  17. package/dist/facets/manager.d.ts +240 -109
  18. package/dist/facets/manager.d.ts.map +1 -1
  19. package/dist/facets/manager.js +661 -337
  20. package/dist/facets/process.d.ts +20 -16
  21. package/dist/facets/process.d.ts.map +1 -1
  22. package/dist/facets/process.js +59 -28
  23. package/dist/facets/real-vite-fs-shim.js +2 -2
  24. package/dist/facets/vite-dev-server.d.ts +25 -47
  25. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  26. package/dist/facets/vite-dev-server.js +185 -219
  27. package/dist/facets/wasm-image-digest.d.ts +25 -0
  28. package/dist/facets/wasm-image-digest.d.ts.map +1 -0
  29. package/dist/facets/wasm-image-digest.js +25 -0
  30. package/dist/facets/wasm-swap-registry.d.ts +51 -92
  31. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  32. package/dist/facets/wasm-swap-registry.js +68 -227
  33. package/dist/git/network-facet.d.ts.map +1 -1
  34. package/dist/git/network-facet.js +6 -5
  35. package/dist/loaders/child-process/spawn-pool.d.ts +3 -2
  36. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  37. package/dist/loaders/child-process/spawn-pool.js +3 -2
  38. package/dist/loaders/generated-workers.d.ts +2 -2
  39. package/dist/loaders/generated-workers.d.ts.map +1 -1
  40. package/dist/loaders/generated-workers.js +3 -3
  41. package/dist/loaders/npm-resolve-preamble.d.ts +3 -6
  42. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  43. package/dist/loaders/npm-resolve-preamble.js +34 -108
  44. package/dist/node-shims-artifact.generated.js +3 -3
  45. package/dist/npm/install-batch-facet.d.ts +3 -2
  46. package/dist/npm/install-batch-facet.d.ts.map +1 -1
  47. package/dist/npm/install-batch-facet.js +45 -15
  48. package/dist/npm/installer.d.ts +22 -17
  49. package/dist/npm/installer.d.ts.map +1 -1
  50. package/dist/npm/installer.js +209 -193
  51. package/dist/npm/pre-bundle-facet.d.ts +1 -1
  52. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  53. package/dist/npm/pre-bundle-facet.js +1 -1
  54. package/dist/npm/resolve-facet.d.ts +6 -0
  55. package/dist/npm/resolve-facet.d.ts.map +1 -1
  56. package/dist/npm/resolve-one-facet.d.ts +21 -20
  57. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  58. package/dist/npm/resolve-one-facet.js +85 -84
  59. package/dist/npm/semver.d.ts +59 -0
  60. package/dist/npm/semver.d.ts.map +1 -0
  61. package/dist/npm/semver.js +226 -0
  62. package/dist/router/remote-api.js +31 -1
  63. package/dist/runtime/html-entrypoint.d.ts +7 -0
  64. package/dist/runtime/html-entrypoint.d.ts.map +1 -1
  65. package/dist/runtime/html-entrypoint.js +18 -2
  66. package/dist/runtime/node-runner.d.ts +3 -0
  67. package/dist/runtime/node-runner.d.ts.map +1 -1
  68. package/dist/runtime/node-runner.js +7 -0
  69. package/dist/runtime/node-shims.d.ts.map +1 -1
  70. package/dist/runtime/node-shims.js +305 -29
  71. package/dist/runtime/opencode-facet-runner.js +2 -2
  72. package/dist/session/helpers.d.ts +38 -0
  73. package/dist/session/helpers.d.ts.map +1 -1
  74. package/dist/session/helpers.js +76 -0
  75. package/dist/session/init-phases.d.ts +1 -1
  76. package/dist/session/init-phases.d.ts.map +1 -1
  77. package/dist/session/init-phases.js +2 -12
  78. package/dist/session/init.d.ts +15 -1
  79. package/dist/session/init.d.ts.map +1 -1
  80. package/dist/session/init.js +82 -603
  81. package/dist/session/nimbus-session.d.ts +56 -22
  82. package/dist/session/nimbus-session.d.ts.map +1 -1
  83. package/dist/session/nimbus-session.js +130 -101
  84. package/dist/session/npm-install-port.d.ts +16 -0
  85. package/dist/session/npm-install-port.d.ts.map +1 -0
  86. package/dist/session/npm-install-port.js +37 -0
  87. package/dist/session/port-capability.d.ts +44 -0
  88. package/dist/session/port-capability.d.ts.map +1 -1
  89. package/dist/session/port-capability.js +110 -0
  90. package/dist/session/programmatic.d.ts +31 -5
  91. package/dist/session/programmatic.d.ts.map +1 -1
  92. package/dist/session/programmatic.js +94 -68
  93. package/dist/session/routes.d.ts +30 -17
  94. package/dist/session/routes.d.ts.map +1 -1
  95. package/dist/session/routes.js +42 -131
  96. package/dist/session/rpc.d.ts +15 -15
  97. package/dist/session/rpc.d.ts.map +1 -1
  98. package/dist/session/rpc.js +97 -47
  99. package/dist/session/serving-port.d.ts +27 -0
  100. package/dist/session/serving-port.d.ts.map +1 -0
  101. package/dist/session/serving-port.js +27 -0
  102. package/dist/session/start-real-vite.d.ts +12 -0
  103. package/dist/session/start-real-vite.d.ts.map +1 -1
  104. package/dist/session/start-real-vite.js +4 -4
  105. package/dist/session/supervisor-op.d.ts +2 -2
  106. package/dist/session/supervisor-op.d.ts.map +1 -1
  107. package/dist/session/supervisor-op.js +13 -7
  108. package/dist/session/supervisor-rpc.d.ts +7 -7
  109. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  110. package/dist/session/supervisor-rpc.js +4 -0
  111. package/dist/session/vite-command.d.ts +18 -0
  112. package/dist/session/vite-command.d.ts.map +1 -0
  113. package/dist/session/vite-command.js +609 -0
  114. package/dist/session/ws.d.ts +61 -0
  115. package/dist/session/ws.d.ts.map +1 -1
  116. package/dist/session/ws.js +122 -12
  117. package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
  118. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  119. package/dist/shell/npm-bin-entrypoints.js +12 -85
  120. package/package.json +24 -4
  121. package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
  122. package/public/index.html +1 -1
  123. package/scripts/bundle-facet-workers.mjs +1 -1
  124. package/scripts/bundle-npm-cjs.mjs +2 -2
  125. package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
  126. package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
  127. package/dist/facets/on-demand-bundle-gate.js +0 -125
  128. package/dist/npm/install-args.d.ts +0 -21
  129. package/dist/npm/install-args.d.ts.map +0 -1
  130. package/dist/npm/install-args.js +0 -70
  131. package/dist/npm/npm-log.d.ts +0 -31
  132. package/dist/npm/npm-log.d.ts.map +0 -1
  133. package/dist/npm/npm-log.js +0 -51
@@ -123,6 +123,109 @@ async function __nimbusUseRpcResultUnref(promise, use) {
123
123
  finally { __nimbusDisposeRpcResult(value); }
124
124
  }
125
125
 
126
+ // ═══════════════════════════════════════════════════════════════════════
127
+ // ── Precompiled wasm ───────────────────────────────────────────────
128
+ // A wasm image can only become a WebAssembly.Module through the Worker
129
+ // Loader's module map; new WebAssembly.Module(bytes) at request time is
130
+ // refused by the runtime. A launch whose closure carries an image (its VFS
131
+ // path, or its content digest for an image inlined as base64) gets it
132
+ // compiled at load and parked here. fs.readFileSync tags the bytes it hands
133
+ // out for such a path, and the WebAssembly seam below answers a compile of
134
+ // tagged or digest-matched bytes with the module the loader already built —
135
+ // so a package's own new WebAssembly.Module(readFileSync(__dirname + '/x.wasm'))
136
+ // works unchanged.
137
+ const __nimbusPrecompiledWasm = globalThis.__nimbusPrecompiledWasm instanceof Map
138
+ ? globalThis.__nimbusPrecompiledWasm : new Map();
139
+ const __nimbusWasmModuleTag = Symbol.for("nimbus.precompiledWasmModule");
140
+ /**
141
+ * Precompiled modules keyed by a digest of their BYTES, for an image that
142
+ * never passes through the filesystem.
143
+ *
144
+ * Vite inlines es-module-lexer's parser as a base64 literal in its own source
145
+ * and compiles it at module top level — from a cell that is request time, and
146
+ * the runtime refuses it. There is no path to tag, so the launch registers
147
+ * the image by content instead and the seam recognises the same bytes when
148
+ * they arrive.
149
+ */
150
+ const __nimbusPrecompiledWasmByDigest = globalThis.__nimbusPrecompiledWasmByDigest instanceof Map
151
+ ? globalThis.__nimbusPrecompiledWasmByDigest : new Map();
152
+ /**
153
+ * A synchronous content key: length and FNV-1a over every byte.
154
+ *
155
+ * Synchronous because new WebAssembly.Module(bytes) is, and SubtleCrypto is
156
+ * not. Collisions do not matter for correctness the way they would in a
157
+ * security check: the set is the handful of images one launch registered, and
158
+ * the length is part of the key.
159
+ */
160
+ function __nimbusWasmDigest(bytes) {
161
+ const view = bytes instanceof Uint8Array
162
+ ? bytes
163
+ : (bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : null);
164
+ if (!view) return null;
165
+ let hash = 0x811c9dc5;
166
+ for (let i = 0; i < view.length; i++) {
167
+ hash ^= view[i];
168
+ hash = Math.imul(hash, 0x01000193) >>> 0;
169
+ }
170
+ return view.length + ":" + hash.toString(16);
171
+ }
172
+ (() => {
173
+ const WA = globalThis.WebAssembly;
174
+ if (!WA || WA.__nimbusPrecompiledSeam) return;
175
+ const RealModule = WA.Module;
176
+ const tagged = (bytes) => {
177
+ if (!bytes || typeof bytes !== "object") return undefined;
178
+ const byTag = bytes[__nimbusWasmModuleTag];
179
+ if (byTag !== undefined) return byTag;
180
+ if (__nimbusPrecompiledWasmByDigest.size === 0) return undefined;
181
+ const digest = __nimbusWasmDigest(bytes);
182
+ return digest === null ? undefined : __nimbusPrecompiledWasmByDigest.get(digest);
183
+ };
184
+ // The runtime compiles wasm only while the loader stages a module map; a
185
+ // compile from bytes at any later point is refused with a message that names
186
+ // neither the module nor the reason it cannot work. Say both: the caller is
187
+ // an installed package whose image has to travel as a map member (the
188
+ // closure walk registers it), or be inlined in module text the loader
189
+ // itself evaluates.
190
+ const refusal = (e, bytes) => {
191
+ const size = (bytes && typeof bytes === "object" && typeof bytes.byteLength === "number") ? bytes.byteLength : 0;
192
+ const where = globalThis.__currentModulePath ? " while loading " + globalThis.__currentModulePath : "";
193
+ return new Error(
194
+ "Nimbus: WebAssembly cannot be compiled from bytes here" + where + " (" + size + " bytes): "
195
+ + ((e && e.message) || String(e))
196
+ + ". The runtime compiles wasm only when the module loader stages it, so the image must ride in the "
197
+ + "process's module map — a launch names one via the closure's wasmImages — rather than be compiled at runtime."
198
+ + " Images this launch does carry: " + (__nimbusPrecompiledWasm.size + __nimbusPrecompiledWasmByDigest.size) + ".",
199
+ );
200
+ };
201
+ const Module = function Module(bytes) {
202
+ const compiled = tagged(bytes);
203
+ if (compiled !== undefined) return compiled;
204
+ try { return new RealModule(bytes); } catch (e) { throw refusal(e, bytes); }
205
+ };
206
+ Module.prototype = RealModule.prototype;
207
+ for (const k of ["exports", "imports", "customSections"]) Module[k] = RealModule[k];
208
+ Object.defineProperty(WA, "Module", { value: Module, writable: true, configurable: true });
209
+ const realCompile = WA.compile.bind(WA);
210
+ WA.compile = (bytes) => {
211
+ const compiled = tagged(bytes);
212
+ if (compiled !== undefined) return Promise.resolve(compiled);
213
+ return realCompile(bytes).catch((e) => { throw refusal(e, bytes); });
214
+ };
215
+ const realInstantiate = WA.instantiate.bind(WA);
216
+ WA.instantiate = (source, imports) => {
217
+ const compiled = tagged(source);
218
+ if (compiled !== undefined) {
219
+ return realInstantiate(compiled, imports).then((instance) => ({ module: compiled, instance }));
220
+ }
221
+ // A Module source instantiates; only BYTES are a compile, and only those
222
+ // can be refused for it.
223
+ if (source instanceof RealModule) return realInstantiate(source, imports);
224
+ return realInstantiate(source, imports).catch((e) => { throw refusal(e, source); });
225
+ };
226
+ WA.__nimbusPrecompiledSeam = true;
227
+ })();
228
+
126
229
  // ═══════════════════════════════════════════════════════════════════════
127
230
  // ── fetch default User-Agent ───────────────────────────────────────
128
231
  // workerd's global fetch sends no User-Agent by default, but Node's
@@ -470,6 +573,33 @@ const __BufferMod = (() => {
470
573
  return B;
471
574
  })();
472
575
 
576
+ // ═══════════════════════════════════════════════════════════════════════
577
+ // ── Process output is bytes ─────────────────────────────────────────
578
+ // ═══════════════════════════════════════════════════════════════════════
579
+ // A process's stdout and stderr are byte streams: esbuild's service protocol
580
+ // is binary packets, and so is any program piping an image or an archive.
581
+ // The relay to the supervisor carries Uint8Array; a text producer encodes
582
+ // at its own edge, and the facet's REPORTED result — the \`stdout\`/\`stderr\`
583
+ // strings the wrapper declares — decodes at its edge with one streaming
584
+ // decoder per stream, so a multibyte character split across two writes
585
+ // still reads as one character.
586
+ const __nimbusOutEnc = new TextEncoder();
587
+ const __nimbusOutDec = { stdout: new TextDecoder("utf-8"), stderr: new TextDecoder("utf-8") };
588
+ /** \`process.stdout.write(d, enc)\` payload as bytes. */
589
+ function __nimbusOutBytes(d, enc) {
590
+ if (d instanceof Uint8Array) return d;
591
+ if (typeof d === "string") {
592
+ return typeof enc === "string" && enc !== "utf8" && enc !== "utf-8"
593
+ ? __BufferMod.from(d, enc)
594
+ : __nimbusOutEnc.encode(d);
595
+ }
596
+ return __nimbusOutEnc.encode(String(d));
597
+ }
598
+ /** Decode one stream's bytes into its text accumulator, streaming. */
599
+ function __nimbusOutText(streamName, bytes) {
600
+ return __nimbusOutDec[streamName === "stderr" ? "stderr" : "stdout"].decode(bytes, { stream: true });
601
+ }
602
+
473
603
  /**
474
604
  * What the resident set holds under a directory prefix — the ONE question the
475
605
  * shims ask of it that a plain object cannot answer cheaply.
@@ -2339,8 +2469,14 @@ const __fsMod = (() => {
2339
2469
  return _asString(content);
2340
2470
  }
2341
2471
  // No encoding requested — produce a Buffer-shaped Uint8Array.
2342
- if (_isBytes(content)) return __BufferMod.from(content);
2343
- return __BufferMod.from(content);
2472
+ const bytes = __BufferMod.from(content);
2473
+ // A wasm image the launch compiled through the module map is tagged on
2474
+ // the way out, so the WebAssembly seam below can answer the package's own
2475
+ // new WebAssembly.Module(readFileSync(...)) with the compiled module —
2476
+ // request-time compilation from bytes is refused by the runtime.
2477
+ const precompiled = __nimbusPrecompiledWasm.get(_strip(absPath));
2478
+ if (precompiled !== undefined) bytes[__nimbusWasmModuleTag] = precompiled;
2479
+ return bytes;
2344
2480
  }
2345
2481
 
2346
2482
  // ── writeFileSync ──
@@ -3101,9 +3237,8 @@ const __fsMod = (() => {
3101
3237
  function writeSync(fd, data, a, b, c) {
3102
3238
  const n = Number(fd);
3103
3239
  if (n === 1 || n === 2) {
3104
- // The stream shim stringifies whatever it is given, so decode first.
3105
3240
  const bytes = _normWriteArgs(data, a, b, c).bytes;
3106
- (n === 2 ? __processMod.stderr : __processMod.stdout).write(_dec.decode(bytes));
3241
+ (n === 2 ? __processMod.stderr : __processMod.stdout).write(bytes);
3107
3242
  return bytes.byteLength;
3108
3243
  }
3109
3244
  if (n === 0) throw _fsErr("EBADF", "write", fd);
@@ -4195,6 +4330,106 @@ const __utilMod = {
4195
4330
  }
4196
4331
  return opens + String(text) + closes;
4197
4332
  },
4333
+ // util.parseArgs({ args, options, strict, allowPositionals, allowNegative })
4334
+ // — Node 18.3+. The CLI argument parser modern npm bins reach for instead
4335
+ // of a dependency: json-server's lib/bin.js destructures it at module
4336
+ // init, so its absence crashed the bin at "parseArgs is not a function"
4337
+ // before --version could answer. Node's contract, minus the tokens
4338
+ // debugging output:
4339
+ // - --name, --name=value, --name value for string options;
4340
+ // - -s, -s value, -svalue, and grouped booleans -abc for shorts;
4341
+ // - --no-name sets a boolean false when allowNegative is on;
4342
+ // - -- ends option parsing, the rest are positionals;
4343
+ // - strict (default true) throws Node's own error codes for an unknown
4344
+ // option, a string option with no value, or a positional when they
4345
+ // are not allowed; lax mode records unknown options as booleans.
4346
+ parseArgs: (config) => {
4347
+ const cfg = config || {};
4348
+ const args = Array.isArray(cfg.args) ? cfg.args.slice() : (__processMod.argv || []).slice(2);
4349
+ const options = cfg.options || {};
4350
+ const strict = cfg.strict !== false;
4351
+ const allowPositionals = cfg.allowPositionals === undefined ? !strict : !!cfg.allowPositionals;
4352
+ const allowNegative = !!cfg.allowNegative;
4353
+ const values = {};
4354
+ const positionals = [];
4355
+ const err = (code, message) => { const e = new TypeError(message); e.code = code; return e; };
4356
+ const shortToLong = {};
4357
+ for (const [name, spec] of Object.entries(options)) {
4358
+ if (!spec || (spec.type !== "string" && spec.type !== "boolean")) {
4359
+ throw err("ERR_INVALID_ARG_TYPE", "The \\"options." + name + ".type\\" property must be one of: 'string', 'boolean'.");
4360
+ }
4361
+ if (spec.short) shortToLong[spec.short] = name;
4362
+ if (spec.default !== undefined) values[name] = spec.default;
4363
+ }
4364
+ const store = (name, value) => {
4365
+ const spec = options[name];
4366
+ if (spec && spec.multiple) {
4367
+ if (!Array.isArray(values[name]) || (spec.default !== undefined && values[name] === spec.default)) values[name] = [];
4368
+ values[name].push(value);
4369
+ } else {
4370
+ values[name] = value;
4371
+ }
4372
+ };
4373
+ const optionValue = (name, inlineValue, next, raw) => {
4374
+ const spec = options[name];
4375
+ if (!spec) {
4376
+ if (strict) throw err("ERR_PARSE_ARGS_UNKNOWN_OPTION", "Unknown option '" + raw + "'." + (allowPositionals ? " To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- \\"" + raw + "\\"'." : ""));
4377
+ if (inlineValue !== undefined) return { value: inlineValue, consumed: 0 };
4378
+ return { value: true, consumed: 0 };
4379
+ }
4380
+ if (spec.type === "boolean") {
4381
+ if (inlineValue !== undefined && strict) throw err("ERR_PARSE_ARGS_INVALID_OPTION_VALUE", "Option '" + raw + "' does not take an argument.");
4382
+ return { value: inlineValue !== undefined ? inlineValue : true, consumed: 0 };
4383
+ }
4384
+ if (inlineValue !== undefined) return { value: inlineValue, consumed: 0 };
4385
+ if (next === undefined || (strict && next.startsWith("-") && next !== "-")) {
4386
+ if (strict) throw err("ERR_PARSE_ARGS_INVALID_OPTION_VALUE", "Option '" + raw + " <value>' argument missing");
4387
+ return { value: undefined, consumed: 0 };
4388
+ }
4389
+ return { value: next, consumed: 1 };
4390
+ };
4391
+ for (let i = 0; i < args.length; i++) {
4392
+ const arg = args[i];
4393
+ if (arg === "--") { positionals.push(...args.slice(i + 1)); break; }
4394
+ if (arg.startsWith("--") && arg.length > 2) {
4395
+ const eq = arg.indexOf("=");
4396
+ let name = eq === -1 ? arg.slice(2) : arg.slice(2, eq);
4397
+ const inline = eq === -1 ? undefined : arg.slice(eq + 1);
4398
+ if (allowNegative && name.startsWith("no-") && options[name.slice(3)] && options[name.slice(3)].type === "boolean") {
4399
+ store(name.slice(3), false);
4400
+ continue;
4401
+ }
4402
+ const r = optionValue(name, inline, args[i + 1], "--" + name);
4403
+ store(name, r.value);
4404
+ i += r.consumed;
4405
+ continue;
4406
+ }
4407
+ if (arg.startsWith("-") && arg.length > 1 && arg !== "-") {
4408
+ // Short: -s, -s value, -svalue (string) or grouped -abc (booleans).
4409
+ const first = arg[1];
4410
+ const long = shortToLong[first] || first;
4411
+ const spec = options[long];
4412
+ if (spec && spec.type === "string") {
4413
+ const inline = arg.length > 2 ? arg.slice(2) : undefined;
4414
+ const r = optionValue(long, inline, args[i + 1], "-" + first);
4415
+ store(long, r.value);
4416
+ i += r.consumed;
4417
+ continue;
4418
+ }
4419
+ for (const ch of arg.slice(1)) {
4420
+ const l = shortToLong[ch] || ch;
4421
+ const r = optionValue(l, undefined, undefined, "-" + ch);
4422
+ store(l, r.value);
4423
+ }
4424
+ continue;
4425
+ }
4426
+ if (!allowPositionals) {
4427
+ throw err("ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL", "Unexpected argument '" + arg + "'. This command does not take positional arguments");
4428
+ }
4429
+ positionals.push(arg);
4430
+ }
4431
+ return { values, positionals };
4432
+ },
4198
4433
  };
4199
4434
 
4200
4435
  // ═══════════════════════════════════════════════════════════════════════
@@ -4631,27 +4866,34 @@ const __childProcessMod = (() => {
4631
4866
  const HAS_SUPERVISOR = !!(__supervisor && typeof __supervisor.cpSpawn === "function");
4632
4867
 
4633
4868
  /**
4634
- * Child stdout/stderr. Defaults to utf8 so consumers see strings (the
4635
- * common cross-spawn / husky pattern); callers override via
4636
- * .setEncoding('hex'), .setEncoding(null), etc. Flowing-mode resumption
4637
- * and encoding are the Readable base class's job — see streams.ts.
4869
+ * Child stdout/stderr. Bytes, as Node's: a 'data' listener sees a Buffer
4870
+ * until the consumer calls .setEncoding(), which is how a binary protocol
4871
+ * (esbuild's service) reads its packets and how a text consumer opts into
4872
+ * text. It used to default to utf8 for the cross-spawn / husky pattern;
4873
+ * that pattern reads \`String(chunk)\` and works on a Buffer, and the
4874
+ * default turned every byte above 0x7f into U+FFFD for everyone else.
4875
+ * Flowing-mode resumption and encoding are the Readable base class's job —
4876
+ * see streams.ts.
4638
4877
  */
4639
4878
  function _makeReadable() {
4640
- return new __streamMod.PassThrough({ encoding: "utf8" });
4879
+ return new __streamMod.PassThrough();
4641
4880
  }
4642
4881
 
4643
4882
  /**
4644
4883
  * Create a workerd-Writable backed by cpStdinWrite RPC.
4645
- * Decodes Uint8Array chunks to UTF-8 strings before pushing to RPC
4646
- * (workerd's Writable encodes string→bytes internally; we need to
4647
- * round-trip back to a string for the supervisor's stdin queue).
4884
+ *
4885
+ * A child's stdin is BYTES. esbuild's service protocol is binary packets,
4886
+ * and so is anything piping an image or an archive to a child. The relay
4887
+ * used to decode each chunk to a UTF-8 string here, which turned every
4888
+ * byte sequence that is not valid UTF-8 into U+FFFD — unrecoverable, and
4889
+ * measured at twice the length for a buffer covering all 256 values. The
4890
+ * queue and the RPC carry Uint8Array now; text callers encode at this
4891
+ * edge, which is the only place that knows it had text.
4648
4892
  */
4649
- function _toUtf8(chunk) {
4650
- if (typeof chunk === "string") return chunk;
4651
- if (chunk instanceof Uint8Array) {
4652
- try { return new TextDecoder("utf-8").decode(chunk); } catch { return String(chunk); }
4653
- }
4654
- return String(chunk);
4893
+ function _toBytes(chunk) {
4894
+ if (chunk instanceof Uint8Array) return chunk;
4895
+ if (typeof chunk === "string") return new TextEncoder().encode(chunk);
4896
+ return new TextEncoder().encode(String(chunk));
4655
4897
  }
4656
4898
  function _queueStdinWrite(child, data) {
4657
4899
  if (!child.pid) {
@@ -4683,8 +4925,7 @@ const __childProcessMod = (() => {
4683
4925
  function _makeWritable(child) {
4684
4926
  const w = new __streamMod.Writable({
4685
4927
  write(chunk, enc, cb) {
4686
- const s = _toUtf8(chunk);
4687
- _queueStdinWrite(child, s)
4928
+ _queueStdinWrite(child, _toBytes(chunk))
4688
4929
  .then(() => cb())
4689
4930
  .catch((e) => cb(e));
4690
4931
  },
@@ -4832,7 +5073,9 @@ const __childProcessMod = (() => {
4832
5073
  if (r && Array.isArray(r.chunks) && r.chunks.length > 0) {
4833
5074
  backoff = 100; // reset — child is producing
4834
5075
  for (const c of r.chunks) {
4835
- stream.write(c.data);
5076
+ // The queue hands back bytes; a Readable given a string would
5077
+ // encode it again.
5078
+ stream.write(__BufferMod.from(c.data));
4836
5079
  if (typeof c.seq === "number" && c.seq > sinceSeqRef.value) {
4837
5080
  sinceSeqRef.value = c.seq;
4838
5081
  }
@@ -5201,11 +5444,11 @@ const __childProcessMod = (() => {
5201
5444
  __supervisor.cpDrainOutput(pid),
5202
5445
  (result) => result,
5203
5446
  );
5204
- if (r && r.stdout && child.stdout) {
5205
- try { child.stdout.write(r.stdout); } catch {}
5447
+ if (r && r.stdout && r.stdout.byteLength > 0 && child.stdout) {
5448
+ try { child.stdout.write(__BufferMod.from(r.stdout)); } catch {}
5206
5449
  }
5207
- if (r && r.stderr && child.stderr) {
5208
- try { child.stderr.write(r.stderr); } catch {}
5450
+ if (r && r.stderr && r.stderr.byteLength > 0 && child.stderr) {
5451
+ try { child.stderr.write(__BufferMod.from(r.stderr)); } catch {}
5209
5452
  }
5210
5453
  // Force-close streams so listeners receive 'end'. The 'end'
5211
5454
  // event listeners in _makeChild flip _stdoutEnded/_stderrEnded.
@@ -5423,7 +5666,11 @@ function __makeProcessStdin() {
5423
5666
  throw new __ProcessExit(code);
5424
5667
  }
5425
5668
  }
5426
- if (packet && packet.data) r.write(packet.data);
5669
+ // The queue hands back bytes; a Readable given a string would encode
5670
+ // it again.
5671
+ if (packet && packet.data && packet.data.byteLength > 0) {
5672
+ r.write(__BufferMod.from(packet.data));
5673
+ }
5427
5674
  if (packet && packet.ended) {
5428
5675
  r.end();
5429
5676
  break;
@@ -5448,7 +5695,7 @@ function __makeProcessStdin() {
5448
5695
  }
5449
5696
  const trace = (e && e.stack) || (e && e.message) || String(e);
5450
5697
  stderr += trace + "\\n";
5451
- try { __nimbusUseRpcResult(__supervisor.stderr(trace + "\\n"), () => undefined).catch(() => {}); } catch {}
5698
+ try { __nimbusUseRpcResult(__supervisor.stderr(__nimbusOutEnc.encode(trace + "\\n")), () => undefined).catch(() => {}); } catch {}
5452
5699
  try { __nimbusUseRpcResult(__supervisor.reportExit(1, trace + "\\n"), () => undefined).catch(() => {}); } catch {}
5453
5700
  try { r.end(); } catch {}
5454
5701
  });
@@ -5519,7 +5766,8 @@ function __makeProcessOutputStream(streamName) {
5519
5766
  errored: null,
5520
5767
  write(d, enc, cb) {
5521
5768
  if (typeof enc === "function") cb = enc;
5522
- const s = String(d);
5769
+ // The reported result is text; decode the bytes at this edge only.
5770
+ const s = __nimbusOutText(streamName, __nimbusOutBytes(d, enc));
5523
5771
  if (streamName === "stderr") stderr += s;
5524
5772
  else stdout += s;
5525
5773
  if (typeof cb === "function") queueMicrotask(cb);
@@ -5710,7 +5958,7 @@ function __nimbusFailUnhandledAsync(error, kind) {
5710
5958
  const line = label + __nimbusRuntimeErrorTrace(error) + "\\n";
5711
5959
  stderr += line;
5712
5960
  if (__supervisor && typeof __supervisor.stderr === "function") {
5713
- try { __nimbusUseRpcResult(__supervisor.stderr(line), () => undefined).catch(() => {}); } catch {}
5961
+ try { __nimbusUseRpcResult(__supervisor.stderr(__nimbusOutEnc.encode(line)), () => undefined).catch(() => {}); } catch {}
5714
5962
  }
5715
5963
  __nimbusReportProcessExit(1, line);
5716
5964
  }
@@ -6845,6 +7093,34 @@ builtins["node:util/types"] = builtins["util/types"];
6845
7093
  // skips it via the same FACET_PROVIDED_PACKAGES list.
6846
7094
  builtins.undici = __undiciMod;
6847
7095
 
7096
+ /**
7097
+ * A cell's dynamic import() call.
7098
+ *
7099
+ * A cell is compiled with new Function, so an import() left in its body
7100
+ * is the RUNTIME's: it resolves against the module map and hands back the
7101
+ * platform's own builtins, not this process's. Real Vite reaches
7102
+ * node:http that way (config.js:14968), got a server whose listen bound no
7103
+ * port here, and the facet exited with no handles the moment boot returned.
7104
+ *
7105
+ * The ESM→CJS rewriter routes those calls here with the cell's own
7106
+ * require, so resolution is the one the process already has. The result is
7107
+ * shaped as a module namespace, since import() resolves to one and callers
7108
+ * destructure named exports off it.
7109
+ */
7110
+ globalThis.__nimbusCellImport = (req, id) => Promise.resolve().then(() => {
7111
+ const loaded = req(id);
7112
+ if (loaded && (loaded.__esModule || loaded[Symbol.toStringTag] === "Module")) return loaded;
7113
+ // A CJS module's exports ARE the namespace's named exports, with the whole
7114
+ // object as the default export — what an ESM importer of a CJS module sees.
7115
+ if (loaded && (typeof loaded === "object" || typeof loaded === "function")) {
7116
+ const ns = Object.create(null);
7117
+ for (const key of Object.keys(loaded)) ns[key] = loaded[key];
7118
+ if (!("default" in ns)) ns.default = loaded;
7119
+ Object.defineProperty(ns, Symbol.toStringTag, { value: "Module" });
7120
+ return ns;
7121
+ }
7122
+ return { default: loaded };
7123
+ });
6848
7124
  // ═══════════════════════════════════════════════════════════════════════
6849
7125
  // ── require() — full Node.js module resolution ─────────────────────
6850
7126
  // ═══════════════════════════════════════════════════════════════════════
@@ -938,7 +938,7 @@ async function __ocDrainVfsWrites() {
938
938
  stderr += trace + "\\n";
939
939
  exitCode = 1;
940
940
  if (__ocResident) {
941
- try { await __supervisor.stderr(trace + "\\n"); } catch {}
941
+ try { await __supervisor.stderr(new TextEncoder().encode(trace + "\\n")); } catch {}
942
942
  }
943
943
  }
944
944
  }
@@ -1093,7 +1093,7 @@ function __ocEmitMemDiag(tag) {
1093
1093
  // RPC that lands in the process log even when the chain is wedged —
1094
1094
  // discriminates a dead event loop from a wedged outbound chain.
1095
1095
  if (tag === "p" && __supervisor) {
1096
- try { __supervisor.stderr("[oc-mem-direct]" + __line).catch(() => {}); } catch {}
1096
+ try { __supervisor.stderr(new TextEncoder().encode("[oc-mem-direct]" + __line)).catch(() => {}); } catch {}
1097
1097
  }
1098
1098
  } finally {
1099
1099
  __ocDiag.busy = false;
@@ -127,6 +127,28 @@ export declare function _classifyCommand(name: string): {
127
127
  * Returns the detected bundler bin name (e.g. "vite") or null.
128
128
  */
129
129
  export declare function detectBundlerBin(script: string): string | null;
130
+ /**
131
+ * Whether `npm run <scriptName>` (or `npm start`/`npm test`) should refuse
132
+ * before dispatch because the resolved script invokes `next` on a
133
+ * subcommand Nimbus cannot run: `dev`, `start`, `build`, or `export` all
134
+ * need the same missing pipeline — webpack/Turbopack bundling,
135
+ * child_process.fork with v8-IPC, custom http.Server semantics.
136
+ *
137
+ * Returns the blocked subcommand ('dev'|'start'|'build'|'export') or null.
138
+ * `--force` / `--allow-next` in the script args bypasses the refusal.
139
+ * scriptName 'dev'/'start' on a next-depending package refuses even when
140
+ * the script body doesn't name `next` (custom dev servers), matching the
141
+ * pre-extension dev/start-only behavior.
142
+ */
143
+ export declare function refusedNextSubcommand(scriptName: string, script: string, pkg: {
144
+ dependencies?: Record<string, string>;
145
+ devDependencies?: Record<string, string>;
146
+ }, scriptArgs: readonly string[]): 'dev' | 'start' | 'build' | 'export' | null;
147
+ /**
148
+ * The refusal message for `refusedNextSubcommand` — identical blockers and
149
+ * escape hatch for every blocked subcommand.
150
+ */
151
+ export declare const NEXT_REFUSAL_MESSAGE: string;
130
152
  /**
131
153
  * Check whether a project directory has installed dependencies.
132
154
  *
@@ -140,4 +162,20 @@ export declare function checkNodeModulesGuard(vfs: CredentialedVfs, projectRoot:
140
162
  missing: boolean;
141
163
  depCount: number;
142
164
  };
165
+ /**
166
+ * Bound for the `vite build` esbuild bundle step (init.ts). Demo-app
167
+ * builds take seconds; anything past this is a stall, not a build.
168
+ */
169
+ export declare const VITE_BUILD_TIMEOUT_MS = 120000;
170
+ /**
171
+ * G5: race an unbounded await against a loud timeout.
172
+ *
173
+ * The timeout does not cancel `work` (there is nothing to cancel an
174
+ * in-isolate esbuild bundle with) — it stops *waiting* and rejects
175
+ * with an error that names what was attempted and how long it ran,
176
+ * so a stalled build surfaces as a timeout error instead of silence.
177
+ * The timer handle never escapes the executor, so there is nothing
178
+ * to null-check: settle clears it on every path.
179
+ */
180
+ export declare function withLoudTimeout<T>(work: Promise<T>, timeoutMs: number, what: string): Promise<T>;
143
181
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/session/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;CAC9B,GAAG,MAAM,CAiHT;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,UAehC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAI5F,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,aAQjC,CAAC;AACH,eAAO,MAAM,iCAAiC,aAG5C,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAoBzF;AAED;;;;;;;;;;;GAWG;AAiBH,eAAO,MAAM,kCAAkC,UAQ9C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAwC5F;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,aAS3B,CAAC;AACH,eAAO,MAAM,gBAAgB,aAS3B,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,cAAc,GAAG,cAAc,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,CAU3G;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,eAAe,EACpB,WAAW,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAiBxC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/session/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEzE;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;CAC9B,GAAG,MAAM,CAiHT;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,UAehC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAI5F,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,aAQjC,CAAC;AACH,eAAO,MAAM,iCAAiC,aAG5C,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAoBzF;AAED;;;;;;;;;;;GAWG;AAiBH,eAAO,MAAM,kCAAkC,UAQ9C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAwC5F;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,aAS3B,CAAC;AACH,eAAO,MAAM,gBAAgB,aAS3B,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,cAAc,GAAG,cAAc,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,CAU3G;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EACxF,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,IAAI,CAkB7C;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAQuC,CAAC;AAEzE;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,eAAe,EACpB,WAAW,EAAE,MAAM,GAClB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAiBxC;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,SAAU,CAAC;AAE7C;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,CAAC,CAaZ"}
@@ -430,6 +430,58 @@ export function detectBundlerBin(script) {
430
430
  }
431
431
  return null;
432
432
  }
433
+ /**
434
+ * Whether `npm run <scriptName>` (or `npm start`/`npm test`) should refuse
435
+ * before dispatch because the resolved script invokes `next` on a
436
+ * subcommand Nimbus cannot run: `dev`, `start`, `build`, or `export` all
437
+ * need the same missing pipeline — webpack/Turbopack bundling,
438
+ * child_process.fork with v8-IPC, custom http.Server semantics.
439
+ *
440
+ * Returns the blocked subcommand ('dev'|'start'|'build'|'export') or null.
441
+ * `--force` / `--allow-next` in the script args bypasses the refusal.
442
+ * scriptName 'dev'/'start' on a next-depending package refuses even when
443
+ * the script body doesn't name `next` (custom dev servers), matching the
444
+ * pre-extension dev/start-only behavior.
445
+ */
446
+ export function refusedNextSubcommand(scriptName, script, pkg, scriptArgs) {
447
+ if (scriptArgs.includes('--force') || scriptArgs.includes('--allow-next'))
448
+ return null;
449
+ if (!(pkg.dependencies?.next || pkg.devDependencies?.next))
450
+ return null;
451
+ if (scriptName === 'dev' || scriptName === 'start')
452
+ return scriptName;
453
+ // For other script names the script body must actually invoke a blocked
454
+ // next subcommand. Tokens: skip env assignments and cross-env/env/npx.
455
+ const tokens = (script || '').trim().split(/\s+/);
456
+ let i = 0;
457
+ while (i < tokens.length) {
458
+ const t = tokens[i];
459
+ if (/^[A-Z_][A-Z0-9_]*=/.test(t) || t === 'cross-env' || t === 'env' || t === 'npx') {
460
+ i++;
461
+ continue;
462
+ }
463
+ break;
464
+ }
465
+ const bin = (tokens[i] || '').replace(/^\.\/node_modules\/\.bin\//, '');
466
+ if (bin !== 'next' && !bin.startsWith('next.'))
467
+ return null;
468
+ const sub = tokens[i + 1];
469
+ if (sub === 'dev' || sub === 'start' || sub === 'build' || sub === 'export')
470
+ return sub;
471
+ return null;
472
+ }
473
+ /**
474
+ * The refusal message for `refusedNextSubcommand` — identical blockers and
475
+ * escape hatch for every blocked subcommand.
476
+ */
477
+ export const NEXT_REFUSAL_MESSAGE = '\x1b[31m✘\x1b[0m \x1b[1mNext.js is not supported in Nimbus.\x1b[0m\n' +
478
+ ' Specific blockers:\n' +
479
+ " 1. \x1b[2mchild_process.fork\x1b[0m IPC uses v8-serializer (Nimbus ships JSON projection).\n" +
480
+ ' 2. webpack / Turbopack bundlers are not integrated with the pre-bundle pipeline.\n' +
481
+ ' 3. Custom \x1b[2mhttp.Server\x1b[0m semantics (keep-alive, raw sockets) are facet-incompatible.\n' +
482
+ '\n' +
483
+ ' Workaround: run the Next.js project outside Nimbus (or a hosted runtime),\n' +
484
+ ' or pass \x1b[36m--allow-next\x1b[0m to bypass at your own risk.\n';
433
485
  /**
434
486
  * Check whether a project directory has installed dependencies.
435
487
  *
@@ -462,3 +514,27 @@ export function checkNodeModulesGuard(vfs, projectRoot) {
462
514
  return { missing: false, depCount: 0 };
463
515
  }
464
516
  }
517
+ /**
518
+ * Bound for the `vite build` esbuild bundle step (init.ts). Demo-app
519
+ * builds take seconds; anything past this is a stall, not a build.
520
+ */
521
+ export const VITE_BUILD_TIMEOUT_MS = 120_000;
522
+ /**
523
+ * G5: race an unbounded await against a loud timeout.
524
+ *
525
+ * The timeout does not cancel `work` (there is nothing to cancel an
526
+ * in-isolate esbuild bundle with) — it stops *waiting* and rejects
527
+ * with an error that names what was attempted and how long it ran,
528
+ * so a stalled build surfaces as a timeout error instead of silence.
529
+ * The timer handle never escapes the executor, so there is nothing
530
+ * to null-check: settle clears it on every path.
531
+ */
532
+ export function withLoudTimeout(work, timeoutMs, what) {
533
+ return new Promise((resolve, reject) => {
534
+ const timer = setTimeout(() => {
535
+ reject(new Error(`${what} produced no result after ${(timeoutMs / 1000).toFixed(0)}s — ` +
536
+ 'stopped waiting (the work may still finish in the background; re-run to retry).'));
537
+ }, timeoutMs);
538
+ work.then((value) => { clearTimeout(timer); resolve(value); }, (error) => { clearTimeout(timer); reject(error); });
539
+ });
540
+ }
@@ -88,6 +88,6 @@ export declare function joinExistingSession(self: {
88
88
  };
89
89
  _b4Phase: SessionState | null;
90
90
  _b4WarmJoinCount: number;
91
- }, ws: WebSocket, appendScrollback: (ctx: any, data: string, atMs: number) => void, loadScrollback: (ctx: any) => string): void;
91
+ }, ws: WebSocket, tee: (frame: string) => void, loadScrollback: (ctx: any) => string): void;
92
92
  export {};
93
93
  //# sourceMappingURL=init-phases.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init-phases.d.ts","sourceRoot":"","sources":["../../src/session/init-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAElG,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE7E;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE;IAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,EACtD,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,GACd,IAAI,CAcN;AAED,KAAK,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB,EAAE,OAAO,EAAE,SAAS,SAAS,EAAE,EAAE,GAAG,GAAE,MAAmB,GAAG,iBAAiB,CAG7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE;IACJ,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE;QAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACpG,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,EACD,EAAE,EAAE,SAAS,EACb,gBAAgB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,EAChE,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GACnC,IAAI,CAsCN"}
1
+ {"version":3,"file":"init-phases.d.ts","sourceRoot":"","sources":["../../src/session/init-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAElG,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE7E;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE;IAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,EACtD,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,GACd,IAAI,CAcN;AAED,KAAK,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB,EAAE,OAAO,EAAE,SAAS,SAAS,EAAE,EAAE,GAAG,GAAE,MAAmB,GAAG,iBAAiB,CAG7E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE;IACJ,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE;QAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACpG,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,EACD,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAC5B,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GACnC,IAAI,CAiCN"}
@@ -91,7 +91,7 @@ export function classifyWsUpgrade(self, sockets, now = Date.now()) {
91
91
  * needed here; init-phases.ts shouldn't grow a circular dep on
92
92
  * nimbus-session-internal.
93
93
  */
94
- export function joinExistingSession(self, ws, appendScrollback, loadScrollback) {
94
+ export function joinExistingSession(self, ws, tee, loadScrollback) {
95
95
  // Phase R — pure SQL reads. No-op on warm rejoin (live state is
96
96
  // already correct in self.shell / self.terminal). Recorded in the
97
97
  // ring for symmetry with cold init.
@@ -101,17 +101,7 @@ export function joinExistingSession(self, ws, appendScrollback, loadScrollback)
101
101
  // the same WebSocketTerminal instance is preserved (we mutate
102
102
  // its internal ws ref via attach()).
103
103
  setPhase(self, 'wire', 'warm-rejoin');
104
- self.terminal.attach(ws, (frame) => {
105
- try {
106
- appendScrollback(self.ctx, frame, Date.now());
107
- }
108
- catch (e) {
109
- try {
110
- console.warn("[B'.3] appendScrollback failed:", e?.message || e);
111
- }
112
- catch { }
113
- }
114
- });
104
+ self.terminal.attach(ws, tee);
115
105
  // Replay scrollback to the new ws so the user sees the prior
116
106
  // session's terminal contents. Same shape as cold-init's replay
117
107
  // when persisted state exists.