opensteer 0.9.6 → 0.9.7

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 (33) hide show
  1. package/dist/{chunk-BVRIPCWA.js → chunk-3OHKIPBD.js} +316 -465
  2. package/dist/chunk-3OHKIPBD.js.map +1 -0
  3. package/dist/{chunk-L4NF74KI.js → chunk-52UNH5UW.js} +5 -5
  4. package/dist/{chunk-L4NF74KI.js.map → chunk-52UNH5UW.js.map} +1 -1
  5. package/dist/{chunk-3XBQRZZC.js → chunk-PJXN7HED.js} +115 -14
  6. package/dist/chunk-PJXN7HED.js.map +1 -0
  7. package/dist/{chunk-3I3A5OLB.js → chunk-R33BXCMQ.js} +16 -7
  8. package/dist/chunk-R33BXCMQ.js.map +1 -0
  9. package/dist/{chunk-T5P2QGZ3.js → chunk-U4BUCIZ4.js} +153 -12
  10. package/dist/chunk-U4BUCIZ4.js.map +1 -0
  11. package/dist/cli/bin.cjs +663 -544
  12. package/dist/cli/bin.cjs.map +1 -1
  13. package/dist/cli/bin.js +66 -50
  14. package/dist/cli/bin.js.map +1 -1
  15. package/dist/index.cjs +584 -495
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +26 -50
  18. package/dist/index.d.ts +26 -50
  19. package/dist/index.js +4 -4
  20. package/dist/local-view/public/assets/app.js +10 -1
  21. package/dist/local-view/serve-entry.cjs +687 -494
  22. package/dist/local-view/serve-entry.cjs.map +1 -1
  23. package/dist/local-view/serve-entry.js +2 -2
  24. package/dist/opensteer-CY2QUJEG.js +6 -0
  25. package/dist/{opensteer-UGA6YBRN.js.map → opensteer-CY2QUJEG.js.map} +1 -1
  26. package/dist/{session-control-U3L5H2ZI.js → session-control-FIP6ZJLH.js} +4 -4
  27. package/dist/{session-control-U3L5H2ZI.js.map → session-control-FIP6ZJLH.js.map} +1 -1
  28. package/package.json +7 -7
  29. package/dist/chunk-3I3A5OLB.js.map +0 -1
  30. package/dist/chunk-3XBQRZZC.js.map +0 -1
  31. package/dist/chunk-BVRIPCWA.js.map +0 -1
  32. package/dist/chunk-T5P2QGZ3.js.map +0 -1
  33. package/dist/opensteer-UGA6YBRN.js +0 -6
@@ -1,4 +1,4 @@
1
- import { writeLocalViewServiceState, CURRENT_PROCESS_OWNER, OPENSTEER_LOCAL_VIEW_SERVICE_VERSION, OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT, clearLocalViewServiceState, readLocalViewSessionManifest, listLocalViewSessionManifests, deleteLocalViewSessionManifest, isProcessRunning, pathExists, readPersistedLocalBrowserSessionRecord, inspectCdpEndpoint } from './chunk-T5P2QGZ3.js';
1
+ import { writeLocalViewServiceState, CURRENT_PROCESS_OWNER, OPENSTEER_LOCAL_VIEW_SERVICE_VERSION, OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT, clearLocalViewServiceState, readLocalViewSessionManifest, listLocalViewSessionManifests, deleteLocalViewSessionManifest, getPersistedLocalBrowserSessionOwnership, isProcessRunning, pathExists, readPersistedLocalBrowserSessionRecord, buildLocalViewSessionIdForRecord, isAttachedLocalBrowserSessionReachable, inspectCdpEndpoint } from './chunk-U4BUCIZ4.js';
2
2
  import { randomBytes } from 'crypto';
3
3
  import { createServer } from 'http';
4
4
  import { readFile } from 'fs/promises';
@@ -52,13 +52,13 @@ async function resolveSessionSummary(manifest) {
52
52
  return {
53
53
  sessionId: manifest.sessionId,
54
54
  label: manifest.workspace ?? (path2.basename(manifest.rootPath) || manifest.sessionId),
55
- status: isProcessRunning(record.pid) ? "live" : "stale",
55
+ status: getPersistedLocalBrowserSessionOwnership(record) === "attached" || isProcessRunning(record.pid) ? "live" : "stale",
56
56
  ...manifest.workspace === void 0 ? {} : { workspace: manifest.workspace },
57
57
  rootPath: manifest.rootPath,
58
58
  engine: record.engine,
59
59
  ownership: manifest.ownership,
60
- pid: record.pid,
61
60
  startedAt: record.startedAt,
61
+ ...record.pid > 0 ? { pid: record.pid } : {},
62
62
  ...browserName === void 0 ? {} : { browserName }
63
63
  };
64
64
  }
@@ -86,7 +86,16 @@ async function readLiveRecord(manifest) {
86
86
  if (!record) {
87
87
  return void 0;
88
88
  }
89
- if (record.pid !== manifest.pid || record.startedAt !== manifest.startedAt || !isProcessRunning(record.pid)) {
89
+ if (buildLocalViewSessionIdForRecord({
90
+ rootPath: manifest.rootPath,
91
+ live: record
92
+ }) !== manifest.sessionId || record.startedAt !== manifest.startedAt || record.engine !== manifest.engine || getPersistedLocalBrowserSessionOwnership(record) !== manifest.ownership) {
93
+ return void 0;
94
+ }
95
+ if (getPersistedLocalBrowserSessionOwnership(record) === "attached") {
96
+ return await isAttachedLocalBrowserSessionReachable(record) ? record : void 0;
97
+ }
98
+ if (record.pid !== manifest.pid || !isProcessRunning(record.pid)) {
90
99
  return void 0;
91
100
  }
92
101
  return record;
@@ -1661,7 +1670,7 @@ async function handleHttpRequest(args) {
1661
1670
  return;
1662
1671
  }
1663
1672
  const sessionId = decodeURIComponent(closeMatch[1]);
1664
- const { closeLocalViewSessionBrowser, LocalViewSessionCloseError } = await import('./session-control-U3L5H2ZI.js');
1673
+ const { closeLocalViewSessionBrowser, LocalViewSessionCloseError } = await import('./session-control-FIP6ZJLH.js');
1665
1674
  try {
1666
1675
  await closeLocalViewSessionBrowser(sessionId);
1667
1676
  } catch (error) {
@@ -1796,5 +1805,5 @@ async function runLocalViewService() {
1796
1805
  }
1797
1806
 
1798
1807
  export { runLocalViewService };
1799
- //# sourceMappingURL=chunk-3I3A5OLB.js.map
1800
- //# sourceMappingURL=chunk-3I3A5OLB.js.map
1808
+ //# sourceMappingURL=chunk-R33BXCMQ.js.map
1809
+ //# sourceMappingURL=chunk-R33BXCMQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/local-view/resolve-browser-websocket.ts","../src/local-view/discovery.ts","../src/local-view/runtime-state.ts","../src/local-view/ws-types.ts","../src/local-view/cdp-proxy.ts","../src/local-view/tab-state-tracker.ts","../src/local-view/view-stream-capture-policy.ts","../src/local-view/view-stream-protocol.ts","../src/local-view/view-stream.ts","../src/local-view/server.ts","../src/local-view/serve.ts"],"names":["path","wsModule","WebSocket","url","randomBytes"],"mappings":";;;;;;;;;;;;AAGA,eAAsB,2BACpB,MAAA,EACiB;AACjB,EAAA,IAAI,MAAA,CAAO,WAAW,YAAA,EAAc;AAClC,IAAA,IAAI,CAAC,OAAO,QAAA,EAAU;AACpB,MAAA,MAAM,IAAI,MAAM,mEAAmE,CAAA;AAAA,IACrF;AACA,IAAA,OAAO,MAAA,CAAO,QAAA;AAAA,EAChB;AAEA,EAAA,IAAI,CAAC,OAAO,kBAAA,EAAoB;AAC9B,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACxE;AAEA,EAAA,MAAM,SAAA,GAAY,MAAM,kBAAA,CAAmB;AAAA,IACzC,UAAU,MAAA,CAAO,kBAAA;AAAA,IACjB,SAAA,EAAW;AAAA,GACZ,CAAA;AACD,EAAA,OAAO,SAAA,CAAU,QAAA;AACnB;;;ACKA,eAAsB,6BAAA,GAEpB;AACA,EAAA,MAAM,SAAA,GAAY,MAAM,6BAAA,EAA8B;AACtD,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,GAAA,CAAI,SAAA,CAAU,GAAA,CAAI,CAAC,QAAA,KAAa,qBAAA,CAAsB,QAAQ,CAAC,CAAC,CAAA;AAC/F,EAAA,OAAO,SACJ,MAAA,CAAO,CAAC,OAAA,KAAyD,OAAA,KAAY,MAAS,CAAA,CACtF,IAAA;AAAA,IACC,CAAC,IAAA,EAAM,KAAA,KAAU,KAAA,CAAM,SAAA,GAAY,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,KAAA,CAAM,aAAA,CAAc,KAAA,CAAM,KAAK;AAAA,GAC3F;AACJ;AAEA,eAAsB,wBACpB,SAAA,EAC+C;AAC/C,EAAA,MAAM,QAAA,GAAW,MAAM,4BAAA,CAA6B,SAAS,CAAA;AAC7D,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,6BAA6B,QAAQ,CAAA;AAC9C;AAEA,eAAe,sBACb,QAAA,EACuD;AACvD,EAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,QAAQ,CAAA;AAC5C,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,8BAAA,CAA+B,SAAS,SAAS,CAAA;AACvD,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,cAAA,GACvBA,KAAA,CAAK,QAAA,CAAS,MAAA,CAAO,cAAc,CAAA,CAAE,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA,GACnE,MAAA;AAEJ,EAAA,OAAO;AAAA,IACL,WAAW,QAAA,CAAS,SAAA;AAAA,IACpB,KAAA,EAAO,SAAS,SAAA,KAAcA,KAAA,CAAK,SAAS,QAAA,CAAS,QAAQ,KAAK,QAAA,CAAS,SAAA,CAAA;AAAA,IAC3E,MAAA,EACE,yCAAyC,MAAM,CAAA,KAAM,cACrD,gBAAA,CAAiB,MAAA,CAAO,GAAG,CAAA,GACvB,MAAA,GACA,OAAA;AAAA,IACN,GAAI,SAAS,SAAA,KAAc,MAAA,GAAY,EAAC,GAAI,EAAE,SAAA,EAAW,QAAA,CAAS,SAAA,EAAU;AAAA,IAC5E,UAAU,QAAA,CAAS,QAAA;AAAA,IACnB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,WAAW,QAAA,CAAS,SAAA;AAAA,IACpB,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,GAAI,OAAO,GAAA,GAAM,CAAA,GAAI,EAAE,GAAA,EAAK,MAAA,CAAO,GAAA,EAAI,GAAI,EAAC;AAAA,IAC5C,GAAI,WAAA,KAAgB,MAAA,GAAY,EAAC,GAAI,EAAE,WAAA;AAAY,GACrD;AACF;AAEA,eAAe,6BACb,QAAA,EAC+C;AAC/C,EAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,QAAQ,CAAA;AAC5C,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,8BAAA,CAA+B,SAAS,SAAS,CAAA;AACvD,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,sBAAsB,MAAM,0BAAA,CAA2B,MAAM,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAC1F,EAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,eAAe,eACb,QAAA,EACyD;AACzD,EAAA,IAAI,CAAE,MAAM,UAAA,CAAW,QAAA,CAAS,QAAQ,CAAA,EAAI;AAC1C,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAA,GAAS,MAAM,sCAAA,CAAuC,QAAA,CAAS,QAAQ,CAAA;AAC7E,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IACE,gCAAA,CAAiC;AAAA,IAC/B,UAAU,QAAA,CAAS,QAAA;AAAA,IACnB,IAAA,EAAM;AAAA,GACP,CAAA,KAAM,QAAA,CAAS,SAAA,IAChB,MAAA,CAAO,cAAc,QAAA,CAAS,SAAA,IAC9B,MAAA,CAAO,MAAA,KAAW,SAAS,MAAA,IAC3B,wCAAA,CAAyC,MAAM,CAAA,KAAM,SAAS,SAAA,EAC9D;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,wCAAA,CAAyC,MAAM,CAAA,KAAM,UAAA,EAAY;AACnE,IAAA,OAAQ,MAAM,sCAAA,CAAuC,MAAM,CAAA,GAAK,MAAA,GAAS,MAAA;AAAA,EAC3E;AAEA,EAAA,IAAI,MAAA,CAAO,QAAQ,QAAA,CAAS,GAAA,IAAO,CAAC,gBAAA,CAAiB,MAAA,CAAO,GAAG,CAAA,EAAG;AAChE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA;AACT;;;ACjIO,IAAM,wBAAN,MAA4B;AAAA,EAChB,2BAAA,uBAAkC,GAAA,EAAkC;AAAA,EAErF,uBAAA,CAAwB,WAAmB,QAAA,EAAwB;AACjE,IAAA,IAAA,CAAK,2BAAA,CAA4B,IAAI,SAAA,EAAW;AAAA,MAC9C,QAAA;AAAA,MACA,EAAA,EAAI,KAAK,GAAA;AAAI,KACd,CAAA;AAAA,EACH;AAAA,EAEA,wBAAwB,SAAA,EAAqD;AAC3E,IAAA,OAAO,IAAA,CAAK,2BAAA,CAA4B,GAAA,CAAI,SAAS,CAAA;AAAA,EACvD;AAAA,EAEA,yBAAA,CAA0B,WAAmB,QAAA,EAAyB;AACpE,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,2BAAA,CAA4B,GAAA,CAAI,SAAS,CAAA;AAC9D,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,QAAA,KAAa,MAAA,IAAa,OAAA,CAAQ,QAAA,KAAa,QAAA,EAAU;AAC3D,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,2BAAA,CAA4B,OAAO,SAAS,CAAA;AAAA,EACnD;AACF,CAAA;ACeO,IAAM,wBAAA,GAIXC,UAAA,CAAA,eAAA;;;ACnCF,IAAM,uCAAA,GAA0C,GAAA;AAChD,IAAM,gCAAA,GAAmC,GAAA;AASlC,IAAM,oBAAN,MAAwB;AAAA,EAM7B,YAA6B,IAAA,EAA6B;AAA7B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAC3B,IAAA,IAAA,CAAK,MAAM,IAAI,wBAAA,CAAyB,EAAE,QAAA,EAAU,MAAM,CAAA;AAC1D,IAAA,IAAA,CAAK,uBACH,IAAA,CAAK,oBAAA,KAAyB,CAAC,GAAA,KAAQ,IAAIC,oBAAU,GAAG,CAAA,CAAA;AAC1D,IAAA,IAAA,CAAK,2BAAA,GACH,KAAK,2BAAA,IAA+B,uCAAA;AACtC,IAAA,IAAA,CAAK,qBAAA,GAAwB,KAAK,qBAAA,IAAyB,gCAAA;AAAA,EAC7D;AAAA,EAZiB,GAAA;AAAA,EACA,oBAAA;AAAA,EACA,2BAAA;AAAA,EACA,qBAAA;AAAA,EAWjB,aAAA,CAAc,GAAA,EAAsB,MAAA,EAAgB,IAAA,EAAoB;AACtE,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,GAAA,CAAI,GAAA,IAAO,KAAK,kBAAkB,CAAA;AACtD,IAAA,MAAM,QAAQ,GAAA,CAAI,QAAA,CAAS,MAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,KAAA,CAAM,CAAC,CAAA,KAAM,IAAA,IAAQ,KAAA,CAAM,CAAC,CAAA,KAAM,KAAA;AAC1E,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAA,CAAO,OAAA,EAAQ;AACf,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,MAAM,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,IAAI,aAAA,CAAc,GAAA,EAAK,MAAA,EAAQ,IAAA,EAAM,CAAC,YAAA,KAAiB;AAC1D,MAAA,KAAK,KAAK,SAAA,CAAU,YAAA,EAAc,SAAS,CAAA,CAAE,MAAM,MAAM;AACvD,QAAA,eAAA,CAAgB,YAAY,CAAA;AAAA,MAC9B,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,KAAA,MAAW,MAAA,IAAU,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS;AACrC,MAAA,eAAA,CAAgB,MAAM,CAAA;AAAA,IACxB;AACA,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,EACjB;AAAA,EAEA,MAAc,SAAA,CAAU,YAAA,EAA+B,SAAA,EAAkC;AACvF,IAAA,MAAM,QAAA,GAAW,MAAM,uBAAA,CAAwB,SAAS,CAAA;AACxD,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,eAAA,CAAgB,YAAY,CAAA;AAC5B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,oBAAA,CAAqB,QAAA,CAAS,mBAAmB,CAAA;AACvE,IAAA,MAAM,6BAAA,uBAAoC,GAAA,EAAY;AACtD,IAAA,MAAM,mCAAA,uBAA0C,GAAA,EAAoB;AACpE,IAAA,MAAM,2BAAA,uBAAkC,GAAA,EAAoB;AAC5D,IAAA,MAAM,wBAGD,EAAC;AACN,IAAA,IAAI,wBAAA,GAA2B,CAAA;AAC/B,IAAA,IAAI,MAAA,GAAS,KAAA;AACb,IAAA,IAAI,mBAAA,GAA6C,IAAA;AAEjD,IAAA,MAAM,kBAAkB,MAAM;AAC5B,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA;AAAA,MACF;AACA,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,IAAI,mBAAA,EAAqB;AACvB,QAAA,YAAA,CAAa,mBAAmB,CAAA;AAChC,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB;AACA,MAAA,qBAAA,CAAsB,MAAA,GAAS,CAAA;AAC/B,MAAA,wBAAA,GAA2B,CAAA;AAC3B,MAAA,eAAA,CAAgB,QAAQ,CAAA;AACxB,MAAA,eAAA,CAAgB,YAAY,CAAA;AAAA,IAC9B,CAAA;AAEA,IAAA,mBAAA,GAAsB,WAAW,MAAM;AACrC,MAAA,IAAI,QAAA,CAAS,UAAA,KAAeA,mBAAAA,CAAU,IAAA,EAAM;AAC1C,QAAA;AAAA,MACF;AACA,MAAA,eAAA,EAAgB;AAAA,IAClB,CAAA,EAAG,KAAK,qBAAqB,CAAA;AAE7B,IAAA,YAAA,CAAa,EAAA,CAAG,SAAA,EAAW,CAAC,IAAA,EAAyB,QAAA,KAAsB;AACzE,MAAA,MAAM,YAAA,GAAe,IAAA;AAErB,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,MAAM,OAAA,GAAU,wBAAwB,IAAI,CAAA;AAC5C,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,MAAM,iBAAA,GAAoB,kCAAkC,OAAO,CAAA;AACnE,UAAA,IAAI,iBAAA,EAAmB;AACrB,YAAA,IAAA,CAAK,IAAA,CAAK,YAAA,CAAa,uBAAA,CAAwB,SAAA,EAAW,iBAAiB,CAAA;AAAA,UAC7E;AAEA,UAAA,MAAM,qBAAA,GAAwB,0BAA0B,OAAO,CAAA;AAC/D,UAAA,IAAI,0BAA0B,IAAA,EAAM;AAClC,YAAA,6BAAA,CAA8B,IAAI,qBAAqB,CAAA;AAAA,UACzD;AAEA,UAAA,MAAM,mBAAA,GAAsB,wBAAwB,OAAO,CAAA;AAC3D,UAAA,IAAI,mBAAA,EAAqB;AACvB,YAAA,mCAAA,CAAoC,GAAA;AAAA,cAClC,mBAAA,CAAoB,EAAA;AAAA,cACpB,mBAAA,CAAoB;AAAA,aACtB;AAAA,UACF;AAEA,UAAA,MAAM,mBAAA,GAAsB,uBAAA,CAAwB,OAAA,EAAS,2BAA2B,CAAA;AACxF,UAAA,IAAI,mBAAA,EAAqB;AACvB,YAAA,IAAA,CAAK,IAAA,CAAK,YAAA,CAAa,uBAAA,CAAwB,SAAA,EAAW,mBAAmB,CAAA;AAAA,UAC/E;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,QAAA,CAAS,UAAA,KAAeA,mBAAAA,CAAU,IAAA,EAAM;AAC1C,QAAA,QAAA,CAAS,IAAA,CAAK,YAAA,EAAc,EAAE,MAAA,EAAQ,UAAU,CAAA;AAChD,QAAA;AAAA,MACF;AACA,MAAA,IAAI,QAAA,CAAS,UAAA,KAAeA,mBAAAA,CAAU,UAAA,EAAY;AAChD,QAAA,eAAA,EAAgB;AAChB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,SAAA,GAAY,iBAAiB,YAAY,CAAA;AAC/C,MAAA,IAAI,wBAAA,GAA2B,SAAA,GAAY,IAAA,CAAK,2BAAA,EAA6B;AAC3E,QAAA,eAAA,EAAgB;AAChB,QAAA;AAAA,MACF;AACA,MAAA,qBAAA,CAAsB,IAAA,CAAK,EAAE,IAAA,EAAM,YAAA,EAAc,UAAU,CAAA;AAC3D,MAAA,wBAAA,IAA4B,SAAA;AAAA,IAC9B,CAAC,CAAA;AAED,IAAA,QAAA,CAAS,EAAA,CAAG,QAAQ,MAAM;AACxB,MAAA,IAAI,mBAAA,EAAqB;AACvB,QAAA,YAAA,CAAa,mBAAmB,CAAA;AAChC,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB;AACA,MAAA,KAAA,MAAW,cAAA,IAAkB,qBAAA,CAAsB,MAAA,CAAO,CAAC,CAAA,EAAG;AAC5D,QAAA,QAAA,CAAS,KAAK,cAAA,CAAe,IAAA,EAAM,EAAE,MAAA,EAAQ,cAAA,CAAe,UAAU,CAAA;AAAA,MACxE;AACA,MAAA,wBAAA,GAA2B,CAAA;AAAA,IAC7B,CAAC,CAAA;AAED,IAAA,QAAA,CAAS,EAAA,CAAG,SAAA,EAAW,CAAC,IAAA,EAAyB,QAAA,KAAsB;AACrE,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,MAAM,OAAA,GAAU,wBAAwB,IAAI,CAAA;AAC5C,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,MAAM,eAAA,GAAkB,8BAAA;AAAA,YACtB,OAAA;AAAA,YACA;AAAA,WACF;AACA,UAAA,IAAI,eAAA,EAAiB;AACnB,YAAA,IAAA,CAAK,IAAA,CAAK,YAAA,CAAa,uBAAA,CAAwB,SAAA,EAAW,eAAe,CAAA;AAAA,UAC3E;AAEA,UAAA,MAAM,cAAA,GAAiB,sBAAA;AAAA,YACrB,OAAA;AAAA,YACA;AAAA,WACF;AACA,UAAA,IAAI,cAAA,EAAgB;AAClB,YAAA,2BAAA,CAA4B,GAAA,CAAI,cAAA,CAAe,SAAA,EAAW,cAAA,CAAe,QAAQ,CAAA;AAAA,UACnF;AAEA,UAAA,MAAM,iBAAA,GAAoB,4BAA4B,OAAO,CAAA;AAC7D,UAAA,IAAI,iBAAA,EAAmB;AACrB,YAAA,2BAAA,CAA4B,OAAO,iBAAiB,CAAA;AAAA,UACtD;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,YAAA,CAAa,UAAA,KAAeA,mBAAAA,CAAU,IAAA,EAAM;AAC9C,QAAA,YAAA,CAAa,IAAA,CAAK,IAAA,EAAM,EAAE,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC9C;AAAA,IACF,CAAC,CAAA;AAED,IAAA,YAAA,CAAa,EAAA,CAAG,SAAS,eAAe,CAAA;AACxC,IAAA,YAAA,CAAa,EAAA,CAAG,SAAS,eAAe,CAAA;AACxC,IAAA,QAAA,CAAS,EAAA,CAAG,SAAS,eAAe,CAAA;AACpC,IAAA,QAAA,CAAS,EAAA,CAAG,SAAS,eAAe,CAAA;AAAA,EACtC;AACF,CAAA;AAUA,SAAS,wBAAwB,IAAA,EAA0D;AACzF,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,eAAA,CAAgB,IAAI,CAAC,CAAA;AAC/C,IAAA,OAAO,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,IAAA;AAAA,EACzD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,0BAA0B,OAAA,EAAkD;AACnF,EAAA,OAAO,OAAA,CAAQ,WAAW,qBAAA,IAAyB,OAAO,QAAQ,EAAA,KAAO,QAAA,GACrE,QAAQ,EAAA,GACR,IAAA;AACN;AAEA,SAAS,8BAAA,CACP,SACA,iBAAA,EACe;AACf,EAAA,IAAI,OAAO,QAAQ,EAAA,KAAO,QAAA,IAAY,CAAC,iBAAA,CAAkB,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,iBAAA,CAAkB,MAAA,CAAO,QAAQ,EAAE,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,QAAQ,MAAA,EAAQ,QAAA;AACjC,EAAA,OAAO,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,IAAI,QAAA,GAAW,IAAA;AAC1E;AAEA,SAAS,kCAAkC,OAAA,EAAkD;AAC3F,EAAA,MAAM,WACJ,OAAA,CAAQ,MAAA,KAAW,uBAAA,GAA0B,OAAA,CAAQ,QAAQ,QAAA,GAAW,MAAA;AAC1E,EAAA,OAAO,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,IAAI,QAAA,GAAW,IAAA;AAC1E;AAEA,SAAS,wBAAwB,OAAA,EAGxB;AACP,EAAA,IAAI,QAAQ,MAAA,KAAW,uBAAA,IAA2B,OAAO,OAAA,CAAQ,OAAO,QAAA,EAAU;AAChF,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,QAAQ,MAAA,EAAQ,QAAA;AACjC,EAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,CAAS,WAAW,CAAA,EAAG;AACzD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO;AAAA,IACL,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ;AAAA,GACF;AACF;AAEA,SAAS,sBAAA,CACP,SACA,gBAAA,EAIO;AACP,EAAA,IAAI,OAAO,OAAA,CAAQ,EAAA,KAAO,QAAA,EAAU;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA;AAChD,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,gBAAA,CAAiB,MAAA,CAAO,QAAQ,EAAE,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAA,EAAQ,SAAA;AAClC,EAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,SAAA,CAAU,WAAW,CAAA,EAAG;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,uBAAA,CACP,SACA,2BAAA,EACe;AACf,EAAA,MAAM,YAAY,OAAA,CAAQ,SAAA;AAC1B,EAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,SAAA,CAAU,WAAW,CAAA,EAAG;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IACE,CAAC,OAAA,CAAQ,MAAA,IACR,CAAC,QAAQ,MAAA,CAAO,UAAA,CAAW,QAAQ,CAAA,IAAK,CAAC,OAAA,CAAQ,MAAA,CAAO,UAAA,CAAW,OAAO,CAAA,EAC3E;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,2BAAA,CAA4B,GAAA,CAAI,SAAS,CAAA,IAAK,IAAA;AACvD;AAEA,SAAS,4BAA4B,OAAA,EAAkD;AACrF,EAAA,IAAI,OAAA,CAAQ,WAAW,2BAAA,EAA6B;AAClD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAA,EAAQ,SAAA;AAClC,EAAA,OAAO,OAAO,SAAA,KAAc,QAAA,IAAY,SAAA,CAAU,MAAA,GAAS,IAAI,SAAA,GAAY,IAAA;AAC7E;AAEA,SAAS,gBAAgB,IAAA,EAAiC;AACxD,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,SAAS,MAAM,CAAA;AAAA,EAC1C;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA,CAAE,SAAS,MAAM,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,IAAA,CAAK,SAAS,MAAM,CAAA;AAC7B;AAEA,SAAS,iBAAiB,IAAA,EAAiC;AACzD,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,OAAO,MAAA,CAAO,WAAW,IAAI,CAAA;AAAA,EAC/B;AACA,EAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA,CAAK,OAAO,CAAC,KAAA,EAAO,UAAU,KAAA,GAAQ,KAAA,CAAM,YAAY,CAAC,CAAA;AAAA,EAClE;AACA,EAAA,OAAO,IAAA,CAAK,UAAA;AACd;AAEA,SAAS,gBAAgB,MAAA,EAA+B;AACtD,EAAA,IAAI;AACF,IAAA,MAAA,CAAO,KAAA,EAAM;AAAA,EACf,CAAA,CAAA,MAAQ;AAAA,EAAC;AACX;;;ACzUA,IAAM,oCAAA,GAAuC,GAAA;AActC,IAAM,kBAAN,MAAsB;AAAA,EACV,IAAA;AAAA,EACT,KAAA,GAA+B,IAAA;AAAA,EAC/B,OAAA,GAAU,KAAA;AAAA,EACV,cAAA,GAA8B,IAAA;AAAA,EAC9B,iBAAA,GAAoB,EAAA;AAAA,EACpB,YAAA,GAAe,KAAA;AAAA,EACN,cAAA,uBAAqB,GAAA,EAA8B;AAAA,EACnD,cAAA,uBAAqB,OAAA,EAAsB;AAAA,EAC3C,iBAAA,uBAAwB,GAAA,EAAsB;AAAA,EACvD,mBAAA,GAA2C,IAAA;AAAA,EAEnD,YAAY,IAAA,EAA2B;AACrC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,IAAA,KAAK,KAAK,SAAA,CAAU;AAAA,MAClB,YAAA,EAAc,IAAA;AAAA,MACd,eAAA,EAAiB;AAAA,KAClB,CAAA;AAAA,EACH;AAAA,EAEA,IAAA,GAAa;AACX,IAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AACf,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AACxB,MAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,IACf;AACA,IAAA,IAAA,CAAK,mBAAA,IAAsB;AAC3B,IAAA,IAAA,CAAK,mBAAA,GAAsB,IAAA;AAC3B,IAAA,KAAA,MAAW,OAAA,IAAW,IAAA,CAAK,iBAAA,CAAkB,MAAA,EAAO,EAAG;AACrD,MAAA,OAAA,EAAQ;AAAA,IACV;AACA,IAAA,IAAA,CAAK,kBAAkB,KAAA,EAAM;AAC7B,IAAA,IAAA,CAAK,eAAe,KAAA,EAAM;AAAA,EAC5B;AAAA,EAEQ,iBAAA,GAA0B;AAChC,IAAA,IAAI,KAAK,mBAAA,EAAqB;AAC5B,MAAA,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA;AACtD,MAAA,IAAA,CAAK,cAAc,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,KAAA,GAAQ,MAAM,CAAA;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,CAAC,IAAA,KAAe;AAC7B,MAAA,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA;AACtD,MAAA,IAAA,CAAK,cAAc,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,KAAA,GAAQ,MAAM,CAAA;AAC1D,MAAA,IAAA,CAAK,oBAAoB,IAAI,CAAA;AAC7B,MAAA,KAAK,KAAK,SAAA,CAAU;AAAA,QAClB,YAAA,EAAc,IAAA;AAAA,QACd,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,IACH,CAAA;AAEA,IAAA,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,EAAA,CAAG,MAAA,EAAQ,MAAM,CAAA;AAC1C,IAAA,IAAA,CAAK,sBAAsB,MAAM;AAC/B,MAAA,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AAAA,IAC7C,CAAA;AAEA,IAAA,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA;AACtD,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,KAAA,GAAQ,MAAM,CAAA;AAAA,EAC5D;AAAA,EAEQ,iBAAiB,KAAA,EAA8B;AACrD,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,KAAK,CAAA;AAE/B,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,KAAK,IAAA,CAAK,iBAAA,CAAkB,SAAQ,EAAG;AAC9D,MAAA,IAAI,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AACvB,QAAA;AAAA,MACF;AACA,MAAA,OAAA,EAAQ;AACR,MAAA,IAAA,CAAK,iBAAA,CAAkB,OAAO,IAAI,CAAA;AAClC,MAAA,IAAA,CAAK,cAAA,CAAe,OAAO,IAAI,CAAA;AAAA,IACjC;AAEA,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAA,CAAK,oBAAoB,IAAI,CAAA;AAAA,IAC/B;AAAA,EACF;AAAA,EAEQ,oBAAoB,IAAA,EAAkB;AAC5C,IAAA,IAAI,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA,EAAG;AACpC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,kBAAkB,MAAM;AAC5B,MAAA,KAAK,KAAK,SAAA,CAAU;AAAA,QAClB,YAAA,EAAc,KAAA;AAAA,QACd,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,IACH,CAAA;AACA,IAAA,MAAM,cAAc,MAAM;AACxB,MAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA,IAAI;AACnC,MAAA,IAAA,CAAK,iBAAA,CAAkB,OAAO,IAAI,CAAA;AAClC,MAAA,IAAA,CAAK,cAAA,CAAe,OAAO,IAAI,CAAA;AAC/B,MAAA,KAAK,KAAK,SAAA,CAAU;AAAA,QAClB,YAAA,EAAc,IAAA;AAAA,QACd,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,IACH,CAAA;AAEA,IAAA,IAAA,CAAK,EAAA,CAAG,SAAS,WAAW,CAAA;AAC5B,IAAA,IAAA,CAAK,EAAA,CAAG,oBAAoB,eAAe,CAAA;AAC3C,IAAA,IAAA,CAAK,EAAA,CAAG,QAAQ,eAAe,CAAA;AAC/B,IAAA,IAAA,CAAK,EAAA,CAAG,kBAAkB,eAAe,CAAA;AAEzC,IAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAA,EAAM,MAAM;AACrC,MAAA,IAAA,CAAK,GAAA,CAAI,SAAS,WAAW,CAAA;AAC7B,MAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,eAAe,CAAA;AAC5C,MAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,eAAe,CAAA;AAChC,MAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,eAAe,CAAA;AAAA,IAC5C,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,cAAc,SAAA,EAAyB;AAC7C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,IAAW,SAAA,GAAY,CAAA;AAC/C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AACxB,QAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,MACf;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,KAAA,GAAQ,YAAY,MAAM;AAC7B,MAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,OAAM,CAAE,MAAA;AAC1D,MAAA,KAAK,KAAK,SAAA,CAAU;AAAA,QAClB,cAAc,gBAAA,GAAmB,CAAA;AAAA,QACjC,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,IACH,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AAAA,EACrB;AAAA,EAEA,MAAc,UAAU,IAAA,EAGN;AAChB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,YAAA,EAAc;AACtC,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAEpB,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,KAAA,EAAM;AAC7C,MAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA;AAC3B,MAAA,IAAA,CAAK,aAAA,CAAc,MAAM,MAAM,CAAA;AAC/B,MAAA,MAAM,mBAAA,GAAsB,IAAA,CAAK,cAAA,IAAkB,KAAA,CAAM,CAAC,CAAA,IAAK,IAAA;AAE/D,MAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,GAAA;AAAA,QAC/B,KAAA,CAAM,GAAA,CAAI,OAAO,IAAA,EAAM,KAAA,KAAU;AAC/B,UAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,gBAAA,CAAiB,IAAA,EAAM;AAAA,YACjD,SAAS,IAAA,CAAK;AAAA,WACf,CAAA;AACD,UAAA,MAAM,aAAa,IAAA,CAAK,YAAA,GACpB,MAAM,IAAA,CAAK,cAAA,CAAe,IAAI,CAAA,GAC9B;AAAA,YACE,WAAW,IAAA,KAAS,mBAAA;AAAA,YACpB,UAAU,IAAA,KAAS;AAAA,WACrB;AAEJ,UAAA,OAAO;AAAA,YACL,IAAA;AAAA,YACA,KAAA;AAAA,YACA,UAAU,QAAA,CAAS,QAAA;AAAA,YACnB,GAAA,EAAK,KAAK,GAAA,EAAI;AAAA,YACd,OAAO,QAAA,CAAS,KAAA;AAAA,YAChB,WAAW,UAAA,CAAW,SAAA;AAAA,YACtB,UAAU,UAAA,CAAW;AAAA,WACvB;AAAA,QACF,CAAC;AAAA,OACH;AAEA,MAAA,MAAM,aAAa,IAAA,CAAK,cAAA;AAAA,QACtB,UAAA;AAAA,QACA,IAAA,CAAK,cAAA;AAAA,QACL,mBAAA;AAAA,QACA,IAAA,CAAK,kBAAkB,UAAU;AAAA,OACnC;AACA,MAAA,IAAI,UAAA,IAAc,UAAA,KAAe,IAAA,CAAK,cAAA,EAAgB;AACpD,QAAA,IAAA,CAAK,cAAA,GAAiB,UAAA;AACtB,QAAA,IAAA,CAAK,IAAA,CAAK,oBAAoB,UAAU,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QACtC,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,GAAI,MAAM,QAAA,KAAa,KAAA,CAAA,GAAY,EAAC,GAAI,EAAE,QAAA,EAAU,KAAA,CAAM,QAAA,EAAS;AAAA,QACnE,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,MAAA,EAAQ,UAAA,GAAa,KAAA,CAAM,IAAA,KAAS,UAAA,GAAa;AAAA,OACnD,CAAE,CAAA;AACF,MAAA,MAAM,iBAAiB,IAAA,CAAK,SAAA,CAAU,CAAC,GAAA,KAAQ,IAAI,MAAM,CAAA;AACzD,MAAA,MAAM,SAAA,GAAY,KAAK,SAAA,CAAU;AAAA,QAC/B,cAAA;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,MAAS;AAAA,UACvB,OAAO,GAAA,CAAI,KAAA;AAAA,UACX,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,OAAO,GAAA,CAAI,KAAA;AAAA,UACX,QAAQ,GAAA,CAAI;AAAA,SACd,CAAE;AAAA,OACH,CAAA;AAED,MAAA,IAAI,SAAA,KAAc,KAAK,iBAAA,EAAmB;AACxC,QAAA,IAAA,CAAK,iBAAA,GAAoB,SAAA;AACzB,QAAA,IAAA,CAAK,KAAK,aAAA,CAAc;AAAA,UACtB,IAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAc,gBAAA,CACZ,IAAA,EACA,OAAA,EAG6B;AAC7B,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA;AAC3C,IAAA,IAAI,MAAA,IAAU,CAAC,OAAA,CAAQ,OAAA,EAAS;AAC9B,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MAC1C,KAAK,KAAA,EAAM,CAAE,MAAM,MAAM,MAAA,EAAQ,SAAS,EAAE,CAAA;AAAA,MAC5C,KAAK,eAAA,CAAgB,IAAI,EAAE,KAAA,CAAM,MAAM,QAAQ,QAAQ;AAAA,KACxD,CAAA;AACD,IAAA,MAAM,YAAA,GAAe;AAAA,MACnB,KAAA;AAAA,MACA,UAAU,QAAA,IAAY;AAAA,KACxB;AACA,IAAA,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,IAAA,EAAM,YAAY,CAAA;AAC1C,IAAA,OAAO,YAAA;AAAA,EACT;AAAA,EAEA,MAAc,gBAAgB,IAAA,EAAoC;AAChE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA;AAC3C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,OAAA,EAAQ,CAAE,cAAc,IAAI,CAAA;AACnD,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAU,MAAM,GAAA,CAAI,IAAA,CAAK,sBAAsB,CAAA;AAKrD,MAAA,MAAM,QAAA,GAAW,QAAQ,UAAA,EAAY,QAAA;AACrC,MAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,CAAS,SAAS,CAAA,EAAG;AACvD,QAAA,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA;AACtC,QAAA,OAAO,QAAA;AAAA,MACT;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,MAAM,GAAA,CAAI,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAc,eAAe,IAAA,EAG1B;AACD,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAU,MAAM,IAAA,CAAK,QAAA,CAAS,OAAO;AAAA,QACzC,eAAA,EACE,WAKA,QAAA,EAAU,eAAA;AAAA,QACZ,QAAA,EAEI,UAAA,CAKA,QAAA,EAAU,QAAA,IAAW,IAAK;AAAA,OAChC,CAAE,CAAA;AAIF,MAAA,OAAO;AAAA,QACL,SAAA,EAAW,OAAO,eAAA,KAAoB,SAAA;AAAA,QACtC,QAAA,EAAU,OAAO,QAAA,KAAa;AAAA,OAChC;AAAA,IACF,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO;AAAA,QACL,SAAA,EAAW,KAAA;AAAA,QACX,QAAA,EAAU;AAAA,OACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAA,CACN,UAAA,EAMA,cAAA,EACA,YAAA,EACA,MAAA,EACa;AACb,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAEA,IAAA,MAAM,mBAAA,GAAsB,WAAW,MAAA,CAAO,CAAC,UAAU,KAAA,CAAM,SAAA,IAAa,MAAM,QAAQ,CAAA;AAC1F,IAAA,IAAI,mBAAA,CAAoB,WAAW,CAAA,EAAG;AACpC,MAAA,OAAO,mBAAA,CAAoB,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,IACzC;AAEA,IAAA,MAAM,eAAe,UAAA,CAAW,MAAA,CAAO,CAAC,KAAA,KAAU,MAAM,SAAS,CAAA;AACjE,IAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC7B,MAAA,OAAO,YAAA,CAAa,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,IAClC;AAEA,IAAA,MAAM,mBAAA,GAAsB,cAAA,GACvB,UAAA,CAAW,IAAA,CAAK,CAAC,UAAU,KAAA,CAAM,IAAA,KAAS,cAAc,CAAA,IAAK,IAAA,GAC9D,IAAA;AACJ,IAAA,IACE,mBAAA,KACE,mBAAA,CAAoB,MAAA,GAAS,CAAA,IAC7B,oBAAoB,SAAA,IACpB,mBAAA,CAAoB,QAAA,IACnB,YAAA,CAAa,SAAS,CAAA,IAAK,mBAAA,CAAoB,SAAA,IAChD,YAAA,CAAa,WAAW,CAAA,CAAA,EAC1B;AACA,MAAA,OAAO,cAAA;AAAA,IACT;AAEA,IAAA,MAAM,iBAAA,GAAoB,YAAA,GACrB,UAAA,CAAW,IAAA,CAAK,CAAC,UAAU,KAAA,CAAM,IAAA,KAAS,YAAY,CAAA,IAAK,IAAA,GAC5D,IAAA;AACJ,IAAA,IACE,iBAAA,KACE,mBAAA,CAAoB,MAAA,GAAS,CAAA,IAC7B,iBAAA,CAAkB,SAAA,IAClB,iBAAA,CAAkB,QAAA,IACjB,YAAA,CAAa,MAAA,GAAS,CAAA,IAAK,iBAAA,CAAkB,SAAA,CAAA,EAChD;AACA,MAAA,OAAO,YAAA;AAAA,IACT;AAEA,IAAA,IAAI,mBAAA,CAAoB,SAAS,CAAA,EAAG;AAClC,MAAA,OAAO,mBAAA,CAAoB,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,IACzC;AAEA,IAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,MAAA,OAAO,YAAA,CAAa,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,IAClC;AAEA,IAAA,IAAI,mBAAA,EAAqB;AACvB,MAAA,OAAO,mBAAA,CAAoB,IAAA;AAAA,IAC7B;AAEA,IAAA,IAAI,iBAAA,EAAmB;AACrB,MAAA,OAAO,iBAAA,CAAkB,IAAA;AAAA,IAC3B;AAEA,IAAA,OAAO,UAAA,CAAW,CAAC,CAAA,EAAG,IAAA,IAAQ,IAAA;AAAA,EAChC;AAAA,EAEQ,kBACN,UAAA,EAIgC;AAChC,IAAA,MAAM,SAAS,IAAA,CAAK,IAAA,CAAK,aAAa,uBAAA,CAAwB,IAAA,CAAK,KAAK,SAAS,CAAA;AACjF,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAU,WAAW,IAAA,CAAK,CAAC,UAAU,KAAA,CAAM,QAAA,KAAa,OAAO,QAAQ,CAAA;AAC7E,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,MAAA,CAAO,KAAK,oCAAA,EAAsC;AACjE,QAAA,IAAA,CAAK,KAAK,YAAA,CAAa,yBAAA,CAA0B,KAAK,IAAA,CAAK,SAAA,EAAW,OAAO,QAAQ,CAAA;AAAA,MACvF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAA,CAAK,KAAK,YAAA,CAAa,yBAAA,CAA0B,KAAK,IAAA,CAAK,SAAA,EAAW,OAAO,QAAQ,CAAA;AACrF,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAK;AAAA,EAC9B;AACF,CAAA;;;ACpaA,IAAM,wBAAA,GAA2B,GAAA;AACjC,IAAM,wBAAA,GAA2B,IAAA;AACjC,IAAM,iBAAA,GAAoB,EAAA;AAEnB,SAAS,qBAAqB,IAAA,EAGN;AAC7B,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,IAAA,CAAK,QAAQ,CAAA;AAChD,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,iBAAA,GAAoB,CAAA;AACxB,EAAA,IAAI,kBAAA,GAAqB,CAAA;AACzB,EAAA,KAAA,MAAW,aAAA,IAAiB,KAAK,cAAA,EAAgB;AAC/C,IAAA,MAAM,UAAA,GAAa,uBAAuB,aAAa,CAAA;AACvD,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,iBAAA,GAAoB,IAAA,CAAK,GAAA,CAAI,iBAAA,EAAmB,UAAA,CAAW,KAAK,CAAA;AAChE,IAAA,kBAAA,GAAqB,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,UAAA,CAAW,MAAM,CAAA;AAAA,EACrE;AAEA,EAAA,IACE,iBAAA,GAAoB,wBAAA,IACpB,kBAAA,GAAqB,wBAAA,EACrB;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,eAAe,IAAA,CAAK,GAAA;AAAA,IACxB,oBAAoB,QAAA,CAAS,KAAA;AAAA,IAC7B,qBAAqB,QAAA,CAAS;AAAA,GAChC;AACA,EAAA,IAAI,gBAAgB,CAAA,EAAG;AACrB,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,KAAA,IAAS,QAAA,CAAS,MAAA;AAC7C,EAAA,MAAM,aAAA,GAAgB,SAAA,GAAY,QAAA,CAAS,KAAA,GAAQ,QAAA,CAAS,MAAA;AAC5D,EAAA,MAAM,eAAA,GAAkB,SAAA,GAAY,QAAA,CAAS,MAAA,GAAS,QAAA,CAAS,KAAA;AAC/D,EAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,aAAA,GAAgB,YAAY,CAAA;AAChE,EAAA,MAAM,gBAAgB,cAAA,CAAe,IAAA,CAAK,MAAO,WAAA,GAAc,aAAA,GAAiB,eAAe,CAAC,CAAA;AAChG,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,SAAA,GACH,EAAE,KAAA,EAAO,WAAA,EAAa,MAAA,EAAQ,aAAA,EAAc,GAC5C,EAAE,KAAA,EAAO,aAAA,EAAe,MAAA,EAAQ,WAAA,EAAY;AAClD;AAEA,SAAS,kBAAkB,QAAA,EAAyD;AAClF,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,QAAA,CAAS,KAAK,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,QAAA,CAAS,MAAM,CAAA;AAC7C,EAAA,OAAO,KAAA,IAAS,MAAA,GAAS,EAAE,KAAA,EAAO,QAAO,GAAI,IAAA;AAC/C;AAEA,SAAS,uBAAuB,aAAA,EAAgE;AAC9F,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,aAAA,CAAc,KAAK,CAAA;AAChD,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,aAAA,CAAc,MAAM,CAAA;AAClD,EAAA,OAAO,KAAA,IAAS,MAAA,GAAS,EAAE,KAAA,EAAO,QAAO,GAAI,IAAA;AAC/C;AAEA,SAAS,eAAe,KAAA,EAA8B;AACpD,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACnC,EAAA,IAAI,aAAa,wBAAA,EAA0B;AACzC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,wBAAA,EAA0B,UAAU,CAAA;AACtD;AAEA,SAAS,gBAAgB,KAAA,EAAuB;AAC9C,EAAA,MAAM,QAAA,GACJ,KAAK,IAAA,CAAK,IAAA,CAAK,IAAI,wBAAA,EAA0B,KAAK,CAAA,GAAI,iBAAiB,CAAA,GAAI,iBAAA;AAC7E,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,wBAAA,EAA0B,QAAQ,CAAA;AACpD;AChFO,SAAS,kBAAkB,IAAA,EAQI;AACpC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,IACb,QAAA,EAAU,YAAA;AAAA,IACV,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,UAAU,IAAA,CAAK;AAAA,GACjB;AACF;AAEO,SAAS,iBAAiB,IAAA,EAIK;AACpC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA;AAAA,IACN,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,IACb,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,gBAAgB,IAAA,CAAK;AAAA,GACvB;AACF;AAEO,SAAS,mBAAmB,IAAA,EAGG;AACpC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,IACb,QAAQ,IAAA,CAAK;AAAA,GACf;AACF;AAEO,SAAS,kBAAkB,IAAA,EAGI;AACpC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,IACb,OAAO,IAAA,CAAK;AAAA,GACd;AACF;AAEO,SAAS,kBAAA,CACd,IACA,OAAA,EACM;AACN,EAAA,IAAI,EAAA,CAAG,UAAA,KAAeA,mBAAAA,CAAU,IAAA,EAAM;AACpC,IAAA;AAAA,EACF;AACA,EAAA,IAAI;AACF,IAAA,EAAA,CAAG,IAAA,CAAK,KAAK,SAAA,CAAU,OAAO,GAAG,EAAE,MAAA,EAAQ,OAAO,CAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AAAA,EAAC;AACX;AAEO,SAAS,uBAAuB,GAAA,EAAsD;AAC3F,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,MAAA,EAAQ,SAAS,eAAA,EAAiB;AACpC,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,WAAA,GAAc,wBAAA,CAAyB,MAAA,CAAO,WAAW,CAAA;AAC/D,IAAA,MAAM,YAAA,GAAe,wBAAA,CAAyB,MAAA,CAAO,YAAY,CAAA;AACjE,IAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,YAAA,KAAiB,IAAA,EAAM;AACjD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,eAAA;AAAA,MACN,WAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,yBAAyB,KAAA,EAA+B;AAC/D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACxD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACnC,EAAA,IAAI,aAAa,GAAA,EAAK;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAO,UAAU,CAAA;AACnC;;;AC9FA,IAAM,8BAAA,GAAiC,CAAA;AACvC,IAAM,oCAAA,GAAuC,GAAA;AAC7C,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,2BAAA,GAA8B,EAAA;AAgB7B,IAAM,qBAAN,MAAyB;AAAA,EACb,IAAA;AAAA,EACA,SAAA,uBAAgB,GAAA,EAAuC;AAAA,EAExE,YAAY,IAAA,EAA8B;AACxC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA,EAEA,YAAA,CAAa,WAAmB,EAAA,EAA2B;AACzD,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAS,CAAA;AAC3C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,GAAW,IAAI,yBAAA,CAA0B;AAAA,QACvC,SAAA;AAAA,QACA,YAAA,EAAc,KAAK,IAAA,CAAK,YAAA;AAAA,QACxB,MAAA,EAAQ,KAAK,IAAA,CAAK,MAAA;AAAA,QAClB,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,QACnB,oBAAA,EAAsB,KAAK,IAAA,CAAK,oBAAA;AAAA,QAChC,WAAW,MAAM;AACf,UAAA,IAAA,CAAK,SAAA,CAAU,OAAO,SAAS,CAAA;AAAA,QACjC;AAAA,OACD,CAAA;AACD,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAA,EAAW,QAAQ,CAAA;AAAA,IACxC;AAEA,IAAA,QAAA,CAAS,UAAU,EAAE,CAAA;AAAA,EACvB;AACF,CAAA;AAWA,IAAM,4BAAN,MAAgC;AAAA,EACb,IAAA;AAAA,EACA,OAAA,uBAAc,GAAA,EAAqB;AAAA,EACnC,mBAAA,uBAA0B,GAAA,EAAwC;AAAA,EAClE,eAAA;AAAA,EACT,OAAA,GAAkC,IAAA;AAAA,EAClC,OAAA,GAA0B,IAAA;AAAA,EAC1B,0BAAA,GAAkE,IAAA;AAAA,EAClE,OAAA,GAAiC,IAAA;AAAA,EACjC,UAAA,GAAgC,IAAA;AAAA,EAChC,iBAAA,GAEG,IAAA;AAAA,EACH,oBAAA,GAA4C,IAAA;AAAA,EAC5C,UAAA,GAA0B,IAAA;AAAA,EAC1B,cAAA,GAA2C,IAAA;AAAA,EAC3C,uBAAA,GAAyC,IAAA;AAAA,EACzC,oBAAA,GAA8C,IAAA;AAAA,EAC9C,QAAA,GAAiC,IAAA;AAAA,EACjC,OAAA,GAAU,KAAA;AAAA,EACV,SAAA,GAA2B,QAAQ,OAAA,EAAQ;AAAA,EAC3C,OAAA,GAAU,KAAA;AAAA,EACV,eAAA,GAAkB,CAAA;AAAA,EAClB,eAAA,GAAiC,IAAA;AAAA,EACjC,eAAA,GAGG,IAAA;AAAA,EAEX,YAAY,IAAA,EAAqC;AAC/C,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,GAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,MAAM,CAAC,CAAC,CAAA;AAAA,EAChF;AAAA,EAEA,UAAU,EAAA,EAA2B;AACnC,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,EAAA,CAAG,KAAA,CAAM,MAAM,6BAA6B,CAAA;AAC5C,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAI,EAAE,CAAA;AACnB,IAAA,IAAA,CAAK,mBAAA,CAAoB,IAAI,EAAA,EAAI;AAAA,MAC/B,mBAAA,EAAqB,IAAA;AAAA,MACrB,iBAAA,EAAmB,KAAA;AAAA,MACnB,kBAAA,EAAoB,IAAA;AAAA,MACpB,iBAAA,EAAmB;AAAA,KACpB,CAAA;AAED,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,kBAAA;AAAA,QACE,EAAA;AAAA,QACA,iBAAA,CAAkB;AAAA,UAChB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,GAAA,EAAK,KAAK,IAAA,CAAK,MAAA;AAAA,UACf,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,UACnB,UAAU,IAAA,CAAK;AAAA,SAChB;AAAA,OACH;AAAA,IACF;AACA,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,kBAAA;AAAA,QACE,EAAA;AAAA,QACA,gBAAA,CAAiB;AAAA,UACf,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,IAAA,EAAM,KAAK,eAAA,CAAgB,IAAA;AAAA,UAC3B,cAAA,EAAgB,KAAK,eAAA,CAAgB;AAAA,SACtC;AAAA,OACH;AAAA,IACF;AACA,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,qBAAA,CAAsB,EAAA,EAAI,KAAK,eAAe,CAAA;AAClE,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,IAAA,CAAK,aAAa,EAAE,CAAA;AACpB,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM;AACnB,MAAA,IAAA,CAAK,aAAa,EAAE,CAAA;AAAA,IACtB,CAAC,CAAA;AACD,IAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM;AACnB,MAAA,IAAA,CAAK,aAAa,EAAE,CAAA;AAAA,IACtB,CAAC,CAAA;AACD,IAAA,EAAA,CAAG,EAAA,CAAG,SAAA,EAAW,CAAC,GAAA,EAAc,QAAA,KAAsB;AACpD,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA;AAAA,MACF;AACA,MAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,aAAA,CAAc,GAAG,CAAC,CAAA;AACzD,MAAA,IAAI,OAAA,EAAS,SAAS,eAAA,EAAiB;AACrC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW;AAAA,QACf,OAAO,OAAA,CAAQ,WAAA;AAAA,QACf,QAAQ,OAAA,CAAQ;AAAA,OAClB;AACA,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,EAAE,CAAA;AACnD,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,YAAY,WAAA,CAAY,mBAAA;AAC9B,MAAA,IAAI,WAAW,KAAA,KAAU,QAAA,CAAS,SAAS,SAAA,EAAW,MAAA,KAAW,SAAS,MAAA,EAAQ;AAChF,QAAA;AAAA,MACF;AACA,MAAA,WAAA,CAAY,mBAAA,GAAsB,QAAA;AAClC,MAAA,IAAA,CAAK,gCAAA,EAAiC;AAAA,IACxC,CAAC,CAAA;AAED,IAAA,KAAK,KAAK,aAAA,EAAc;AAAA,EAC1B;AAAA,EAEQ,gCAAA,GAAyC;AAC/C,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,IAAc,CAAC,IAAA,CAAK,OAAA,IAAW,KAAK,OAAA,EAAS;AACrD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,KAAK,6BAAA,EAA8B;AACvD,IAAA,IAAI,WAAA,KAAgB,KAAK,uBAAA,EAAyB;AAChD,MAAA;AAAA,IACF;AAEA,IAAA,KAAK,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,UAAA,EAAY,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EACnF;AAAA,EAEQ,aAAa,EAAA,EAA2B;AAC9C,IAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,EAAE,CAAA;AACtB,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,EAAE,CAAA;AACnD,IAAA,IAAI,aAAa,iBAAA,EAAmB;AAClC,MAAA,YAAA,CAAa,YAAY,iBAAiB,CAAA;AAAA,IAC5C;AACA,IAAA,IAAA,CAAK,mBAAA,CAAoB,OAAO,EAAE,CAAA;AAClC,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,KAAS,CAAA,EAAG;AAC3B,MAAA,KAAK,KAAK,IAAA,EAAK;AACf,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,gCAAA,EAAiC;AAAA,EACxC;AAAA,EAEA,MAAc,aAAA,GAA+B;AAC3C,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,OAAA,EAAS;AAChC,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,OAAO,IAAA,CAAK,QAAA;AAAA,IACd;AAEA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,KAAA,EAAM,CACxB,KAAK,MAAM;AACV,MAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,QAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,MACjB;AAAA,IACF,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,IAClB,CAAC,CAAA;AAEH,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,QAAA;AAAA,IACb,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,gBAAA;AAAA,QACH,iBAAA,CAAkB;AAAA,UAChB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,KAAA,EAAO;AAAA,SACR;AAAA,OACH;AACA,MAAA,IAAA,CAAK,eAAA,CAAgB,MAAM,oBAAoB,CAAA;AAC/C,MAAA,MAAM,KAAK,IAAA,EAAK;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAc,KAAA,GAAuB;AACnC,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,cAAA,EAAe;AAC1C,IAAA,IAAA,CAAK,gBAAA;AAAA,MACH,kBAAA,CAAmB;AAAA,QACjB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,QACrB,MAAA,EAAQ;AAAA,OACT;AAAA,KACH;AAEA,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,6BAA6B,MAAM;AACtC,MAAA,IAAI,KAAK,OAAA,EAAS;AAChB,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,0BAAA,GAA6B,IAAA;AAClC,MAAA,IAAA,CAAK,gBAAA;AAAA,QACH,iBAAA,CAAkB;AAAA,UAChB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,KAAA,EAAO;AAAA,SACR;AAAA,OACH;AACA,MAAA,IAAA,CAAK,eAAA,CAAgB,MAAM,oBAAoB,CAAA;AAC/C,MAAA,KAAK,KAAK,IAAA,EAAK;AAAA,IACjB,CAAA;AACA,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,cAAA,EAAgB,IAAA,CAAK,0BAA0B,CAAA;AAEjE,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,IAAA;AAC1B,IAAA,IAAA,CAAK,cAAA,GAAiB,MAAM,mBAAA,CAAoB,OAAA,CAAQ,IAAI,CAAA;AAC5D,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,gBAAA;AAAA,QACH,iBAAA,CAAkB;AAAA,UAChB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,GAAA,EAAK,KAAK,IAAA,CAAK,MAAA;AAAA,UACf,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,UACnB,UAAU,IAAA,CAAK;AAAA,SAChB;AAAA,OACH;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB;AAAA,MACjC,gBAAgB,OAAA,CAAQ,OAAA;AAAA,MACxB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,MACrB,MAAA,EAAQ,iBAAA;AAAA,MACR,YAAA,EAAc,KAAK,IAAA,CAAK,YAAA;AAAA,MACxB,mBAAA,EAAqB,CAAC,IAAA,KAAS;AAC7B,QAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,QAAA,KAAK,KAAK,eAAA,CAAgB,IAAI,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,MACvD,CAAA;AAAA,MACA,aAAA,EAAe,CAAC,EAAE,IAAA,EAAM,gBAAe,KAAM;AAC3C,QAAA,IAAA,CAAK,eAAA,GAAkB,EAAE,IAAA,EAAM,cAAA,EAAe;AAC9C,QAAA,IAAA,CAAK,gBAAA;AAAA,UACH,gBAAA,CAAiB;AAAA,YACf,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,YACrB,IAAA;AAAA,YACA;AAAA,WACD;AAAA,SACH;AAAA,MACF;AAAA,KACD,CAAA;AACD,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAEnB,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,OAAA,CAAQ,IAAI,CAAA;AACvC,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,gBAAA;AAAA,MACH,kBAAA,CAAmB;AAAA,QACjB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,QACrB,MAAA,EAAQ;AAAA,OACT;AAAA,KACH;AAAA,EACF;AAAA,EAEQ,eAAA,CACN,IAAA,EACA,OAAA,GAEI,EAAC,EACU;AACf,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,SAAA,CACnB,KAAA,CAAM,MAAM,MAAS,CAAA,CACrB,IAAA,CAAK,MAAM,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,OAAO,CAAC,CAAA;AAC5C,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,MAAc,UAAA,CACZ,IAAA,EACA,OAAA,GAEI,EAAC,EACU;AACf,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,gBAAA,GAAmB,KAAK,6BAAA,EAA8B;AAC5D,IAAA,IACE,CAAC,OAAA,CAAQ,KAAA,IACT,IAAA,CAAK,UAAA,KAAe,QACpB,IAAA,CAAK,UAAA,IACL,IAAA,CAAK,uBAAA,KAA4B,gBAAA,EACjC;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,IACnD;AACA,IAAA,MAAM,aAAA,GAAgB,KAAK,0BAAA,EAA2B;AACtD,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,IAAA,IAAA,CAAK,uBAAA,GAA0B,gBAAA;AAC/B,IAAA,IAAA,CAAK,cAAA,GAAiB,MAAM,mBAAA,CAAoB,IAAI,CAAA;AACpD,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,gBAAA;AAAA,QACH,iBAAA,CAAkB;AAAA,UAChB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,GAAA,EAAK,KAAK,IAAA,CAAK,MAAA;AAAA,UACf,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,UACnB,UAAU,IAAA,CAAK;AAAA,SAChB;AAAA,OACH;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,aAAA,CAAc,IAAI,CAAA;AACnD,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,UAAA,CAAW,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAC/C,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAElB,IAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAAiE;AAChF,MAAA,KAAK,IAAA,CAAK,sBAAsB,KAAK,CAAA;AAAA,IACvC,CAAA;AACA,IAAA,IAAA,CAAK,iBAAA,GAAoB,OAAA;AAEzB,IAAA,UAAA,CAAW,EAAA,CAAG,wBAAwB,OAAO,CAAA;AAC7C,IAAA,MAAM,UAAA,CAAW,KAAK,aAAa,CAAA;AACnC,IAAA,MAAM,UAAA,CAAW,KAAK,sBAAA,EAAwB;AAAA,MAC5C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,MACnB,aAAA,EAAe,CAAA;AAAA,MACf,GAAI,aAAA,GACA;AAAA,QACE,UAAU,aAAA,CAAc,KAAA;AAAA,QACxB,WAAW,aAAA,CAAc;AAAA,UAE3B;AAAC,KACN,CAAA;AACD,IAAA,IAAA,CAAK,6BAAA,CAA8B,MAAM,UAAU,CAAA;AACnD,IAAA,KAAK,KAAK,gBAAA,CAAiB,UAAU,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EAC9D;AAAA,EAEA,MAAc,cAAA,GAIX;AACD,IAAA,MAAM,QAAA,GAAW,MAAM,uBAAA,CAAwB,IAAA,CAAK,KAAK,SAAS,CAAA;AAClE,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,gBAAA,CAAkB,CAAA;AAAA,IAC7E;AAEA,IAAA,MAAM,OAAA,GAAU,MAAM,gCAAA,CAAiC;AAAA,MACrD,KAAK,QAAA,CAAS;AAAA,KACf,CAAA;AACD,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,QAAA,EAAS,CAAE,CAAC,CAAA;AACpC,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,MAChF;AAEA,MAAA,MAAM,IAAA,GAAO,QAAQ,KAAA,EAAM,CAAE,CAAC,CAAA,IAAM,MAAM,QAAQ,OAAA,EAAQ;AAC1D,MAAA,OAAO;AAAA,QACL,OAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,mCAAA,CAAoC,OAAO,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AACxE,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsB,KAAA,EAGlB;AAChB,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AACxB,IAAA,IAAI,CAAC,UAAA,IAAc,IAAA,CAAK,OAAA,EAAS;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,MAAM,QAAQ,CAAA;AACpD,IAAA,IAAA,CAAK,eAAA,GAAkB,WAAA;AAEvB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,eAAA,IAAmB,GAAA,GAAM,KAAK,eAAA,CAAgB,CAAA;AAC/E,IAAA,IAAI,YAAY,CAAA,EAAG;AACjB,MAAA,IAAA,CAAK,oBAAA,CAAqB;AAAA,QACxB,UAAA;AAAA,QACA,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB;AAAA,OACD,CAAA;AACD,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,yBAAyB,IAAA,EAAM;AACtC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,oBAAA,GAAuB,WAAW,MAAM;AAC3C,MAAA,IAAA,CAAK,oBAAA,GAAuB,IAAA;AAC5B,MAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,UAAA,KAAe,UAAA,EAAY;AAClD,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,oBAAA,CAAqB;AAAA,QACxB,UAAA;AAAA,QACA,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB;AAAA,OACD,CAAA;AAAA,IACH,GAAG,OAAO,CAAA;AAAA,EACZ;AAAA,EAEQ,qBAAqB,IAAA,EAIpB;AACP,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,EAAI;AAChC,IAAA,IAAA,CAAK,cAAA,CAAe,KAAK,WAAW,CAAA;AACpC,IAAA,KAAK,IAAA,CAAK,UAAA,CACP,IAAA,CAAK,yBAAA,EAA2B,EAAE,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,CAAA,CAC7D,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EAC1B;AAAA,EAEQ,eAAe,WAAA,EAA2B;AAChD,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,IAAI,CAAC,IAAA,CAAK,qBAAA,CAAsB,MAAA,EAAQ,WAAW,CAAA,EAAG;AACpD,QAAA,IAAA,CAAK,aAAa,MAAM,CAAA;AAAA,MAC1B;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,KAAS,CAAA,EAAG;AAC3B,MAAA,KAAK,KAAK,IAAA,EAAK;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,qBAAA,CAAsB,QAAyB,WAAA,EAA8B;AACnF,IAAA,IAAI,MAAA,CAAO,UAAA,KAAeA,mBAAAA,CAAU,IAAA,EAAM;AACxC,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,MAAM,CAAA;AACvD,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,WAAA,CAAY,kBAAA,GAAqB,WAAA;AACjC,IAAA,IAAA,CAAK,yBAAyB,MAAM,CAAA;AACpC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEQ,yBAAyB,MAAA,EAA+B;AAC9D,IAAA,IAAI,MAAA,CAAO,UAAA,KAAeA,mBAAAA,CAAU,IAAA,EAAM;AACxC,MAAA,IAAA,CAAK,aAAa,MAAM,CAAA;AACxB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,MAAM,CAAA;AACvD,IAAA,IAAI,CAAC,WAAA,IAAe,WAAA,CAAY,iBAAA,IAAqB,CAAC,YAAY,kBAAA,EAAoB;AACpF,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,YAAY,iBAAA,EAAmB;AACjC,MAAA,YAAA,CAAa,YAAY,iBAAiB,CAAA;AAC1C,MAAA,WAAA,CAAY,iBAAA,GAAoB,IAAA;AAAA,IAClC;AAEA,IAAA,IAAI,MAAA,CAAO,cAAA,GAAiB,IAAA,CAAK,IAAA,CAAK,oBAAA,EAAsB;AAC1D,MAAA,WAAA,CAAY,iBAAA,GAAoB,WAAW,MAAM;AAC/C,QAAA,WAAA,CAAY,iBAAA,GAAoB,IAAA;AAChC,QAAA,IAAA,CAAK,yBAAyB,MAAM,CAAA;AAAA,MACtC,GAAG,2BAA2B,CAAA;AAC9B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,cAAc,WAAA,CAAY,kBAAA;AAChC,IAAA,WAAA,CAAY,kBAAA,GAAqB,IAAA;AACjC,IAAA,WAAA,CAAY,iBAAA,GAAoB,IAAA;AAEhC,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,KAAK,WAAA,EAAa,EAAE,QAAQ,IAAA,EAAK,EAAG,CAAC,KAAA,KAAkB;AAC5D,QAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,MAAM,CAAA;AAC7D,QAAA,IAAI,iBAAA,EAAmB;AACrB,UAAA,iBAAA,CAAkB,iBAAA,GAAoB,KAAA;AAAA,QACxC;AACA,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,IAAA,CAAK,aAAa,MAAM,CAAA;AACxB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,yBAAyB,MAAM,CAAA;AAAA,MACtC,CAAC,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AACN,MAAA,WAAA,CAAY,iBAAA,GAAoB,KAAA;AAChC,MAAA,IAAA,CAAK,aAAa,MAAM,CAAA;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,iBAAiB,OAAA,EAAyD;AAChF,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,kBAAA,CAAmB,QAAQ,OAAO,CAAA;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,eAAA,CAAgB,MAAc,MAAA,EAAsB;AAC1D,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,IAAI;AACF,QAAA,MAAA,CAAO,KAAA,CAAM,MAAM,MAAM,CAAA;AAAA,MAC3B,CAAA,CAAA,MAAQ;AAAA,MAAC;AAAA,IACX;AACA,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,IAAA,KAAA,MAAW,WAAA,IAAe,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAO,EAAG;AAC3D,MAAA,IAAI,YAAY,iBAAA,EAAmB;AACjC,QAAA,YAAA,CAAa,YAAY,iBAAiB,CAAA;AAAA,MAC5C;AAAA,IACF;AACA,IAAA,IAAA,CAAK,oBAAoB,KAAA,EAAM;AAAA,EACjC;AAAA,EAEA,MAAc,IAAA,GAAsB;AAClC,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AAEf,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,QAAQ,IAAA,EAAK;AAClB,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,IACjB;AACA,IAAA,MAAM,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,MAAM,MAAS,CAAA;AAC1C,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,IAAA,MAAM,6BAA6B,IAAA,CAAK,0BAAA;AACxC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,0BAAA,GAA6B,IAAA;AAClC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI,0BAAA,EAA4B;AAC9B,QAAA,OAAA,CAAQ,GAAA,CAAI,gBAAgB,0BAA0B,CAAA;AAAA,MACxD;AACA,MAAA,MAAM,mCAAA,CAAoC,OAAO,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,IAC1E;AACA,IAAA,IAAA,CAAK,KAAK,SAAA,EAAU;AAAA,EACtB;AAAA,EAEA,MAAc,cAAA,GAAgC;AAC5C,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AACxB,IAAA,MAAM,UAAU,IAAA,CAAK,iBAAA;AACrB,IAAA,MAAM,uBAAuB,IAAA,CAAK,oBAAA;AAElC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAA;AACzB,IAAA,IAAA,CAAK,oBAAA,GAAuB,IAAA;AAC5B,IAAA,IAAA,CAAK,uBAAA,GAA0B,IAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,yBAAyB,IAAA,EAAM;AACtC,MAAA,YAAA,CAAa,KAAK,oBAAoB,CAAA;AACtC,MAAA,IAAA,CAAK,oBAAA,GAAuB,IAAA;AAAA,IAC9B;AAEA,IAAA,oBAAA,IAAuB;AAEvB,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,UAAA,CAAW,GAAA,CAAI,wBAAwB,OAAO,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,WAAW,IAAA,CAAK,qBAAqB,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAClE,IAAA,MAAM,UAAA,CAAW,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EACjD;AAAA,EAEQ,6BAAA,CAA8B,MAAY,UAAA,EAA8B;AAC9E,IAAA,IAAA,CAAK,oBAAA,IAAuB;AAE5B,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,KAAK,KAAK,gBAAA,CAAiB,IAAA,EAAM,UAAU,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,IACpE,CAAA;AAEA,IAAA,IAAA,CAAK,EAAA,CAAG,oBAAoB,OAAO,CAAA;AACnC,IAAA,IAAA,CAAK,EAAA,CAAG,QAAQ,OAAO,CAAA;AACvB,IAAA,IAAA,CAAK,EAAA,CAAG,kBAAkB,OAAO,CAAA;AACjC,IAAA,IAAA,CAAK,uBAAuB,MAAM;AAChC,MAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,OAAO,CAAA;AACpC,MAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,OAAO,CAAA;AACxB,MAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,OAAO,CAAA;AAAA,IACpC,CAAA;AAAA,EACF;AAAA,EAEA,MAAc,gBAAA,CAAiB,IAAA,EAAY,UAAA,EAAuC;AAChF,IAAA,IAAI,KAAK,OAAA,IAAW,IAAA,CAAK,eAAe,UAAA,IAAc,IAAA,CAAK,eAAe,IAAA,EAAM;AAC9E,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,mBAAA,CAAoB,IAAI,CAAA;AAC/C,IAAA,IAAI,YAAY,IAAA,CAAK,UAAA,KAAe,UAAA,IAAc,IAAA,CAAK,eAAe,IAAA,EAAM;AAC1E,MAAA,IAAA,CAAK,cAAA,GAAiB,QAAA;AACtB,MAAA,IAAA,CAAK,gBAAA;AAAA,QACH,iBAAA,CAAkB;AAAA,UAChB,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,UACrB,GAAA,EAAK,KAAK,IAAA,CAAK,MAAA;AAAA,UACf,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,UACnB;AAAA,SACD;AAAA,OACH;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,OAAA,IAAW,IAAA,CAAK,eAAe,UAAA,IAAc,IAAA,CAAK,eAAe,IAAA,EAAM;AAC9E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAAA,EACxC;AAAA,EAEA,MAAc,iBAAiB,UAAA,EAAuC;AACpE,IAAA,IAAI,SAAA,GAAqB,IAAA;AAEzB,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,8BAAA,EAAgC,WAAW,CAAA,EAAG;AAC7E,MAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,UAAA,KAAe,UAAA,EAAY;AAClD,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,mBAAA,CAAoB,UAAU,CAAA;AAChE,QAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,UAAA,KAAe,UAAA,EAAY;AAClD,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,cAAA,EAAgB,QAAQ,CAAA;AACxD,QAAA,IAAA,CAAK,eAAA,GAAkB,WAAA;AACvB,QAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,EAAI;AAChC,QAAA,IAAA,CAAK,eAAe,WAAW,CAAA;AAC/B,QAAA;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,SAAA,GAAY,KAAA;AAAA,MACd;AAEA,MAAA,IAAI,UAAU,8BAAA,EAAgC;AAC5C,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,oCAAoC,CAAC,CAAA;AAAA,MAC1F;AAAA,IACF;AAEA,IAAA,IAAI,qBAAqB,KAAA,EAAO;AAC9B,MAAA,MAAM,SAAA;AAAA,IACR;AAEA,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAAA,EAEA,MAAc,oBAAoB,UAAA,EAAyC;AACzE,IAAA,MAAM,aAAA,GAAgB;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,KAAK,IAAA,CAAK,OAAA;AAAA,MACnB,gBAAA,EAAkB;AAAA,KACpB;AACA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAU,MAAM,UAAA,CAAW,IAAA,CAAK,0BAA0B,aAAa,CAAA;AAG7E,MAAA,IAAI,MAAA,IAAU,OAAO,MAAA,CAAO,IAAA,KAAS,YAAY,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,EAAG;AACvE,QAAA,OAAO,MAAA,CAAO,IAAA;AAAA,MAChB;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAAC;AAET,IAAA,MAAM,cAAA,GAAkB,MAAM,UAAA,CAAW,IAAA,CAAK,wBAAA,EAA0B;AAAA,MACtE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,KAAK,IAAA,CAAK;AAAA,KACpB,CAAA;AAGD,IAAA,IACE,CAAC,kBACD,OAAO,cAAA,CAAe,SAAS,QAAA,IAC/B,cAAA,CAAe,IAAA,CAAK,MAAA,KAAW,CAAA,EAC/B;AACA,MAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,IAChE;AAEA,IAAA,OAAO,cAAA,CAAe,IAAA;AAAA,EACxB;AAAA,EAEQ,0BAAA,GAAyD;AAC/D,IAAA,IAAI,KAAK,OAAA,CAAQ,IAAA,KAAS,CAAA,IAAK,CAAC,KAAK,cAAA,EAAgB;AACnD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,iBAAwC,EAAC;AAC/C,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,OAAA,EAAS;AACjC,MAAA,MAAM,gBAAgB,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,MAAM,GAAG,mBAAA,IAAuB,IAAA;AACnF,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,cAAA,CAAe,KAAK,aAAa,CAAA;AAAA,IACnC;AAEA,IAAA,OAAO,oBAAA,CAAqB;AAAA,MAC1B,UAAU,IAAA,CAAK,cAAA;AAAA,MACf;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEQ,6BAAA,GAA+C;AACrD,IAAA,MAAM,IAAA,GAAO,KAAK,0BAAA,EAA2B;AAC7C,IAAA,OAAO,OAAO,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,MAAM,CAAA,CAAA,GAAK,IAAA;AAAA,EACjD;AACF,CAAA;AAEA,eAAe,oBAAoB,IAAA,EAA+C;AAChF,EAAA,MAAM,MAAM,MAAM,IAAA,CAAK,OAAA,EAAQ,CAAE,cAAc,IAAI,CAAA;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAU,MAAM,GAAA,CAAI,IAAA,CAAK,uBAAuB,CAAA;AAkBtD,IAAA,MAAM,UAAA,GAAa;AAAA,MACjB,MAAA,EAAQ,iBAAA;AAAA,MACR,MAAA,EAAQ,iBAAA;AAAA,MACR,MAAA,EAAQ,cAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AAEA,IAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,MAAA,MAAM,KAAA,GAAQ,0BAAA,CAA2B,SAAA,EAAW,WAAW,CAAA;AAC/D,MAAA,MAAM,MAAA,GAAS,0BAAA,CAA2B,SAAA,EAAW,YAAY,CAAA;AACjE,MAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,MAAA,KAAW,IAAA,EAAM;AACrC,QAAA,OAAO,EAAE,OAAO,MAAA,EAAO;AAAA,MACzB;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,YAAA,GAAe,KAAK,YAAA,EAAa;AACvC,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,KAAA,GAAQ,0BAAA,CAA2B,YAAA,CAAa,KAAK,CAAA;AAC3D,IAAA,MAAM,MAAA,GAAS,0BAAA,CAA2B,YAAA,CAAa,MAAM,CAAA;AAC7D,IAAA,OAAO,UAAU,IAAA,IAAQ,MAAA,KAAW,OAAO,EAAE,KAAA,EAAO,QAAO,GAAI,IAAA;AAAA,EACjE,CAAA,SAAE;AACA,IAAA,MAAM,GAAA,CAAI,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EAC1C;AACF;AAEA,SAAS,2BAA2B,KAAA,EAA+B;AACjE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACxD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACnC,EAAA,IAAI,aAAa,GAAA,EAAK;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAO,UAAU,CAAA;AACnC;AAEA,SAAS,cAAc,GAAA,EAAsB;AAC3C,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,IAAI,eAAe,WAAA,EAAa;AAC9B,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,SAAS,MAAM,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACtB,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,CAAE,SAAS,MAAM,CAAA;AAAA,EAC3C;AACA,EAAA,OAAO,GAAA,CAAI,SAAS,MAAM,CAAA;AAC5B;AAEA,eAAe,iCAAiC,KAAA,EAAmD;AACjG,EAAA,MAAM,EAAE,gCAAA,EAAkC,OAAA,EAAQ,GAChD,MAAM,OAAO,8BAA8B,CAAA;AAC7C,EAAA,OAAO,QAAQ,KAAK,CAAA;AACtB;AAEA,eAAe,oCAAoC,OAAA,EAAiC;AAClF,EAAA,MAAM,EAAE,mCAAA,EAAqC,UAAA,EAAW,GACtD,MAAM,OAAO,8BAA8B,CAAA;AAC7C,EAAA,MAAM,WAAW,OAAO,CAAA;AAC1B;;;AC9zBA,IAAM,eAAA,GAAkB,EAAA;AACxB,IAAM,eAAA,GAAkB,EAAA;AACxB,IAAM,kCAAkC,GAAA,GAAM,IAAA;AAC9C,IAAM,+BAA+B,MAAA,CAAO,gBAAA;AAQ5C,eAAsB,oBAAA,CACpB,KAAA,GAII,EAAC,EACqB;AAC1B,EAAA,MAAM,QAAQ,KAAA,CAAM,KAAA,IAAS,YAAY,EAAE,CAAA,CAAE,SAAS,KAAK,CAAA;AAC3D,EAAA,MAAM,YAAA,GAAe,IAAI,qBAAA,EAAsB;AAC/C,EAAA,MAAM,aAAA,GAAgB,IAAI,kBAAA,CAAmB;AAAA,IAC3C,YAAA;AAAA,IACA,MAAA,EAAQ,eAAA;AAAA,IACR,OAAA,EAAS,eAAA;AAAA,IACT,oBAAA,EAAsB;AAAA,GACvB,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,IAAI,iBAAA,CAAkB;AAAA,IACrC;AAAA,GACD,CAAA;AAED,EAAA,MAAM,UAAA,GAAa,YAAA,CAAa,CAAC,OAAA,EAAS,QAAA,KAAa;AACrD,IAAA,KAAK,iBAAA,CAAkB,EAAE,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,UAAU,WAAA,EAAa,CAAA,CAAE,KAAA,CAAM,MAAM;AACtF,MAAA,IAAI,CAAC,QAAA,CAAS,WAAA,IAAe,CAAC,SAAS,aAAA,EAAe;AACpD,QAAA,SAAA,CAAU,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,0BAA0B,CAAA;AAC5D,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,OAAA,EAAQ;AAAA,IACnB,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,MAAM,UAAU,IAAI,wBAAA,CAAyB,EAAE,QAAA,EAAU,MAAM,CAAA;AAC/D,EAAA,OAAA,CAAQ,EAAA,CAAG,YAAA,EAAc,CAAC,EAAA,EAAI,OAAA,KAA6B;AACzD,IAAA,MAAMC,OAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,IAAO,KAAK,kBAAkB,CAAA;AAC1D,IAAA,MAAM,QAAQA,IAAAA,CAAI,QAAA,CAAS,MAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,MAAM,CAAC,CAAA;AACzB,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,EAAA,CAAG,KAAA,CAAM,MAAM,yBAAyB,CAAA;AACxC,MAAA;AAAA,IACF;AACA,IAAA,aAAA,CAAc,YAAA,CAAa,WAAW,EAAE,CAAA;AAAA,EAC1C,CAAC,CAAA;AAED,EAAA,UAAA,CAAW,EAAA,CAAG,SAAA,EAAW,CAAC,OAAA,EAAS,QAAQ,IAAA,KAAS;AAClD,IAAA,MAAMA,OAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,IAAO,KAAK,kBAAkB,CAAA;AAC1D,IAAA,MAAM,UAAA,GAAaA,IAAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAO,CAAA;AAC/C,IAAA,IAAI,eAAe,KAAA,IAAS,CAAC,gBAAgB,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpE,MAAA,MAAA,CAAO,OAAA,EAAQ;AACf,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAQA,IAAAA,CAAI,QAAA,CAAS,MAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AACpD,IAAA,IAAI,MAAM,CAAC,CAAA,KAAM,IAAA,IAAQ,KAAA,CAAM,WAAW,CAAA,EAAG;AAC3C,MAAA,MAAA,CAAO,OAAA,EAAQ;AACf,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,KAAM,MAAA,EAAQ;AACvB,MAAA,OAAA,CAAQ,aAAA,CAAc,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,CAAC,EAAA,KAAO;AACnD,QAAA,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,EAAA,EAAI,OAAO,CAAA;AAAA,MACxC,CAAC,CAAA;AACD,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,KAAM,KAAA,EAAO;AACtB,MAAA,QAAA,CAAS,aAAA,CAAc,OAAA,EAAS,MAAA,EAAQ,IAAI,CAAA;AAC5C,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,IAAI,YAAA;AACJ,EAAA,eAAe,WAAA,GAA6B;AAC1C,IAAA,YAAA,KAAA,CAAkB,YAAY;AAC5B,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,CAAC,MAAA,KAAW;AAClC,QAAA,IAAI;AACF,UAAA,MAAA,CAAO,KAAA,EAAM;AAAA,QACf,CAAA,CAAA,MAAQ;AAAA,QAAC;AAAA,MACX,CAAC,CAAA;AACD,MAAA,OAAA,CAAQ,KAAA,EAAM;AACd,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,UAAA,CAAW,KAAA,EAAM;AACjB,MAAA,MAAM,IAAA,CAAK,YAAY,OAAO,CAAA;AAC9B,MAAA,MAAM,2BAA2B,EAAE,GAAA,EAAK,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAC5D,MAAA,MAAM,MAAM,QAAA,IAAW;AAAA,IACzB,CAAA,GAAG;AACH,IAAA,MAAM,YAAA;AAAA,EACR;AAEA,EAAA,UAAA,CAAW,MAAA,CAAO,KAAA,CAAM,IAAA,IAAQ,CAAA,EAAG,WAAW,CAAA;AAC9C,EAAA,MAAM,IAAA,CAAK,YAAY,WAAW,CAAA;AAClC,EAAA,MAAM,OAAA,GAAU,WAAW,OAAA,EAAQ;AACnC,EAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,EAAU;AAC3C,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACpE;AAEA,EAAA,MAAM,GAAA,GAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,CAAA;AACpD,EAAA,MAAM,0BAAA,CAA2B;AAAA,IAC/B,MAAA,EAAQ,mCAAA;AAAA,IACR,OAAA,EAAS,oCAAA;AAAA,IACT,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,oBAAoB,qBAAA,CAAsB,kBAAA;AAAA,IAC1C,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,IACpB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,KAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA,EAAO;AAAA,GACT;AACF;AAEA,eAAe,kBAAkB,IAAA,EAKf;AAChB,EAAA,MAAM,MAAM,IAAI,GAAA,CAAI,KAAK,OAAA,CAAQ,GAAA,IAAO,KAAK,kBAAkB,CAAA;AAE/D,EAAA,IAAI,GAAA,CAAI,aAAa,aAAA,EAAe;AAClC,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,KAAK,CAAA,EAAG;AACrD,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,iBAAiB,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,EAAA,EAAI,MAAM,CAAA;AAC1C,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,aAAa,eAAA,EAAiB;AACpC,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,KAAK,CAAA,EAAG;AACrD,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,iBAAiB,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,6BAAA,EAA8B;AACrD,IAAA,MAAM,OAAA,GAA8C,EAAE,QAAA,EAAS;AAC/D,IAAA,SAAA,CAAU,IAAA,CAAK,QAAA,EAAU,GAAA,EAAK,OAAO,CAAA;AACrC,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,aAAa,mBAAA,EAAqB;AACxC,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,KAAK,CAAA,EAAG;AACrD,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,iBAAiB,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,MAAA,KAAW,MAAA,EAAQ;AAClC,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,uBAAuB,CAAA;AAC9D,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,MAAM;AACjC,MAAA,KAAK,KAAK,QAAA,EAAS;AAAA,IACrB,CAAC,CAAA;AACD,IAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAC/C,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,GAAA,CAAI,QAAA,CAAS,KAAA,CAAM,qCAAqC,CAAA;AAC5E,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,KAAK,CAAA,EAAG;AACrD,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,iBAAiB,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,WAAA,CAAY,CAAC,CAAE,CAAA;AACpD,IAAA,IAAI,CAAE,MAAM,uBAAA,CAAwB,SAAS,CAAA,EAAI;AAC/C,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,sBAAsB,CAAA;AAC7D,MAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAA+C;AAAA,MACnD,SAAA;AAAA,MACA,SAAA,EAAW,4BAAA;AAAA,MACX,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM;AAAA,UACJ,IAAA,EAAM,MAAA;AAAA,UACN,SAAA,EAAW,IAAA;AAAA,UACX,GAAA,EAAK,GAAG,gBAAA,CAAiB,IAAA,CAAK,OAAO,CAAC,CAAA,SAAA,EAAY,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA;AAAA,UAC/E,OAAO,IAAA,CAAK,KAAA;AAAA,UACZ,SAAA,EAAW;AAAA,SACb;AAAA,QACA,GAAA,EAAK;AAAA,UACH,IAAA,EAAM,KAAA;AAAA,UACN,SAAA,EAAW,IAAA;AAAA,UACX,GAAA,EAAK,GAAG,gBAAA,CAAiB,IAAA,CAAK,OAAO,CAAC,CAAA,QAAA,EAAW,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA;AAAA,UAC9E,OAAO,IAAA,CAAK,KAAA;AAAA,UACZ,SAAA,EAAW;AAAA;AACb;AACF,KACF;AACA,IAAA,SAAA,CAAU,IAAA,CAAK,QAAA,EAAU,GAAA,EAAK,OAAO,CAAA;AACrC,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,UAAA,GAAa,GAAA,CAAI,QAAA,CAAS,KAAA,CAAM,oCAAoC,CAAA;AAC1E,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,KAAK,CAAA,EAAG;AACrD,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,iBAAiB,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,MAAA,KAAW,MAAA,EAAQ;AAClC,MAAA,SAAA,CAAU,KAAK,QAAA,EAAU,GAAA,EAAK,EAAE,KAAA,EAAO,uBAAuB,CAAA;AAC9D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,UAAA,CAAW,CAAC,CAAE,CAAA;AACnD,IAAA,MAAM,EAAE,4BAAA,EAA8B,0BAAA,EAA2B,GAC/D,MAAM,OAAO,+BAAsB,CAAA;AACrC,IAAA,IAAI;AACF,MAAA,MAAM,6BAA6B,SAAS,CAAA;AAAA,IAC9C,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,iBAAiB,0BAAA,EAA4B;AAC/C,QAAA,SAAA,CAAU,IAAA,CAAK,UAAU,KAAA,CAAM,UAAA,EAAY,EAAE,KAAA,EAAO,KAAA,CAAM,SAAS,CAAA;AACnE,QAAA;AAAA,MACF;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAEA,IAAA,MAAM,OAAA,GAAkD;AAAA,MACtD,SAAA;AAAA,MACA,MAAA,EAAQ;AAAA,KACV;AACA,IAAA,SAAA,CAAU,IAAA,CAAK,QAAA,EAAU,GAAA,EAAK,OAAO,CAAA;AACrC,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,aAAa,cAAA,EAAgB;AACnC,IAAA,IAAA,CAAK,SAAS,UAAA,GAAa,GAAA;AAC3B,IAAA,IAAA,CAAK,SAAS,GAAA,EAAI;AAClB,IAAA;AAAA,EACF;AAEA,EAAA,IACE,GAAA,CAAI,QAAA,KAAa,GAAA,IACjB,GAAA,CAAI,QAAA,CAAS,UAAA,CAAW,UAAU,CAAA,IAClC,GAAA,CAAI,QAAA,CAAS,UAAA,CAAW,UAAU,CAAA,EAClC;AACA,IAAA,MAAM,iBAAiB,IAAA,CAAK,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,KAAK,KAAK,CAAA;AAC9D,IAAA;AAAA,EACF;AAEA,EAAA,IAAA,CAAK,SAAS,UAAA,GAAa,GAAA;AAC3B,EAAA,IAAA,CAAK,QAAA,CAAS,IAAI,WAAW,CAAA;AAC/B;AAEA,eAAe,gBAAA,CACb,QAAA,EACA,QAAA,EACA,KAAA,EACe;AACf,EAAA,MAAM,YAAY,yBAAA,EAA0B;AAC5C,EAAA,MAAM,eAAe,QAAA,KAAa,GAAA,GAAM,YAAA,GAAe,QAAA,CAAS,MAAM,CAAC,CAAA;AACvE,EAAA,MAAM,SAAA,GAAYH,KAAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,YAAY,CAAA;AACtD,EAAA,MAAM,iBAAA,GAAoBA,KAAAA,CAAK,QAAA,CAAS,SAAA,EAAW,SAAS,CAAA;AAC5D,EAAA,IACE,iBAAA,CAAkB,UAAA,CAAW,IAAI,CAAA,IACjCA,KAAAA,CAAK,UAAA,CAAW,iBAAiB,CAAA,IACjC,CAAC,UAAA,CAAW,SAAS,CAAA,EACrB;AACA,IAAA,QAAA,CAAS,UAAA,GAAa,GAAA;AACtB,IAAA,QAAA,CAAS,IAAI,WAAW,CAAA;AACxB,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,iBAAiB,YAAA,EAAc;AACjC,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,SAAA,EAAW,MAAM,CAAA;AAC7C,IAAA,QAAA,CAAS,SAAA,CAAU,gBAAgB,0BAA0B,CAAA;AAC7D,IAAA,QAAA,CAAS,SAAA,CAAU,iBAAiB,UAAU,CAAA;AAC9C,IAAA,QAAA,CAAS,GAAA;AAAA,MACP,IAAA,CAAK,OAAA;AAAA,QACH,oCAAA;AAAA,QACA,KAAK,SAAA,CAAU;AAAA,UACb,WAAA,EAAa,MAAA;AAAA,UACb;AAAA,SACD;AAAA;AACH,KACF;AACA,IAAA;AAAA,EACF;AAEA,EAAA,QAAA,CAAS,SAAA,CAAU,cAAA,EAAgB,gBAAA,CAAiB,SAAS,CAAC,CAAA;AAC9D,EAAA,QAAA,CAAS,SAAA,CAAU,iBAAiB,UAAU,CAAA;AAC9C,EAAA,QAAA,CAAS,GAAA,CAAI,MAAM,QAAA,CAAS,SAAS,CAAC,CAAA;AACxC;AAEA,SAAS,yBAAA,GAAoC;AAC3C,EAAA,MAAM,YAAYA,KAAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AAC7D,EAAA,MAAM,UAAA,GAAa;AAAA,IACjBA,KAAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,YAAA,EAAc,QAAQ,CAAA;AAAA,IAC9CA,KAAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,QAAQ,CAAA;AAAA,IAChCA,KAAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,IAAA,EAAM,cAAc,QAAQ;AAAA,GACtD;AACA,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,MAAA,OAAO,SAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gDAAA,EAAmD,SAAS,CAAA,CAAA,CAAG,CAAA;AACjF;AAEA,SAAS,sBAAA,CAAuB,SAA0B,KAAA,EAAwB;AAChF,EAAA,OACE,OAAA,CAAQ,QAAQ,yBAAyB,CAAA,KAAM,SAAS,eAAA,CAAgB,OAAA,CAAQ,QAAQ,MAAM,CAAA;AAElG;AAEA,SAAS,gBAAgB,MAAA,EAAqC;AAC5D,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,MAAM,CAAA;AAC1B,IAAA,MAAM,OAAO,GAAA,CAAI,QAAA;AACjB,IAAA,OAAO,SAAS,WAAA,IAAe,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,SAAS,IAAA,KAAS,OAAA;AAAA,EACpF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,OAAA,EAAkC;AAC1D,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,IAAQ,WAAA;AACrC,EAAA,OAAO,QAAQ,IAAI,CAAA,CAAA;AACrB;AAEA,SAAS,SAAA,CAAU,QAAA,EAA0B,UAAA,EAAoB,KAAA,EAAsB;AACrF,EAAA,QAAA,CAAS,UAAA,GAAa,UAAA;AACtB,EAAA,QAAA,CAAS,SAAA,CAAU,gBAAgB,iCAAiC,CAAA;AACpE,EAAA,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AACpC;AAEA,SAAS,iBAAiB,SAAA,EAA2B;AACnD,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAO,yBAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,KAAK,CAAA,EAAG;AAC7B,IAAA,OAAO,uCAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAO,eAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,OAAO,CAAA,EAAG;AAC/B,IAAA,OAAO,iCAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAO,WAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAO,cAAA;AAAA,EACT;AACA,EAAA,OAAO,0BAAA;AACT;;;AChYA,eAAsB,mBAAA,GAAqC;AACzD,EAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,CAAqB;AAAA,IACxC,KAAA,EAAO,QAAQ,GAAA,CAAI,+BAAA,IAAmCI,YAAY,EAAE,CAAA,CAAE,SAAS,KAAK,CAAA;AAAA,IACpF,UAAU,MAAM;AACd,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,GACD,CAAA;AAED,EAAA,MAAM,uBAAuB,MAAM;AACjC,IAAA,KAAK,OAAO,KAAA,EAAM;AAAA,EACpB,CAAA;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,UAAU,oBAAoB,CAAA;AAC3C,EAAA,OAAA,CAAQ,IAAA,CAAK,WAAW,oBAAoB,CAAA;AAE5C,EAAA,MAAM,IAAI,OAAA,CAAc,MAAM,MAAS,CAAA;AACzC","file":"chunk-R33BXCMQ.js","sourcesContent":["import { inspectCdpEndpoint } from \"../local-browser/cdp-discovery.js\";\nimport type { PersistedLocalBrowserSessionRecord } from \"../live-session.js\";\n\nexport async function resolveBrowserWebSocketUrl(\n record: PersistedLocalBrowserSessionRecord,\n): Promise<string> {\n if (record.engine === \"playwright\") {\n if (!record.endpoint) {\n throw new Error(\"Local Playwright session is missing a browser WebSocket endpoint.\");\n }\n return record.endpoint;\n }\n\n if (!record.remoteDebuggingUrl) {\n throw new Error(\"Local ABP session is missing a remote debugging URL.\");\n }\n\n const inspected = await inspectCdpEndpoint({\n endpoint: record.remoteDebuggingUrl,\n timeoutMs: 5_000,\n });\n return inspected.endpoint;\n}\n","import path from \"node:path\";\n\nimport type { OpensteerLocalViewSessionSummary } from \"@opensteer/protocol\";\n\nimport { pathExists } from \"../internal/filesystem.js\";\nimport {\n getPersistedLocalBrowserSessionOwnership,\n isAttachedLocalBrowserSessionReachable,\n readPersistedLocalBrowserSessionRecord,\n type PersistedLocalBrowserSessionRecord,\n} from \"../live-session.js\";\nimport { isProcessRunning } from \"../local-browser/process-owner.js\";\nimport {\n deleteLocalViewSessionManifest,\n listLocalViewSessionManifests,\n readLocalViewSessionManifest,\n buildLocalViewSessionIdForRecord,\n type PersistedLocalViewSessionManifest,\n} from \"./session-manifest.js\";\nimport { resolveBrowserWebSocketUrl } from \"./resolve-browser-websocket.js\";\n\nexport interface ResolvedLocalViewSession {\n readonly manifest: PersistedLocalViewSessionManifest;\n readonly record: PersistedLocalBrowserSessionRecord;\n readonly browserWebSocketUrl: string;\n}\n\nexport async function listResolvedLocalViewSessions(): Promise<\n readonly OpensteerLocalViewSessionSummary[]\n> {\n const manifests = await listLocalViewSessionManifests();\n const resolved = await Promise.all(manifests.map((manifest) => resolveSessionSummary(manifest)));\n return resolved\n .filter((session): session is OpensteerLocalViewSessionSummary => session !== undefined)\n .sort(\n (left, right) => right.startedAt - left.startedAt || left.label.localeCompare(right.label),\n );\n}\n\nexport async function resolveLocalViewSession(\n sessionId: string,\n): Promise<ResolvedLocalViewSession | undefined> {\n const manifest = await readLocalViewSessionManifest(sessionId);\n if (!manifest) {\n return undefined;\n }\n\n return readResolvedLocalViewSession(manifest);\n}\n\nasync function resolveSessionSummary(\n manifest: PersistedLocalViewSessionManifest,\n): Promise<OpensteerLocalViewSessionSummary | undefined> {\n const record = await readLiveRecord(manifest);\n if (!record) {\n await deleteLocalViewSessionManifest(manifest.sessionId);\n return undefined;\n }\n\n const browserName = record.executablePath\n ? path.basename(record.executablePath).replace(/\\.[A-Za-z0-9]+$/u, \"\")\n : undefined;\n\n return {\n sessionId: manifest.sessionId,\n label: manifest.workspace ?? (path.basename(manifest.rootPath) || manifest.sessionId),\n status:\n getPersistedLocalBrowserSessionOwnership(record) === \"attached\" ||\n isProcessRunning(record.pid)\n ? \"live\"\n : \"stale\",\n ...(manifest.workspace === undefined ? {} : { workspace: manifest.workspace }),\n rootPath: manifest.rootPath,\n engine: record.engine,\n ownership: manifest.ownership,\n startedAt: record.startedAt,\n ...(record.pid > 0 ? { pid: record.pid } : {}),\n ...(browserName === undefined ? {} : { browserName }),\n };\n}\n\nasync function readResolvedLocalViewSession(\n manifest: PersistedLocalViewSessionManifest,\n): Promise<ResolvedLocalViewSession | undefined> {\n const record = await readLiveRecord(manifest);\n if (!record) {\n await deleteLocalViewSessionManifest(manifest.sessionId);\n return undefined;\n }\n\n const browserWebSocketUrl = await resolveBrowserWebSocketUrl(record).catch(() => undefined);\n if (!browserWebSocketUrl) {\n return undefined;\n }\n\n return {\n manifest,\n record,\n browserWebSocketUrl,\n };\n}\n\nasync function readLiveRecord(\n manifest: PersistedLocalViewSessionManifest,\n): Promise<PersistedLocalBrowserSessionRecord | undefined> {\n if (!(await pathExists(manifest.rootPath))) {\n return undefined;\n }\n\n const record = await readPersistedLocalBrowserSessionRecord(manifest.rootPath);\n if (!record) {\n return undefined;\n }\n\n if (\n buildLocalViewSessionIdForRecord({\n rootPath: manifest.rootPath,\n live: record,\n }) !== manifest.sessionId ||\n record.startedAt !== manifest.startedAt ||\n record.engine !== manifest.engine ||\n getPersistedLocalBrowserSessionOwnership(record) !== manifest.ownership\n ) {\n return undefined;\n }\n\n if (getPersistedLocalBrowserSessionOwnership(record) === \"attached\") {\n return (await isAttachedLocalBrowserSessionReachable(record)) ? record : undefined;\n }\n\n if (record.pid !== manifest.pid || !isProcessRunning(record.pid)) {\n return undefined;\n }\n return record;\n}\n","export interface PageActivationIntent {\n readonly targetId: string;\n readonly ts: number;\n}\n\nexport class LocalViewRuntimeState {\n private readonly activationIntentBySessionId = new Map<string, PageActivationIntent>();\n\n setPageActivationIntent(sessionId: string, targetId: string): void {\n this.activationIntentBySessionId.set(sessionId, {\n targetId,\n ts: Date.now(),\n });\n }\n\n getPageActivationIntent(sessionId: string): PageActivationIntent | undefined {\n return this.activationIntentBySessionId.get(sessionId);\n }\n\n clearPageActivationIntent(sessionId: string, targetId?: string): void {\n const current = this.activationIntentBySessionId.get(sessionId);\n if (!current) {\n return;\n }\n if (targetId !== undefined && current.targetId !== targetId) {\n return;\n }\n this.activationIntentBySessionId.delete(sessionId);\n }\n}\n","import type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\n\nimport * as wsModule from \"ws\";\nimport WebSocket from \"ws\";\n\nexport interface LocalViewSocket {\n readonly readyState: number;\n readonly bufferedAmount: number;\n on(event: \"open\" | \"close\", listener: () => void): this;\n on(event: \"message\", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;\n on(event: \"error\", listener: (error: Error) => void): this;\n off(event: \"close\", listener: () => void): this;\n off(event: \"message\", listener: (data: WebSocket.RawData, isBinary: boolean) => void): this;\n send(\n data: WebSocket.RawData,\n options?: {\n readonly binary?: boolean;\n },\n callback?: (error?: Error) => void,\n ): void;\n close(code?: number, data?: string | Buffer): void;\n}\n\nexport interface LocalViewSocketServer {\n readonly clients: Set<LocalViewSocket>;\n on(\n event: \"connection\",\n listener: (socket: LocalViewSocket, request: IncomingMessage) => void,\n ): this;\n handleUpgrade(\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n callback: (socket: LocalViewSocket) => void,\n ): void;\n emit(event: \"connection\", socket: LocalViewSocket, request: IncomingMessage): boolean;\n close(callback?: () => void): void;\n}\n\ninterface LocalViewSocketServerConstructor {\n new (options?: { readonly noServer?: boolean }): LocalViewSocketServer;\n}\n\nexport const LocalViewWebSocketServer = (\n wsModule as unknown as {\n readonly WebSocketServer: LocalViewSocketServerConstructor;\n }\n).WebSocketServer;\n","import type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\n\nimport WebSocket from \"ws\";\n\nimport { resolveLocalViewSession } from \"./discovery.js\";\nimport { LocalViewRuntimeState } from \"./runtime-state.js\";\nimport {\n LocalViewWebSocketServer,\n type LocalViewSocket,\n type LocalViewSocketServer,\n} from \"./ws-types.js\";\n\nconst DEFAULT_MAX_PENDING_CLIENT_BUFFER_BYTES = 1_000_000;\nconst DEFAULT_UPSTREAM_OPEN_TIMEOUT_MS = 10_000;\n\nexport interface LocalViewCdpProxyDeps {\n readonly runtimeState: LocalViewRuntimeState;\n readonly createUpstreamSocket?: (url: string) => LocalViewSocket;\n readonly maxPendingClientBufferBytes?: number;\n readonly upstreamOpenTimeoutMs?: number;\n}\n\nexport class LocalViewCdpProxy {\n private readonly wss: LocalViewSocketServer;\n private readonly createUpstreamSocket: (url: string) => LocalViewSocket;\n private readonly maxPendingClientBufferBytes: number;\n private readonly upstreamOpenTimeoutMs: number;\n\n constructor(private readonly deps: LocalViewCdpProxyDeps) {\n this.wss = new LocalViewWebSocketServer({ noServer: true });\n this.createUpstreamSocket =\n deps.createUpstreamSocket ?? ((url) => new WebSocket(url) as unknown as LocalViewSocket);\n this.maxPendingClientBufferBytes =\n deps.maxPendingClientBufferBytes ?? DEFAULT_MAX_PENDING_CLIENT_BUFFER_BYTES;\n this.upstreamOpenTimeoutMs = deps.upstreamOpenTimeoutMs ?? DEFAULT_UPSTREAM_OPEN_TIMEOUT_MS;\n }\n\n handleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer): void {\n const url = new URL(req.url || \"/\", \"http://localhost\");\n const parts = url.pathname.split(\"/\").filter(Boolean);\n const isCdpPath = parts.length === 3 && parts[0] === \"ws\" && parts[1] === \"cdp\";\n if (!isCdpPath) {\n socket.destroy();\n return;\n }\n\n const sessionId = parts[2]!;\n this.wss.handleUpgrade(req, socket, head, (clientSocket) => {\n void this.bindProxy(clientSocket, sessionId).catch(() => {\n safeCloseSocket(clientSocket);\n });\n });\n }\n\n close(): void {\n for (const client of this.wss.clients) {\n safeCloseSocket(client);\n }\n this.wss.close();\n }\n\n private async bindProxy(clientSocket: LocalViewSocket, sessionId: string): Promise<void> {\n const resolved = await resolveLocalViewSession(sessionId);\n if (!resolved) {\n safeCloseSocket(clientSocket);\n return;\n }\n\n const upstream = this.createUpstreamSocket(resolved.browserWebSocketUrl);\n const pendingCreateTargetCommandIds = new Set<number>();\n const pendingAttachTargetCommandTargetIds = new Map<number, string>();\n const targetIdByAttachedSessionId = new Map<string, string>();\n const pendingClientMessages: Array<{\n readonly data: WebSocket.RawData;\n readonly isBinary: boolean;\n }> = [];\n let pendingClientBufferBytes = 0;\n let closed = false;\n let upstreamOpenTimeout: NodeJS.Timeout | null = null;\n\n const closeConnection = () => {\n if (closed) {\n return;\n }\n closed = true;\n if (upstreamOpenTimeout) {\n clearTimeout(upstreamOpenTimeout);\n upstreamOpenTimeout = null;\n }\n pendingClientMessages.length = 0;\n pendingClientBufferBytes = 0;\n safeCloseSocket(upstream);\n safeCloseSocket(clientSocket);\n };\n\n upstreamOpenTimeout = setTimeout(() => {\n if (upstream.readyState === WebSocket.OPEN) {\n return;\n }\n closeConnection();\n }, this.upstreamOpenTimeoutMs);\n\n clientSocket.on(\"message\", (data: WebSocket.RawData, isBinary: boolean) => {\n const outboundData = data;\n\n if (!isBinary) {\n const message = parseCdpProtocolMessage(data);\n if (message) {\n const activatedTargetId = readActivateTargetCommandTargetId(message);\n if (activatedTargetId) {\n this.deps.runtimeState.setPageActivationIntent(sessionId, activatedTargetId);\n }\n\n const createTargetCommandId = readCreateTargetCommandId(message);\n if (createTargetCommandId !== null) {\n pendingCreateTargetCommandIds.add(createTargetCommandId);\n }\n\n const attachTargetCommand = readAttachTargetCommand(message);\n if (attachTargetCommand) {\n pendingAttachTargetCommandTargetIds.set(\n attachTargetCommand.id,\n attachTargetCommand.targetId,\n );\n }\n\n const interactionTargetId = readInteractionTargetId(message, targetIdByAttachedSessionId);\n if (interactionTargetId) {\n this.deps.runtimeState.setPageActivationIntent(sessionId, interactionTargetId);\n }\n }\n }\n\n if (upstream.readyState === WebSocket.OPEN) {\n upstream.send(outboundData, { binary: isBinary });\n return;\n }\n if (upstream.readyState !== WebSocket.CONNECTING) {\n closeConnection();\n return;\n }\n\n const sizeBytes = rawDataSizeBytes(outboundData);\n if (pendingClientBufferBytes + sizeBytes > this.maxPendingClientBufferBytes) {\n closeConnection();\n return;\n }\n pendingClientMessages.push({ data: outboundData, isBinary });\n pendingClientBufferBytes += sizeBytes;\n });\n\n upstream.on(\"open\", () => {\n if (upstreamOpenTimeout) {\n clearTimeout(upstreamOpenTimeout);\n upstreamOpenTimeout = null;\n }\n for (const pendingMessage of pendingClientMessages.splice(0)) {\n upstream.send(pendingMessage.data, { binary: pendingMessage.isBinary });\n }\n pendingClientBufferBytes = 0;\n });\n\n upstream.on(\"message\", (data: WebSocket.RawData, isBinary: boolean) => {\n if (!isBinary) {\n const message = parseCdpProtocolMessage(data);\n if (message) {\n const createdTargetId = readCreateTargetResultTargetId(\n message,\n pendingCreateTargetCommandIds,\n );\n if (createdTargetId) {\n this.deps.runtimeState.setPageActivationIntent(sessionId, createdTargetId);\n }\n\n const attachedTarget = readAttachTargetResult(\n message,\n pendingAttachTargetCommandTargetIds,\n );\n if (attachedTarget) {\n targetIdByAttachedSessionId.set(attachedTarget.sessionId, attachedTarget.targetId);\n }\n\n const detachedSessionId = readDetachedTargetSessionId(message);\n if (detachedSessionId) {\n targetIdByAttachedSessionId.delete(detachedSessionId);\n }\n }\n }\n\n if (clientSocket.readyState === WebSocket.OPEN) {\n clientSocket.send(data, { binary: isBinary });\n }\n });\n\n clientSocket.on(\"close\", closeConnection);\n clientSocket.on(\"error\", closeConnection);\n upstream.on(\"close\", closeConnection);\n upstream.on(\"error\", closeConnection);\n }\n}\n\ninterface ParsedCdpProtocolMessage {\n readonly id?: number;\n readonly method?: string;\n readonly sessionId?: string;\n readonly params?: Record<string, unknown>;\n readonly result?: Record<string, unknown>;\n}\n\nfunction parseCdpProtocolMessage(data: WebSocket.RawData): ParsedCdpProtocolMessage | null {\n try {\n const parsed = JSON.parse(rawDataToString(data)) as ParsedCdpProtocolMessage | null;\n return parsed && typeof parsed === \"object\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\nfunction readCreateTargetCommandId(message: ParsedCdpProtocolMessage): number | null {\n return message.method === \"Target.createTarget\" && typeof message.id === \"number\"\n ? message.id\n : null;\n}\n\nfunction readCreateTargetResultTargetId(\n message: ParsedCdpProtocolMessage,\n pendingCommandIds: Set<number>,\n): string | null {\n if (typeof message.id !== \"number\" || !pendingCommandIds.has(message.id)) {\n return null;\n }\n pendingCommandIds.delete(message.id);\n const targetId = message.result?.targetId;\n return typeof targetId === \"string\" && targetId.length > 0 ? targetId : null;\n}\n\nfunction readActivateTargetCommandTargetId(message: ParsedCdpProtocolMessage): string | null {\n const targetId =\n message.method === \"Target.activateTarget\" ? message.params?.targetId : undefined;\n return typeof targetId === \"string\" && targetId.length > 0 ? targetId : null;\n}\n\nfunction readAttachTargetCommand(message: ParsedCdpProtocolMessage): {\n readonly id: number;\n readonly targetId: string;\n} | null {\n if (message.method !== \"Target.attachToTarget\" || typeof message.id !== \"number\") {\n return null;\n }\n const targetId = message.params?.targetId;\n if (typeof targetId !== \"string\" || targetId.length === 0) {\n return null;\n }\n return {\n id: message.id,\n targetId,\n };\n}\n\nfunction readAttachTargetResult(\n message: ParsedCdpProtocolMessage,\n pendingTargetIds: Map<number, string>,\n): {\n readonly sessionId: string;\n readonly targetId: string;\n} | null {\n if (typeof message.id !== \"number\") {\n return null;\n }\n const targetId = pendingTargetIds.get(message.id);\n if (!targetId) {\n return null;\n }\n pendingTargetIds.delete(message.id);\n const sessionId = message.result?.sessionId;\n if (typeof sessionId !== \"string\" || sessionId.length === 0) {\n return null;\n }\n return {\n sessionId,\n targetId,\n };\n}\n\nfunction readInteractionTargetId(\n message: ParsedCdpProtocolMessage,\n targetIdByAttachedSessionId: Map<string, string>,\n): string | null {\n const sessionId = message.sessionId;\n if (typeof sessionId !== \"string\" || sessionId.length === 0) {\n return null;\n }\n if (\n !message.method ||\n (!message.method.startsWith(\"Input.\") && !message.method.startsWith(\"Page.\"))\n ) {\n return null;\n }\n return targetIdByAttachedSessionId.get(sessionId) ?? null;\n}\n\nfunction readDetachedTargetSessionId(message: ParsedCdpProtocolMessage): string | null {\n if (message.method !== \"Target.detachedFromTarget\") {\n return null;\n }\n const sessionId = message.params?.sessionId;\n return typeof sessionId === \"string\" && sessionId.length > 0 ? sessionId : null;\n}\n\nfunction rawDataToString(data: WebSocket.RawData): string {\n if (typeof data === \"string\") {\n return data;\n }\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data).toString(\"utf8\");\n }\n if (Array.isArray(data)) {\n return Buffer.concat(data).toString(\"utf8\");\n }\n return data.toString(\"utf8\");\n}\n\nfunction rawDataSizeBytes(data: WebSocket.RawData): number {\n if (typeof data === \"string\") {\n return Buffer.byteLength(data);\n }\n if (data instanceof ArrayBuffer) {\n return data.byteLength;\n }\n if (Array.isArray(data)) {\n return data.reduce((total, entry) => total + entry.byteLength, 0);\n }\n return data.byteLength;\n}\n\nfunction safeCloseSocket(socket: LocalViewSocket): void {\n try {\n socket.close();\n } catch {}\n}\n","import type { BrowserContext, Page } from \"playwright\";\n\nimport type { OpensteerViewStreamTab } from \"@opensteer/protocol\";\n\nimport { LocalViewRuntimeState } from \"./runtime-state.js\";\n\ninterface CachedPageMetadata {\n readonly title: string;\n readonly targetId: string | undefined;\n}\n\nconst ACTIVATION_INTENT_DISCOVERY_GRACE_MS = 2_000;\n\nexport interface TabStateTrackerDeps {\n readonly browserContext: BrowserContext;\n readonly sessionId: string;\n readonly pollMs: number;\n readonly runtimeState: LocalViewRuntimeState;\n readonly onTabsChanged: (payload: {\n readonly tabs: readonly OpensteerViewStreamTab[];\n readonly activeTabIndex: number;\n }) => void;\n readonly onActivePageChanged: (page: Page) => void;\n}\n\nexport class TabStateTracker {\n private readonly deps: TabStateTrackerDeps;\n private timer: NodeJS.Timeout | null = null;\n private running = false;\n private lastActivePage: Page | null = null;\n private lastTabsSignature = \"\";\n private tickInFlight = false;\n private readonly metadataByPage = new Map<Page, CachedPageMetadata>();\n private readonly targetIdByPage = new WeakMap<Page, string>();\n private readonly pageCleanupByPage = new Map<Page, () => void>();\n private boundContextCleanup: (() => void) | null = null;\n\n constructor(deps: TabStateTrackerDeps) {\n this.deps = deps;\n }\n\n start(): void {\n if (this.running) {\n return;\n }\n this.running = true;\n this.bindContextEvents();\n void this.reconcile({\n includeFocus: true,\n refreshMetadata: true,\n });\n }\n\n stop(): void {\n this.running = false;\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.boundContextCleanup?.();\n this.boundContextCleanup = null;\n for (const cleanup of this.pageCleanupByPage.values()) {\n cleanup();\n }\n this.pageCleanupByPage.clear();\n this.metadataByPage.clear();\n }\n\n private bindContextEvents(): void {\n if (this.boundContextCleanup) {\n this.syncTrackedPages(this.deps.browserContext.pages());\n this.updatePolling(this.deps.browserContext.pages().length);\n return;\n }\n\n const onPage = (page: Page) => {\n this.syncTrackedPages(this.deps.browserContext.pages());\n this.updatePolling(this.deps.browserContext.pages().length);\n this.attachPageListeners(page);\n void this.reconcile({\n includeFocus: true,\n refreshMetadata: true,\n });\n };\n\n this.deps.browserContext.on(\"page\", onPage);\n this.boundContextCleanup = () => {\n this.deps.browserContext.off(\"page\", onPage);\n };\n\n this.syncTrackedPages(this.deps.browserContext.pages());\n this.updatePolling(this.deps.browserContext.pages().length);\n }\n\n private syncTrackedPages(pages: readonly Page[]): void {\n const nextPages = new Set(pages);\n\n for (const [page, cleanup] of this.pageCleanupByPage.entries()) {\n if (nextPages.has(page)) {\n continue;\n }\n cleanup();\n this.pageCleanupByPage.delete(page);\n this.metadataByPage.delete(page);\n }\n\n for (const page of pages) {\n this.attachPageListeners(page);\n }\n }\n\n private attachPageListeners(page: Page): void {\n if (this.pageCleanupByPage.has(page)) {\n return;\n }\n\n const refreshMetadata = () => {\n void this.reconcile({\n includeFocus: false,\n refreshMetadata: true,\n });\n };\n const handleClose = () => {\n this.pageCleanupByPage.get(page)?.();\n this.pageCleanupByPage.delete(page);\n this.metadataByPage.delete(page);\n void this.reconcile({\n includeFocus: true,\n refreshMetadata: true,\n });\n };\n\n page.on(\"close\", handleClose);\n page.on(\"domcontentloaded\", refreshMetadata);\n page.on(\"load\", refreshMetadata);\n page.on(\"framenavigated\", refreshMetadata);\n\n this.pageCleanupByPage.set(page, () => {\n page.off(\"close\", handleClose);\n page.off(\"domcontentloaded\", refreshMetadata);\n page.off(\"load\", refreshMetadata);\n page.off(\"framenavigated\", refreshMetadata);\n });\n }\n\n private updatePolling(pageCount: number): void {\n const shouldPoll = this.running && pageCount > 0;\n if (!shouldPoll) {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n return;\n }\n\n if (this.timer) {\n return;\n }\n\n this.timer = setInterval(() => {\n const trackedPageCount = this.deps.browserContext.pages().length;\n void this.reconcile({\n includeFocus: trackedPageCount > 1,\n refreshMetadata: true,\n });\n }, this.deps.pollMs);\n }\n\n private async reconcile(args: {\n readonly includeFocus: boolean;\n readonly refreshMetadata: boolean;\n }): Promise<void> {\n if (!this.running || this.tickInFlight) {\n return;\n }\n this.tickInFlight = true;\n\n try {\n this.bindContextEvents();\n const pages = this.deps.browserContext.pages();\n this.syncTrackedPages(pages);\n this.updatePolling(pages.length);\n const preferredActivePage = this.lastActivePage ?? pages[0] ?? null;\n\n const pageStates = await Promise.all(\n pages.map(async (page, index) => {\n const metadata = await this.readPageMetadata(page, {\n refresh: args.refreshMetadata,\n });\n const focusState = args.includeFocus\n ? await this.readFocusState(page)\n : {\n isVisible: page === preferredActivePage,\n hasFocus: page === preferredActivePage,\n };\n\n return {\n page,\n index,\n targetId: metadata.targetId,\n url: page.url(),\n title: metadata.title,\n isVisible: focusState.isVisible,\n hasFocus: focusState.hasFocus,\n };\n }),\n );\n\n const activePage = this.pickActivePage(\n pageStates,\n this.lastActivePage,\n preferredActivePage,\n this.resolveIntentPage(pageStates),\n );\n if (activePage && activePage !== this.lastActivePage) {\n this.lastActivePage = activePage;\n this.deps.onActivePageChanged(activePage);\n }\n\n const tabs = pageStates.map((state) => ({\n index: state.index,\n ...(state.targetId === undefined ? {} : { targetId: state.targetId }),\n url: state.url,\n title: state.title,\n active: activePage ? state.page === activePage : false,\n })) satisfies OpensteerViewStreamTab[];\n const activeTabIndex = tabs.findIndex((tab) => tab.active);\n const signature = JSON.stringify({\n activeTabIndex,\n tabs: tabs.map((tab) => ({\n index: tab.index,\n targetId: tab.targetId,\n url: tab.url,\n title: tab.title,\n active: tab.active,\n })),\n });\n\n if (signature !== this.lastTabsSignature) {\n this.lastTabsSignature = signature;\n this.deps.onTabsChanged({\n tabs,\n activeTabIndex,\n });\n }\n } finally {\n this.tickInFlight = false;\n }\n }\n\n private async readPageMetadata(\n page: Page,\n options: {\n readonly refresh: boolean;\n },\n ): Promise<CachedPageMetadata> {\n const cached = this.metadataByPage.get(page);\n if (cached && !options.refresh) {\n return cached;\n }\n\n const [title, targetId] = await Promise.all([\n page.title().catch(() => cached?.title ?? \"\"),\n this.resolveTargetId(page).catch(() => cached?.targetId),\n ]);\n const nextMetadata = {\n title,\n targetId: targetId ?? undefined,\n } satisfies CachedPageMetadata;\n this.metadataByPage.set(page, nextMetadata);\n return nextMetadata;\n }\n\n private async resolveTargetId(page: Page): Promise<string | null> {\n const cached = this.targetIdByPage.get(page);\n if (cached) {\n return cached;\n }\n\n const cdp = await page.context().newCDPSession(page);\n try {\n const result = (await cdp.send(\"Target.getTargetInfo\")) as {\n readonly targetInfo?: {\n readonly targetId?: unknown;\n };\n } | null;\n const targetId = result?.targetInfo?.targetId;\n if (typeof targetId === \"string\" && targetId.length > 0) {\n this.targetIdByPage.set(page, targetId);\n return targetId;\n }\n return null;\n } finally {\n await cdp.detach().catch(() => undefined);\n }\n }\n\n private async readFocusState(page: Page): Promise<{\n readonly isVisible: boolean;\n readonly hasFocus: boolean;\n }> {\n try {\n const result = (await page.evaluate(() => ({\n visibilityState: (\n globalThis as {\n readonly document?: {\n readonly visibilityState?: unknown;\n };\n }\n ).document?.visibilityState,\n hasFocus:\n (\n globalThis as {\n readonly document?: {\n readonly hasFocus?: (() => boolean) | undefined;\n };\n }\n ).document?.hasFocus?.() ?? false,\n }))) as {\n readonly visibilityState?: unknown;\n readonly hasFocus?: unknown;\n };\n return {\n isVisible: result.visibilityState === \"visible\",\n hasFocus: result.hasFocus === true,\n };\n } catch {\n return {\n isVisible: false,\n hasFocus: false,\n };\n }\n }\n\n private pickActivePage(\n pageStates: Array<{\n readonly page: Page;\n readonly targetId: string | undefined;\n readonly isVisible: boolean;\n readonly hasFocus: boolean;\n }>,\n lastActivePage: Page | null,\n fallbackPage: Page | null,\n intent: { readonly page: Page } | null,\n ): Page | null {\n if (intent) {\n return intent.page;\n }\n\n const focusedVisiblePages = pageStates.filter((state) => state.isVisible && state.hasFocus);\n if (focusedVisiblePages.length === 1) {\n return focusedVisiblePages[0]?.page ?? null;\n }\n\n const visiblePages = pageStates.filter((state) => state.isVisible);\n if (visiblePages.length === 1) {\n return visiblePages[0]?.page ?? null;\n }\n\n const lastActivePageState = lastActivePage\n ? (pageStates.find((state) => state.page === lastActivePage) ?? null)\n : null;\n if (\n lastActivePageState &&\n ((focusedVisiblePages.length > 1 &&\n lastActivePageState.isVisible &&\n lastActivePageState.hasFocus) ||\n (visiblePages.length > 1 && lastActivePageState.isVisible) ||\n visiblePages.length === 0)\n ) {\n return lastActivePage;\n }\n\n const fallbackPageState = fallbackPage\n ? (pageStates.find((state) => state.page === fallbackPage) ?? null)\n : null;\n if (\n fallbackPageState &&\n ((focusedVisiblePages.length > 1 &&\n fallbackPageState.isVisible &&\n fallbackPageState.hasFocus) ||\n (visiblePages.length > 1 && fallbackPageState.isVisible))\n ) {\n return fallbackPage;\n }\n\n if (focusedVisiblePages.length > 0) {\n return focusedVisiblePages[0]?.page ?? null;\n }\n\n if (visiblePages.length > 0) {\n return visiblePages[0]?.page ?? null;\n }\n\n if (lastActivePageState) {\n return lastActivePageState.page;\n }\n\n if (fallbackPageState) {\n return fallbackPageState.page;\n }\n\n return pageStates[0]?.page ?? null;\n }\n\n private resolveIntentPage(\n pageStates: Array<{\n readonly page: Page;\n readonly targetId: string | undefined;\n }>,\n ): { readonly page: Page } | null {\n const intent = this.deps.runtimeState.getPageActivationIntent(this.deps.sessionId);\n if (!intent) {\n return null;\n }\n\n const matched = pageStates.find((state) => state.targetId === intent.targetId);\n if (!matched) {\n if (Date.now() - intent.ts > ACTIVATION_INTENT_DISCOVERY_GRACE_MS) {\n this.deps.runtimeState.clearPageActivationIntent(this.deps.sessionId, intent.targetId);\n }\n return null;\n }\n\n this.deps.runtimeState.clearPageActivationIntent(this.deps.sessionId, intent.targetId);\n return { page: matched.page };\n }\n}\n","import type { OpensteerViewport } from \"@opensteer/protocol\";\n\nexport interface RequestedStreamSize {\n readonly width: number;\n readonly height: number;\n}\n\nconst MIN_CAPTURE_DIMENSION_PX = 100;\nconst MAX_CAPTURE_DIMENSION_PX = 8_192;\nconst CAPTURE_BUCKET_PX = 64;\n\nexport function selectScreencastSize(args: {\n readonly viewport: OpensteerViewport;\n readonly requestedSizes: readonly RequestedStreamSize[];\n}): RequestedStreamSize | null {\n const viewport = normalizeViewport(args.viewport);\n if (!viewport) {\n return null;\n }\n\n let maxRequestedWidth = 0;\n let maxRequestedHeight = 0;\n for (const requestedSize of args.requestedSizes) {\n const normalized = normalizeRequestedSize(requestedSize);\n if (!normalized) {\n return null;\n }\n maxRequestedWidth = Math.max(maxRequestedWidth, normalized.width);\n maxRequestedHeight = Math.max(maxRequestedHeight, normalized.height);\n }\n\n if (\n maxRequestedWidth < MIN_CAPTURE_DIMENSION_PX ||\n maxRequestedHeight < MIN_CAPTURE_DIMENSION_PX\n ) {\n return null;\n }\n\n const desiredScale = Math.max(\n maxRequestedWidth / viewport.width,\n maxRequestedHeight / viewport.height,\n );\n if (desiredScale >= 1) {\n return viewport;\n }\n\n const landscape = viewport.width >= viewport.height;\n const sourcePrimary = landscape ? viewport.width : viewport.height;\n const sourceSecondary = landscape ? viewport.height : viewport.width;\n const nextPrimary = bucketDimension(sourcePrimary * desiredScale);\n const nextSecondary = clampDimension(Math.round((nextPrimary / sourcePrimary) * sourceSecondary));\n if (!nextSecondary) {\n return null;\n }\n\n return landscape\n ? { width: nextPrimary, height: nextSecondary }\n : { width: nextSecondary, height: nextPrimary };\n}\n\nfunction normalizeViewport(viewport: OpensteerViewport): RequestedStreamSize | null {\n const width = clampDimension(viewport.width);\n const height = clampDimension(viewport.height);\n return width && height ? { width, height } : null;\n}\n\nfunction normalizeRequestedSize(requestedSize: RequestedStreamSize): RequestedStreamSize | null {\n const width = clampDimension(requestedSize.width);\n const height = clampDimension(requestedSize.height);\n return width && height ? { width, height } : null;\n}\n\nfunction clampDimension(value: number): number | null {\n if (!Number.isFinite(value)) {\n return null;\n }\n\n const normalized = Math.floor(value);\n if (normalized < MIN_CAPTURE_DIMENSION_PX) {\n return null;\n }\n\n return Math.min(MAX_CAPTURE_DIMENSION_PX, normalized);\n}\n\nfunction bucketDimension(value: number): number {\n const bucketed =\n Math.ceil(Math.max(MIN_CAPTURE_DIMENSION_PX, value) / CAPTURE_BUCKET_PX) * CAPTURE_BUCKET_PX;\n return Math.min(MAX_CAPTURE_DIMENSION_PX, bucketed);\n}\n","import type {\n OpensteerViewStreamClientMessage,\n OpensteerViewStreamControlMessage,\n OpensteerViewStreamTab,\n} from \"@opensteer/protocol\";\nimport WebSocket from \"ws\";\n\nimport type { LocalViewSocket } from \"./ws-types.js\";\n\nexport function buildHelloMessage(args: {\n readonly sessionId: string;\n readonly fps: number;\n readonly quality: number;\n readonly viewport: {\n readonly width: number;\n readonly height: number;\n };\n}): OpensteerViewStreamControlMessage {\n return {\n type: \"hello\",\n sessionId: args.sessionId,\n ts: Date.now(),\n mimeType: \"image/jpeg\",\n fps: args.fps,\n quality: args.quality,\n viewport: args.viewport,\n };\n}\n\nexport function buildTabsMessage(args: {\n readonly sessionId: string;\n readonly tabs: readonly OpensteerViewStreamTab[];\n readonly activeTabIndex: number;\n}): OpensteerViewStreamControlMessage {\n return {\n type: \"tabs\",\n sessionId: args.sessionId,\n ts: Date.now(),\n tabs: args.tabs,\n activeTabIndex: args.activeTabIndex,\n };\n}\n\nexport function buildStatusMessage(args: {\n readonly sessionId: string;\n readonly status: string;\n}): OpensteerViewStreamControlMessage {\n return {\n type: \"status\",\n sessionId: args.sessionId,\n ts: Date.now(),\n status: args.status,\n };\n}\n\nexport function buildErrorMessage(args: {\n readonly sessionId: string;\n readonly error: string;\n}): OpensteerViewStreamControlMessage {\n return {\n type: \"error\",\n sessionId: args.sessionId,\n ts: Date.now(),\n error: args.error,\n };\n}\n\nexport function sendControlMessage(\n ws: LocalViewSocket,\n message: OpensteerViewStreamControlMessage,\n): void {\n if (ws.readyState !== WebSocket.OPEN) {\n return;\n }\n try {\n ws.send(JSON.stringify(message), { binary: false });\n } catch {}\n}\n\nexport function parseViewClientMessage(raw: string): OpensteerViewStreamClientMessage | null {\n try {\n const parsed = JSON.parse(raw) as Partial<OpensteerViewStreamClientMessage> | null;\n if (parsed?.type !== \"stream-config\") {\n return null;\n }\n\n const renderWidth = normalizeRenderDimension(parsed.renderWidth);\n const renderHeight = normalizeRenderDimension(parsed.renderHeight);\n if (renderWidth === null || renderHeight === null) {\n return null;\n }\n\n return {\n type: \"stream-config\",\n renderWidth,\n renderHeight,\n };\n } catch {\n return null;\n }\n}\n\nfunction normalizeRenderDimension(value: unknown): number | null {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return null;\n }\n\n const normalized = Math.floor(value);\n if (normalized < 100) {\n return null;\n }\n\n return Math.min(8_192, normalized);\n}\n","import type { Page, Browser, BrowserContext, CDPSession } from \"playwright\";\nimport WebSocket, { type RawData } from \"ws\";\n\nimport type { OpensteerViewport, OpensteerViewStreamTab } from \"@opensteer/protocol\";\n\nimport { resolveLocalViewSession } from \"./discovery.js\";\nimport { LocalViewRuntimeState } from \"./runtime-state.js\";\nimport { TabStateTracker } from \"./tab-state-tracker.js\";\nimport { selectScreencastSize, type RequestedStreamSize } from \"./view-stream-capture-policy.js\";\nimport {\n buildErrorMessage,\n buildHelloMessage,\n buildStatusMessage,\n buildTabsMessage,\n parseViewClientMessage,\n sendControlMessage,\n} from \"./view-stream-protocol.js\";\nimport type { LocalViewSocket } from \"./ws-types.js\";\n\nconst INITIAL_FRAME_CAPTURE_ATTEMPTS = 3;\nconst INITIAL_FRAME_CAPTURE_RETRY_DELAY_MS = 150;\nconst TAB_STATE_POLL_MS = 1_000;\nconst CLIENT_FRAME_FLUSH_RETRY_MS = 16;\n\ninterface ClientStreamState {\n requestedRenderSize: RequestedStreamSize | null;\n frameSendInFlight: boolean;\n pendingFrameBuffer: Buffer | null;\n pendingFlushTimer: NodeJS.Timeout | null;\n}\n\nexport interface LocalViewStreamHubDeps {\n readonly runtimeState: LocalViewRuntimeState;\n readonly maxFps: number;\n readonly quality: number;\n readonly maxClientBufferBytes: number;\n}\n\nexport class LocalViewStreamHub {\n private readonly deps: LocalViewStreamHubDeps;\n private readonly producers = new Map<string, SessionViewStreamProducer>();\n\n constructor(deps: LocalViewStreamHubDeps) {\n this.deps = deps;\n }\n\n attachClient(sessionId: string, ws: LocalViewSocket): void {\n let producer = this.producers.get(sessionId);\n if (!producer) {\n producer = new SessionViewStreamProducer({\n sessionId,\n runtimeState: this.deps.runtimeState,\n maxFps: this.deps.maxFps,\n quality: this.deps.quality,\n maxClientBufferBytes: this.deps.maxClientBufferBytes,\n onDrained: () => {\n this.producers.delete(sessionId);\n },\n });\n this.producers.set(sessionId, producer);\n }\n\n producer.addClient(ws);\n }\n}\n\ninterface SessionViewStreamProducerDeps {\n readonly sessionId: string;\n readonly runtimeState: LocalViewRuntimeState;\n readonly maxFps: number;\n readonly quality: number;\n readonly maxClientBufferBytes: number;\n readonly onDrained: () => void;\n}\n\nclass SessionViewStreamProducer {\n private readonly deps: SessionViewStreamProducerDeps;\n private readonly clients = new Set<LocalViewSocket>();\n private readonly clientStateBySocket = new Map<LocalViewSocket, ClientStreamState>();\n private readonly frameIntervalMs: number;\n private tracker: TabStateTracker | null = null;\n private browser: Browser | null = null;\n private browserDisconnectedHandler: ((browser: Browser) => void) | null = null;\n private context: BrowserContext | null = null;\n private cdpSession: CDPSession | null = null;\n private screencastHandler:\n | ((event: { readonly data: string; readonly sessionId: number }) => void)\n | null = null;\n private pageLifecycleCleanup: (() => void) | null = null;\n private activePage: Page | null = null;\n private activeViewport: OpensteerViewport | null = null;\n private activeScreencastSizeKey: string | null = null;\n private pendingFrameAckTimer: NodeJS.Timeout | null = null;\n private starting: Promise<void> | null = null;\n private started = false;\n private rebinding: Promise<void> = Promise.resolve();\n private stopped = false;\n private lastFrameSentAt = 0;\n private lastFrameBuffer: Buffer | null = null;\n private lastTabsPayload: {\n readonly tabs: readonly OpensteerViewStreamTab[];\n readonly activeTabIndex: number;\n } | null = null;\n\n constructor(deps: SessionViewStreamProducerDeps) {\n this.deps = deps;\n this.frameIntervalMs = Math.max(1, Math.floor(1000 / Math.max(1, deps.maxFps)));\n }\n\n addClient(ws: LocalViewSocket): void {\n if (this.stopped) {\n ws.close(1011, \"View stream is unavailable.\");\n return;\n }\n\n this.clients.add(ws);\n this.clientStateBySocket.set(ws, {\n requestedRenderSize: null,\n frameSendInFlight: false,\n pendingFrameBuffer: null,\n pendingFlushTimer: null,\n });\n\n if (this.activeViewport) {\n sendControlMessage(\n ws,\n buildHelloMessage({\n sessionId: this.deps.sessionId,\n fps: this.deps.maxFps,\n quality: this.deps.quality,\n viewport: this.activeViewport,\n }),\n );\n }\n if (this.lastTabsPayload) {\n sendControlMessage(\n ws,\n buildTabsMessage({\n sessionId: this.deps.sessionId,\n tabs: this.lastTabsPayload.tabs,\n activeTabIndex: this.lastTabsPayload.activeTabIndex,\n }),\n );\n }\n if (this.lastFrameBuffer) {\n const queued = this.enqueueFrameForClient(ws, this.lastFrameBuffer);\n if (!queued) {\n this.removeClient(ws);\n return;\n }\n }\n\n ws.on(\"close\", () => {\n this.removeClient(ws);\n });\n ws.on(\"error\", () => {\n this.removeClient(ws);\n });\n ws.on(\"message\", (raw: RawData, isBinary: boolean) => {\n if (isBinary) {\n return;\n }\n const message = parseViewClientMessage(readTextFrame(raw));\n if (message?.type !== \"stream-config\") {\n return;\n }\n\n const nextSize = {\n width: message.renderWidth,\n height: message.renderHeight,\n };\n const clientState = this.clientStateBySocket.get(ws);\n if (!clientState) {\n return;\n }\n const priorSize = clientState.requestedRenderSize;\n if (priorSize?.width === nextSize.width && priorSize?.height === nextSize.height) {\n return;\n }\n clientState.requestedRenderSize = nextSize;\n this.maybeRebindForStreamConfigChange();\n });\n\n void this.ensureStarted();\n }\n\n private maybeRebindForStreamConfigChange(): void {\n if (!this.activePage || !this.started || this.stopped) {\n return;\n }\n\n const nextSizeKey = this.getRequestedScreencastSizeKey();\n if (nextSizeKey === this.activeScreencastSizeKey) {\n return;\n }\n\n void this.queueBindToPage(this.activePage, { force: true }).catch(() => undefined);\n }\n\n private removeClient(ws: LocalViewSocket): void {\n this.clients.delete(ws);\n const clientState = this.clientStateBySocket.get(ws);\n if (clientState?.pendingFlushTimer) {\n clearTimeout(clientState.pendingFlushTimer);\n }\n this.clientStateBySocket.delete(ws);\n if (this.clients.size === 0) {\n void this.stop();\n return;\n }\n this.maybeRebindForStreamConfigChange();\n }\n\n private async ensureStarted(): Promise<void> {\n if (this.stopped || this.started) {\n return;\n }\n if (this.starting) {\n return this.starting;\n }\n\n this.starting = this.start()\n .then(() => {\n if (!this.stopped) {\n this.started = true;\n }\n })\n .finally(() => {\n this.starting = null;\n });\n\n try {\n await this.starting;\n } catch {\n this.broadcastControl(\n buildErrorMessage({\n sessionId: this.deps.sessionId,\n error: \"Failed to start live browser stream.\",\n }),\n );\n this.closeAllClients(1011, \"View stream failed\");\n await this.stop();\n }\n }\n\n private async start(): Promise<void> {\n const session = await this.connectSession();\n this.broadcastControl(\n buildStatusMessage({\n sessionId: this.deps.sessionId,\n status: \"starting\",\n }),\n );\n\n this.browser = session.browser;\n this.browserDisconnectedHandler = () => {\n if (this.stopped) {\n return;\n }\n this.browserDisconnectedHandler = null;\n this.broadcastControl(\n buildErrorMessage({\n sessionId: this.deps.sessionId,\n error: \"Live browser stream disconnected.\",\n }),\n );\n this.closeAllClients(1011, \"View stream failed\");\n void this.stop();\n };\n this.browser.once(\"disconnected\", this.browserDisconnectedHandler);\n\n this.context = session.context;\n this.activePage = session.page;\n this.activeViewport = await readViewportForPage(session.page);\n if (this.stopped) {\n return;\n }\n if (this.activeViewport) {\n this.broadcastControl(\n buildHelloMessage({\n sessionId: this.deps.sessionId,\n fps: this.deps.maxFps,\n quality: this.deps.quality,\n viewport: this.activeViewport,\n }),\n );\n }\n\n this.tracker = new TabStateTracker({\n browserContext: session.context,\n sessionId: this.deps.sessionId,\n pollMs: TAB_STATE_POLL_MS,\n runtimeState: this.deps.runtimeState,\n onActivePageChanged: (page) => {\n this.activePage = page;\n void this.queueBindToPage(page).catch(() => undefined);\n },\n onTabsChanged: ({ tabs, activeTabIndex }) => {\n this.lastTabsPayload = { tabs, activeTabIndex };\n this.broadcastControl(\n buildTabsMessage({\n sessionId: this.deps.sessionId,\n tabs,\n activeTabIndex,\n }),\n );\n },\n });\n this.tracker.start();\n\n await this.queueBindToPage(session.page);\n if (this.stopped) {\n return;\n }\n this.broadcastControl(\n buildStatusMessage({\n sessionId: this.deps.sessionId,\n status: \"live\",\n }),\n );\n }\n\n private queueBindToPage(\n page: Page,\n options: {\n readonly force?: boolean;\n } = {},\n ): Promise<void> {\n this.rebinding = this.rebinding\n .catch(() => undefined)\n .then(() => this.bindToPage(page, options));\n return this.rebinding;\n }\n\n private async bindToPage(\n page: Page,\n options: {\n readonly force?: boolean;\n } = {},\n ): Promise<void> {\n if (this.stopped) {\n return;\n }\n const requestedSizeKey = this.getRequestedScreencastSizeKey();\n if (\n !options.force &&\n this.activePage === page &&\n this.cdpSession &&\n this.activeScreencastSizeKey === requestedSizeKey\n ) {\n return;\n }\n\n await this.stopScreencast();\n if (this.stopped) {\n return;\n }\n\n const context = this.context;\n if (!context) {\n throw new Error(\"Browser context is unavailable.\");\n }\n const requestedSize = this.getRequestedScreencastSize();\n this.activePage = page;\n this.activeScreencastSizeKey = requestedSizeKey;\n this.activeViewport = await readViewportForPage(page);\n if (this.activeViewport) {\n this.broadcastControl(\n buildHelloMessage({\n sessionId: this.deps.sessionId,\n fps: this.deps.maxFps,\n quality: this.deps.quality,\n viewport: this.activeViewport,\n }),\n );\n }\n\n const cdpSession = await context.newCDPSession(page);\n if (this.stopped) {\n await cdpSession.detach().catch(() => undefined);\n return;\n }\n this.cdpSession = cdpSession;\n\n const onFrame = (event: { readonly data: string; readonly sessionId: number }) => {\n void this.handleScreencastFrame(event);\n };\n this.screencastHandler = onFrame;\n\n cdpSession.on(\"Page.screencastFrame\", onFrame);\n await cdpSession.send(\"Page.enable\");\n await cdpSession.send(\"Page.startScreencast\", {\n format: \"jpeg\",\n quality: this.deps.quality,\n everyNthFrame: 1,\n ...(requestedSize\n ? {\n maxWidth: requestedSize.width,\n maxHeight: requestedSize.height,\n }\n : {}),\n });\n this.bindPageLifecycleFrameRefresh(page, cdpSession);\n void this.seedInitialFrame(cdpSession).catch(() => undefined);\n }\n\n private async connectSession(): Promise<{\n readonly browser: Browser;\n readonly context: BrowserContext;\n readonly page: Page;\n }> {\n const resolved = await resolveLocalViewSession(this.deps.sessionId);\n if (!resolved) {\n throw new Error(`Local view session ${this.deps.sessionId} is unavailable.`);\n }\n\n const browser = await connectPlaywrightChromiumBrowser({\n url: resolved.browserWebSocketUrl,\n });\n try {\n const context = browser.contexts()[0];\n if (!context) {\n throw new Error(\"Connected browser did not expose a Chromium browser context.\");\n }\n\n const page = context.pages()[0] ?? (await context.newPage());\n return {\n browser,\n context,\n page,\n };\n } catch (error) {\n await disconnectPlaywrightChromiumBrowser(browser).catch(() => undefined);\n throw error;\n }\n }\n\n private async handleScreencastFrame(event: {\n readonly data: string;\n readonly sessionId: number;\n }): Promise<void> {\n const cdpSession = this.cdpSession;\n if (!cdpSession || this.stopped) {\n return;\n }\n\n const frameBuffer = Buffer.from(event.data, \"base64\");\n this.lastFrameBuffer = frameBuffer;\n\n const now = Date.now();\n const delayMs = Math.max(0, this.frameIntervalMs - (now - this.lastFrameSentAt));\n if (delayMs === 0) {\n this.flushScreencastFrame({\n cdpSession,\n sessionId: event.sessionId,\n frameBuffer,\n });\n return;\n }\n\n if (this.pendingFrameAckTimer !== null) {\n return;\n }\n\n this.pendingFrameAckTimer = setTimeout(() => {\n this.pendingFrameAckTimer = null;\n if (this.stopped || this.cdpSession !== cdpSession) {\n return;\n }\n this.flushScreencastFrame({\n cdpSession,\n sessionId: event.sessionId,\n frameBuffer,\n });\n }, delayMs);\n }\n\n private flushScreencastFrame(args: {\n readonly cdpSession: CDPSession;\n readonly sessionId: number;\n readonly frameBuffer: Buffer;\n }): void {\n this.lastFrameSentAt = Date.now();\n this.broadcastFrame(args.frameBuffer);\n void args.cdpSession\n .send(\"Page.screencastFrameAck\", { sessionId: args.sessionId })\n .catch(() => undefined);\n }\n\n private broadcastFrame(frameBuffer: Buffer): void {\n for (const client of this.clients) {\n if (!this.enqueueFrameForClient(client, frameBuffer)) {\n this.removeClient(client);\n }\n }\n\n if (this.clients.size === 0) {\n void this.stop();\n }\n }\n\n private enqueueFrameForClient(client: LocalViewSocket, frameBuffer: Buffer): boolean {\n if (client.readyState !== WebSocket.OPEN) {\n return false;\n }\n\n const clientState = this.clientStateBySocket.get(client);\n if (!clientState) {\n return false;\n }\n\n clientState.pendingFrameBuffer = frameBuffer;\n this.flushQueuedFrameToClient(client);\n return true;\n }\n\n private flushQueuedFrameToClient(client: LocalViewSocket): void {\n if (client.readyState !== WebSocket.OPEN) {\n this.removeClient(client);\n return;\n }\n\n const clientState = this.clientStateBySocket.get(client);\n if (!clientState || clientState.frameSendInFlight || !clientState.pendingFrameBuffer) {\n return;\n }\n\n if (clientState.pendingFlushTimer) {\n clearTimeout(clientState.pendingFlushTimer);\n clientState.pendingFlushTimer = null;\n }\n\n if (client.bufferedAmount > this.deps.maxClientBufferBytes) {\n clientState.pendingFlushTimer = setTimeout(() => {\n clientState.pendingFlushTimer = null;\n this.flushQueuedFrameToClient(client);\n }, CLIENT_FRAME_FLUSH_RETRY_MS);\n return;\n }\n\n const frameBuffer = clientState.pendingFrameBuffer;\n clientState.pendingFrameBuffer = null;\n clientState.frameSendInFlight = true;\n\n try {\n client.send(frameBuffer, { binary: true }, (error?: Error) => {\n const latestClientState = this.clientStateBySocket.get(client);\n if (latestClientState) {\n latestClientState.frameSendInFlight = false;\n }\n if (error) {\n this.removeClient(client);\n return;\n }\n this.flushQueuedFrameToClient(client);\n });\n } catch {\n clientState.frameSendInFlight = false;\n this.removeClient(client);\n }\n }\n\n private broadcastControl(message: Parameters<typeof sendControlMessage>[1]): void {\n for (const client of this.clients) {\n sendControlMessage(client, message);\n }\n }\n\n private closeAllClients(code: number, reason: string): void {\n for (const client of this.clients) {\n try {\n client.close(code, reason);\n } catch {}\n }\n this.clients.clear();\n for (const clientState of this.clientStateBySocket.values()) {\n if (clientState.pendingFlushTimer) {\n clearTimeout(clientState.pendingFlushTimer);\n }\n }\n this.clientStateBySocket.clear();\n }\n\n private async stop(): Promise<void> {\n if (this.stopped) {\n return;\n }\n this.stopped = true;\n this.started = false;\n\n if (this.tracker) {\n this.tracker.stop();\n this.tracker = null;\n }\n await this.rebinding.catch(() => undefined);\n await this.stopScreencast();\n const browser = this.browser;\n const browserDisconnectedHandler = this.browserDisconnectedHandler;\n this.browser = null;\n this.browserDisconnectedHandler = null;\n this.context = null;\n this.activePage = null;\n if (browser) {\n if (browserDisconnectedHandler) {\n browser.off(\"disconnected\", browserDisconnectedHandler);\n }\n await disconnectPlaywrightChromiumBrowser(browser).catch(() => undefined);\n }\n this.deps.onDrained();\n }\n\n private async stopScreencast(): Promise<void> {\n const cdpSession = this.cdpSession;\n const handler = this.screencastHandler;\n const pageLifecycleCleanup = this.pageLifecycleCleanup;\n\n this.cdpSession = null;\n this.screencastHandler = null;\n this.pageLifecycleCleanup = null;\n this.activeScreencastSizeKey = null;\n if (this.pendingFrameAckTimer !== null) {\n clearTimeout(this.pendingFrameAckTimer);\n this.pendingFrameAckTimer = null;\n }\n\n pageLifecycleCleanup?.();\n\n if (!cdpSession) {\n return;\n }\n\n if (handler) {\n cdpSession.off(\"Page.screencastFrame\", handler);\n }\n\n await cdpSession.send(\"Page.stopScreencast\").catch(() => undefined);\n await cdpSession.detach().catch(() => undefined);\n }\n\n private bindPageLifecycleFrameRefresh(page: Page, cdpSession: CDPSession): void {\n this.pageLifecycleCleanup?.();\n\n const refresh = () => {\n void this.refreshPageFrame(page, cdpSession).catch(() => undefined);\n };\n\n page.on(\"domcontentloaded\", refresh);\n page.on(\"load\", refresh);\n page.on(\"framenavigated\", refresh);\n this.pageLifecycleCleanup = () => {\n page.off(\"domcontentloaded\", refresh);\n page.off(\"load\", refresh);\n page.off(\"framenavigated\", refresh);\n };\n }\n\n private async refreshPageFrame(page: Page, cdpSession: CDPSession): Promise<void> {\n if (this.stopped || this.cdpSession !== cdpSession || this.activePage !== page) {\n return;\n }\n\n const viewport = await readViewportForPage(page);\n if (viewport && this.cdpSession === cdpSession && this.activePage === page) {\n this.activeViewport = viewport;\n this.broadcastControl(\n buildHelloMessage({\n sessionId: this.deps.sessionId,\n fps: this.deps.maxFps,\n quality: this.deps.quality,\n viewport,\n }),\n );\n }\n\n if (this.stopped || this.cdpSession !== cdpSession || this.activePage !== page) {\n return;\n }\n await this.seedInitialFrame(cdpSession);\n }\n\n private async seedInitialFrame(cdpSession: CDPSession): Promise<void> {\n let lastError: unknown = null;\n\n for (let attempt = 1; attempt <= INITIAL_FRAME_CAPTURE_ATTEMPTS; attempt += 1) {\n if (this.stopped || this.cdpSession !== cdpSession) {\n return;\n }\n\n try {\n const screenshotData = await this.captureCurrentFrame(cdpSession);\n if (this.stopped || this.cdpSession !== cdpSession) {\n return;\n }\n\n const frameBuffer = Buffer.from(screenshotData, \"base64\");\n this.lastFrameBuffer = frameBuffer;\n this.lastFrameSentAt = Date.now();\n this.broadcastFrame(frameBuffer);\n return;\n } catch (error) {\n lastError = error;\n }\n\n if (attempt < INITIAL_FRAME_CAPTURE_ATTEMPTS) {\n await new Promise((resolve) => setTimeout(resolve, INITIAL_FRAME_CAPTURE_RETRY_DELAY_MS));\n }\n }\n\n if (lastError instanceof Error) {\n throw lastError;\n }\n\n throw new Error(\"Failed to capture initial stream screenshot.\");\n }\n\n private async captureCurrentFrame(cdpSession: CDPSession): Promise<string> {\n const primaryParams = {\n format: \"jpeg\" as const,\n quality: this.deps.quality,\n optimizeForSpeed: true as const,\n };\n try {\n const result = (await cdpSession.send(\"Page.captureScreenshot\", primaryParams)) as {\n readonly data?: unknown;\n } | null;\n if (result && typeof result.data === \"string\" && result.data.length > 0) {\n return result.data;\n }\n } catch {}\n\n const fallbackResult = (await cdpSession.send(\"Page.captureScreenshot\", {\n format: \"jpeg\",\n quality: this.deps.quality,\n })) as {\n readonly data?: unknown;\n } | null;\n if (\n !fallbackResult ||\n typeof fallbackResult.data !== \"string\" ||\n fallbackResult.data.length === 0\n ) {\n throw new Error(\"Failed to capture initial stream screenshot.\");\n }\n\n return fallbackResult.data;\n }\n\n private getRequestedScreencastSize(): RequestedStreamSize | null {\n if (this.clients.size === 0 || !this.activeViewport) {\n return null;\n }\n\n const requestedSizes: RequestedStreamSize[] = [];\n for (const client of this.clients) {\n const requestedSize = this.clientStateBySocket.get(client)?.requestedRenderSize ?? null;\n if (!requestedSize) {\n return null;\n }\n requestedSizes.push(requestedSize);\n }\n\n return selectScreencastSize({\n viewport: this.activeViewport,\n requestedSizes,\n });\n }\n\n private getRequestedScreencastSizeKey(): string | null {\n const size = this.getRequestedScreencastSize();\n return size ? `${size.width}x${size.height}` : null;\n }\n}\n\nasync function readViewportForPage(page: Page): Promise<OpensteerViewport | null> {\n const cdp = await page.context().newCDPSession(page);\n try {\n const result = (await cdp.send(\"Page.getLayoutMetrics\")) as {\n readonly cssVisualViewport?: {\n readonly clientWidth?: unknown;\n readonly clientHeight?: unknown;\n };\n readonly cssLayoutViewport?: {\n readonly clientWidth?: unknown;\n readonly clientHeight?: unknown;\n };\n readonly visualViewport?: {\n readonly clientWidth?: unknown;\n readonly clientHeight?: unknown;\n };\n readonly layoutViewport?: {\n readonly clientWidth?: unknown;\n readonly clientHeight?: unknown;\n };\n } | null;\n const candidates = [\n result?.cssVisualViewport,\n result?.cssLayoutViewport,\n result?.visualViewport,\n result?.layoutViewport,\n ];\n\n for (const candidate of candidates) {\n const width = normalizeViewportDimension(candidate?.clientWidth);\n const height = normalizeViewportDimension(candidate?.clientHeight);\n if (width !== null && height !== null) {\n return { width, height };\n }\n }\n return null;\n } catch {\n const viewportSize = page.viewportSize();\n if (!viewportSize) {\n return null;\n }\n const width = normalizeViewportDimension(viewportSize.width);\n const height = normalizeViewportDimension(viewportSize.height);\n return width !== null && height !== null ? { width, height } : null;\n } finally {\n await cdp.detach().catch(() => undefined);\n }\n}\n\nfunction normalizeViewportDimension(value: unknown): number | null {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return null;\n }\n\n const normalized = Math.floor(value);\n if (normalized < 100) {\n return null;\n }\n return Math.min(8_192, normalized);\n}\n\nfunction readTextFrame(raw: RawData): string {\n if (typeof raw === \"string\") {\n return raw;\n }\n if (raw instanceof ArrayBuffer) {\n return Buffer.from(raw).toString(\"utf8\");\n }\n if (Array.isArray(raw)) {\n return Buffer.concat(raw).toString(\"utf8\");\n }\n return raw.toString(\"utf8\");\n}\n\nasync function connectPlaywrightChromiumBrowser(input: { readonly url: string }): Promise<Browser> {\n const { connectPlaywrightChromiumBrowser: connect } =\n await import(\"@opensteer/engine-playwright\");\n return connect(input);\n}\n\nasync function disconnectPlaywrightChromiumBrowser(browser: Browser): Promise<void> {\n const { disconnectPlaywrightChromiumBrowser: disconnect } =\n await import(\"@opensteer/engine-playwright\");\n await disconnect(browser);\n}\n","import { randomBytes } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { once } from \"node:events\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type {\n OpensteerLocalViewSessionCloseResponse,\n OpensteerLocalViewSessionsResponse,\n OpensteerSessionAccessGrantResponse,\n} from \"@opensteer/protocol\";\n\nimport { listResolvedLocalViewSessions, resolveLocalViewSession } from \"./discovery.js\";\nimport { LocalViewCdpProxy } from \"./cdp-proxy.js\";\nimport { CURRENT_PROCESS_OWNER } from \"../local-browser/process-owner.js\";\nimport { LocalViewRuntimeState } from \"./runtime-state.js\";\nimport { clearLocalViewServiceState } from \"./service-state.js\";\nimport {\n OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT,\n OPENSTEER_LOCAL_VIEW_SERVICE_VERSION,\n writeLocalViewServiceState,\n} from \"./service-state.js\";\nimport { LocalViewStreamHub } from \"./view-stream.js\";\nimport { LocalViewWebSocketServer } from \"./ws-types.js\";\n\nconst DEFAULT_MAX_FPS = 12;\nconst DEFAULT_QUALITY = 75;\nconst DEFAULT_MAX_CLIENT_BUFFER_BYTES = 512 * 1024;\nconst LOCAL_VIEW_ACCESS_EXPIRES_AT = Number.MAX_SAFE_INTEGER;\n\nexport interface LocalViewServer {\n readonly url: string;\n readonly token: string;\n close(): Promise<void>;\n}\n\nexport async function startLocalViewServer(\n input: {\n readonly port?: number;\n readonly token?: string;\n readonly onClosed?: () => void | Promise<void>;\n } = {},\n): Promise<LocalViewServer> {\n const token = input.token ?? randomBytes(24).toString(\"hex\");\n const runtimeState = new LocalViewRuntimeState();\n const viewStreamHub = new LocalViewStreamHub({\n runtimeState,\n maxFps: DEFAULT_MAX_FPS,\n quality: DEFAULT_QUALITY,\n maxClientBufferBytes: DEFAULT_MAX_CLIENT_BUFFER_BYTES,\n });\n const cdpProxy = new LocalViewCdpProxy({\n runtimeState,\n });\n\n const httpServer = createServer((request, response) => {\n void handleHttpRequest({ request, response, token, shutdown: closeServer }).catch(() => {\n if (!response.headersSent && !response.writableEnded) {\n writeJson(response, 500, { error: \"Internal server error.\" });\n return;\n }\n response.destroy();\n });\n });\n\n const viewWss = new LocalViewWebSocketServer({ noServer: true });\n viewWss.on(\"connection\", (ws, request: IncomingMessage) => {\n const url = new URL(request.url ?? \"/\", \"http://localhost\");\n const parts = url.pathname.split(\"/\").filter(Boolean);\n const sessionId = parts[2];\n if (!sessionId) {\n ws.close(1008, \"Session id is required.\");\n return;\n }\n viewStreamHub.attachClient(sessionId, ws);\n });\n\n httpServer.on(\"upgrade\", (request, socket, head) => {\n const url = new URL(request.url ?? \"/\", \"http://localhost\");\n const tokenParam = url.searchParams.get(\"token\");\n if (tokenParam !== token || !isAllowedOrigin(request.headers.origin)) {\n socket.destroy();\n return;\n }\n\n const parts = url.pathname.split(\"/\").filter(Boolean);\n if (parts[0] !== \"ws\" || parts.length !== 3) {\n socket.destroy();\n return;\n }\n\n if (parts[1] === \"view\") {\n viewWss.handleUpgrade(request, socket, head, (ws) => {\n viewWss.emit(\"connection\", ws, request);\n });\n return;\n }\n\n if (parts[1] === \"cdp\") {\n cdpProxy.handleUpgrade(request, socket, head);\n return;\n }\n\n socket.destroy();\n });\n\n let closePromise: Promise<void> | undefined;\n async function closeServer(): Promise<void> {\n closePromise ??= (async () => {\n viewWss.clients.forEach((client) => {\n try {\n client.close();\n } catch {}\n });\n viewWss.close();\n cdpProxy.close();\n httpServer.close();\n await once(httpServer, \"close\");\n await clearLocalViewServiceState({ pid: process.pid, token });\n await input.onClosed?.();\n })();\n await closePromise;\n }\n\n httpServer.listen(input.port ?? 0, \"127.0.0.1\");\n await once(httpServer, \"listening\");\n const address = httpServer.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Failed to resolve the local view server address.\");\n }\n\n const url = `http://127.0.0.1:${String(address.port)}`;\n await writeLocalViewServiceState({\n layout: OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT,\n version: OPENSTEER_LOCAL_VIEW_SERVICE_VERSION,\n pid: process.pid,\n processStartedAtMs: CURRENT_PROCESS_OWNER.processStartedAtMs,\n startedAt: Date.now(),\n port: address.port,\n token,\n url,\n });\n\n return {\n url,\n token,\n close: closeServer,\n };\n}\n\nasync function handleHttpRequest(args: {\n readonly request: IncomingMessage;\n readonly response: ServerResponse;\n readonly token: string;\n readonly shutdown: () => Promise<void>;\n}): Promise<void> {\n const url = new URL(args.request.url ?? \"/\", \"http://localhost\");\n\n if (url.pathname === \"/api/health\") {\n if (!isAuthorizedApiRequest(args.request, args.token)) {\n writeJson(args.response, 401, { error: \"Unauthorized.\" });\n return;\n }\n writeJson(args.response, 200, { ok: true });\n return;\n }\n\n if (url.pathname === \"/api/sessions\") {\n if (!isAuthorizedApiRequest(args.request, args.token)) {\n writeJson(args.response, 401, { error: \"Unauthorized.\" });\n return;\n }\n const sessions = await listResolvedLocalViewSessions();\n const payload: OpensteerLocalViewSessionsResponse = { sessions };\n writeJson(args.response, 200, payload);\n return;\n }\n\n if (url.pathname === \"/api/service/stop\") {\n if (!isAuthorizedApiRequest(args.request, args.token)) {\n writeJson(args.response, 401, { error: \"Unauthorized.\" });\n return;\n }\n if (args.request.method !== \"POST\") {\n writeJson(args.response, 405, { error: \"Method not allowed.\" });\n return;\n }\n\n args.response.once(\"finish\", () => {\n void args.shutdown();\n });\n writeJson(args.response, 200, { stopped: true });\n return;\n }\n\n const accessMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/access$/u);\n if (accessMatch) {\n if (!isAuthorizedApiRequest(args.request, args.token)) {\n writeJson(args.response, 401, { error: \"Unauthorized.\" });\n return;\n }\n const sessionId = decodeURIComponent(accessMatch[1]!);\n if (!(await resolveLocalViewSession(sessionId))) {\n writeJson(args.response, 404, { error: \"Session not found.\" });\n return;\n }\n const payload: OpensteerSessionAccessGrantResponse = {\n sessionId,\n expiresAt: LOCAL_VIEW_ACCESS_EXPIRES_AT,\n grants: {\n view: {\n kind: \"view\",\n transport: \"ws\",\n url: `${resolveWsBaseUrl(args.request)}/ws/view/${encodeURIComponent(sessionId)}`,\n token: args.token,\n expiresAt: LOCAL_VIEW_ACCESS_EXPIRES_AT,\n },\n cdp: {\n kind: \"cdp\",\n transport: \"ws\",\n url: `${resolveWsBaseUrl(args.request)}/ws/cdp/${encodeURIComponent(sessionId)}`,\n token: args.token,\n expiresAt: LOCAL_VIEW_ACCESS_EXPIRES_AT,\n },\n },\n };\n writeJson(args.response, 200, payload);\n return;\n }\n\n const closeMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/close$/u);\n if (closeMatch) {\n if (!isAuthorizedApiRequest(args.request, args.token)) {\n writeJson(args.response, 401, { error: \"Unauthorized.\" });\n return;\n }\n if (args.request.method !== \"POST\") {\n writeJson(args.response, 405, { error: \"Method not allowed.\" });\n return;\n }\n\n const sessionId = decodeURIComponent(closeMatch[1]!);\n const { closeLocalViewSessionBrowser, LocalViewSessionCloseError } =\n await import(\"./session-control.js\");\n try {\n await closeLocalViewSessionBrowser(sessionId);\n } catch (error) {\n if (error instanceof LocalViewSessionCloseError) {\n writeJson(args.response, error.statusCode, { error: error.message });\n return;\n }\n throw error;\n }\n\n const payload: OpensteerLocalViewSessionCloseResponse = {\n sessionId,\n closed: true,\n };\n writeJson(args.response, 200, payload);\n return;\n }\n\n if (url.pathname === \"/favicon.ico\") {\n args.response.statusCode = 204;\n args.response.end();\n return;\n }\n\n if (\n url.pathname === \"/\" ||\n url.pathname.startsWith(\"/assets/\") ||\n url.pathname.startsWith(\"/images/\")\n ) {\n await serveStaticAsset(args.response, url.pathname, args.token);\n return;\n }\n\n args.response.statusCode = 404;\n args.response.end(\"not found\");\n}\n\nasync function serveStaticAsset(\n response: ServerResponse,\n pathname: string,\n token: string,\n): Promise<void> {\n const publicDir = resolveLocalViewPublicDir();\n const relativePath = pathname === \"/\" ? \"index.html\" : pathname.slice(1);\n const assetPath = path.resolve(publicDir, relativePath);\n const relativeAssetPath = path.relative(publicDir, assetPath);\n if (\n relativeAssetPath.startsWith(\"..\") ||\n path.isAbsolute(relativeAssetPath) ||\n !existsSync(assetPath)\n ) {\n response.statusCode = 404;\n response.end(\"not found\");\n return;\n }\n\n if (relativePath === \"index.html\") {\n const html = await readFile(assetPath, \"utf8\");\n response.setHeader(\"content-type\", \"text/html; charset=utf-8\");\n response.setHeader(\"cache-control\", \"no-store\");\n response.end(\n html.replace(\n \"__OPENSTEER_LOCAL_BOOTSTRAP_JSON__\",\n JSON.stringify({\n apiBasePath: \"/api\",\n token,\n }),\n ),\n );\n return;\n }\n\n response.setHeader(\"content-type\", guessContentType(assetPath));\n response.setHeader(\"cache-control\", \"no-store\");\n response.end(await readFile(assetPath));\n}\n\nfunction resolveLocalViewPublicDir(): string {\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(moduleDir, \"local-view\", \"public\"),\n path.resolve(moduleDir, \"public\"),\n path.resolve(moduleDir, \"..\", \"local-view\", \"public\"),\n ];\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n throw new Error(`Could not resolve local view public assets from ${moduleDir}.`);\n}\n\nfunction isAuthorizedApiRequest(request: IncomingMessage, token: string): boolean {\n return (\n request.headers[\"x-opensteer-local-token\"] === token && isAllowedOrigin(request.headers.origin)\n );\n}\n\nfunction isAllowedOrigin(origin: string | undefined): boolean {\n if (origin === undefined) {\n return true;\n }\n try {\n const url = new URL(origin);\n const host = url.hostname;\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\" || host === \"[::1]\";\n } catch {\n return false;\n }\n}\n\nfunction resolveWsBaseUrl(request: IncomingMessage): string {\n const host = request.headers.host ?? \"127.0.0.1\";\n return `ws://${host}`;\n}\n\nfunction writeJson(response: ServerResponse, statusCode: number, value: unknown): void {\n response.statusCode = statusCode;\n response.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n response.end(JSON.stringify(value));\n}\n\nfunction guessContentType(assetPath: string): string {\n if (assetPath.endsWith(\".css\")) {\n return \"text/css; charset=utf-8\";\n }\n if (assetPath.endsWith(\".js\")) {\n return \"application/javascript; charset=utf-8\";\n }\n if (assetPath.endsWith(\".svg\")) {\n return \"image/svg+xml\";\n }\n if (assetPath.endsWith(\".json\")) {\n return \"application/json; charset=utf-8\";\n }\n if (assetPath.endsWith(\".png\")) {\n return \"image/png\";\n }\n if (assetPath.endsWith(\".ico\")) {\n return \"image/x-icon\";\n }\n return \"application/octet-stream\";\n}\n","import { randomBytes } from \"node:crypto\";\n\nimport { startLocalViewServer } from \"./server.js\";\n\nexport async function runLocalViewService(): Promise<void> {\n const server = await startLocalViewServer({\n token: process.env.OPENSTEER_LOCAL_VIEW_BOOT_TOKEN ?? randomBytes(24).toString(\"hex\"),\n onClosed: () => {\n process.exit(0);\n },\n });\n\n const handleShutdownSignal = () => {\n void server.close();\n };\n process.once(\"SIGINT\", handleShutdownSignal);\n process.once(\"SIGTERM\", handleShutdownSignal);\n\n await new Promise<void>(() => undefined);\n}\n"]}
@@ -2,7 +2,7 @@ import { execFileSync, execFile } from 'child_process';
2
2
  import { existsSync, readFileSync } from 'fs';
3
3
  import { homedir } from 'os';
4
4
  import path3, { join, resolve, basename } from 'path';
5
- import { mkdir, access, readFile, writeFile, rename, open, readdir, rm } from 'fs/promises';
5
+ import { mkdir, access, readFile, writeFile, rename, open, readdir, rm, stat } from 'fs/promises';
6
6
  import { randomUUID, createHash } from 'crypto';
7
7
  import { pathToFileURL } from 'url';
8
8
  import { promisify } from 'util';
@@ -692,6 +692,11 @@ function stableJsonString(value) {
692
692
 
693
693
  // ../runtime-core/src/internal/filesystem.ts
694
694
  var LOCK_RETRY_DELAYS_MS = [1, 2, 5, 10, 20, 50];
695
+ var LOCK_METADATA_FILENAME = "owner.json";
696
+ var LOCK_METADATA_VERSION = 1;
697
+ var LOCK_HEARTBEAT_INTERVAL_MS = 1e3;
698
+ var LOCK_ORPHAN_GRACE_MS = 2e3;
699
+ var LOCK_METADATALESS_STALE_MS = 3e4;
695
700
  function normalizeNonEmptyString(name, value) {
696
701
  const normalized = value.trim();
697
702
  if (normalized.length === 0) {
@@ -797,24 +802,119 @@ function isAlreadyExistsError(error) {
797
802
  }
798
803
  async function withFilesystemLock(lockPath, task) {
799
804
  await ensureDirectory(path3.dirname(lockPath));
805
+ const ownerToken = randomUUID();
800
806
  let attempt = 0;
801
807
  while (true) {
802
808
  try {
803
809
  await mkdir(lockPath);
810
+ const acquiredAt = Date.now();
811
+ await writeLockMetadata(lockPath, {
812
+ version: LOCK_METADATA_VERSION,
813
+ ownerToken,
814
+ pid: process.pid,
815
+ acquiredAt,
816
+ heartbeatAt: acquiredAt
817
+ });
804
818
  break;
805
819
  } catch (error) {
806
820
  if (!isAlreadyExistsError(error)) {
807
821
  throw error;
808
822
  }
823
+ if (await tryRecoverFilesystemLock(lockPath)) {
824
+ attempt = 0;
825
+ continue;
826
+ }
809
827
  const delayMs = LOCK_RETRY_DELAYS_MS[Math.min(attempt, LOCK_RETRY_DELAYS_MS.length - 1)];
810
828
  attempt += 1;
811
829
  await new Promise((resolve3) => setTimeout(resolve3, delayMs));
812
830
  }
813
831
  }
832
+ const heartbeatTimer = setInterval(() => {
833
+ void touchLockMetadata(lockPath, ownerToken);
834
+ }, LOCK_HEARTBEAT_INTERVAL_MS);
835
+ heartbeatTimer.unref?.();
814
836
  try {
815
837
  return await task();
816
838
  } finally {
817
- await rm(lockPath, { recursive: true, force: true });
839
+ clearInterval(heartbeatTimer);
840
+ const metadata = await readLockMetadata(lockPath);
841
+ if (metadata?.ownerToken === ownerToken) {
842
+ await rm(lockPath, { recursive: true, force: true });
843
+ }
844
+ }
845
+ }
846
+ async function tryRecoverFilesystemLock(lockPath) {
847
+ if (!await shouldRecoverFilesystemLock(lockPath)) {
848
+ return false;
849
+ }
850
+ await rm(lockPath, { recursive: true, force: true });
851
+ return true;
852
+ }
853
+ async function shouldRecoverFilesystemLock(lockPath) {
854
+ const metadata = await readLockMetadata(lockPath);
855
+ if (metadata !== void 0) {
856
+ if (isProcessRunning(metadata.pid)) {
857
+ return false;
858
+ }
859
+ return Date.now() - metadata.heartbeatAt >= LOCK_ORPHAN_GRACE_MS;
860
+ }
861
+ const lockStat = await stat(lockPath).catch(() => void 0);
862
+ if (lockStat === void 0) {
863
+ return false;
864
+ }
865
+ return Date.now() - lockStat.mtimeMs >= LOCK_METADATALESS_STALE_MS;
866
+ }
867
+ async function readLockMetadata(lockPath) {
868
+ const metadataPath = path3.join(lockPath, LOCK_METADATA_FILENAME);
869
+ if (!await pathExists(metadataPath)) {
870
+ return void 0;
871
+ }
872
+ try {
873
+ const parsed = await readJsonFile(metadataPath);
874
+ const pid = parsed.pid;
875
+ const acquiredAt = parsed.acquiredAt;
876
+ const heartbeatAt = parsed.heartbeatAt;
877
+ if (parsed.version !== LOCK_METADATA_VERSION || typeof parsed.ownerToken !== "string" || parsed.ownerToken.length === 0 || typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || typeof acquiredAt !== "number" || !Number.isFinite(acquiredAt) || typeof heartbeatAt !== "number" || !Number.isFinite(heartbeatAt)) {
878
+ return void 0;
879
+ }
880
+ return {
881
+ version: LOCK_METADATA_VERSION,
882
+ ownerToken: parsed.ownerToken,
883
+ pid,
884
+ acquiredAt,
885
+ heartbeatAt
886
+ };
887
+ } catch {
888
+ return void 0;
889
+ }
890
+ }
891
+ async function writeLockMetadata(lockPath, metadata) {
892
+ try {
893
+ await writeJsonFileAtomic(path3.join(lockPath, LOCK_METADATA_FILENAME), metadata);
894
+ } catch (error) {
895
+ await rm(lockPath, { recursive: true, force: true }).catch(() => void 0);
896
+ throw error;
897
+ }
898
+ }
899
+ async function touchLockMetadata(lockPath, ownerToken) {
900
+ const metadata = await readLockMetadata(lockPath);
901
+ if (metadata === void 0 || metadata.ownerToken !== ownerToken) {
902
+ return;
903
+ }
904
+ await writeJsonFileAtomic(path3.join(lockPath, LOCK_METADATA_FILENAME), {
905
+ ...metadata,
906
+ heartbeatAt: Date.now()
907
+ }).catch(() => void 0);
908
+ }
909
+ function isProcessRunning(pid) {
910
+ if (!Number.isInteger(pid) || pid <= 0) {
911
+ return false;
912
+ }
913
+ try {
914
+ process.kill(pid, 0);
915
+ return true;
916
+ } catch (error) {
917
+ return error?.code === "EPERM";
818
918
  }
819
919
  }
820
920
 
@@ -858,11 +958,31 @@ async function writePersistedSessionRecord(rootPath, record) {
858
958
  async function clearPersistedSessionRecord(rootPath, provider) {
859
959
  await rm(resolveLiveSessionRecordPath(rootPath, provider), { force: true });
860
960
  }
961
+ function getPersistedLocalBrowserSessionOwnership(record) {
962
+ return record.ownership === "attached" ? "attached" : "owned";
963
+ }
964
+ async function isAttachedLocalBrowserSessionReachable(record) {
965
+ if (getPersistedLocalBrowserSessionOwnership(record) !== "attached") {
966
+ return false;
967
+ }
968
+ if (record.engine !== "playwright" || record.endpoint === void 0) {
969
+ return false;
970
+ }
971
+ try {
972
+ await inspectCdpEndpoint({
973
+ endpoint: record.endpoint,
974
+ timeoutMs: 1500
975
+ });
976
+ return true;
977
+ } catch {
978
+ return false;
979
+ }
980
+ }
861
981
  function isPersistedCloudSessionRecord(value) {
862
982
  return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "cloud" && typeof value.sessionId === "string" && value.sessionId.length > 0 && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt);
863
983
  }
864
984
  function isPersistedLocalBrowserSessionRecord(value) {
865
- return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "local" && (value.engine === "playwright" || value.engine === "abp") && typeof value.pid === "number" && Number.isFinite(value.pid) && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && typeof value.userDataDir === "string" && value.userDataDir.length > 0;
985
+ return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "local" && (value.engine === "playwright" || value.engine === "abp") && (value.ownership === void 0 || value.ownership === "owned" || value.ownership === "attached") && typeof value.pid === "number" && Number.isFinite(value.pid) && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && typeof value.userDataDir === "string" && value.userDataDir.length > 0;
866
986
  }
867
987
  function resolveOpensteerStateDir() {
868
988
  const explicit = process.env.OPENSTEER_HOME?.trim();
@@ -906,19 +1026,40 @@ function resolveLocalViewServiceStatePath() {
906
1026
  var OPENSTEER_LOCAL_VIEW_SESSION_LAYOUT = "opensteer-local-view-session";
907
1027
  var OPENSTEER_LOCAL_VIEW_SESSION_VERSION = 1;
908
1028
  function buildLocalViewSessionId(input) {
1029
+ const ownership = input.ownership ?? "owned";
1030
+ const identity = ownership === "attached" ? input.endpoint ?? input.remoteDebuggingUrl ?? input.baseUrl ?? "attached" : `pid:${String(input.pid ?? 0)}`;
909
1031
  const hash = createHash("sha256").update(`${input.rootPath}
910
- ${String(input.pid)}
1032
+ ${ownership}
1033
+ ${identity}
911
1034
  ${String(input.startedAt)}`).digest("hex");
912
1035
  return `local_${hash.slice(0, 24)}`;
913
1036
  }
1037
+ function buildLocalViewSessionIdForRecord(input) {
1038
+ const ownership = getPersistedLocalBrowserSessionOwnership(input.live);
1039
+ if (ownership === "attached") {
1040
+ return buildLocalViewSessionId({
1041
+ rootPath: input.rootPath,
1042
+ ownership,
1043
+ startedAt: input.live.startedAt,
1044
+ ...input.live.endpoint === void 0 ? {} : { endpoint: input.live.endpoint },
1045
+ ...input.live.baseUrl === void 0 ? {} : { baseUrl: input.live.baseUrl },
1046
+ ...input.live.remoteDebuggingUrl === void 0 ? {} : { remoteDebuggingUrl: input.live.remoteDebuggingUrl }
1047
+ });
1048
+ }
1049
+ return buildLocalViewSessionId({
1050
+ rootPath: input.rootPath,
1051
+ ownership,
1052
+ startedAt: input.live.startedAt,
1053
+ pid: input.live.pid
1054
+ });
1055
+ }
914
1056
  function createLocalViewSessionManifest(input) {
915
1057
  return {
916
1058
  layout: OPENSTEER_LOCAL_VIEW_SESSION_LAYOUT,
917
1059
  version: OPENSTEER_LOCAL_VIEW_SESSION_VERSION,
918
- sessionId: buildLocalViewSessionId({
1060
+ sessionId: buildLocalViewSessionIdForRecord({
919
1061
  rootPath: input.rootPath,
920
- pid: input.live.pid,
921
- startedAt: input.live.startedAt
1062
+ live: input.live
922
1063
  }),
923
1064
  rootPath: input.rootPath,
924
1065
  ...input.workspace === void 0 ? {} : { workspace: input.workspace },
@@ -1008,9 +1149,9 @@ async function getProcessLiveness(owner) {
1008
1149
  if (typeof startedAtMs === "number") {
1009
1150
  return hasMatchingProcessStartTime(owner.processStartedAtMs, startedAtMs) ? "live" : "dead";
1010
1151
  }
1011
- return isProcessRunning(owner.pid) ? "unknown" : "dead";
1152
+ return isProcessRunning2(owner.pid) ? "unknown" : "dead";
1012
1153
  }
1013
- function isProcessRunning(pid) {
1154
+ function isProcessRunning2(pid) {
1014
1155
  try {
1015
1156
  process.kill(pid, 0);
1016
1157
  return true;
@@ -1170,6 +1311,6 @@ function isPersistedLocalViewServiceState(value) {
1170
1311
  return value?.layout === OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT && value.version === OPENSTEER_LOCAL_VIEW_SERVICE_VERSION && typeof value.pid === "number" && Number.isFinite(value.pid) && typeof value.processStartedAtMs === "number" && Number.isFinite(value.processStartedAtMs) && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.port === "number" && Number.isFinite(value.port) && typeof value.token === "string" && value.token.length > 0 && typeof value.url === "string" && value.url.length > 0;
1171
1312
  }
1172
1313
 
1173
- export { CURRENT_PROCESS_OWNER, OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT, OPENSTEER_LOCAL_VIEW_SERVICE_VERSION, OpensteerAttachAmbiguousError, __require, buildLocalViewSessionId, canonicalJsonString, clearLocalViewServiceState, clearPersistedSessionRecord, createLocalViewSessionManifest, deleteLocalViewSessionManifest, detectInstalledBrowserBrands, discoverLocalCdpBrowsers, encodePathSegment, ensureDirectory, expandHome, filePathToUri, getBrowserBrand, getLocalViewServiceStateLiveness, getProcessLiveness, inspectCdpEndpoint, isAlreadyExistsError, isLocalViewServiceStateLive, isProcessRunning, joinStoragePath, listJsonFiles, listLocalChromeProfiles, listLocalViewSessionManifests, normalizeNonEmptyString, normalizeTimestamp, parseProcessOwner, pathExists, processOwnersEqual, readBinaryFile, readDevToolsActivePort, readJsonFile, readLocalViewServiceState, readLocalViewSessionManifest, readPersistedCloudSessionRecord, readPersistedLocalBrowserSessionRecord, readPersistedSessionRecord, resolveBrandUserDataDir, resolveChromeExecutablePath, resolveCloudSessionRecordPath, resolveLiveSessionRecordPath, resolveLocalSessionRecordPath, resolveLocalViewPreferencesPath, resolveLocalViewServiceLockDir, resolveStoragePath, selectAttachBrowserCandidate, sha256Hex, toCanonicalJsonValue, withFilesystemLock, writeBufferIfMissing, writeJsonFileAtomic, writeJsonFileExclusive, writeLocalViewServiceState, writeLocalViewSessionManifest, writePersistedSessionRecord };
1174
- //# sourceMappingURL=chunk-T5P2QGZ3.js.map
1175
- //# sourceMappingURL=chunk-T5P2QGZ3.js.map
1314
+ export { CURRENT_PROCESS_OWNER, OPENSTEER_LOCAL_VIEW_SERVICE_LAYOUT, OPENSTEER_LOCAL_VIEW_SERVICE_VERSION, OpensteerAttachAmbiguousError, __require, buildLocalViewSessionId, buildLocalViewSessionIdForRecord, canonicalJsonString, clearLocalViewServiceState, clearPersistedSessionRecord, createLocalViewSessionManifest, deleteLocalViewSessionManifest, detectInstalledBrowserBrands, discoverLocalCdpBrowsers, encodePathSegment, ensureDirectory, expandHome, filePathToUri, getBrowserBrand, getLocalViewServiceStateLiveness, getPersistedLocalBrowserSessionOwnership, getProcessLiveness, inspectCdpEndpoint, isAlreadyExistsError, isAttachedLocalBrowserSessionReachable, isLocalViewServiceStateLive, isProcessRunning2 as isProcessRunning, joinStoragePath, listJsonFiles, listLocalChromeProfiles, listLocalViewSessionManifests, normalizeNonEmptyString, normalizeTimestamp, parseProcessOwner, pathExists, processOwnersEqual, readBinaryFile, readDevToolsActivePort, readJsonFile, readLocalViewServiceState, readLocalViewSessionManifest, readPersistedCloudSessionRecord, readPersistedLocalBrowserSessionRecord, readPersistedSessionRecord, resolveBrandUserDataDir, resolveChromeExecutablePath, resolveCloudSessionRecordPath, resolveLiveSessionRecordPath, resolveLocalSessionRecordPath, resolveLocalViewPreferencesPath, resolveLocalViewServiceLockDir, resolveStoragePath, selectAttachBrowserCandidate, sha256Hex, toCanonicalJsonValue, withFilesystemLock, writeBufferIfMissing, writeJsonFileAtomic, writeJsonFileExclusive, writeLocalViewServiceState, writeLocalViewSessionManifest, writePersistedSessionRecord };
1315
+ //# sourceMappingURL=chunk-U4BUCIZ4.js.map
1316
+ //# sourceMappingURL=chunk-U4BUCIZ4.js.map