@nimbus-sh/worker 0.5.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 (164) hide show
  1. package/README.md +2 -2
  2. package/dist/_shared/preview-host.d.ts +26 -8
  3. package/dist/_shared/preview-host.d.ts.map +1 -1
  4. package/dist/_shared/preview-host.js +51 -11
  5. package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
  6. package/dist/cirrus-npm-cjs.generated.js +1 -1
  7. package/dist/facets/cirrus-real.d.ts.map +1 -1
  8. package/dist/facets/cirrus-real.js +6 -5
  9. package/dist/facets/compose.d.ts +148 -0
  10. package/dist/facets/compose.d.ts.map +1 -0
  11. package/dist/facets/compose.js +146 -0
  12. package/dist/facets/durable-images.d.ts +18 -5
  13. package/dist/facets/durable-images.d.ts.map +1 -1
  14. package/dist/facets/durable-images.js +36 -7
  15. package/dist/facets/durable-slots.d.ts +1 -1
  16. package/dist/facets/durable-slots.d.ts.map +1 -1
  17. package/dist/facets/durable-slots.js +2 -1
  18. package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
  19. package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
  20. package/dist/facets/esbuild-bundle-pool.js +122 -0
  21. package/dist/facets/exec-telemetry.d.ts +8 -0
  22. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  23. package/dist/facets/manager.d.ts +337 -123
  24. package/dist/facets/manager.d.ts.map +1 -1
  25. package/dist/facets/manager.js +1100 -449
  26. package/dist/facets/process.d.ts +20 -16
  27. package/dist/facets/process.d.ts.map +1 -1
  28. package/dist/facets/process.js +59 -28
  29. package/dist/facets/real-vite-fs-shim.js +2 -2
  30. package/dist/facets/resident-identity.d.ts +23 -0
  31. package/dist/facets/resident-identity.d.ts.map +1 -0
  32. package/dist/facets/resident-identity.js +31 -0
  33. package/dist/facets/vite-dev-server.d.ts +25 -47
  34. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  35. package/dist/facets/vite-dev-server.js +185 -219
  36. package/dist/facets/wasm-image-digest.d.ts +25 -0
  37. package/dist/facets/wasm-image-digest.d.ts.map +1 -0
  38. package/dist/facets/wasm-image-digest.js +25 -0
  39. package/dist/facets/wasm-swap-registry.d.ts +51 -92
  40. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  41. package/dist/facets/wasm-swap-registry.js +68 -227
  42. package/dist/git/commands.d.ts +0 -1
  43. package/dist/git/commands.d.ts.map +1 -1
  44. package/dist/git/commands.js +0 -3
  45. package/dist/git/network-facet.d.ts.map +1 -1
  46. package/dist/git/network-facet.js +6 -5
  47. package/dist/loaders/child-process/spawn-pool.d.ts +3 -2
  48. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  49. package/dist/loaders/child-process/spawn-pool.js +3 -2
  50. package/dist/loaders/generated-workers.d.ts +2 -2
  51. package/dist/loaders/generated-workers.d.ts.map +1 -1
  52. package/dist/loaders/generated-workers.js +3 -3
  53. package/dist/loaders/npm-resolve-preamble.d.ts +3 -6
  54. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  55. package/dist/loaders/npm-resolve-preamble.js +34 -108
  56. package/dist/node-shims-artifact.generated.js +3 -3
  57. package/dist/npm/install-batch-facet.d.ts +3 -2
  58. package/dist/npm/install-batch-facet.d.ts.map +1 -1
  59. package/dist/npm/install-batch-facet.js +45 -15
  60. package/dist/npm/installer.d.ts +22 -17
  61. package/dist/npm/installer.d.ts.map +1 -1
  62. package/dist/npm/installer.js +209 -193
  63. package/dist/npm/pre-bundle-facet.d.ts +1 -1
  64. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  65. package/dist/npm/pre-bundle-facet.js +1 -1
  66. package/dist/npm/resolve-facet.d.ts +6 -0
  67. package/dist/npm/resolve-facet.d.ts.map +1 -1
  68. package/dist/npm/resolve-one-facet.d.ts +21 -20
  69. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  70. package/dist/npm/resolve-one-facet.js +85 -84
  71. package/dist/npm/semver.d.ts +59 -0
  72. package/dist/npm/semver.d.ts.map +1 -0
  73. package/dist/npm/semver.js +226 -0
  74. package/dist/router/index.d.ts.map +1 -1
  75. package/dist/router/index.js +47 -10
  76. package/dist/router/public-directory.d.ts +5 -1
  77. package/dist/router/public-directory.d.ts.map +1 -1
  78. package/dist/router/public-directory.js +9 -2
  79. package/dist/router/remote-api.d.ts +18 -0
  80. package/dist/router/remote-api.d.ts.map +1 -1
  81. package/dist/router/remote-api.js +64 -5
  82. package/dist/runtime/cpython-resident.d.ts.map +1 -1
  83. package/dist/runtime/cpython-resident.js +3 -1
  84. package/dist/runtime/html-entrypoint.d.ts +7 -0
  85. package/dist/runtime/html-entrypoint.d.ts.map +1 -1
  86. package/dist/runtime/html-entrypoint.js +18 -2
  87. package/dist/runtime/node-runner.d.ts +3 -0
  88. package/dist/runtime/node-runner.d.ts.map +1 -1
  89. package/dist/runtime/node-runner.js +7 -0
  90. package/dist/runtime/node-shims.d.ts.map +1 -1
  91. package/dist/runtime/node-shims.js +305 -29
  92. package/dist/runtime/opencode-facet-runner.js +2 -2
  93. package/dist/runtime/package-manager.d.ts +44 -1
  94. package/dist/runtime/package-manager.d.ts.map +1 -1
  95. package/dist/runtime/package-manager.js +168 -3
  96. package/dist/runtime/ruby-resident.d.ts.map +1 -1
  97. package/dist/runtime/ruby-resident.js +2 -0
  98. package/dist/session/agent.d.ts.map +1 -1
  99. package/dist/session/agent.js +28 -1
  100. package/dist/session/helpers.d.ts +38 -0
  101. package/dist/session/helpers.d.ts.map +1 -1
  102. package/dist/session/helpers.js +76 -0
  103. package/dist/session/init-phases.d.ts +1 -1
  104. package/dist/session/init-phases.d.ts.map +1 -1
  105. package/dist/session/init-phases.js +2 -12
  106. package/dist/session/init.d.ts +15 -1
  107. package/dist/session/init.d.ts.map +1 -1
  108. package/dist/session/init.js +91 -603
  109. package/dist/session/keys.d.ts +4 -0
  110. package/dist/session/keys.d.ts.map +1 -1
  111. package/dist/session/keys.js +4 -0
  112. package/dist/session/nimbus-session.d.ts +90 -23
  113. package/dist/session/nimbus-session.d.ts.map +1 -1
  114. package/dist/session/nimbus-session.js +200 -110
  115. package/dist/session/npm-install-port.d.ts +16 -0
  116. package/dist/session/npm-install-port.d.ts.map +1 -0
  117. package/dist/session/npm-install-port.js +37 -0
  118. package/dist/session/port-capability.d.ts +90 -0
  119. package/dist/session/port-capability.d.ts.map +1 -1
  120. package/dist/session/port-capability.js +219 -9
  121. package/dist/session/programmatic.d.ts +125 -5
  122. package/dist/session/programmatic.d.ts.map +1 -1
  123. package/dist/session/programmatic.js +439 -89
  124. package/dist/session/routes.d.ts +39 -17
  125. package/dist/session/routes.d.ts.map +1 -1
  126. package/dist/session/routes.js +67 -131
  127. package/dist/session/rpc.d.ts +39 -16
  128. package/dist/session/rpc.d.ts.map +1 -1
  129. package/dist/session/rpc.js +137 -130
  130. package/dist/session/serving-port.d.ts +27 -0
  131. package/dist/session/serving-port.d.ts.map +1 -0
  132. package/dist/session/serving-port.js +27 -0
  133. package/dist/session/start-real-vite.d.ts +12 -0
  134. package/dist/session/start-real-vite.d.ts.map +1 -1
  135. package/dist/session/start-real-vite.js +4 -4
  136. package/dist/session/supervisor-op.d.ts +41 -4
  137. package/dist/session/supervisor-op.d.ts.map +1 -1
  138. package/dist/session/supervisor-op.js +101 -73
  139. package/dist/session/supervisor-rpc.d.ts +7 -7
  140. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  141. package/dist/session/supervisor-rpc.js +6 -3
  142. package/dist/session/vite-command.d.ts +18 -0
  143. package/dist/session/vite-command.d.ts.map +1 -0
  144. package/dist/session/vite-command.js +609 -0
  145. package/dist/session/ws.d.ts +61 -0
  146. package/dist/session/ws.d.ts.map +1 -1
  147. package/dist/session/ws.js +122 -12
  148. package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
  149. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  150. package/dist/shell/npm-bin-entrypoints.js +12 -85
  151. package/package.json +24 -4
  152. package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
  153. package/public/index.html +1 -1
  154. package/scripts/bundle-facet-workers.mjs +1 -1
  155. package/scripts/bundle-npm-cjs.mjs +2 -2
  156. package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
  157. package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
  158. package/dist/facets/on-demand-bundle-gate.js +0 -125
  159. package/dist/npm/install-args.d.ts +0 -21
  160. package/dist/npm/install-args.d.ts.map +0 -1
  161. package/dist/npm/install-args.js +0 -70
  162. package/dist/npm/npm-log.d.ts +0 -31
  163. package/dist/npm/npm-log.d.ts.map +0 -1
  164. package/dist/npm/npm-log.js +0 -51
@@ -200,12 +200,19 @@ export async function ensureRuntimesProgrammatic(deps, specs, opts = {}) {
200
200
  }
201
201
  return results;
202
202
  }
203
+ const NIMBUS_USAGE = [
204
+ 'usage: nimbus install <name>[@<version>] | nimbus install --list | nimbus install --available | nimbus uninstall <name>',
205
+ ' nimbus expose <port|pid> [--public] [--name <name>]',
206
+ ' nimbus app list | url <name|port> | rotate <name|port> | remove <name|port>',
207
+ ' nimbus start [--restart never|on-failure] <command> [args...]',
208
+ ].join('\n');
203
209
  /**
204
210
  * Build the shell-command handler that implements `nimbus install …`,
205
- * `nimbus uninstall …`. Registered under the name `nimbus`.
211
+ * `nimbus uninstall …`, `nimbus expose …`, `nimbus app …` and
212
+ * `nimbus start …`. Registered under the name `nimbus`.
206
213
  */
207
214
  export function makeNimbusVerbHandler(deps) {
208
- const { env, registry, getHome, warmRuntime } = deps;
215
+ const { env, registry, getHome, warmRuntime, apps } = deps;
209
216
  const vfs = deps.vfs.as(CRED_KERNEL);
210
217
  return async function nimbus(ctx) {
211
218
  const argv = ctx.args || [];
@@ -217,12 +224,170 @@ export function makeNimbusVerbHandler(deps) {
217
224
  if (verb === 'uninstall') {
218
225
  return runUninstall(rest, ctx, { vfs, registry, getHome });
219
226
  }
227
+ if (verb === 'expose' || verb === 'app' || verb === 'start') {
228
+ if (verb === 'start')
229
+ return runStart(rest, ctx, registry);
230
+ if (!apps) {
231
+ ctx.stderr.write(`nimbus ${verb}: this host has no session to address applications on\n`);
232
+ return 1;
233
+ }
234
+ try {
235
+ return verb === 'expose' ? await runExpose(rest, ctx, apps) : await runApp(rest, ctx, apps);
236
+ }
237
+ catch (e) {
238
+ ctx.stderr.write(`nimbus ${verb}: ${e instanceof Error ? e.message : String(e)}\n`);
239
+ return 1;
240
+ }
241
+ }
220
242
  // Unknown verb.
221
243
  ctx.stderr.write(`nimbus: unknown subcommand '${verb || '(none)'}'\n`);
222
- ctx.stderr.write(`usage: nimbus install <name>[@<version>] | nimbus install --list | nimbus install --available | nimbus uninstall <name>\n`);
244
+ ctx.stderr.write(`${NIMBUS_USAGE}\n`);
223
245
  return 2;
224
246
  };
225
247
  }
248
+ // ── expose / app / start ─────────────────────────────────────────────
249
+ /** `<port|pid|name>` as the verbs take it: digits are a port or pid, anything else a name. */
250
+ function appTargetArg(raw) {
251
+ return /^\d+$/.test(raw) ? Number(raw) : raw;
252
+ }
253
+ async function runExpose(args, ctx, apps) {
254
+ let target;
255
+ let name;
256
+ let visibility;
257
+ for (let i = 0; i < args.length; i++) {
258
+ const arg = args[i];
259
+ if (arg === '--public')
260
+ visibility = 'public';
261
+ else if (arg === '--scoped')
262
+ visibility = 'scoped';
263
+ else if (arg === '--name') {
264
+ name = args[++i];
265
+ }
266
+ else if (arg.startsWith('--name='))
267
+ name = arg.slice('--name='.length);
268
+ else if (arg.startsWith('--')) {
269
+ ctx.stderr.write(`nimbus expose: unknown flag ${arg}\n`);
270
+ return 2;
271
+ }
272
+ else if (target === undefined)
273
+ target = arg;
274
+ else {
275
+ ctx.stderr.write('nimbus expose: one target only\n');
276
+ return 2;
277
+ }
278
+ }
279
+ if (target === undefined) {
280
+ ctx.stderr.write('usage: nimbus expose <port|pid> [--public] [--name <name>]\n');
281
+ return 2;
282
+ }
283
+ const exposed = await apps.expose(appTargetArg(target), {
284
+ ...(visibility !== undefined ? { visibility } : {}),
285
+ ...(name !== undefined ? { name } : {}),
286
+ });
287
+ ctx.stdout.write(`${exposed.url ?? `(no URL: port ${exposed.port}, capability ${exposed.capability ?? 'none'})`}\n`);
288
+ ctx.stdout.write(` ${exposed.visibility} · ${exposed.name ?? exposed.owner} · port ${exposed.port}\n`);
289
+ return 0;
290
+ }
291
+ async function runApp(args, ctx, apps) {
292
+ const [sub, target] = args;
293
+ if (sub === 'list' || sub === 'ls') {
294
+ const rows = await apps.list();
295
+ if (rows.length === 0) {
296
+ ctx.stdout.write('(no applications)\n');
297
+ return 0;
298
+ }
299
+ for (const app of rows) {
300
+ const label = app.name ?? app.owner;
301
+ const where = app.port === null ? '-' : String(app.port);
302
+ const pid = app.pid === null ? '-' : String(app.pid);
303
+ const status = app.diagnostic ? `${app.status} (${app.diagnostic})` : app.status;
304
+ ctx.stdout.write(`${label}\t${where}\t${pid}\t${status}\t${app.visibility}\t${app.restart}\t${app.url ?? '-'}\n`);
305
+ }
306
+ return 0;
307
+ }
308
+ if (target === undefined || (sub !== 'url' && sub !== 'rotate' && sub !== 'remove')) {
309
+ ctx.stderr.write('usage: nimbus app list | url <name|port> | rotate <name|port> | remove <name|port>\n');
310
+ return 2;
311
+ }
312
+ const t = appTargetArg(target);
313
+ if (sub === 'url') {
314
+ const app = (await apps.list()).find((row) => row.name === t || row.owner === t || row.port === t || row.pid === t);
315
+ if (!app) {
316
+ ctx.stderr.write(`nimbus app url: no application matches ${target}\n`);
317
+ return 1;
318
+ }
319
+ ctx.stdout.write(`${app.url ?? `(no URL: port ${app.port ?? '-'})`}\n`);
320
+ return 0;
321
+ }
322
+ if (sub === 'rotate') {
323
+ const rotated = await apps.rotateLink(t);
324
+ ctx.stdout.write(`${rotated.url ?? `(no URL: port ${rotated.port}, capability ${rotated.capability ?? 'none'})`}\n`);
325
+ return 0;
326
+ }
327
+ const removed = await apps.remove(t);
328
+ ctx.stdout.write(removed.removed
329
+ ? `removed ${removed.owner}${removed.port !== null ? ` (port ${removed.port} released)` : ''}\n`
330
+ : `nothing to remove for ${removed.owner}\n`);
331
+ return removed.removed ? 0 : 1;
332
+ }
333
+ /**
334
+ * `nimbus start [--restart <policy>] <command> [args...]` — run a
335
+ * registered command with the restart policy in its environment, which is
336
+ * where the resident it starts reads the policy from (`NIMBUS_RESTART`),
337
+ * exactly as the SDK's `startProcess({ restart })` carries it.
338
+ */
339
+ async function runStart(args, ctx, registry) {
340
+ let restart = 'never';
341
+ let i = 0;
342
+ for (; i < args.length; i++) {
343
+ const arg = args[i];
344
+ if (arg === '--restart') {
345
+ const policy = args[++i];
346
+ if (policy !== 'never' && policy !== 'on-failure') {
347
+ ctx.stderr.write(`nimbus start: --restart must be never or on-failure, got ${policy ?? '(none)'}\n`);
348
+ return 2;
349
+ }
350
+ restart = policy;
351
+ }
352
+ else if (arg.startsWith('--restart=')) {
353
+ const policy = arg.slice('--restart='.length);
354
+ if (policy !== 'never' && policy !== 'on-failure') {
355
+ ctx.stderr.write(`nimbus start: --restart must be never or on-failure, got ${policy}\n`);
356
+ return 2;
357
+ }
358
+ restart = policy;
359
+ }
360
+ else if (arg === '--') {
361
+ i += 1;
362
+ break;
363
+ }
364
+ else if (arg.startsWith('--')) {
365
+ ctx.stderr.write(`nimbus start: unknown flag ${arg}\n`);
366
+ return 2;
367
+ }
368
+ else
369
+ break;
370
+ }
371
+ const [command, ...commandArgs] = args.slice(i);
372
+ if (!command) {
373
+ ctx.stderr.write('usage: nimbus start [--restart never|on-failure] <command> [args...]\n');
374
+ return 2;
375
+ }
376
+ const handler = registry.resolve ? await registry.resolve(command) : null;
377
+ if (!handler) {
378
+ ctx.stderr.write(`nimbus start: ${command}: command not found\n`);
379
+ return 127;
380
+ }
381
+ // The shell hands `nimbus` its full CommandContext; ShellCtx is only the
382
+ // slice this module reads, so the spread carries everything the command
383
+ // needs (signal, vfs, stdin, ...) through untouched.
384
+ const full = ctx;
385
+ return handler({
386
+ ...full,
387
+ args: commandArgs,
388
+ env: { ...full.env, NIMBUS_RESTART: restart },
389
+ });
390
+ }
226
391
  // ── install ──────────────────────────────────────────────────────────
227
392
  async function runInstall(args, ctx, deps) {
228
393
  // Flag parsing.
@@ -1 +1 @@
1
- {"version":3,"file":"ruby-resident.d.ts","sourceRoot":"","sources":["../../src/runtime/ruby-resident.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAezD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,iBAAiB,CA8E3E;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiLrE"}
1
+ {"version":3,"file":"ruby-resident.d.ts","sourceRoot":"","sources":["../../src/runtime/ruby-resident.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAezD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,iBAAiB,CAgF3E;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiLrE"}
@@ -28,6 +28,8 @@ export function rubyResidentStart(facetMgr) {
28
28
  const command = args.command;
29
29
  const workerCode = buildRubySocketProcessWorker(buildRubyPreamble());
30
30
  const spawned = await facetMgr.spawnWorker(workerCode, command, args.cwd, {
31
+ resident: { argv: args.argv, runtime: 'ruby' },
32
+ restart: args.startArgs.userEnv.NIMBUS_RESTART === 'on-failure' ? 'on-failure' : 'never',
31
33
  compatibilityFlags: ['nodejs_compat'],
32
34
  // By path, not by value: the image is 34.3 MiB — more than a single RPC
33
35
  // value may carry — so whichever host runs this process reads it itself.
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAUL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAiB3B,UAAU,YAAY;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE;QACzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;KAC3E,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC/B;AAED,UAAU,IAAK,SAAQ,gBAAgB,EAAE,aAAa;IACpD,GAAG,EAAE;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE,CAAC;IAC/B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxD;AAED,UAAU,iBAAiB;IACzB,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA2BD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2ClG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAQxF"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAiB3B,UAAU,YAAY;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE;QACzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;KAC3E,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC/B;AAED,UAAU,IAAK,SAAQ,gBAAgB,EAAE,aAAa;IACpD,GAAG,EAAE;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE,CAAC;IAC/B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxD;AAED,UAAU,iBAAiB;IACzB,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA2BD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2ClG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAQxF"}
@@ -12,7 +12,7 @@ import { BASE_PATH_HEADER, TENANT_HEADER } from '../_shared/session-router.js';
12
12
  import { decodeJsonBase64Url, encodeJsonBase64Url, pkceChallenge, randomBase64Url, sealJson, unsealJson, } from '@nimbus-sh/core/_shared/crypto.js';
13
13
  import { clearNimbusAgentOAuthCookie, fetchNimbusCloudflareAccounts, isNimbusCloudflareAccountId, isNimbusTenantSegment, NIMBUS_CF_OAUTH_AUTH_URL, readNimbusCookie, readNimbusAgentCookieSecret, readNimbusAgentOAuthConfig, requestNimbusCloudflareOAuthToken, serializeNimbusCookie, } from './agent-oauth.js';
14
14
  import { clearSessionAiCredential, createSessionAiModel, describeSessionAiConnection, readSessionAiConfig, resolveSessionAiCredential, sessionAiAccountIsAvailable, setSessionAiAccount, storeSessionAiCredential, } from './ai.js';
15
- import { ensureProgrammaticReady, rpcExec, rpcEnsureRuntimes, rpcInstallRuntime, rpcKillProcess, rpcListPorts, rpcListProcesses, rpcProcessLogs, rpcStartProcess, } from './programmatic.js';
15
+ import { ensureProgrammaticReady, rpcExec, rpcEnsureRuntimes, rpcInstallRuntime, rpcExposeApp, rpcKillProcess, rpcListApps, rpcListPorts, rpcListProcesses, rpcProcessLogs, rpcStartProcess, } from './programmatic.js';
16
16
  import { resolveVfsPath } from '@nimbus-sh/core/vfs/path.js';
17
17
  import { appendTextPart, interruptRunningTools, textFromParts, upsertStoredMessage, upsertToolPart, } from './agent-contract.js';
18
18
  import { CRED_KERNEL } from '@nimbus-sh/core/runtime/os-contracts.js';
@@ -645,6 +645,20 @@ function createAiSdkTools(self) {
645
645
  inputSchema: toolSchema({}, []),
646
646
  execute: async (args) => runTool(self, 'list_ports', args),
647
647
  }),
648
+ expose_app: aiTool({
649
+ description: 'Expose a running application by port, pid or name: reserves its port under its identity, optionally names it and makes it public, and returns its URL.',
650
+ inputSchema: toolSchema({
651
+ target: stringProp('Port number, process id, or app name.'),
652
+ visibility: stringProp("'scoped' (default) or 'public' — public mints a shareable capability URL."),
653
+ name: stringProp('Optional DNS-label name for the app, e.g. "api".'),
654
+ }, ['target']),
655
+ execute: async (args) => runTool(self, 'expose_app', args),
656
+ }),
657
+ list_apps: aiTool({
658
+ description: 'List every application the session knows: owner, name, port, pid, status, visibility, restart policy and URL.',
659
+ inputSchema: toolSchema({}, []),
660
+ execute: async (args) => runTool(self, 'list_apps', args),
661
+ }),
648
662
  };
649
663
  }
650
664
  function collectTurnParts(result) {
@@ -872,6 +886,19 @@ async function runTool(self, name, args) {
872
886
  }
873
887
  if (name === 'list_ports')
874
888
  return rpcListPorts(self);
889
+ if (name === 'expose_app') {
890
+ const raw = String(args.target ?? '').trim();
891
+ if (!raw)
892
+ return { error: 'target is required' };
893
+ const visibility = args.visibility === 'public' ? 'public' : args.visibility === 'scoped' ? 'scoped' : undefined;
894
+ const appName = typeof args.name === 'string' && args.name.trim() ? args.name.trim() : undefined;
895
+ return rpcExposeApp(self, /^\d+$/.test(raw) ? Number(raw) : raw, {
896
+ ...(visibility !== undefined ? { visibility } : {}),
897
+ ...(appName !== undefined ? { name: appName } : {}),
898
+ });
899
+ }
900
+ if (name === 'list_apps')
901
+ return rpcListApps(self);
875
902
  return { error: `unknown tool: ${name}` };
876
903
  }
877
904
  catch (e) {
@@ -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.
@@ -47,6 +47,20 @@ type InitHost = SessionInternal & {
47
47
  readonly ctx: any;
48
48
  readonly env: any;
49
49
  };
50
- export declare function initSession(self: InitHost, ws: WebSocket): Promise<void>;
50
+ /**
51
+ * How the socket being wired came to need a session.
52
+ *
53
+ * - reconnect: a fresh terminal on a fresh /ws upgrade. Its screen is
54
+ * empty, so the persisted scrollback is replayed above the live prompt.
55
+ * - wake: the socket was accepted by a previous instance and outlived it
56
+ * in hibernation; the peer's screen still shows everything up to the
57
+ * sleep. Replaying scrollback there duplicates what the peer already
58
+ * has, and a driver waiting for a fresh prompt would take the replayed
59
+ * one for its answer. Only the resumed-instance notice is written.
60
+ */
61
+ export interface InitSessionOptions {
62
+ resume?: 'reconnect' | 'wake';
63
+ }
64
+ export declare function initSession(self: InitHost, ws: WebSocket, options?: InitSessionOptions): Promise<void>;
51
65
  export {};
52
66
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AA8EH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;GAQG;AACH,KAAK,QAAQ,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAAC;AAa3E,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAysF9E"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAkFH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;GAQG;AACH,KAAK,QAAQ,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;CAAE,CAAC;AAQ3E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;CAC/B;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,SAAS,EACb,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAgsEf"}