@nimbus-sh/worker 0.4.0 → 0.5.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 (83) hide show
  1. package/README.md +46 -43
  2. package/dist/_shared/preview-host.d.ts +14 -1
  3. package/dist/_shared/preview-host.d.ts.map +1 -1
  4. package/dist/_shared/preview-host.js +28 -3
  5. package/dist/_shared/session-router.d.ts +43 -0
  6. package/dist/_shared/session-router.d.ts.map +1 -1
  7. package/dist/_shared/session-router.js +59 -12
  8. package/dist/facets/durable-images.d.ts +50 -0
  9. package/dist/facets/durable-images.d.ts.map +1 -0
  10. package/dist/facets/durable-images.js +75 -0
  11. package/dist/facets/durable-slots.d.ts +45 -0
  12. package/dist/facets/durable-slots.d.ts.map +1 -0
  13. package/dist/facets/durable-slots.js +94 -0
  14. package/dist/facets/esbuild-transform.d.ts +10 -0
  15. package/dist/facets/esbuild-transform.d.ts.map +1 -0
  16. package/dist/facets/esbuild-transform.js +36 -0
  17. package/dist/facets/manager.d.ts +160 -5
  18. package/dist/facets/manager.d.ts.map +1 -1
  19. package/dist/facets/manager.js +554 -97
  20. package/dist/git/commands.d.ts +22 -0
  21. package/dist/git/commands.d.ts.map +1 -1
  22. package/dist/git/commands.js +431 -424
  23. package/dist/git-bundle.generated.d.ts +2 -2
  24. package/dist/git-bundle.generated.d.ts.map +1 -1
  25. package/dist/git-bundle.generated.js +3 -3
  26. package/dist/index.d.ts +2 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +2 -1
  29. package/dist/node-shims-artifact.generated.js +3 -3
  30. package/dist/router/index.d.ts.map +1 -1
  31. package/dist/router/index.js +59 -2
  32. package/dist/router/public-directory-do.d.ts +17 -0
  33. package/dist/router/public-directory-do.d.ts.map +1 -0
  34. package/dist/router/public-directory-do.js +16 -0
  35. package/dist/router/public-directory.d.ts +75 -0
  36. package/dist/router/public-directory.d.ts.map +1 -0
  37. package/dist/router/public-directory.js +115 -0
  38. package/dist/router/remote-api.d.ts +9 -1
  39. package/dist/router/remote-api.d.ts.map +1 -1
  40. package/dist/router/remote-api.js +19 -2
  41. package/dist/runtime/node-shims.d.ts +4 -1
  42. package/dist/runtime/node-shims.d.ts.map +1 -1
  43. package/dist/runtime/node-shims.js +324 -6
  44. package/dist/session/agent.d.ts +11 -0
  45. package/dist/session/agent.d.ts.map +1 -1
  46. package/dist/session/helpers.js +1 -1
  47. package/dist/session/init-phases.d.ts +17 -23
  48. package/dist/session/init-phases.d.ts.map +1 -1
  49. package/dist/session/init-phases.js +17 -41
  50. package/dist/session/init.d.ts.map +1 -1
  51. package/dist/session/init.js +19 -15
  52. package/dist/session/keys.d.ts +8 -0
  53. package/dist/session/keys.d.ts.map +1 -1
  54. package/dist/session/keys.js +8 -0
  55. package/dist/session/nimbus-session.d.ts +29 -4
  56. package/dist/session/nimbus-session.d.ts.map +1 -1
  57. package/dist/session/nimbus-session.js +62 -9
  58. package/dist/session/port-capability.d.ts +95 -8
  59. package/dist/session/port-capability.d.ts.map +1 -1
  60. package/dist/session/port-capability.js +165 -8
  61. package/dist/session/programmatic.d.ts +50 -2
  62. package/dist/session/programmatic.d.ts.map +1 -1
  63. package/dist/session/programmatic.js +104 -6
  64. package/dist/session/routes.d.ts +17 -0
  65. package/dist/session/routes.d.ts.map +1 -1
  66. package/dist/session/routes.js +92 -25
  67. package/dist/session/rpc.d.ts.map +1 -1
  68. package/dist/session/rpc.js +14 -4
  69. package/dist/session/shell-socket.d.ts +76 -0
  70. package/dist/session/shell-socket.d.ts.map +1 -0
  71. package/dist/session/shell-socket.js +172 -0
  72. package/dist/session/start-real-vite.js +1 -1
  73. package/dist/session/supervisor-op.d.ts +5 -0
  74. package/dist/session/supervisor-op.d.ts.map +1 -0
  75. package/dist/session/supervisor-op.js +74 -0
  76. package/dist/session/supervisor-rpc.d.ts +6 -10
  77. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  78. package/dist/session/supervisor-rpc.js +91 -70
  79. package/dist/session/ws.d.ts.map +1 -1
  80. package/dist/session/ws.js +19 -4
  81. package/package.json +4 -4
  82. package/public/_assets/runtime/{node-shims-fea906843f6d594e.js → node-shims-9e1380d9ee430fcc.js} +320 -5
  83. package/public/s/index.html +101 -5
@@ -9,7 +9,10 @@
9
9
  * - events: full EventEmitter
10
10
  * - stream: real Readable/Writable/Transform/Duplex with backpressure
11
11
  * - crypto: createHash (FNV-1a sync, SubtleCrypto async), randomBytes/UUID
12
- * - zlib: real gzip/gunzip/deflate via CompressionStream/DecompressionStream
12
+ * - zlib: forward to workerd's native node:zlib when the facet real-import
13
+ * block materialised (full sync/brotli/stream surface; results are the
14
+ * host realm's own Buffers, recognized by the widened isBuffer);
15
+ * CompressionStream fallback with honest sync refusal
13
16
  * - dns: real DNS resolution via Cloudflare DNS-over-HTTPS
14
17
  * - http: virtual server with port registry for supervisor routing
15
18
  * - https: fetch()-backed request/get
@@ -386,7 +389,19 @@ const __BufferMod = (() => {
386
389
 
387
390
  function alloc(n, fill) { const a = new Uint8Array(n); if (fill !== undefined) a.fill(typeof fill === "number" ? fill : 0); return _wrap(a); }
388
391
  function allocUnsafe(n) { return _wrap(new Uint8Array(Number(n) || 0)); }
389
- function isBuffer(o) { return o instanceof Uint8Array && typeof o.toString === "function" && o.__isBuffer; }
392
+ // Marker check plus native-brand recognition: forwarded node:* builtins
393
+ // (zlib streams and results, crypto) hand back the host realm's own Buffer
394
+ // instances, which carry no __isBuffer marker. Their constructor brand is
395
+ // the closest cross-realm equivalent of Node's instanceof check, so
396
+ // Buffer.isBuffer stays truthful across the shim/native boundary instead
397
+ // of rejecting genuine host Buffers. Always returns a boolean (the old
398
+ // single-expression form leaked an undefined when the marker was absent).
399
+ function isBuffer(o) {
400
+ if (!(o instanceof Uint8Array)) return false;
401
+ if (o.__isBuffer) return true;
402
+ const ctor = o.constructor;
403
+ return typeof ctor === "function" && ctor.name === "Buffer";
404
+ }
390
405
  function concat(bufs, len) {
391
406
  const total = len ?? bufs.reduce((s, b) => s + b.length, 0);
392
407
  const r = new Uint8Array(total); let off = 0;
@@ -5593,6 +5608,21 @@ const __processMod = {
5593
5608
  },
5594
5609
  platform: "linux", arch: "x64",
5595
5610
  version: ${NODE_VERSION_LITERAL}, versions: ${NODE_VERSIONS_LITERAL},
5611
+ features: Object.freeze({
5612
+ inspector: false,
5613
+ debug: false,
5614
+ uv: false,
5615
+ ipv6: true,
5616
+ tls_alpn: true,
5617
+ tls_sni: true,
5618
+ tls_ocsp: false,
5619
+ tls: true,
5620
+ openssl_is_boringssl: true,
5621
+ }),
5622
+ getBuiltinModule: (specifier) => {
5623
+ const key = String(specifier).replace(/^node:/, "");
5624
+ return Object.prototype.hasOwnProperty.call(builtins, key) ? builtins[key] : undefined;
5625
+ },
5596
5626
  execPath: "/usr/local/bin/node",
5597
5627
  execArgv: [],
5598
5628
  pid: 1, ppid: 0, title: "node",
@@ -6152,10 +6182,295 @@ const __nimbusFacetProvidedPackages = new Set(${FACET_PROVIDED_PACKAGES_LITERAL}
6152
6182
  // timers.setInterval(...)), which clack's spinner — used by
6153
6183
  // create-cloudflare — triggers.
6154
6184
  builtins.timers = { setTimeout: globalThis.setTimeout.bind(globalThis), setInterval: globalThis.setInterval.bind(globalThis), clearTimeout: globalThis.clearTimeout.bind(globalThis), clearInterval: globalThis.clearInterval.bind(globalThis), setImmediate: (fn,...a) => globalThis.setTimeout(fn,0,...a), clearImmediate: globalThis.clearTimeout.bind(globalThis) };
6185
+ // ── zlib ───────────────────────────────────────────────────────────
6186
+ //
6187
+ // Two runtimes, one surface:
6188
+ // 1. Facet templates prepend the static import block
6189
+ // (_shared/real-node-imports.ts), which carries workerd's native
6190
+ // node:zlib — complete at the production compat date: every *Sync
6191
+ // variant, brotli/zstd, crc32, constants, and real streaming create*
6192
+ // factories. Forward verbatim: results are the host realm's own Buffer
6193
+ // instances, and __BufferMod.isBuffer recognizes that brand (see the
6194
+ // Buffer shim), so Buffer checks stay truthful without copying every
6195
+ // result or intercepting stream chunks.
6196
+ // 2. Scopes without the import block keep the CompressionStream fallback.
6197
+ // It is async-only by nature; the sync names refuse with an honest,
6198
+ // actionable error instead of pretending.
6155
6199
  builtins.zlib = (() => {
6156
- function _c(d,a) { const i=typeof d==="string"?new TextEncoder().encode(d):d; return new Response(new Blob([i]).stream().pipeThrough(new CompressionStream(a))).arrayBuffer().then(ab=>__BufferMod.from(new Uint8Array(ab))); }
6157
- function _d(d,a) { const i=d instanceof Uint8Array?d:new Uint8Array(d); return new Response(new Blob([i]).stream().pipeThrough(new DecompressionStream(a))).arrayBuffer().then(ab=>__BufferMod.from(new Uint8Array(ab))); }
6158
- return { gzip:(d,o,cb)=>{if(typeof o==="function")cb=o;_c(d,"gzip").then(r=>cb(null,r)).catch(e=>cb(e));}, gunzip:(d,o,cb)=>{if(typeof o==="function")cb=o;_d(d,"gzip").then(r=>cb(null,r)).catch(e=>cb(e));}, deflate:(d,o,cb)=>{if(typeof o==="function")cb=o;_c(d,"deflate").then(r=>cb(null,r)).catch(e=>cb(e));}, inflate:(d,o,cb)=>{if(typeof o==="function")cb=o;_d(d,"deflate").then(r=>cb(null,r)).catch(e=>cb(e));}, gzipSync:()=>{throw new Error("use async gzip()");}, gunzipSync:()=>{throw new Error("use async gunzip()");}, createGzip:()=>new __streamMod.Transform({transform(c,e,cb){_c(c,"gzip").then(r=>cb(null,r)).catch(e=>cb(e));}}), createGunzip:()=>new __streamMod.Transform({transform(c,e,cb){_d(c,"gzip").then(r=>cb(null,r)).catch(e=>cb(e));}}), createDeflate:()=>new __streamMod.Transform({transform(c,e,cb){_c(c,"deflate").then(r=>cb(null,r)).catch(e=>cb(e));}}), createInflate:()=>new __streamMod.Transform({transform(c,e,cb){_d(c,"deflate").then(r=>cb(null,r)).catch(e=>cb(e));}}), constants:{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1} };
6200
+ const __real = (typeof __real_zlib !== "undefined") ? (__real_zlib.default ?? __real_zlib) : null;
6201
+ if (__real && typeof __real.gzipSync === "function") {
6202
+ const mod = {};
6203
+ // Constants, lookup tables, crc32, and the stream factories/classes pass
6204
+ // through bound to the native module (capitalized names are classes —
6205
+ // binding would strip their prototype and break \`new\`).
6206
+ for (const k of Object.keys(__real)) {
6207
+ const v = __real[k];
6208
+ mod[k] = (typeof v === "function" && /^[a-z]/.test(k)) ? v.bind(__real) : v;
6209
+ }
6210
+ if (__real.promises) mod.promises = __real.promises;
6211
+ mod.default = mod;
6212
+ return mod;
6213
+ }
6214
+ function _c(i,a) { return new Response(new Blob([i]).stream().pipeThrough(new CompressionStream(a))).arrayBuffer().then(ab=>__BufferMod.from(new Uint8Array(ab))); }
6215
+ // Decompression is driven by hand rather than piped: feeding and draining
6216
+ // run together, because a write only completes while somebody reads.
6217
+ async function _d(i,a) {
6218
+ const codec = _openCodec("decompress", a);
6219
+ const chunks = [];
6220
+ let failure = null;
6221
+ const record = (reason) => { if (!failure) failure = { reason }; };
6222
+ const drain = (async () => {
6223
+ for (;;) {
6224
+ const next = await codec.reader.read();
6225
+ if (next.done) return;
6226
+ chunks.push(next.value);
6227
+ }
6228
+ })().catch(record);
6229
+ const feed = (async () => {
6230
+ await codec.writer.write(i);
6231
+ await codec.writer.close();
6232
+ })().catch(record);
6233
+ await Promise.all([drain, feed]);
6234
+ if (failure) throw _decompressFailure(failure.reason);
6235
+ return __BufferMod.from(_concat(chunks));
6236
+ }
6237
+ function _syncRefusal(name, asyncName) {
6238
+ const e = new Error("zlib." + name + ": synchronous compression is not available on this runtime (no native node:zlib in scope). Use the async zlib." + asyncName + "(data, callback) form.");
6239
+ e.code = "ERR_ZLIB_SYNC_UNAVAILABLE";
6240
+ throw e;
6241
+ }
6242
+ // Node accepts strings, ArrayBuffers, and any ArrayBufferView; one funnel
6243
+ // yields a byte-addressed Uint8Array over the caller's own region —
6244
+ // byteOffset/byteLength preserved, element values never reinterpreted.
6245
+ function _u8(d) {
6246
+ if (typeof d === "string") return new TextEncoder().encode(d);
6247
+ if (d instanceof Uint8Array) return d;
6248
+ if (ArrayBuffer.isView(d)) return new Uint8Array(d.buffer, d.byteOffset, d.byteLength);
6249
+ return new Uint8Array(d);
6250
+ }
6251
+ // Node splits decompression failures two ways, and the engine's own
6252
+ // failure is the only thing that can tell them apart: an input that ran
6253
+ // out is Z_BUF_ERROR / errno -5, everything else — bad header, bad block,
6254
+ // and a checksum or length trailer that only fails once the member is
6255
+ // complete — is Z_DATA_ERROR / errno -3. Which side of a write or close
6256
+ // the failure lands on says nothing about that, so it is not consulted.
6257
+ function _zdata(e) {
6258
+ const err = new Error(e instanceof Error && e.message ? e.message : String(e));
6259
+ err.code = "Z_DATA_ERROR";
6260
+ err.errno = -3;
6261
+ err.cause = e;
6262
+ return err;
6263
+ }
6264
+ function _zbuf(e) {
6265
+ const err = new Error("unexpected end of file");
6266
+ err.code = "Z_BUF_ERROR";
6267
+ err.errno = -5;
6268
+ if (e != null) err.cause = e;
6269
+ return err;
6270
+ }
6271
+ function _isUnexpectedEnd(e) {
6272
+ const m = e instanceof Error && typeof e.message === "string" ? e.message : String(e);
6273
+ return /unexpected end|end of (?:file|input|stream)|premature|truncated|\\bEOF\\b/i.test(m);
6274
+ }
6275
+ function _decompressFailure(e) { return _isUnexpectedEnd(e) ? _zbuf(e) : _zdata(e); }
6276
+ function _destroyedWrite() {
6277
+ const e = new Error("Cannot call write after a stream was destroyed");
6278
+ e.code = "ERR_STREAM_DESTROYED";
6279
+ return e;
6280
+ }
6281
+ // Node throws synchronously rather than deferring a callback that is not
6282
+ // there; this surface has no promise form to fall back on.
6283
+ function _invalidCallback(v) {
6284
+ const got = v === undefined ? "undefined"
6285
+ : v === null ? "null"
6286
+ : typeof v === "object" ? "an instance of " + ((v.constructor && v.constructor.name) || "Object")
6287
+ : "type " + typeof v + " (" + String(v) + ")";
6288
+ const e = new TypeError('The "callback" argument must be of type function. Received ' + got);
6289
+ e.code = "ERR_INVALID_ARG_TYPE";
6290
+ return e;
6291
+ }
6292
+ // Node's Unzip contract sniffs the wrapper itself: gzip magic or zlib.
6293
+ function _isGzip(u8) { return u8.length >= 2 && u8[0] === 0x1f && u8[1] === 0x8b; }
6294
+ function _concat(chunks) {
6295
+ let n = 0;
6296
+ for (const c of chunks) n += c.length;
6297
+ const out = new Uint8Array(n);
6298
+ let o = 0;
6299
+ for (const c of chunks) { out.set(c, o); o += c.length; }
6300
+ return out;
6301
+ }
6302
+ function _process(mode, fmt, input) {
6303
+ const algo = mode === "compress" ? fmt : (fmt || (_isGzip(input) ? "gzip" : "deflate"));
6304
+ return mode === "compress" ? _c(input, algo) : _d(input, algo);
6305
+ }
6306
+ function _async(mode, fmt) {
6307
+ return (d, o, cb) => {
6308
+ const callback = typeof o === "function" ? o : cb;
6309
+ if (typeof callback !== "function") throw _invalidCallback(callback);
6310
+ // Two arms, not .then().catch(): a callback that throws on success must
6311
+ // not be handed its own exception as a second, failed invocation.
6312
+ _process(mode, fmt, _u8(d)).then(
6313
+ (r) => callback(null, r),
6314
+ (e) => callback(e instanceof Error ? e : new Error(String(e))),
6315
+ );
6316
+ };
6317
+ }
6318
+ // Live codec per Transform lifetime: every write feeds one real
6319
+ // CompressionStream/DecompressionStream writer (its queue serializes
6320
+ // ordering; the write promise settles before the callback), a reader pump
6321
+ // relays output as it is produced instead of accumulating the payload,
6322
+ // and flush closes the writer then awaits full drain before completing.
6323
+ // Chunks are copied so later caller mutations cannot reach the codec, and
6324
+ // createUnzip holds copies only until two bytes decide the wrapper.
6325
+ function _openCodec(openMode, openAlgo) {
6326
+ const cs = openMode === "compress" ? new CompressionStream(openAlgo) : new DecompressionStream(openAlgo);
6327
+ return { writer: cs.writable.getWriter(), reader: cs.readable.getReader() };
6328
+ }
6329
+ // The legacy Readable has no resume notification, so room below the
6330
+ // high-water mark is observed by yielding to the task queue until the
6331
+ // consumer drains or the stream is destroyed.
6332
+ async function _drainRoom(stream) {
6333
+ while (
6334
+ stream._readableState &&
6335
+ !stream._readableState.destroyed &&
6336
+ stream.readableLength >= stream._readableState.highWaterMark
6337
+ ) {
6338
+ await new Promise((tick) => setTimeout(tick, 0));
6339
+ }
6340
+ // True when the wait ended because the stream went away, not because
6341
+ // the consumer made room.
6342
+ return !!(stream._readableState && stream._readableState.destroyed);
6343
+ }
6344
+ function _streamFactory(factoryMode, fmt) {
6345
+ return () => {
6346
+ let writer = null;
6347
+ let reader = null;
6348
+ let drained = Promise.resolve();
6349
+ let pumpFailure = null;
6350
+ let algo = fmt;
6351
+ let held = [];
6352
+ let heldLen = 0;
6353
+ let destroyed = false;
6354
+ const t = new __streamMod.Transform({
6355
+ transform: async (chunk, _enc, cb) => {
6356
+ try {
6357
+ if (destroyed) return cb(_destroyedWrite());
6358
+ const bytes = _u8(chunk).slice();
6359
+ let feed = bytes;
6360
+ if (!writer) {
6361
+ if (fmt === null && heldLen + bytes.length < 2) {
6362
+ held.push(bytes);
6363
+ heldLen += bytes.length;
6364
+ return cb();
6365
+ }
6366
+ if (heldLen > 0) feed = _concat([...held, bytes]);
6367
+ held = [];
6368
+ heldLen = 0;
6369
+ if (fmt === null) algo = _isGzip(feed) ? "gzip" : "deflate";
6370
+ start();
6371
+ }
6372
+ await writer.write(feed);
6373
+ cb();
6374
+ } catch (e) {
6375
+ cb(destroyed ? _destroyedWrite() : factoryMode === "decompress" ? _decompressFailure(e) : e);
6376
+ }
6377
+ },
6378
+ flush: async (cb) => {
6379
+ try {
6380
+ if (destroyed) return cb(_destroyedWrite());
6381
+ if (!writer) {
6382
+ if (factoryMode !== "compress") {
6383
+ // Nothing was ever fed: the input ended before a member
6384
+ // began, which is Node's unexpected-end buffer error rather
6385
+ // than corrupt data. No codec is invented to hide it.
6386
+ return cb(_zbuf(null));
6387
+ }
6388
+ start();
6389
+ }
6390
+ await writer.close();
6391
+ await drained;
6392
+ cb(pumpFailure);
6393
+ } catch (e) {
6394
+ if (pumpFailure) return cb(pumpFailure);
6395
+ if (destroyed) return cb(_destroyedWrite());
6396
+ cb(factoryMode === "decompress" ? _decompressFailure(e) : e);
6397
+ }
6398
+ },
6399
+ });
6400
+ // Every destroy exit fires 'close' on the custom Transform — even when
6401
+ // the pump sits parked inside reader.read() on truncated input that can
6402
+ // never decode. Waking there is immediate: cancel settles the parked
6403
+ // read, abort fails queued writes, and writes arriving after destroy
6404
+ // report ERR_STREAM_DESTROYED instead of silent acceptance.
6405
+ t.on("close", () => {
6406
+ destroyed = true;
6407
+ _releaseCodec();
6408
+ });
6409
+ // One cleanup path for every destroy exit: cancel the readable side,
6410
+ // abort the writable side, and stop the pump.
6411
+ function _releaseCodec() {
6412
+ if (reader) reader.cancel().catch(() => {});
6413
+ if (writer) writer.abort().catch(() => {});
6414
+ }
6415
+ function start() {
6416
+ const opened = _openCodec(factoryMode, algo);
6417
+ writer = opened.writer;
6418
+ reader = opened.reader;
6419
+ drained = (async () => {
6420
+ try {
6421
+ for (;;) {
6422
+ // A destroy can land while a read is in flight; check on both
6423
+ // sides so nothing buffers after the stream went away.
6424
+ if (destroyed) return _releaseCodec();
6425
+ const next = await reader.read();
6426
+ if (destroyed) return _releaseCodec();
6427
+ if (next.done) {
6428
+ return;
6429
+ }
6430
+ // Backpressure: once push reports pressure, park the pump and
6431
+ // do not read again until the consumer drains below the
6432
+ // high-water mark. The pending writer.write promise then holds
6433
+ // the transform callback, so producer writes stop resolving
6434
+ // instead of accumulating. A destroy while parked releases the
6435
+ // codec through the close hook above.
6436
+ if (!t.push(__BufferMod.from(next.value))) {
6437
+ if (await _drainRoom(t)) return _releaseCodec();
6438
+ }
6439
+ }
6440
+ } catch (e) {
6441
+ pumpFailure = factoryMode === "decompress"
6442
+ ? _decompressFailure(e)
6443
+ : (e instanceof Error ? e : new Error(String(e)));
6444
+ }
6445
+ })();
6446
+ }
6447
+ return t;
6448
+ };
6449
+ }
6450
+ return {
6451
+ gzip: _async("compress", "gzip"),
6452
+ gunzip: _async("decompress", "gzip"),
6453
+ deflate: _async("compress", "deflate"),
6454
+ inflate: _async("decompress", "deflate"),
6455
+ deflateRaw: _async("compress", "deflate-raw"),
6456
+ inflateRaw: _async("decompress", "deflate-raw"),
6457
+ unzip: _async("decompress", null),
6458
+ gzipSync: (d, o) => _syncRefusal("gzipSync", "gzip"),
6459
+ gunzipSync: (d, o) => _syncRefusal("gunzipSync", "gunzip"),
6460
+ deflateSync: (d, o) => _syncRefusal("deflateSync", "deflate"),
6461
+ inflateSync: (d, o) => _syncRefusal("inflateSync", "inflate"),
6462
+ deflateRawSync: (d, o) => _syncRefusal("deflateRawSync", "deflateRaw"),
6463
+ inflateRawSync: (d, o) => _syncRefusal("inflateRawSync", "inflateRaw"),
6464
+ unzipSync: (d, o) => _syncRefusal("unzipSync", "unzip"),
6465
+ createGzip: _streamFactory("compress", "gzip"),
6466
+ createGunzip: _streamFactory("decompress", "gzip"),
6467
+ createDeflate: _streamFactory("compress", "deflate"),
6468
+ createInflate: _streamFactory("decompress", "deflate"),
6469
+ createDeflateRaw: _streamFactory("compress", "deflate-raw"),
6470
+ createInflateRaw: _streamFactory("decompress", "deflate-raw"),
6471
+ createUnzip: _streamFactory("decompress", null),
6472
+ constants: { Z_NO_FLUSH: 0, Z_PARTIAL_FLUSH: 1, Z_SYNC_FLUSH: 2, Z_FULL_FLUSH: 3, Z_FINISH: 4, Z_BEST_COMPRESSION: 9, Z_DEFAULT_COMPRESSION: -1 },
6473
+ };
6159
6474
  })();
6160
6475
  builtins.readline = (() => {
6161
6476
  function emitKeypressEvents(stream) {
@@ -6880,9 +7195,11 @@ function __resolveImportsField(name, fromDir) {
6880
7195
  function __mkCompiledFn(code) {
6881
7196
  const reFn = /(?:^|\\n|;)\\s*(?:const|let|var)\\s+__filename\\s*=/m;
6882
7197
  const reDn = /(?:^|\\n|;)\\s*(?:const|let|var)\\s+__dirname\\s*=/m;
7198
+ const reRequire = /(?:^|\\n|;)\\s*(?:const|let|var)\\s+require\\s*=/m;
6883
7199
  const fnName = reFn.test(code) ? "__filename__nimbus_unused" : "__filename";
6884
7200
  const dnName = reDn.test(code) ? "__dirname__nimbus_unused" : "__dirname";
6885
- return new Function("exports", "require", "module", fnName, dnName, code);
7201
+ const requireName = reRequire.test(code) ? "require__nimbus_unused" : "require";
7202
+ return new Function("exports", requireName, "module", fnName, dnName, code);
6886
7203
  }
6887
7204
 
6888
7205
  function __exportsTarget(mod) {
@@ -6961,6 +7278,7 @@ function __loadModule(resolvedPath) {
6961
7278
  };
6962
7279
  scopedRequire.cache = __moduleCache;
6963
7280
  scopedRequire.main = __require.main;
7281
+ mod.require = scopedRequire;
6964
7282
 
6965
7283
  // X.5-M3: thread currently-loading module path through globalThis so the
6966
7284
  // URL shim null-base fallback (in node-shims url module) can compose
@@ -15,6 +15,17 @@ interface AgentStorage {
15
15
  delete(key: string): Promise<void>;
16
16
  deleteAll(): Promise<void>;
17
17
  deleteAlarm(): Promise<void>;
18
+ list<T = unknown>(options: {
19
+ prefix: string;
20
+ }): Promise<Map<string, T>>;
21
+ transaction<T>(body: (txn: {
22
+ get(key: string): Promise<unknown>;
23
+ put(key: string, value: unknown): Promise<void>;
24
+ delete(key: string): Promise<unknown>;
25
+ list<T2 = unknown>(options: {
26
+ prefix: string;
27
+ }): Promise<Map<string, T2>>;
28
+ }) => Promise<T>): Promise<T>;
18
29
  }
19
30
  interface Host extends ProgrammaticHost, SessionAiHost {
20
31
  ctx: {
@@ -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;CAC9B;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,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"}
@@ -370,7 +370,7 @@ export const _CP_PURE_BUILTIN = new Set([
370
370
  'sleep', 'date', 'whoami', 'id', 'hostname', 'uname', 'clear',
371
371
  'tree', 'find', 'grep', 'head', 'tail', 'wc', 'sort', 'uniq', 'sed',
372
372
  'awk', 'xargs', 'tee', 'du', 'diff', 'base64', 'seq', 'realpath',
373
- 'basename', 'dirname', 'printf', 'sha256sum', 'file', 'xxd',
373
+ 'basename', 'dirname', 'printf', 'sha256sum', 'file', 'xxd', 'od', 'hexdump',
374
374
  'chmod', 'chown', 'ln', 'test', '[', 'read', 'exit', 'set', 'shopt',
375
375
  'trap', 'umask', 'ulimit', 'which', 'uptime',
376
376
  ]);
@@ -33,6 +33,7 @@
33
33
  * additional ring entries, not replacements.
34
34
  */
35
35
  import { type SessionState } from '@nimbus-sh/platform/oom-discriminator.js';
36
+ import { type AutoResponseHost } from './shell-socket.js';
36
37
  /**
37
38
  * Set the current phase + record a transition. Fail-soft on the
38
39
  * observability call; the phase update on `self` is direct and
@@ -42,37 +43,30 @@ export declare function setPhase(self: {
42
43
  _b4Phase: SessionState | null;
43
44
  ctx?: unknown;
44
45
  }, toState: SessionState, trigger: string): void;
46
+ type WsUpgradeDecision = 'warm-join' | 'conflict' | 'cold';
45
47
  /**
46
- * [B'.5] Identify the original phase-based warm-rejoin case. The /ws
47
- * upgrade classifier below also recognizes headless sessions whose
48
- * lifecycle phase does not describe a real terminal attachment.
48
+ * Decide what a /ws upgrade should do with the session it lands on.
49
49
  *
50
- * Conditions for warm rejoin:
51
- * 1. Phase = 'drained' (a wsClose / wsError fired since last init).
52
- * 2. Kernel + Shell + Terminal are still alive in-memory (the
53
- * [B'.5] change to wsClose stopped nulling them).
54
- * 3. Same isolate (no DO eviction since the close).
50
+ * - cold: no session to join. Either nothing was ever built, or a
51
+ * previous teardown left the object half-built. A Shell
52
+ * without its Kernel or its Terminal serves nobody, and
53
+ * nothing else rebuilds one, so the upgrade does.
54
+ * - conflict: another browser terminal holds this session. The caller
55
+ * answers 409, which is what stops two tabs from driving
56
+ * one shell. See `shell-socket.ts` for what proves that a
57
+ * socket still has a peer on it.
58
+ * - warm-join: the session is built and unattended. Skip the rebuild
59
+ * and hand the live Shell to the incoming socket.
55
60
  *
56
- */
57
- export declare function isWarmRejoin(self: {
58
- _b4Phase: SessionState | null;
59
- shell: any;
60
- terminal: any;
61
- kernel: any;
62
- }): boolean;
63
- type WsUpgradeDecision = 'warm-join' | 'conflict' | 'cold';
64
- /**
65
- * Classify a shell WebSocket upgrade from the actual attachment state.
66
- * A non-null Shell can belong to a headless programmatic boot, so only an
67
- * open socket tagged as `shell` proves that another browser terminal is
68
- * currently attached.
61
+ * The caller classifies BEFORE it accepts the incoming socket, so the
62
+ * upgrade cannot count itself as the incumbent.
69
63
  */
70
64
  export declare function classifyWsUpgrade(self: {
71
- _b4Phase: SessionState | null;
72
65
  shell: unknown;
73
66
  terminal: unknown;
74
67
  kernel: unknown;
75
- }, sockets: readonly WebSocket[]): WsUpgradeDecision;
68
+ ctx?: AutoResponseHost;
69
+ }, sockets: readonly WebSocket[], now?: number): WsUpgradeDecision;
76
70
  /**
77
71
  * [B'.5] Run the warm-rejoin path. Skips Phase B (kernel + shell are
78
72
  * already built and alive in-memory). Phase R loads any state that
@@ -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;AAGlG;;;;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;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;CACxC,GAAG,OAAO,CAKV;AAED,KAAK,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB,EAAE,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,iBAAiB,CAmBnD;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,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"}
@@ -34,6 +34,7 @@
34
34
  */
35
35
  import { recordRecoveryEvent } from '@nimbus-sh/platform/oom-discriminator.js';
36
36
  import { generation } from '@nimbus-sh/fabric/generation.js';
37
+ import { hasLiveShellOwner } from './shell-socket.js';
37
38
  /**
38
39
  * Set the current phase + record a transition. Fail-soft on the
39
40
  * observability call; the phase update on `self` is direct and
@@ -56,51 +57,26 @@ export function setPhase(self, toState, trigger) {
56
57
  catch { /* observability is non-critical */ }
57
58
  }
58
59
  /**
59
- * [B'.5] Identify the original phase-based warm-rejoin case. The /ws
60
- * upgrade classifier below also recognizes headless sessions whose
61
- * lifecycle phase does not describe a real terminal attachment.
60
+ * Decide what a /ws upgrade should do with the session it lands on.
62
61
  *
63
- * Conditions for warm rejoin:
64
- * 1. Phase = 'drained' (a wsClose / wsError fired since last init).
65
- * 2. Kernel + Shell + Terminal are still alive in-memory (the
66
- * [B'.5] change to wsClose stopped nulling them).
67
- * 3. Same isolate (no DO eviction since the close).
62
+ * - cold: no session to join. Either nothing was ever built, or a
63
+ * previous teardown left the object half-built. A Shell
64
+ * without its Kernel or its Terminal serves nobody, and
65
+ * nothing else rebuilds one, so the upgrade does.
66
+ * - conflict: another browser terminal holds this session. The caller
67
+ * answers 409, which is what stops two tabs from driving
68
+ * one shell. See `shell-socket.ts` for what proves that a
69
+ * socket still has a peer on it.
70
+ * - warm-join: the session is built and unattended. Skip the rebuild
71
+ * and hand the live Shell to the incoming socket.
68
72
  *
73
+ * The caller classifies BEFORE it accepts the incoming socket, so the
74
+ * upgrade cannot count itself as the incumbent.
69
75
  */
70
- export function isWarmRejoin(self) {
71
- return self._b4Phase === 'drained'
72
- && self.shell != null
73
- && self.terminal != null
74
- && self.kernel != null;
75
- }
76
- /**
77
- * Classify a shell WebSocket upgrade from the actual attachment state.
78
- * A non-null Shell can belong to a headless programmatic boot, so only an
79
- * open socket tagged as `shell` proves that another browser terminal is
80
- * currently attached.
81
- */
82
- export function classifyWsUpgrade(self, sockets) {
83
- if (isWarmRejoin(self))
84
- return 'warm-join';
85
- if (self.shell == null)
76
+ export function classifyWsUpgrade(self, sockets, now = Date.now()) {
77
+ if (self.shell == null || self.terminal == null || self.kernel == null)
86
78
  return 'cold';
87
- if (self.terminal == null || self.kernel == null)
88
- return 'conflict';
89
- const hasOpenShellSocket = sockets.some((socket) => {
90
- if (socket.readyState !== WebSocket.OPEN)
91
- return false;
92
- try {
93
- const attachment = socket.deserializeAttachment();
94
- return typeof attachment === 'object'
95
- && attachment !== null
96
- && 'kind' in attachment
97
- && attachment.kind === 'shell';
98
- }
99
- catch {
100
- return false;
101
- }
102
- });
103
- return hasOpenShellSocket ? 'conflict' : 'warm-join';
79
+ return hasLiveShellOwner(self.ctx, sockets, now) ? 'conflict' : 'warm-join';
104
80
  }
105
81
  /**
106
82
  * [B'.5] Run the warm-rejoin path. Skips Phase B (kernel + shell are
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/session/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AA+EH,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,CAosF9E"}
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"}