@ashlr/hub 3.5.0 → 3.5.1
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.
- package/CHANGELOG.md +51 -0
- package/dist/build-identity.json +2 -2
- package/dist/core/fleet/external-skill-audit.js +1 -1
- package/dist/core/fleet/external-skill-audit.js.map +1 -1
- package/dist/core/local-runtime/llama/config.d.ts +28 -6
- package/dist/core/local-runtime/llama/config.js +28 -6
- package/dist/core/local-runtime/llama/config.js.map +1 -1
- package/dist/core/web/public/next/assets/App-BbVoUCIi.js +7 -0
- package/dist/core/web/public/next/assets/App-BbVoUCIi.js.map +1 -0
- package/dist/core/web/public/next/assets/App-Cgi6j1Gk.css +1 -0
- package/dist/core/web/public/next/assets/ApprovalsSection-BW9iVjUa.js +2 -0
- package/dist/core/web/public/next/assets/ApprovalsSection-BW9iVjUa.js.map +1 -0
- package/dist/core/web/public/next/assets/ApprovalsSection-Su-NUTis.css +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-CRqHUhED.js +2 -0
- package/dist/core/web/public/next/assets/AutonomySection-CRqHUhED.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-Cpk_oEhc.css +1 -0
- package/dist/core/web/public/next/assets/ChatSection-5irrh6Jw.js +80 -0
- package/dist/core/web/public/next/assets/ChatSection-5irrh6Jw.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-LQiAn6Eu.css +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-CXevY3Au.js +2 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-CXevY3Au.js.map +1 -0
- package/dist/core/web/public/next/assets/{ConfirmDialog-cYuivhCX.css → ConfirmDialog-Dx15x0Ho.css} +1 -1
- package/dist/core/web/public/next/assets/Dialog-Bn0CgEGz.js +2 -0
- package/dist/core/web/public/next/assets/Dialog-Bn0CgEGz.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-tQ8kFulD.css +1 -0
- package/dist/core/web/public/next/assets/DiffViewer-C8HHTnVE.css +1 -0
- package/dist/core/web/public/next/assets/DiffViewer-QKyisN2L.js +7 -0
- package/dist/core/web/public/next/assets/DiffViewer-QKyisN2L.js.map +1 -0
- package/dist/core/web/public/next/assets/{MutationTokenDialog-jWLLCxWn.css → MutationTokenDialog-CrfJ0PdD.css} +1 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-DbSHPy3w.js +2 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-DbSHPy3w.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-C-PCgCzo.js +7 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-C-PCgCzo.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-CM_8pJs6.css +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-Dw8ZjmkS.js +2 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-Dw8ZjmkS.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-ekyMXAK8.css +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-BII7TTSD.css +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-CWxtTNlD.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-CWxtTNlD.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Bk5HipM0.js +2 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Bk5HipM0.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Dh7A-hLD.css +1 -0
- package/dist/core/web/public/next/assets/UniverseView-Bqa8DH57.css +1 -0
- package/dist/core/web/public/next/assets/UniverseView-D8k9q0ce.js +9 -0
- package/dist/core/web/public/next/assets/UniverseView-D8k9q0ce.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-B2E06ZH1.js +2 -0
- package/dist/core/web/public/next/assets/UsageSection-B2E06ZH1.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-DwgNOYvi.css +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CRfZUV-T.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CRfZUV-T.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-D2E3mU9a.css +1 -0
- package/dist/core/web/public/next/assets/charts-CsrtT4rk.css +1 -0
- package/dist/core/web/public/next/assets/charts-DSUpczxG.js +2 -0
- package/dist/core/web/public/next/assets/charts-DSUpczxG.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js +2 -0
- package/dist/core/web/public/next/assets/fleet-model-ClBbQ0Uj.js.map +1 -0
- package/dist/core/web/public/next/assets/format-BNYWGJat.js +2 -0
- package/dist/core/web/public/next/assets/format-BNYWGJat.js.map +1 -0
- package/dist/core/web/public/next/assets/global-C4jfYHrj.js +2 -0
- package/dist/core/web/public/next/assets/global-C4jfYHrj.js.map +1 -0
- package/dist/core/web/public/next/assets/global-D463gG1X.css +1 -0
- package/dist/core/web/public/next/assets/icons-BxOX8-XB.js +2 -0
- package/dist/core/web/public/next/assets/icons-BxOX8-XB.js.map +1 -0
- package/dist/core/web/public/next/assets/index-BMRIET7F.js +11 -0
- package/dist/core/web/public/next/assets/index-BMRIET7F.js.map +1 -0
- package/dist/core/web/public/next/assets/queries-AxnVa02h.js +2 -0
- package/dist/core/web/public/next/assets/queries-AxnVa02h.js.map +1 -0
- package/dist/core/web/public/next/assets/use-guarded-action-BO6c94Wp.js +2 -0
- package/dist/core/web/public/next/assets/use-guarded-action-BO6c94Wp.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-CvtK6vP6.js.map +1 -0
- package/dist/core/web/public/next/assets/workspace-model-cE4LkKpE.js +2 -0
- package/dist/core/web/public/next/assets/workspace-model-cE4LkKpE.js.map +1 -0
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/node_modules/marked/README.md +8 -0
- package/node_modules/marked/bin/main.js +12 -11
- package/node_modules/marked/lib/marked.d.ts +88 -25
- package/node_modules/marked/lib/marked.esm.js +50 -44
- package/node_modules/marked/lib/marked.esm.js.map +3 -3
- package/node_modules/marked/lib/marked.umd.js +50 -44
- package/node_modules/marked/lib/marked.umd.js.map +3 -3
- package/node_modules/marked/man/marked.1 +1 -1
- package/node_modules/marked/package.json +21 -21
- package/package.json +13 -8
- package/dist/core/web/public/next/assets/App-BCKqSppK.css +0 -1
- package/dist/core/web/public/next/assets/App-CsbPYQqy.js +0 -16
- package/dist/core/web/public/next/assets/App-CsbPYQqy.js.map +0 -1
- package/dist/core/web/public/next/assets/ApprovalsSection-CBZquyLK.js +0 -2
- package/dist/core/web/public/next/assets/ApprovalsSection-CBZquyLK.js.map +0 -1
- package/dist/core/web/public/next/assets/ApprovalsSection-CRP59wSb.css +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-CQVpEdCE.js +0 -2
- package/dist/core/web/public/next/assets/AutonomySection-CQVpEdCE.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-DTN6m6QE.css +0 -1
- package/dist/core/web/public/next/assets/ChatSection-DiRvNX3Q.css +0 -1
- package/dist/core/web/public/next/assets/ChatSection-DmE9K0Tg.js +0 -77
- package/dist/core/web/public/next/assets/ChatSection-DmE9K0Tg.js.map +0 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-deO0C0iY.js +0 -2
- package/dist/core/web/public/next/assets/ConfirmDialog-deO0C0iY.js.map +0 -1
- package/dist/core/web/public/next/assets/Dialog-CNd7q89m.js +0 -2
- package/dist/core/web/public/next/assets/Dialog-CNd7q89m.js.map +0 -1
- package/dist/core/web/public/next/assets/Dialog-DxN7RgB5.css +0 -1
- package/dist/core/web/public/next/assets/DiffViewer-DTO0KRuG.js +0 -7
- package/dist/core/web/public/next/assets/DiffViewer-DTO0KRuG.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffViewer-hN7X6wGT.css +0 -1
- package/dist/core/web/public/next/assets/Epistemic-53PikaUI.js +0 -2
- package/dist/core/web/public/next/assets/Epistemic-53PikaUI.js.map +0 -1
- package/dist/core/web/public/next/assets/Epistemic-DiyMyeaN.css +0 -1
- package/dist/core/web/public/next/assets/Meter-CGBsbXUX.css +0 -1
- package/dist/core/web/public/next/assets/Meter-DRWZQgr1.js +0 -2
- package/dist/core/web/public/next/assets/Meter-DRWZQgr1.js.map +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-DYF8n_RD.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-DYF8n_RD.js.map +0 -1
- package/dist/core/web/public/next/assets/RefreshIndicator-DXJQXKyA.js +0 -2
- package/dist/core/web/public/next/assets/RefreshIndicator-DXJQXKyA.js.map +0 -1
- package/dist/core/web/public/next/assets/RefreshIndicator-O7jUBOmX.css +0 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-DLl4DbGG.css +0 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-hDSEFdLU.js +0 -7
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-hDSEFdLU.js.map +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-BIpdnxp-.css +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-CZd7ln8v.js +0 -2
- package/dist/core/web/public/next/assets/RouteErrorBoundary-CZd7ln8v.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-C9Qs9JWW.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-C9Qs9JWW.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-DGJMdUh2.css +0 -1
- package/dist/core/web/public/next/assets/Skeleton-D2JaTXyv.css +0 -1
- package/dist/core/web/public/next/assets/Skeleton-YkcOpgFb.js +0 -2
- package/dist/core/web/public/next/assets/Skeleton-YkcOpgFb.js.map +0 -1
- package/dist/core/web/public/next/assets/StatusBadge-DJw0LSPg.js +0 -2
- package/dist/core/web/public/next/assets/StatusBadge-DJw0LSPg.js.map +0 -1
- package/dist/core/web/public/next/assets/StatusBadge-TpDqZf6K.css +0 -1
- package/dist/core/web/public/next/assets/TableView-Bj-w1O6o.js +0 -2
- package/dist/core/web/public/next/assets/TableView-Bj-w1O6o.js.map +0 -1
- package/dist/core/web/public/next/assets/TableView-R6Yeztp1.css +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Bs2fxaen.js +0 -2
- package/dist/core/web/public/next/assets/UniverseConsoleApp-Bs2fxaen.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-CiZZxRPV.css +0 -1
- package/dist/core/web/public/next/assets/UniverseView-B6b2hw-8.js +0 -9
- package/dist/core/web/public/next/assets/UniverseView-B6b2hw-8.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseView-gBxl6yum.css +0 -1
- package/dist/core/web/public/next/assets/UsageSection-C__ziNkV.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-C__ziNkV.js.map +0 -1
- package/dist/core/web/public/next/assets/UsageSection-UUYDidOg.css +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-Cu5aG6J6.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-Cu5aG6J6.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-mOAXvWa6.css +0 -1
- package/dist/core/web/public/next/assets/fleet-model-DXCfVtNW.js +0 -2
- package/dist/core/web/public/next/assets/fleet-model-DXCfVtNW.js.map +0 -1
- package/dist/core/web/public/next/assets/format-fggwu_Rs.js +0 -2
- package/dist/core/web/public/next/assets/format-fggwu_Rs.js.map +0 -1
- package/dist/core/web/public/next/assets/global-BHjd6fVZ.js +0 -2
- package/dist/core/web/public/next/assets/global-BHjd6fVZ.js.map +0 -1
- package/dist/core/web/public/next/assets/global-BeRYd1Bu.css +0 -1
- package/dist/core/web/public/next/assets/index-CJ-e8YA9.js +0 -2
- package/dist/core/web/public/next/assets/index-CJ-e8YA9.js.map +0 -1
- package/dist/core/web/public/next/assets/index-CpgkRaTi.js +0 -51
- package/dist/core/web/public/next/assets/index-CpgkRaTi.js.map +0 -1
- package/dist/core/web/public/next/assets/queries-856qUN3Y.js +0 -2
- package/dist/core/web/public/next/assets/queries-856qUN3Y.js.map +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-Bqa2v0a-.css +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-DwaESKVy.js +0 -2
- package/dist/core/web/public/next/assets/use-guarded-action-DwaESKVy.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-model-Dllo8rRt.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-Dllo8rRt.js.map +0 -1
- package/dist/core/web/public/next/assets/workspace-model-JgmWDKt4.js +0 -2
- package/dist/core/web/public/next/assets/workspace-model-JgmWDKt4.js.map +0 -1
- /package/node_modules/marked/{LICENSE.md → LICENSE} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"mappings":";iVAmBA,MAAMA,GAAwB,wBACxBC,GAAsC,CAAC,gBAAiB,cAAc,EAuBrE,SAASC,GAAaC,EAA+C,CAC1E,GAAIA,IAAe,SAAWA,IAAe,OAAQ,OAAOA,EAC5D,GAAI,CACF,OAAO,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAAS,OAC9E,MAAQ,CAEN,MAAO,OACT,CACF,CAMA,SAASC,IAAoC,CAC3C,OAAQ,OAA4D,iBACtE,CAQO,SAASC,GAAmBF,EAAmC,CACpE,GAAI,CACFC,MAAU,cAAcF,GAAaC,CAAU,CAAC,CAClD,MAAQ,CAER,CACF,CAEA,SAASG,GAAiBC,EAAyC,CACjE,OAAO,OAAOA,GAAU,UAAaN,GAA+B,SAASM,CAAK,CACpF,CAUO,SAASC,GAAyBC,EAAwD,CAC/F,SAASC,EAAUC,EAAoB,CAErC,MAAMC,EADUD,EAA6C,QACrC,QACpBL,GAAiBM,CAAO,GAAGH,EAAQG,CAAO,CAChD,CACA,cAAO,iBAAiBZ,GAAuBU,CAAS,EACjD,IAAM,OAAO,oBAAoBV,GAAuBU,CAAS,CAC1E,CCxEA,SAASG,EAAK,CAAE,KAAAC,EAAO,GAAI,MAAAC,EAAO,SAAAC,EAAU,GAAGC,GAA6C,CAC1F,OACEC,OAAC,OACC,MAAOJ,EACP,OAAQA,EACR,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAa,IACb,cAAc,QACd,eAAe,QACf,UAAU,QACT,GAAIC,EAAQ,CAAE,KAAM,OAAU,CAAE,cAAe,IAC/C,GAAGE,EAEH,UAAAF,EAAQI,MAAC,SAAO,SAAAJ,CAAA,CAAM,EAAW,KACjCC,CAAA,GAGP,CAGO,MAAMI,GAAYC,GACvBF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,uHAAuH,EACjI,EAIWG,GAAWD,GACtBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,MAAM,EAAE,MAAM,MAAM,IAAI,OAAO,IAAI,GAAG,MAAM,EACpDA,MAAC,QAAK,EAAE,uFAAuF,GACjG,EAIWI,GAAaF,GACxBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,0EAA0E,EAClFA,MAAC,QAAK,EAAE,uFAAuF,GACjG,EAGWK,GAAaH,GACxBF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,sBAAsB,EAChC,EAGWM,GAAmBJ,GAC9BH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,UAAO,GAAG,IAAI,GAAG,IAAI,EAAE,IAAI,EAC5BA,MAAC,QAAK,EAAE,yBAAyB,GACnC,EAGWO,GAASL,GACpBF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,qBAAqB,EAC/B,EAIWQ,GAAaN,GACxBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,iCAAiC,EACzCA,MAAC,QAAK,EAAE,iBAAiB,EACzBA,MAAC,UAAO,GAAG,IAAI,GAAG,OAAO,EAAE,MAAM,KAAK,eAAe,OAAO,OAAO,GACrE,EAIWS,GAAeP,GAC1BH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,6CAA6C,QACpD,UAAO,GAAG,IAAI,GAAG,MAAM,EAAE,MAAM,QAC/B,UAAO,GAAG,IAAI,GAAG,OAAO,EAAE,MAAM,GACnC,EAsBWU,GAAaR,GACxBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,4BAA4B,EACpCA,MAAC,QAAK,EAAE,WAAW,EACnBA,MAAC,UAAO,GAAG,IAAI,GAAG,OAAO,EAAE,OAAO,KAAK,eAAe,OAAO,OAAO,GACtE,EAGWW,GAAYT,GACvBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,UAAO,GAAG,IAAI,GAAG,IAAI,EAAE,IAAI,EAC5BA,MAAC,QAAK,EAAE,aAAa,EACrBA,MAAC,UAAO,GAAG,IAAI,GAAG,MAAM,EAAE,OAAO,KAAK,eAAe,OAAO,OAAO,GACrE,EAGWY,GAAYV,GACvBF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,uBAAuB,EACjC,EAGWa,GAAcX,GACzBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,UAAO,GAAG,MAAM,GAAG,MAAM,EAAE,MAAM,EAClCA,MAAC,QAAK,EAAE,qBAAqB,GAC/B,EAGWc,GAAYZ,GACvBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,MAAM,EAAE,MAAM,MAAM,IAAI,OAAO,IAAI,GAAG,MAAM,EACpDA,MAAC,QAAK,EAAE,+EAA+E,GACzF,EAGWe,GAAmBb,GAC9BF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,iBAAiB,EAC3B,EASWgB,GAAoBd,GAC/BF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,iBAAiB,EAC3B,EAsBWiB,GAAaf,GACxBF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,0GAA0G,EACpH,EAGWkB,GAAoBhB,GAC/BH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,mCAAmC,EAC3CA,MAAC,QAAK,EAAE,2FAA2F,GACrG,EAgBWmB,GAAYjB,GACvBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,IAAI,EAAE,IAAI,MAAM,KAAK,OAAO,MAAM,GAAG,MAAM,EACnDA,MAAC,QAAK,EAAE,iCAAiC,GAC3C,EAUWoB,GAAWlB,GACtBH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,UAAO,GAAG,IAAI,GAAG,IAAI,EAAE,MAAM,EAC9BA,MAAC,QAAK,EAAE,mHAAmH,GAC7H,EAGWqB,GAAYnB,GACvBF,MAACN,EAAA,CAAM,GAAGQ,EACR,SAAAF,MAAC,QAAK,EAAE,qDAAqD,EAC/D,EAGWsB,GAAepB,GAC1BH,OAACL,EAAA,CAAM,GAAGQ,EACR,UAAAF,MAAC,QAAK,EAAE,MAAM,EAAE,MAAM,MAAM,OAAO,OAAO,MAAM,GAAG,MAAM,EACzDA,MAAC,QAAK,EAAE,wBAAwB,GAClC,ECrNWuB,GAAWtB,GACXuB,GAAerB,GACfsB,GAAgBrB,GAChBsB,GAAYlB,GACZmB,GAAelB,GACfmB,GAAaf,GACbgB,GAAWjB,GACXkB,GAAYb,GACZc,GAAgBhB,GAChBiB,GAAchB,GAK3B,SAAStB,GAAK,CAAE,KAAAC,EAAO,GAAI,SAAAE,EAAU,GAAGC,GAA6C,CACnF,OACEE,MAAC,OACC,QAAQ,YACR,MAAOL,EACP,OAAQA,EACR,KAAK,OACL,OAAO,eACP,YAAa,IACb,cAAc,QACd,eAAe,QACf,cAAY,OACZ,UAAU,QACT,GAAGG,EAEH,SAAAD,CAAA,EAGP,CAEO,SAASoC,GAAUC,EAAkB,CAC1C,OAAOnC,OAACL,GAAA,CAAM,GAAGwC,EAAO,UAAAlC,MAAC,QAAK,EAAE,MAAM,EAAE,IAAI,MAAM,KAAK,OAAO,KAAK,GAAG,MAAM,EAAEA,MAAC,QAAK,EAAE,WAAW,GAAE,CACrG,CAEO,SAASmC,GAAYD,EAAkB,CAC5C,OAAOnC,OAACL,GAAA,CAAM,GAAGwC,EAAO,UAAAlC,MAAC,QAAK,EAAE,MAAM,EAAE,IAAI,MAAM,KAAK,OAAO,KAAK,GAAG,MAAM,EAAEA,MAAC,QAAK,EAAE,UAAU,GAAE,CACpG,CAGO,SAASoC,GAAUF,EAAkB,CAC1C,KAAM,CAAE,KAAAvC,EAAO,GAAI,GAAGG,GAASoC,EAC/B,OACElC,MAAC,OAAI,QAAQ,YAAY,MAAOL,EAAM,OAAQA,EAAM,KAAK,OAAO,OAAO,eAAe,YAAa,IACjG,eAAe,QAAQ,cAAc,QAAQ,cAAY,OAAO,UAAU,QAAS,GAAGG,EACtF,SAAAE,MAAC,QAAK,EAAE,wDAAwD,GAGtE,CAEO,MAAMqC,GAAiE,CAC5E,KAAMd,GACN,SAAUC,GACV,UAAWC,GACX,MAAOC,GACP,SAAUC,EACZ,6RC5CO,SAASW,EAAO,CACrB,QAAAC,EAAU,SACV,KAAA5C,EAAO,KACP,KAAA6C,EACA,aAAAC,EACA,MAAAC,EAAQ,GACR,KAAAC,EAAO,GACP,SAAAC,EAAW,GACX,UAAAC,EACA,SAAAhD,EACA,SAAAiD,EACA,KAAAC,EAAO,SACP,GAAGjD,EACL,EAAgB,CACd,MAAMkD,GAAU,CACdC,EAAO,OACPA,EAAOV,CAAO,EACdU,EAAOtD,CAAI,EACXiD,EAAWK,EAAO,SAAW,GAC7BP,EAAQO,EAAO,MAAQ,GACvBJ,GAAa,IAEZ,OAAO,OAAO,EACd,KAAK,GAAG,EAEX,OACE9C,OAAC,UACC,KAAAgD,EACA,UAAWC,GACX,SAAUF,GAAYH,EACtB,YAAWA,GAAQ,OAClB,GAAG7C,GAEH,UAAA0C,QAAQ,QAAK,UAAWS,EAAO,MAAQ,WAAK,EAAU,KACtDL,EAAW,KAAO/C,EAClB4C,EAAezC,MAAC,QAAK,UAAWiD,EAAO,MAAQ,WAAa,EAAU,OAG7E,kJChFMC,GAA4C,CAChD,OAAQ,uBACR,MAAO,sBACP,KAAM,qBACN,MAAO,qBACT,EAeO,SAASC,GAAI,CAAE,SAAAtD,EAAU,OAAAuD,EAAQ,KAAAC,EAAO,GAAO,KAAA1D,EAAO,KAAM,IAAA2D,EAAM,GAAO,MAAA1D,EAAO,UAAAiD,CAAA,EAAuB,CAC5G,MAAMU,EAAUD,GAAOF,IAAW,OAClC,OACErD,OAAC,QACC,UAAW,GAAGkD,EAAO,GAAG,IAAIA,EAAOtD,CAAI,CAAC,IAAI0D,EAAOJ,EAAO,KAAO,EAAE,IAAIJ,GAAa,EAAE,GACtF,MAAAjD,EACA,cAAawD,EAEZ,UAAAG,EACCvD,MAAC,QACC,UAAWiD,EAAO,IAClB,MAAOG,EAAS,CAAE,WAAYF,GAAaE,CAAM,GAAM,OACvD,cAAY,SAEZ,KACHvD,CAAA,GAGP,CC7BO,MAAM2D,EAAmF,CAC9F,CAAE,GAAI,OAAQ,MAAO,OAAQ,OAAQ,eACrC,CAAE,GAAI,WAAY,MAAO,WAAY,OAAQ,mBAC7C,CAAE,GAAI,YAAa,MAAO,YAAa,OAAQ,oBAC/C,CAAE,GAAI,QAAS,MAAO,QAAS,OAAQ,gBACvC,CAAE,GAAI,WAAY,MAAO,WAAY,OAAQ,kBAC/C,EAEMC,GAAc,IAAI,IAAYD,EAAe,IAAKE,GAAMA,EAAE,EAAE,CAAC,EAqBtDC,EAAgB,CAAE,IAAK,IAAK,IAAK,IAAK,IAAK,KAC3CC,EAAkB,CAAE,IAAK,IAAK,IAAK,IAAK,IAAK,KAEpDC,GAAc,oBAEdC,EAAyB,CAC7B,QAAS,OACT,aAAcH,EAAc,IAC5B,iBAAkB,GAClB,cAAe,GACf,eAAgBC,EAAgB,IAChC,iBAAkB,EAClB,QAAS,IACX,EAEO,SAASG,EAAW3E,EAAgB4E,EAA0D,CACnG,MAAMC,EAAI,OAAO7E,CAAK,EACtB,MAAI,CAAC,OAAO,SAAS6E,CAAC,GAAKA,GAAK,EAAUD,EAAM,IACzC,KAAK,IAAIA,EAAM,IAAK,KAAK,IAAIA,EAAM,IAAK,KAAK,MAAMC,CAAC,CAAC,CAAC,CAC/D,CAKA,SAASC,IAAqB,CAC5B,GAAI,CACF,MAAMC,EAAM,aAAa,QAAQN,EAAW,EAC5C,GAAI,CAACM,EAAK,OAAOL,EACjB,MAAMM,EAAS,KAAK,MAAMD,CAAG,EAC7B,MAAO,CACL,GAAGL,EACH,QAAS,OAAOM,EAAO,SAAY,UAAYX,GAAY,IAAIW,EAAO,OAAO,EAAKA,EAAO,QAA6BN,EAAS,QAC/H,aAAcC,EAAWK,EAAO,aAAcT,CAAa,EAC3D,iBAAkBS,EAAO,mBAAqB,GAC9C,cAAeA,EAAO,gBAAkB,GACxC,eAAgBL,EAAWK,EAAO,eAAgBR,CAAe,EAErE,MAAQ,CACN,OAAOE,CACT,CACF,CAEA,IAAIO,EAAsBH,GAAA,EACtBI,GAAQ,EACZ,MAAMC,MAAgB,IAEtB,SAASC,GAAQC,EAA0B,CACzC,MAAMC,EAAqB,CACzB,QAASD,EAAK,QACd,aAAcA,EAAK,aACnB,iBAAkBA,EAAK,iBACvB,cAAeA,EAAK,cACpB,eAAgBA,EAAK,gBAEvB,GAAI,CACF,aAAa,QAAQZ,GAAa,KAAK,UAAUa,CAAO,CAAC,CAC3D,MAAQ,CAER,CACF,CAGA,SAASC,EAAMC,EAAoC,CACjD,MAAMH,EAAO,CAAE,GAAGJ,EAAO,GAAGO,CAAA,EAC5B,GAAK,OAAO,KAAKA,CAAK,EAA6B,MAAOC,GAAM,OAAO,GAAGR,EAAMQ,CAAC,EAAGJ,EAAKI,CAAC,CAAC,CAAC,EAAG,OAC/F,MAAMC,EAAiB,CAAC,UAAW,eAAgB,mBAAoB,gBAAiB,gBAAgB,EACrG,KAAMD,GAAM,CAAC,OAAO,GAAGR,EAAMQ,CAAC,EAAGJ,EAAKI,CAAC,CAAC,CAAC,EAC5CR,EAAQI,EACJK,MAAuBL,CAAI,EAC/B,UAAWM,KAAKR,EAAWQ,EAAA,CAC7B,CAEO,SAASC,GAAiBC,EAAkC,CACjEV,SAAU,IAAIU,CAAQ,EACf,IAAMV,EAAU,OAAOU,CAAQ,CACxC,CAEO,SAASC,IAAgC,CAC9C,OAAOb,CACT,CAEO,SAASc,EAAgBC,EAA+B,CAC7DT,EAAM,CAAE,QAAAS,EAAS,CACnB,CAEO,SAASC,GAAqBC,EAAqB,CACxDX,EAAM,CAAE,aAAcZ,EAAWuB,EAAO3B,CAAa,EAAG,CAC1D,CAEO,SAAS4B,GAAyBC,EAA0B,CACjEb,EAAM,CAAE,iBAAkBa,EAAW,CACvC,CAMO,SAASC,GAAsBC,EAAqB,CACzDf,EAAM,CAAE,cAAee,EAAM,CAC/B,CAEO,SAASC,GAAuBL,EAAqB,CAC1DX,EAAM,CAAE,eAAgBZ,EAAWuB,EAAO1B,CAAe,EAAG,CAC9D,CAOO,SAASgC,GAAyBC,EAAqB,CAC5D,MAAM5B,EAAI,OAAO,SAAS4B,CAAK,EAAI,KAAK,IAAI,EAAG,KAAK,MAAMA,CAAK,CAAC,EAAI,EACpElB,EAAM,CAAE,iBAAkBV,EAAG,CAC/B,CAGO,SAAS6B,EAAoBC,EAA8B,CAChEzB,IAAS,EACTK,EAAM,CAAE,QAAS,OAAQ,QAAS,CAAE,KAAAoB,EAAM,MAAAzB,EAAA,EAAS,CACrD,CAEO,SAAS0B,IAA0B,CACxCrB,EAAM,CAAE,QAAS,KAAM,CACzB,CA4CA,MAAMsB,GAAmB,uBAEnBC,GAAoB,GAG1B,IAAIC,EAAqD,KAEzD,SAASC,IAAkD,CACzD,GAAID,EAAY,OAAOA,EACvB,MAAME,EAAuC,GAC7C,GAAI,CACF,MAAMlC,EAAM,aAAa,QAAQ8B,EAAgB,EAC3C7B,EAASD,EAAO,KAAK,MAAMA,CAAG,EAAgB,KACpD,GAAIC,GAAU,OAAOA,GAAW,UAAY,CAAC,MAAM,QAAQA,CAAM,EAC/D,SAAW,CAACkC,EAAMlH,CAAK,IAAK,OAAO,QAAQgF,CAAiC,EAAG,CAC7E,GAAI,CAAChF,GAAS,OAAOA,GAAU,UAAY,MAAM,QAAQA,CAAK,EAAG,SACjE,KAAM,CAAE,OAAAmH,EAAQ,MAAAC,CAAA,EAAUpH,EACtB,OAAOmH,GAAW,UAAYA,EAAO,SAAW,GAChD,OAAOC,GAAU,UAAYA,EAAM,SAAW,IAClDH,EAAIC,CAAI,EAAI,CAAE,OAAAC,EAAQ,MAAAC,CAAA,EACxB,CAEJ,MAAQ,CAER,CACA,OAAAL,EAAaE,EACNA,CACT,CAQO,SAASI,GAAcC,EAAqD,CACjF,MAAMC,EAASP,GAAA,EACf,GAAIM,EAAa,CACf,MAAME,EAAQD,EAAOD,CAAW,EAChC,GAAIE,EAAO,OAAOA,CACpB,CAEA,MAAMC,EAAO,OAAO,KAAKF,CAAM,EACzBG,EAASD,EAAKA,EAAK,OAAS,CAAC,EACnC,OAAOC,EAASH,EAAOG,CAAM,GAAK,KAAO,IAC3C,CAGO,SAASC,GAAkBL,EAAqBM,EAA6B,CAClF,GAAI,CAACN,GAAe,CAACM,EAAK,QAAU,CAACA,EAAK,MAAO,OACjD,MAAML,EAASP,GAAA,EAEf,OAAOO,EAAOD,CAAW,EACzBC,EAAOD,CAAW,EAAI,CAAE,OAAQM,EAAK,OAAQ,MAAOA,EAAK,OACzD,MAAMH,EAAO,OAAO,KAAKF,CAAM,EAC/B,UAAWM,KAASJ,EAAK,MAAM,EAAG,KAAK,IAAI,EAAGA,EAAK,OAASX,EAAiB,CAAC,EAC5E,OAAOS,EAAOM,CAAK,EAErB,GAAI,CACF,aAAa,QAAQhB,GAAkB,KAAK,UAAUU,CAAM,CAAC,CAC/D,MAAQ,CAER,CACF,CCzGO,MAAMO,GACX,4BAEWC,GACX,UA0QF,SAASC,EAAOhI,EAAgD,CAC9D,OAAO,OAAOA,GAAU,UAAYA,IAAU,MAAQ,CAAC,MAAM,QAAQA,CAAK,EACrEA,EACD,IACN,CAEA,SAASiI,EAAIC,EAAiCC,EAA4B,CACxE,MAAMC,EAAIF,EAAOC,CAAG,EACpB,OAAO,OAAOC,GAAM,UAAYA,EAAE,OAAS,EAAIA,EAAI,IACrD,CAEA,SAASC,EAAIH,EAAiCC,EAA4B,CACxE,MAAMC,EAAIF,EAAOC,CAAG,EACpB,OAAO,OAAOC,GAAM,UAAY,OAAO,SAASA,CAAC,EAAIA,EAAI,IAC3D,CAEA,SAASE,EAAKJ,EAAiCC,EAAaI,EAAW,GAAgB,CACrF,MAAMH,EAAIF,EAAOC,CAAG,EACpB,OAAO,OAAOC,GAAM,UAAYA,EAAIG,CACtC,CAEA,SAASC,EAAKxI,EAA2B,CACvC,OAAO,MAAM,QAAQA,CAAK,EAAIA,EAAQ,EACxC,CAQA,MAAMyI,GAAoB,sGAEnB,SAASC,GAAgB1I,EAA+B,CAC7D,GAAI,OAAOA,GAAU,SAAU,OAAO,KACtC,MAAM2I,EAAU3I,EAAM,OAItB,OAHI2I,EAAQ,SAAW,GAAKA,EAAQ,OAAS,KACzCF,GAAkB,KAAKE,CAAO,GAE9B,SAAS,KAAKA,CAAO,EAAU,KAC5BA,CACT,CAEA,SAASC,EAAa5I,EAAqC,CACzD,OAAIA,IAAU,KAAa,KACpB,KAAK,IAAI,EAAG,KAAK,IAAI,IAAKA,CAAK,CAAC,CACzC,CAEA,SAAS6I,GAAc9D,EAAoC,CACzD,MAAM+D,EAAId,EAAOjD,CAAG,EACpB,GAAI,CAAC+D,EAAG,OAAO,KACf,MAAMC,EAAKd,EAAIa,EAAG,IAAI,GAAKb,EAAIa,EAAG,OAAO,EACzC,GAAIC,IAAO,KAAM,OAAO,KACxB,MAAMC,EAAShB,EAAOc,EAAE,YAAe,EACjCG,EAAeX,EAAKQ,EAAG,cAAc,GAAKR,EAAKQ,EAAG,kBAAkB,EACpEI,EAAcJ,EAAE,SACtB,MAAO,CACL,GAAAC,EACA,MAAOd,EAAIa,EAAG,OAAO,EACrB,YAAaF,EAAaP,EAAIS,EAAG,aAAa,GAAKT,EAAIS,EAAG,cAAc,CAAC,EACzE,SAAUb,EAAIa,EAAG,UAAU,GAAKb,EAAIa,EAAG,WAAW,EAClD,kBACGE,EAASf,EAAIe,EAAQ,kBAAkB,EAAI,OAASf,EAAIa,EAAG,kBAAkB,EAChF,aAAAG,EAIA,SAAU,OAAOC,GAAgB,UAAYA,EAAc,CAACD,CAAA,CAEhE,CAEA,SAASE,GAAepE,EAAqC,CAC3D,MAAM+D,EAAId,EAAOjD,CAAG,EACpB,GAAI,CAAC+D,EAAG,OAAO,KACf,MAAMM,EAAUnB,EAAIa,EAAG,SAAS,EAC1B9D,EAASoE,IAAY,KAAOf,EAAIS,EAAG,SAAS,EAAI,OAAO,WAAWM,CAAO,EAC/E,MAAO,CACL,WAAYd,EAAKQ,EAAG,YAAY,GAAKR,EAAKQ,EAAG,aAAa,EAC1D,UAAWR,EAAKQ,EAAG,WAAW,EAC9B,QAAAM,EACA,aAAc,OAAOpE,GAAW,UAAY,OAAO,SAASA,CAAM,EAAIA,EAAS,KAEnF,CAEA,MAAMqE,GAA+B,CAAC,SAAU,QAAS,MAAM,EAE/D,SAASC,GAAevE,EAA8B,CACpD,MAAM+D,EAAId,EAAOjD,CAAG,EACpB,GAAI,CAAC+D,EAAG,OAAO,KACf,MAAMC,EAAKd,EAAIa,EAAG,IAAI,EAChBS,EAAWtB,EAAIa,EAAG,UAAU,EAClC,GAAIC,IAAO,MAAQQ,IAAa,MAAQ,CAACF,GAAU,SAASE,CAAQ,EAAG,OAAO,KAE9E,MAAMC,EAAUhB,EAAKM,EAAE,OAAU,EAC9B,IAAID,EAAa,EACjB,OAAQY,GAA0BA,IAAM,IAAI,EAEzCxE,EAAQgD,EAAIa,EAAG,OAAO,EACtBY,EAAOzB,EAAIa,EAAG,gBAAgB,EAC9Ba,EAAiB3B,EAAOc,EAAE,WAAc,EAE9C,MAAO,CACL,GAAAC,EACA,MAAOd,EAAIa,EAAG,OAAO,GAAKC,EAC1B,SAAAQ,EACA,MACEtE,IAAU,YAAcA,IAAU,YAAcA,IAAU,cAAgBA,IAAU,cAChFA,EACA,cACN,eAAgByE,IAAS,aAAeA,IAAS,aAAeA,EAAO,UACvE,OAAQzB,EAAIa,EAAG,QAAQ,EACvB,SAAUb,EAAIa,EAAG,UAAU,GAAKb,EAAIa,EAAG,WAAW,EAClD,WAAYb,EAAIa,EAAG,YAAY,EAC/B,QAAAU,EACA,QAASX,GAAcC,EAAE,OAAU,EACnC,QAASK,GAAeL,EAAE,OAAU,EACpC,OAAQb,EAAIa,EAAG,QAAQ,EACvB,YAAac,GAAmBd,EAAGa,CAAc,EACjD,iBAAkBjB,GAAgBI,EAAE,gBAAmB,EACvD,MAAON,EAAKM,EAAE,KAAQ,EAAE,OAAQjE,GAAmB,OAAOA,GAAM,QAAQ,EAE5E,CAWA,SAAS+E,GACPd,EACAe,EACwB,CACxB,GAAIA,EACF,MAAO,CACL,KAAM5B,EAAI4B,EAAU,MAAM,GAAK/B,GAC/B,cAAeG,EAAI4B,EAAU,eAAe,GAAK5B,EAAI4B,EAAU,SAAS,GAG5E,MAAMC,EAAS7B,EAAIa,EAAG,QAAQ,EAC9B,OAAIgB,IAAWhC,GAA8B,KACtC,CAAE,KAAMgC,EAAQ,cAAe/B,EAAA,CACxC,CASA,SAASgC,GAAqBC,EAA8C,CAC1E,MAAMC,EAAOhC,EAAI+B,EAAM,eAAe,EACtC,GAAIC,EAAM,OAAOA,EACjB,MAAMC,EAAYlC,EAAOgC,EAAK,SAAY,EAE1C,MADI,CAACE,GACDjC,EAAIiC,EAAW,OAAO,IAAM,oBAA4B,KAE1DjC,EAAIiC,EAAW,MAAM,GACrB,6IAEJ,CAEO,SAASC,GAAwBpF,EAAuC,CAC7E,MAAMiF,EAAOhC,EAAOjD,CAAG,EACvB,GAAI,CAACiF,EAAM,OAAO,KAClB,MAAMI,EAAc,MAAM,QAAQJ,EAAK,QAAW,EAAIA,EAAK,SAAc,MAAM,QAAQjF,CAAG,EAAIA,EAAM,KACpG,OAAIqF,IAAgB,KAAa,KAC1B,CACL,UAAWnC,EAAI+B,EAAM,WAAW,EAChC,WAAY1B,EAAK0B,EAAM,YAAY,EACnC,SAAUI,EAAY,IAAId,EAAc,EAAE,OAAQe,GAAoBA,IAAM,IAAI,EAChF,cAAeN,GAAqBC,CAAI,EAE5C,CAEA,SAASM,GAAWvF,EAAiC,CACnD,MAAM+D,EAAId,EAAOjD,CAAG,EACpB,GAAI,CAAC+D,EAAG,OAAO,KACf,MAAMyB,EAAMtC,EAAIa,EAAG,KAAK,EACxB,OAAIyB,IAAQ,MAAQ,CAAC,sBAAsB,KAAKA,CAAG,EAAU,KACtD,CACL,IAAAA,EACA,SAAUlC,EAAIS,EAAG,UAAU,GAAK,EAChC,UAAWT,EAAIS,EAAG,WAAW,GAAK,EAClC,WAAYT,EAAIS,EAAG,YAAY,GAAK,EACpC,SAAUT,EAAIS,EAAG,UAAU,GAAK,EAChC,UAAWT,EAAIS,EAAG,WAAW,EAC7B,WAAYT,EAAIS,EAAG,YAAY,EAC/B,aAAcT,EAAIS,EAAG,cAAc,EAEvC,CASO,SAAS0B,GAAmBzF,EAAc0F,EAA6C,CAC5F,MAAMT,EAAOhC,EAAOjD,CAAG,EACjB2F,EAAUV,EACZ,MAAM,QAAQA,EAAK,KAAQ,EACzBA,EAAK,MACL,MAAM,QAAQA,EAAK,IAAO,EACxBA,EAAK,KACL,KACJ,MAAM,QAAQjF,CAAG,EACfA,EACA,KACN,GAAI2F,IAAY,KAAM,OAAO,KAC7B,MAAMC,EAAcX,EAAO/B,EAAI+B,EAAM,QAAQ,EAAI,KACjD,MAAO,CACL,OAAQW,IAAgB,MAAQA,IAAgB,MAAQA,EAAcF,EACtE,KAAMC,EACH,IAAIJ,EAAU,EACd,OAAQM,GAAuBA,IAAM,IAAI,EACzC,KAAK,CAACP,EAAGQ,IAAMR,EAAE,IAAI,cAAcQ,EAAE,GAAG,CAAC,EAC5C,YAAab,EAAO/B,EAAI+B,EAAM,aAAa,EAAI,KAI/C,UAAWA,EAAO1B,EAAK0B,EAAM,YAAa,EAAI,EAAI,GAClD,QAASA,EAAOxB,EAAKwB,EAAK,OAAU,EAAE,OAAQc,GAAmB,OAAOA,GAAM,QAAQ,EAAI,EAAC,CAE/F,CAEA,SAASC,GAAkBhG,EAAciG,EAAmD,CAC1F,MAAMlC,EAAId,EAAOjD,CAAG,EACpB,GAAI,CAAC+D,EAAG,OAAO,KAGf,MAAMnC,EAAOsB,EAAIa,EAAG,OAAO,GAAKb,EAAIa,EAAG,IAAI,GAAKb,EAAIa,EAAG,MAAM,GAAKb,EAAIa,EAAG,OAAO,EAChF,GAAInC,IAAS,KAAM,OAAO,KAC1B,MAAMsE,EAAOnC,EAAE,aACT7D,EAAQgD,EAAIa,EAAG,OAAO,EACtBoC,EAAgBpC,EAAE,cAMlBqC,EAAgB9C,EAAIS,EAAG,qBAAqB,GAAKT,EAAIS,EAAG,eAAe,EACvEsC,EAAoB/C,EAAIS,EAAG,eAAe,GAAKT,EAAIS,EAAG,mBAAmB,EAEzEuC,EAAYpD,EAAIa,EAAG,WAAW,EAEpC,MAAO,CACL,KAAAnC,EACA,QAAAqE,EACA,OAAQ/F,IAAU,KAAOA,IAAU,SAAWqD,EAAKQ,EAAG,QAAQ,GAAKR,EAAKQ,EAAG,UAAU,EACrF,UAAWT,EAAIS,EAAG,WAAW,GAAKT,EAAIS,EAAG,MAAM,EAC/C,cAAeT,EAAIS,EAAG,eAAe,GAAKT,EAAIS,EAAG,WAAW,EAC5D,UACEuC,IAAc,OAASA,IAAc,OAASA,IAAc,QAAUA,EAAY,UACpF,WAAYzC,EAAaP,EAAIS,EAAG,YAAY,CAAC,EAC7C,cAAeF,EAAaP,EAAIS,EAAG,eAAe,CAAC,EACnD,OAAQb,EAAIa,EAAG,QAAQ,EACvB,KAAMb,EAAIa,EAAG,MAAM,EACnB,UAAWb,EAAIa,EAAG,WAAW,GAAKb,EAAIa,EAAG,YAAY,EACrD,cAAeb,EAAIa,EAAG,eAAe,GAAKb,EAAIa,EAAG,gBAAgB,EACjE,aAAcb,EAAIa,EAAG,cAAc,GAAKb,EAAIa,EAAG,oBAAoB,EACnE,cAAAqC,EAGA,kBACEC,IAAsB,MAAQD,IAAkB,MAAQC,IAAsBD,EAC1E,KACAC,EACN,aAAc,MAAM,QAAQH,CAAI,EAAIA,EAAK,OAAQH,GAAmB,OAAOA,GAAM,QAAQ,EAAI,KAC7F,cAAe,OAAOI,GAAkB,UAAYA,EAAgB,KAExE,CAEA,SAASI,GACPvG,EACAiG,EAC6D,CAC7D,MAAMlC,EAAId,EAAOjD,CAAG,EACpB,GAAI,CAAC+D,EAAG,OAAO,KACf,MAAMyC,EAAY,MAAM,QAAQzC,EAAE,MAAS,EAAIA,EAAE,OAAY,KAC7D,GAAIyC,IAAc,KAAM,OAAO,KAC/B,MAAMC,EAASD,EACZ,IAAKE,GAAMV,GAAkBU,EAAGT,CAAO,CAAC,EACxC,OAAQS,GAAuBA,IAAM,IAAI,EACtC5D,EAAQS,EAAKQ,EAAG,OAAO,EAC7B,MAAO,CACL,OAAA0C,EACA,OAAQ,CACN,QAAAR,EACA,UAAW1C,EAAKQ,EAAG,WAAW,EAC9B,OAAQb,EAAIa,EAAG,QAAQ,EACvB,MAAAjB,EAGA,WAAYA,EAAQQ,EAAIS,EAAG,YAAY,EAAI,KAC3C,WAAY0C,EAAO,OACrB,CAEJ,CAeO,SAASE,GAAmB3G,EAA0C,CAC3E,MAAMiF,EAAOhC,EAAOjD,CAAG,EACvB,GAAI,CAACiF,EAAM,OAAO,KAElB,MAAM2B,EAASL,GAAqBtB,EAAK,OAAW,QAAQ,EACtD4B,EAAWN,GAAqBtB,EAAK,UAAeA,EAAK,SAAa,UAAU,EAEtF,GAAI2B,IAAW,MAAQC,IAAa,KAAM,CACxC,MAAMC,EAAU,CAACF,EAAQC,CAAQ,EAAE,OAAQE,GAAkCA,IAAM,IAAI,EACjFC,EAAYF,EAAQ,KAAMC,GAAMA,EAAE,OAAO,SAAS,EAClDE,EAAUhE,EAAOgC,EAAK,OAAU,EACtC,MAAO,CACL,UAAA+B,EACA,OAAQF,EAAQ,QAASC,GAAMA,EAAE,MAAM,EACvC,mBACGE,EAAU3D,EAAI2D,EAAS,kBAAkB,EAAI,OAC9C3D,EAAI2B,EAAM,mBAAmB,GAC7B3B,EAAI2B,EAAM,cAAc,EAC1B,gBAAiBgC,EAAU3D,EAAI2D,EAAS,iBAAiB,EAAI,KAC7D,OAAQD,EACJ,KACCF,EAAQ,IAAKC,GAAMA,EAAE,OAAO,MAAM,EAAE,KAAMA,GAAMA,IAAM,IAAI,GAAK,KACpE,SAAUD,EAAQ,IAAKC,GAAMA,EAAE,MAAM,EACrC,MAAOtD,EAAKwB,EAAK,KAAQ,EAAE,OAAQnF,GAAmB,OAAOA,GAAM,QAAQ,EAC3E,UAAWoD,EAAI+B,EAAM,WAAW,EAEpC,CAEA,MAAMuB,EAAY,MAAM,QAAQvB,EAAK,MAAS,EAAIA,EAAK,OAAY,KACnE,OAAIuB,IAAc,KAAa,KACxB,CACL,UAAWjD,EAAK0B,EAAM,YAAa,EAAI,EACvC,OAAQuB,EAAU,IAAKE,GAAMV,GAAkBU,EAAG,IAAI,CAAC,EAAE,OAAQA,GAAuBA,IAAM,IAAI,EAClG,kBAAmBpD,EAAI2B,EAAM,mBAAmB,GAAK3B,EAAI2B,EAAM,cAAc,EAC7E,gBAAiB3B,EAAI2B,EAAM,iBAAiB,EAC5C,OAAQ/B,EAAI+B,EAAM,QAAQ,EAI1B,SAAU,GACV,MAAOxB,EAAKwB,EAAK,KAAQ,EAAE,OAAQnF,GAAmB,OAAOA,GAAM,QAAQ,EAC3E,UAAWoD,EAAI+B,EAAM,WAAW,EAEpC,CChxBO,MAAMiC,GAAqB,uBACrBC,GAA0B,sBAG1BC,GAA8C,CACzD,IAAKF,GACL,MAAQG,GAAWC,EAAsB,aAAcD,CAAM,CAC/D,EASA,SAASE,GAAuBC,EAAsB,CACpD,OAAIA,aAAeC,EACbD,EAAI,SAAW,IACV,6GAEF,qCAAqCA,EAAI,MAAM,KAEjD,kDACT,CAEO,MAAME,GAAgD,CAC3D,IAAKP,GACL,MAAO,MAAOE,GAAW,CACvB,GAAI,CAEF,MAAO,CAAE,IADG,MAAMC,EAAgB,qBAAsBD,CAAM,EAChD,UAAW,GAAM,OAAQ,KACzC,OAASG,EAAK,CAEZ,GADIA,aAAeC,GAAYD,EAAI,SAAW,KAC1CA,aAAe,cAAgBA,EAAI,OAAS,aAAc,MAAMA,EACpE,MAAO,CAAE,IAAK,KAAM,UAAW,GAAO,OAAQD,GAAuBC,CAAG,EAC1E,CACF,CACF,EAiBaG,GAAqB,uBACrBC,GAAyB,2BACzBC,GAA0B,qBASvC,SAASC,GAAwB3F,EAAcqF,EAAsB,CACnE,OAAIA,aAAeC,EACbD,EAAI,SAAW,IACV,+BAA+BrF,CAAI,qCAErC,GAAGA,CAAI,kBAAkBqF,EAAI,MAAM,IAErC,GAAGrF,CAAI,wBAChB,CAEA,SAAS4F,EAAY5F,EAA+D,CAClF,MAAO,OAAOkF,GAAW,CACvB,GAAI,CAEF,MAAO,CAAE,IADG,MAAMC,EAAgBnF,EAAMkF,CAAM,EAChC,UAAW,GAAM,OAAQ,KACzC,OAASG,EAAK,CAEZ,GADIA,aAAeC,GAAYD,EAAI,SAAW,KAC1CA,aAAe,cAAgBA,EAAI,OAAS,aAAc,MAAMA,EACpE,MAAO,CAAE,IAAK,KAAM,UAAW,GAAO,OAAQM,GAAwB3F,EAAMqF,CAAG,EACjF,CACF,CACF,CAGO,MAAMQ,GAA6C,CACxD,IAAKL,GACL,MAAOI,EAAY,qBAAqB,CAC1C,EAmCME,GAA+B,CAAC,IAAK,IAAI,EAEzCC,GAAkBH,EAAY,yBAAyB,EAE7D,SAASI,GAAwBpI,EAA6B,CAC5D,GAAI,CAACA,EAAK,UAAW,MAAO,GAC5B,MAAMqI,EAAWzB,GAAmB5G,EAAK,GAAG,EAC5C,OAAOqI,IAAa,MAAQ,CAACA,EAAS,SACxC,CAEA,SAASC,GAAMC,EAAYjB,EAAqC,CAC9D,OAAO,IAAI,QAAc,CAACkB,EAASC,IAAW,CAC5C,GAAInB,GAAQ,QAAS,CACnBmB,EAAO,IAAI,aAAa,UAAW,YAAY,CAAC,EAChD,MACF,CACA,MAAMC,EAAU,IAAY,CAC1B,aAAaC,CAAK,EAClBF,EAAO,IAAI,aAAa,UAAW,YAAY,CAAC,CAClD,EACME,EAAQ,WAAW,IAAM,CAC7BrB,GAAQ,oBAAoB,QAASoB,CAAO,EAC5CF,EAAA,CACF,EAAGD,CAAE,EACLjB,GAAQ,iBAAiB,QAASoB,EAAS,CAAE,KAAM,GAAM,CAC3D,CAAC,CACH,CAGO,MAAME,GAAgD,CAC3D,IAAKf,GACL,MAAO,MAAOP,GAAW,CACvB,IAAItH,EAAO,MAAMmI,GAAgBb,CAAM,EACvC,UAAWuB,KAAWX,GAA8B,CAClD,GAAI,CAACE,GAAwBpI,CAAI,EAAG,OAAOA,EAC3C,MAAMsI,GAAMO,EAASvB,CAAM,EAC3BtH,EAAO,MAAMmI,GAAgBb,CAAM,CACrC,CACA,OAAOtH,CACT,CACF,EAKM8I,GAA+D,CACnE,KAAM,CACJ,IAAK,GAAGhB,EAAuB,MAC/B,MAAOE,EAAY,mCAAmC,GAExD,MAAO,CACL,IAAK,GAAGF,EAAuB,OAC/B,MAAOE,EAAY,oCAAoC,EAE3D,EAEO,SAASe,GAAiBC,EAA8C,CAC7E,OAAOF,GAAeE,CAAM,CAC9B,CCzKO,MAAMC,EAAkD,CAC7D,CACE,GAAI,UACJ,MAAO,mBACP,SAAU,8EAEZ,CACE,GAAI,WACJ,MAAO,aACP,SAAU,4EAEZ,CACE,GAAI,QACJ,MAAO,gBACP,SAAU,oEAEZ,CACE,GAAI,QACJ,MAAO,qBACP,SAAU,gFAEZ,CACE,GAAI,SACJ,MAAO,gBACP,SAAU,uEAEd,EAEO,SAASC,GAAUC,EAAsB,CAC9C,OAAK,OAAO,SAASA,CAAI,EAClB,KAAK,IAAIF,EAAiB,OAAS,EAAG,KAAK,IAAI,EAAG,KAAK,MAAME,CAAI,CAAC,CAAC,EADvC,CAErC,CA+BA,MAAMC,GAA0D,CAC9D,OAAQ,uEACR,MAAO,sEACP,KAAM,oDACR,EAEA,SAASC,GAAeC,EAAkC,CACxD,MAAMC,EAAQD,EAAQ,OAASA,EAAQ,GACjCE,EAAO,CAAE,GAAIF,EAAQ,GAAI,MAAAC,EAAO,SAAUD,EAAQ,UAExD,GAAIA,EAAQ,iBAAmB,cAAgBA,EAAQ,QAAU,aAC/D,MAAO,CACL,GAAGE,EACH,KAAM,YACN,MAAO,aACP,OACEF,EAAQ,QACRA,EAAQ,MAAM,CAAC,GACf,4BAA4BC,CAAK,uCACnC,IAAKD,EAAQ,kBAAoBF,GAAmBE,EAAQ,QAAQ,GAIxE,GAAIA,EAAQ,YACV,MAAO,CACL,GAAGE,EACH,KAAM,YACN,MAAO,gBACP,OACE,uBAAuBD,CAAK,sCAC3BD,EAAQ,YAAY,cAAgB,KAAKA,EAAQ,YAAY,aAAa,IAAM,IACjF,yGACF,IAAK,MAIT,GAAIA,EAAQ,QAAU,cACpB,MAAO,CACL,GAAGE,EACH,KAAM,UACN,MAAO,aACP,OAAQF,EAAQ,QAAU,kCAAkCC,CAAK,qCACjE,IAAK,MAIT,GAAID,EAAQ,QAAU,WACpB,MAAO,CAAE,GAAGE,EAAM,KAAM,UAAW,MAAO,WAAY,OAAQ,iBAAiBD,CAAK,IAAK,IAAK,MAGhG,MAAME,EAAUH,EAAQ,QAClBI,EAAUD,GAAS,eAAiB,GACpCE,EAAYL,EAAQ,SAAS,aAAe,IAAQA,EAAQ,SAAS,YAAc,GAEzF,GAAII,GAAW,CAACC,EACd,MAAO,CACL,GAAGH,EACH,KAAM,YACN,MAAO,gBACP,OAAQ,GAAGD,CAAK,mFAChB,IAAK,MAIT,GAAIG,GAAWC,EAGb,MAAO,CACL,GAAGH,EACH,KAAM,KACN,MAAO,oBACP,OAAQ,GAAGD,CAAK,gGAChB,IAAK,MAIT,MAAMK,EAAUH,GAAS,WAAa,IAAQ,OAAOA,EAAQ,aAAgB,SAAWA,EAAQ,YAAc,KAC9G,MAAO,CACL,GAAGD,EACH,KAAM,KACN,MAAO,YACP,OACEI,IAAY,KACR,GAAGL,CAAK,gGACR,GAAGA,CAAK,kBAAkB,KAAK,MAAMK,CAAO,CAAC,gCACnD,IAAK,KAET,CAWO,SAASC,GAAsBC,EAAwC,CAC5E,GAAIA,EAAM,QACR,MAAO,CAAE,SAAU,KAAM,QAAS,kDAAmD,OAAQ,KAAM,eAAgB,GAErH,GAAI,CAACA,EAAM,SACT,MAAO,CACL,SAAU,KACV,QAAS,kGACT,OAAQA,EAAM,kBACd,eAAgB,GAIpB,MAAMC,EAAWD,EAAM,SAAS,SAAS,IAAIT,EAAc,EAC3D,GAAIU,EAAS,SAAW,EACtB,MAAO,CACL,SAAAA,EACA,QAAS,6FACT,OAAQD,EAAM,SAAS,cACvB,eAAgB,GAIpB,MAAME,EAAYD,EAAS,OAAQE,GAAMA,EAAE,QAAU,YAAY,EAC3DC,EAASH,EAAS,OAAQE,GAAMA,EAAE,OAAS,IAAI,EAC/CE,EACJH,EAAU,SAAW,EACjB,GAAGE,EAAO,MAAM,OAAOH,EAAS,MAAM,IAAIA,EAAS,SAAW,EAAI,UAAY,WAAW,sBACzF,GAAGC,EAAU,MAAM,IAAIA,EAAU,SAAW,EAAI,UAAY,WAAW,uDAE7E,MAAO,CAAE,SAAAD,EAAU,QAAAI,EAAS,OAAQL,EAAM,SAAS,cAAe,eAAgBE,EAAU,OAC9F,CA0BA,MAAMI,EACJ,mIACIC,EACJ,oHAEK,SAASC,GAAkBR,EAAiC,CACjE,GAAIA,EAAM,QACR,MAAO,CACL,KAAM,UACN,MAAO,WACP,QAAS,8CACT,QAASM,EACT,IAAK,KACL,WAAY,EACZ,iBAAkB,EAClB,MAAO,IAIX,GAAI,CAACN,EAAM,SACT,MAAO,CACL,KAAM,UACN,MAAO,eACP,QAAS,iGACT,QAASO,EACT,IAAKP,EAAM,kBACX,WAAY,EACZ,iBAAkB,EAClB,MAAO,IAIX,MAAMpD,EAASoD,EAAM,SAAS,OACxBS,EAAc7D,EAAO,OAAQC,GAAMA,EAAE,gBAAkB,EAAI,EAAE,OAC7D5D,EAAQ+G,EAAM,SAAS,SAAS,KAAM9F,GAAMA,EAAE,KAAK,EAEzD,OAAK8F,EAAM,SAAS,UAgBhBpD,EAAO,SAAW,EACb,CACL,KAAM,YACN,MAAO,YACP,QAAS,4DACT,QAAS2D,EACT,IAAK,8DACL,WAAY,EACZ,iBAAkB,EAClB,MAAAtH,CAAA,EAIG,CACL,KAAM,KACN,MAAOA,EAAQ,+BAAiC,YAChD,QACE,GAAG2D,EAAO,MAAM,UAAUA,EAAO,SAAW,EAAI,QAAU,QAAQ,cACjE6D,EAAc,EAAI,KAAKA,CAAW,yBAA2B,iCAC7DxH,EAAQ,kDAAoD,IAC/D,QAASwH,EAAc,EACnBH,EACA,GAAGA,CAAuB,8EAC9B,IAAK,KACL,WAAY1D,EAAO,OACnB,iBAAkB6D,EAClB,MAAAxH,CAAA,EAzCO,CACL,KAAM,YACN,MAAO,cAGP,QACE,oIACF,QAASsH,EACT,IAAK,4IACL,WAAY,EACZ,iBAAkB,EAClB,MAAAtH,CAAA,CAgCN,CAsBO,MAAMyH,GAAwC,CACnD,CACE,KAAM,QACN,MAAO,2EACP,MAAO,2DACP,WAAY,gEACZ,KAAM,MAER,CACE,KAAM,YACN,MAAO,wEACP,MAAO,8FACP,WAAY,oEACZ,KAAM,aAER,CACE,KAAM,iBACN,MAAO,2DACP,MAAO,oFACP,WAAY,8EACZ,KAAM,YAEV,ECvVaC,GAA+B,4BAEtCC,GAA0B,CAAE,YAAa,KAAM,YAAa,MAElE,SAASC,IAA+B,CACtC,GAAI,CACF,MAAM1K,EAAM,aAAa,QAAQwK,EAA4B,EAC7D,GAAI,CAACxK,EAAK,OAAOyK,GACjB,MAAMxK,EAAS,KAAK,MAAMD,CAAG,EAC7B,MAAO,CACL,YAAa,OAAOC,EAAO,aAAgB,SAAWA,EAAO,YAAc,KAC3E,YAAa,OAAOA,EAAO,aAAgB,SAAWA,EAAO,YAAc,KAE/E,MAAQ,CAEN,MAAO,CAAE,YAAa,KAAM,gBAAiB,KAAK,CAAC,EAAE,aAAY,CACnE,CACF,CAEA,SAASI,GAAQ4C,EAAgC,CAC/C,GAAI,CACF,aAAa,QAAQuH,GAA8B,KAAK,UAAUvH,CAAM,CAAC,CAC3E,MAAQ,CAER,CACF,CAGO,SAAS0H,GAAW1H,EAAmC,CAC5D,OAAOA,EAAO,cAAgB,MAAQA,EAAO,cAAgB,IAC/D,CAEA,MAAM2H,GAAgBF,GAAA,EAEtB,IAAIxK,EAAyB,CAC3B,GAAG0K,GACH,KAAMD,GAAWC,EAAa,EAC9B,KAAM,CACR,EAEA,MAAMxK,MAAgB,IAEtB,SAASI,EAAMC,EAAuC,CACpD,MAAMH,EAAO,CAAE,GAAGJ,EAAO,GAAGO,CAAA,EAC5B,GAAK,QAAO,KAAKA,CAAK,EAAgC,MAAOC,GAAM,OAAO,GAAGR,EAAMQ,CAAC,EAAGJ,EAAKI,CAAC,CAAC,CAAC,EAC/F,CAAAR,EAAQI,EACR,UAAWM,KAAKR,EAAWQ,EAAA,EAC7B,CAEO,SAASiK,GAAoB/J,EAAkC,CACpE,OAAAV,EAAU,IAAIU,CAAQ,EACf,IAAMV,EAAU,OAAOU,CAAQ,CACxC,CAEO,SAASgK,IAAsC,CACpD,OAAO5K,CACT,CAEO,SAAS6K,GAAkB7B,EAAoB,CACpD1I,EAAM,CAAE,KAAM,KAAK,IAAI,EAAG,KAAK,MAAM0I,CAAI,CAAC,EAAG,CAC/C,CAGO,SAAS8B,IAA0B,CACxC,MAAM/H,EAA2B,CAAE,YAAa/C,EAAM,YAAa,YAAa,IAAI,OAAO,aAAY,EACvGG,GAAQ4C,CAAM,EACdzC,EAAM,CAAE,GAAGyC,EAAQ,KAAM,GAAO,CAClC,CAGO,SAASgI,IAA2B,CACzC,MAAMhI,EAA2B,CAAE,YAAa,IAAI,OAAO,cAAe,YAAa/C,EAAM,aAC7FG,GAAQ4C,CAAM,EACdzC,EAAM,CAAE,GAAGyC,EAAQ,KAAM,GAAO,CAClC,CAIO,SAASiI,IAAyB,CACvC1K,EAAM,CAAE,KAAM,GAAM,KAAM,EAAG,CAC/B,CC7GO,SAAS2K,IAAiC,CAC/C,OAAOC,uBAAqBP,GAAqBC,GAAoBA,EAAkB,CACzF,8rCCsDA,SAASO,GAAS,CAAE,KAAAC,EAAM,MAAAhC,GAA+C,CACvE,MAAMiC,EAAQD,IAAS,KAAOnP,GAAkBmP,IAAS,YAAc/O,GAAYC,GACnF,cACG,QAAK,UAAWsC,EAAO,KAAM,YAAWwM,EACvC,UAAAzP,MAAC0P,GAAM,KAAM,GAAI,cAAY,OAAO,UAAU,QAAQ,EACtD1P,MAAC,QAAK,UAAWiD,EAAO,UAAY,SAAAwK,CAAA,CAAM,GAC5C,CAEJ,CAEA,SAASkC,EAAS,CAAE,SAAA9P,GAAqC,CACvD,OAAOG,MAAC,OAAI,UAAWiD,EAAO,KAAO,SAAApD,EAAS,CAChD,CAMA,MAAM+P,GAAwC,CAC5C,KAAM,iFACN,SAAU,2GACV,UAAW,gGACX,MAAO,mEACP,SAAU,0EACZ,EAEA,SAASC,IAAc,CACrB,cACGF,EAAA,CACC,UAAA3P,MAAC,KAAE,UAAWiD,EAAO,KAAM,gLAG3B,EACAjD,MAAC,MAAG,UAAWiD,EAAO,SACnB,SAAAO,EAAe,IAAI,CAACsM,EAAOC,IAAU,CACpC,MAAMrQ,EAAO2C,GAAayN,EAAM,EAAE,EAClC,OACE/P,OAAC,MAAkB,UAAWkD,EAAO,WACnC,UAAAjD,MAAC,QAAK,UAAWiD,EAAO,YAAa,cAAY,OAC/C,SAAAjD,MAACN,IAAK,EACR,EACAK,OAAC,QAAK,UAAWkD,EAAO,YACtB,UAAAlD,OAAC,QAAK,UAAWkD,EAAO,YACrB,UAAA6M,EAAM,MAAM,IAAC/P,OAAC,OAAI,UAAWkD,EAAO,IAAK,cAAE8M,EAAQ,GAAE,GACxD,EACA/P,MAAC,QAAK,UAAWiD,EAAO,aAAe,SAAA2M,GAAcE,EAAM,EAAE,EAAE,GACjE,IATOA,EAAM,EAUf,CAEJ,CAAC,EACH,GACF,CAEJ,CAMA,SAASE,IAAe,CACtB,MAAM9L,EAAO+L,EAAS9D,EAAkB,EAClC8B,EAAWiC,UACf,IACEnC,GAAsB,CACpB,SAAU7J,EAAK,MAAM,UAAYqF,GAAwBrF,EAAK,KAAK,GAAG,EAAI,KAC1E,QAASA,EAAK,OAAS,QAAaA,EAAK,SAAW,QACpD,kBAAmBA,EAAK,MAAM,QAAUA,EAAK,OAAO,SAAW,KAChE,EACH,CAACA,EAAK,KAAMA,EAAK,OAAQA,EAAK,KAAK,GAGrC,cACGyL,EAAA,CACC,UAAA3P,MAAC,KAAE,UAAWiD,EAAO,KAAO,WAAS,QAAQ,EAC5CgL,EAAS,WAAa,KAAO,KAC5BjO,MAAC,MAAG,UAAWiD,EAAO,SACnB,SAAAgL,EAAS,SAAS,IAAKkC,UACrB,MAAoB,UAAWlN,EAAO,QACrC,UAAAlD,OAAC,OAAI,UAAWkD,EAAO,YACrB,UAAAjD,MAACmD,GAAA,CAAI,OAAQgN,EAAQ,SAAW,WAAQ,MAAM,QAC7CX,GAAA,CAAS,KAAMW,EAAQ,KAAM,MAAOA,EAAQ,MAAO,GACtD,QACC,KAAE,UAAWlN,EAAO,cAAgB,WAAQ,OAAO,EACnDkN,EAAQ,IACPpQ,OAAC,KAAE,UAAWkD,EAAO,WACnB,UAAAjD,MAAC,QAAK,UAAWiD,EAAO,SAAU,eAAG,QACpC,QAAK,UAAWA,EAAO,KAAO,WAAQ,IAAI,GAC7C,EACE,OAXGkN,EAAQ,EAYjB,CACD,EACH,EAEDlC,EAAS,OAASjO,MAAC,KAAE,UAAWiD,EAAO,OAAS,SAAAgL,EAAS,OAAO,EAAO,KACxElO,OAAC,KAAE,UAAWkD,EAAO,MAAO,mFAC6C,IACvEjD,MAAC,OAAI,UAAWiD,EAAO,IAAK,cAAE,EAAM,KACtC,GACF,CAEJ,CAMA,SAASmN,IAAY,CACnB,MAAMlM,EAAO+L,EAASnD,EAAqB,EACrCqD,EAAUD,UACd,IACE1B,GAAkB,CAChB,SAAUtK,EAAK,MAAM,UAAY4G,GAAmB5G,EAAK,KAAK,GAAG,EAAI,KACrE,QAASA,EAAK,OAAS,QAAaA,EAAK,SAAW,QACpD,kBAAmBA,EAAK,MAAM,QAAUA,EAAK,OAAO,SAAW,KAChE,EACH,CAACA,EAAK,KAAMA,EAAK,OAAQA,EAAK,KAAK,GAGrC,cACGyL,EAAA,CACC,UAAA5P,OAAC,OAAI,UAAWkD,EAAO,YACrB,UAAAjD,MAAC,QAAK,UAAWiD,EAAO,UAAW,cAAY,OAC7C,SAAAjD,MAACG,GAAA,CAAQ,KAAM,GAAI,EACrB,QACCqP,GAAA,CAAS,KAAMW,EAAQ,KAAM,MAAOA,EAAQ,MAAO,GACtD,QACC,KAAE,UAAWlN,EAAO,KAAO,WAAQ,QAAQ,QAC3C,KAAE,UAAWA,EAAO,cAAgB,WAAQ,QAAQ,EACpDkN,EAAQ,IACPpQ,OAAC,KAAE,UAAWkD,EAAO,WACnB,UAAAjD,MAAC,QAAK,UAAWiD,EAAO,SAAU,eAAG,QACpC,QAAK,UAAWA,EAAO,QAAU,WAAQ,IAAI,GAChD,EACE,MACN,CAEJ,CAMA,SAASoN,IAAY,CACnB,cACGV,EAAA,CACC,UAAA5P,OAAC,KAAE,UAAWkD,EAAO,KAAM,sBAChBjD,MAAC,OAAI,UAAWiD,EAAO,IAAK,cAAE,EAAM,0HAE/C,EACAjD,MAAC,MAAG,UAAWiD,EAAO,SACnB,SAAAyL,GAAc,IAAK4B,GAClBvQ,OAAC,MAAsB,UAAWkD,EAAO,QACvC,UAAAlD,OAAC,OAAI,UAAWkD,EAAO,YACrB,UAAAjD,MAAC,QAAK,UAAWiD,EAAO,SAAW,WAAQ,KAAK,EAChDjD,MAACwP,GAAA,CAAS,KAAMc,EAAQ,KAAM,MAAOA,EAAQ,OAAS,KAAO,SAAW,SAAU,GACpF,QACC,KAAE,UAAWrN,EAAO,cAAgB,WAAQ,MAAM,QAClD,KAAE,UAAWA,EAAO,cAAgB,WAAQ,MAAM,QAClD,KAAE,UAAWA,EAAO,YAAc,WAAQ,WAAW,IAP/CqN,EAAQ,IAQjB,CACD,EACH,GACF,CAEJ,CAMA,SAASC,IAAa,CACpB,cACGZ,EAAA,CACC,UAAA5P,OAAC,KAAE,UAAWkD,EAAO,KAAM,sBAChBjD,MAAC,OAAI,UAAWiD,EAAO,IAAK,cAAE,EAAM,uJAE/C,EACAjD,MAACsC,EAAA,CACC,QAAQ,SACR,KAAMtC,MAACS,GAAA,CAAY,KAAM,GAAI,EAC7B,QAAS,IAAM0E,EAAgB,UAAU,EAC1C,2BAGDnF,MAAC,KAAE,UAAWiD,EAAO,MAAO,yEAE5B,GACF,CAEJ,CAEA,MAAMuN,GAAkB,CAACX,GAAaG,GAAcI,GAAWC,GAAWE,EAAU,EAM7E,SAASE,IAAiB,CAC/B,KAAM,CAAE,KAAA/K,EAAM,KAAA2H,CAAA,EAASiC,GAAA,EACjBS,EAAQ3C,GAAUC,CAAI,EACtBqD,EAAOvD,EAAiB4C,CAAK,EAC7BY,EAAOH,GAAgBT,CAAK,EAC5Ba,EAAOb,IAAU5C,EAAiB,OAAS,EAE3C0D,EAAQC,cAAY,IAAM3B,GAAA,EAAqB,EAAE,EACjD4B,EAAUC,SAAoB,IAAI,EAyBxC,OAbAC,YAAU,IAAM,CACd,GAAI,CAACvL,EAAM,OACX,SAASwL,EAAM1R,EAAiC,CAC9C,GAAIA,EAAM,MAAQ,SAAU,OAC5B,MAAM2R,EAAOJ,EAAQ,QACjB,CAACI,GAAQ,EAAE3R,EAAM,kBAAkB,OAAS,CAAC2R,EAAK,SAAS3R,EAAM,MAAM,IAC3EA,EAAM,iBACN2P,GAAA,EACF,CACA,gBAAS,iBAAiB,UAAW+B,CAAK,EACnC,IAAM,SAAS,oBAAoB,UAAWA,CAAK,CAC5D,EAAG,CAACxL,CAAI,CAAC,EAEJA,EAGH3F,OAAC,SAAM,IAAKgR,EAAS,UAAW9N,EAAO,KAAM,kBAAgB,yBAAyB,KAAK,SACzF,UAAAlD,OAAC,UAAO,UAAWkD,EAAO,KACxB,UAAAlD,OAAC,OAAI,UAAWkD,EAAO,SACrB,UAAAlD,OAAC,KAAE,UAAWkD,EAAO,QAAS,+BACT8M,EAAQ,EAAE,OAAK5C,EAAiB,QACrD,EACAnN,MAAC,MAAG,GAAG,yBAAyB,UAAWiD,EAAO,MAC/C,WAAK,MACR,QACC,KAAE,UAAWA,EAAO,SAAW,WAAK,SAAS,GAChD,EACAjD,MAACsC,EAAA,CACC,SAAQ,GACR,QAAQ,QACR,KAAK,KACL,aAAW,wBACX,KAAMtC,MAACO,GAAA,CAAM,KAAM,GAAI,EACvB,QAASsQ,CAAA,EACX,EACF,QAECF,EAAA,EAAK,EAEN5Q,OAAC,UAAO,UAAWkD,EAAO,KACxB,UAAAjD,MAAC,MAAG,UAAWiD,EAAO,KAAM,cAAY,OACrC,SAAAkK,EAAiB,IAAI,CAACzJ,EAAG0N,IACxBpR,MAAC,MAAc,UAAWiD,EAAO,IAAK,aAAYmO,IAAMrB,EAAQ,UAAYqB,EAAIrB,EAAQ,OAAS,QAAxFrM,EAAE,EAA8F,CAC1G,EACH,EACA3D,OAAC,OAAI,UAAWkD,EAAO,QACrB,UAAAjD,MAACsC,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAASuO,EAAO,sBAElD,EACCd,EAAQ,EACP/P,MAACsC,EAAA,CAAO,QAAQ,SAAS,KAAK,KAAK,QAAS,IAAM4M,GAAkBa,EAAQ,CAAC,EAAG,gBAEhF,EACE,KACHa,EACC5Q,MAACsC,EAAA,CACC,QAAQ,UACR,KAAK,KACL,KAAMtC,MAACC,GAAA,CAAS,KAAM,GAAI,EAC1B,QAAS,IAAM,CACbmP,GAAA,EAGAtJ,EAAoB,UAAU,CAChC,EACD,gCAID9F,MAACsC,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAAS,IAAM4M,GAAkBa,EAAQ,CAAC,EAAG,gBAEjF,GAEJ,GACF,GACF,EA9DgB,IAgEpB,CC/VO,SAASsB,IAA2B,CACzC,OAAO9B,uBAAqBvK,GAAkBE,GAAiBA,EAAe,CAChF,ihBCiCMoM,GAAkB,uOAAAC,EAAA,qLAAAA,EAAA,mKAAAA,EAAA,wIAAAA,EAAA,sHAQjB,SAASC,EAAe,CAAE,MAAA/D,EAAO,WAAAgE,EAAY,OAAAC,GAAkE,CACpH,cACG,OAAI,UAAWzO,EAAO,QAAS,KAAK,SACnC,UAAAlD,OAAC,MAAG,UAAWkD,EAAO,aAAe,UAAAwK,EAAM,wBAAoB,EAC/D1N,OAAC,KAAE,UAAWkD,EAAO,YAAa,sCACb,QAAK,mCAAuBwO,EAAW,QAAI,EAAO,8IAEvE,EACCC,EAAS1R,MAAC,KAAE,UAAWiD,EAAO,cAAgB,WAAO,EAAO,MAC/D,CAEJ,CAOA,SAAS0O,GAAcxJ,EAA+D,CACpF,MAAM2H,EAAQtM,EAAe,KAAME,GAAMA,EAAE,KAAOyE,CAAE,EAC9CyJ,EAAWN,GAAgB,cAAcxB,EAAM,MAAM,MAAM,EACjE,MAAO,UAAY,CACjB,GAAI,CAAC8B,EAAU,MAAO,CAAE,QAAS,IAAM5R,MAACwR,EAAA,CAAe,MAAO1B,EAAM,MAAO,WAAYA,EAAM,OAAQ,GACrG,GAAI,CACF,MAAM+B,EAAO,MAAMD,EAAA,EACbE,EAAWD,EAAI/B,EAAM,MAAM,GAAK+B,EAAI,QAC1C,OAAI,OAAOC,GAAa,WACf,CACL,QAAS,IACP9R,MAACwR,EAAA,CAAe,MAAO1B,EAAM,MAAO,WAAYA,EAAM,OACpD,OAAQ,sCAAsCA,EAAM,MAAM,iBAAiB,EAI5E,CAAE,QAASgC,CAAA,CACpB,OAASnG,EAAK,CACZ,MAAM+F,EAAS/F,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,EAC9D,MAAO,CAAE,QAAS,IAAM3L,MAACwR,EAAA,CAAe,MAAO1B,EAAM,MAAO,WAAYA,EAAM,OAAQ,OAAA4B,CAAA,CAAgB,EACxG,CACF,CACF,CAGA,MAAMK,GAAqB,IAAI,IAC7BvO,EAAe,IAAKE,GAAM,CAACA,EAAE,GAAIsO,OAAKL,GAAcjO,EAAE,EAAE,CAAC,CAAC,CAAU,CACtE,EASMuO,GAA0BC,GAAe,CAAE,OAAQ,UAAW,MAAO,IAAK,EAEzE,SAASC,IAAW,CACzB,MAAMC,EAAKf,GAAA,EACLgB,EAAQC,GAAA,EACRC,EAAUR,GAAmB,IAAIK,EAAG,OAAO,EAG3CI,EADmBvC,EAASgC,EAAuB,EACnB,MAAM,QAC5ChB,YAAU,IAAM,CAIV,OAAOuB,GAAiB,UAAU5M,GAAyB4M,CAAY,CAC7E,EAAG,CAACA,CAAY,CAAC,EAKjBvB,YAAU,IAAM,CACd,SAASC,EAAM1R,EAAiC,CAC9C,GAAI,EAAEA,EAAM,SAAWA,EAAM,UAAYA,EAAM,QAAUA,EAAM,SAAU,OACzE,MAAMuQ,EAAQ,OAAO,SAASvQ,EAAM,IAAK,EAAE,EAC3C,GAAI,OAAO,UAAUuQ,CAAK,GAAKA,GAAS,GAAKA,GAASvM,EAAe,OAAQ,CAC3EhE,EAAM,iBACN2F,EAAgB3B,EAAeuM,EAAQ,CAAC,EAAG,EAAE,EAC7C,MACF,CACA,OAAQvQ,EAAM,IAAI,cAAY,CAC5B,IAAK,IACHA,EAAM,iBACNsG,EAAoB,gBAAgB,EACpC,MACF,IAAK,IACHtG,EAAM,iBACNsG,EAAoB,UAAU,EAC9B,MACF,IAAK,IACHtG,EAAM,iBACN2F,EAAgB,UAAU,EAC1B,KAEA,CAEN,CACA,gBAAS,iBAAiB,UAAW+L,CAAK,EACnC,IAAM,SAAS,oBAAoB,UAAWA,CAAK,CAC5D,EAAG,EAAE,EAMLD,YAAU,IAAM5R,GAA0BI,GAAY,CAChDA,IAAY,gBAAiB0F,EAAgB,UAAU,EAClD1F,IAAY,gBAAgB4S,EAAM,OAC7C,CAAC,EAAG,CAACA,CAAK,CAAC,EAIXpB,YAAU,IAAM,CAAE/R,GAAmBmT,EAAM,KAAK,CAAG,EAAG,CAACA,EAAM,KAAK,CAAC,EAEnE,MAAMI,EAAavC,UAAQ,IAAM,UAAUmC,EAAM,KAAK,oBAAqB,CAACA,EAAM,KAAK,CAAC,EAExF,OACEtS,OAAC,OAAI,UAAWkD,EAAO,MACrB,UAAAlD,OAAC,OAAI,UAAWkD,EAAO,KAAM,aAAW,iBAQtC,UAAAjD,MAAC,QAAK,UAAWiD,EAAO,cAAe,kBAAgB,OAAO,cAAY,OAAO,SAChF,QAAK,UAAWA,EAAO,KAAM,MAAM,cAClC,UAAAjD,MAACoC,GAAA,EAAU,EACXpC,MAAC,QAAK,UAAU,kBAAkB,uBAAW,GAC/C,EACAA,MAAC,MAAG,UAAWiD,EAAO,SACnB,SAAAO,EAAe,IAAI,CAACsM,EAAOC,IAAU,CACpC,MAAM2C,EAAgBrQ,GAAayN,EAAM,EAAE,EACrC6C,EAAU7C,EAAM,KAAO,YAAcsC,EAAG,iBAAmB,EAC3DQ,EAASR,EAAG,UAAYtC,EAAM,GACpC,aACG,MACC,SAAA/P,OAAC,UAAO,KAAK,SAAS,UAAWkD,EAAO,WAAY,eAAc2P,EAAS,OAAS,OAClF,eAAc9C,EAAM,GAAI,MAAO,GAAGA,EAAM,KAAK,MAAMC,EAAQ,CAAC,IAC5D,aAAY4C,EAAU,EAAI,GAAG7C,EAAM,KAAK,KAAK6C,CAAO,WAAa7C,EAAM,MACvE,QAAS,IAAM3K,EAAgB2K,EAAM,EAAE,EACvC,UAAA9P,MAAC0S,EAAA,EAAc,EACdC,EAAU,EAAI3S,MAAC,QAAK,UAAWiD,EAAO,QAAS,eAAc0P,EAAS,cAAY,OAAO,EAAK,OACjG,EAPO7C,EAAM,EAQf,CAEJ,CAAC,EACH,EACA9P,MAAC,OAAI,UAAWiD,EAAO,SACrB,SAAAjD,MAAC,UAAO,KAAK,SAAS,UAAWiD,EAAO,WAAY,QAASoP,EAAM,MAAO,MAAOI,EAC/E,aAAYA,EAAY,oBAAmBJ,EAAM,MACjD,SAAArS,MAAC6S,GAAA,CAAW,WAAYR,EAAM,MAAO,GACvC,CACF,GACF,EAUArS,MAAC,QAAK,UAAWiD,EAAO,QAAS,eAAcmP,EAAG,QAAS,GAAG,eAAe,SAAU,GACrF,SAAApS,MAAC8S,GAAA,CAAmB,SAAUV,EAAG,QAC/B,SAAApS,MAAC+S,WAAA,CAAS,SAAU/S,MAACgT,GAAA,EAAgB,EACnC,SAAAhT,MAACuS,EAAA,EAAQ,EACX,EACF,EACF,QASC9B,GAAA,EAAe,GAClB,CAEJ,CAOA,SAASoC,GAAW,CAAE,WAAA7T,GAAsC,CAC1D,OACEe,OAAC,OAAI,QAAQ,YAAY,MAAO,GAAI,OAAQ,GAAI,KAAK,OAAO,OAAO,eAAe,YAAa,IAC7F,eAAe,QAAQ,cAAc,QAAQ,cAAY,OAAO,UAAU,QAC1E,UAAAC,MAAC,UAAO,GAAG,IAAI,GAAG,IAAI,EAAE,MAAM,EAC7BhB,IAAe,OAASgB,MAAC,QAAK,EAAE,8BAA8B,KAAK,eAAe,OAAO,OAAO,EAAK,KACrGhB,IAAe,QAAUgB,MAAC,QAAK,EAAE,qGAAqG,EAAK,OAGlJ,CAEA,SAASgT,IAAkB,CACzB,OAAOhT,MAAC,OAAI,UAAWiD,EAAO,QAAS,KAAK,SAAS,YAAU,SAAS,oBAAQ,CAClF,CCnOO,MAAMgQ,GAAsB,kBACtBC,EAAqB,iBAErBC,EAAgD,CAC3D,IAAKF,GACL,MAAQzH,GAAWC,EAAuB,uBAAwBD,CAAM,CAC1E,EAEa4H,GAA+C,CAC1D,IAAKF,EACL,MAAQ1H,GAAWC,EAAuB,sBAAuBD,CAAM,CACzE,EAEO,SAAS6H,EAAiBC,EAAmBC,EAAS,GAAY,CACvE,MAAO,uBAAuB,mBAAmBD,CAAS,CAAC,GAAGC,CAAM,EACtE,CAEO,SAASC,GAAwBF,EAAmB9H,EAAmD,CAC5G,OAAOC,EAA2B4H,EAAiBC,CAAS,EAAG9H,CAAM,CACvE,CAEO,MAAMiI,WAAiC,KAAM,CAClD,aAAc,CACZ,MAAM,yDAAyD,EAC/D,KAAK,KAAO,0BACd,CACF,CAEA,eAAeC,EAAQpN,EAAcqN,EAA2B,CAC9D,MAAMC,EAAQC,GAAA,EACd,GAAI,CAACD,EAAO,MAAM,IAAIH,GACtB,MAAMK,EAAS,MAAMC,GAAWzN,EAAMqN,EAAMC,CAAK,EACjD,OAAAI,GAAA,EACOF,CACT,CAGO,SAASG,IAA6B,CAC3CC,EAAWhB,CAAkB,EAC7BgB,EAAWjB,EAAmB,CAChC,CAEA,eAAsBkB,GAAmBC,EAAuD,CAC9F,MAAMC,EAAU,MAAMX,EAAmB,sBAAuBU,CAAG,EACnE,OAAAH,GAAA,EACOI,CACT,CAEA,eAAsBC,GAAchB,EAAmBiB,EAA0C,CAC/F,MAAMZ,EAAyB,CAAE,KAAAY,CAAA,EAC3BC,EAAW,MAAMd,EAAwBL,EAAiBC,EAAW,QAAQ,EAAGK,CAAI,EAC1F,OAAAO,EAAWhB,CAAkB,EACtBsB,CACT,CAEA,eAAsBC,GAAgBnB,EAAkC,CACtE,MAAMI,EAAmBL,EAAiBC,EAAW,SAAS,EAAG,EAAE,EACnEY,EAAWhB,CAAkB,CAC/B,CAEA,eAAsBwB,GAAmBpB,EAAkC,CACzE,MAAMI,EAAmBL,EAAiBC,EAAW,SAAS,EAAG,EAAE,EACnEW,GAAA,CACF,CAEA,eAAsBU,GAAmBrB,EAAmB1T,EAAsC,CAChG,MAAMyU,EAAU,MAAMX,EAAmBL,EAAiBC,EAAW,SAAS,EAAG,CAAE,MAAA1T,EAAO,EAC1F,OAAAsU,EAAWhB,CAAkB,EACtBmB,CACT,CAMO,MAAMO,GAAuB,mBACvBC,GAA2B,uBAE3BC,GAA0D,CACrE,IAAKF,GACL,MAAQpJ,GAAWC,EAAgC,wBAAyBD,CAAM,CACpF,EAQauJ,GAA4D,CACvE,IAAKF,GACL,MAAQrJ,GAAWC,EAA+B,4BAA6BD,CAAM,CACvF,EASO,SAASwJ,GAAuB1B,EAAmB9H,EAA0D,CAClH,OAAOC,EAAkC4H,EAAiBC,EAAW,QAAQ,EAAG9H,CAAM,CACxF,4ECjHO,SAASyJ,IAAkB,CAChC,MAAMC,EAAQC,GAAA,EAYd,OAXAlE,YAAU,IAAM,CACd,GAAIiE,IAAU,WAAY,OAC1B,IAAIE,EAAY,GAChB,OAAKC,GAAA,EAAsB,KAAMC,GAAY,CAC3C,GAAI,EAAAF,GAAaE,GACjB,OAAOC,GAASpC,EAAoB,IAAKA,EAAoB,KAAK,EAAE,KAAK,IAAM,CACxEiC,GAAWI,GAAkBC,GAAiBtC,EAAoB,GAAG,EAAE,SAAW,SAAS,CAClG,CAAC,CACH,CAAC,EACM,IAAM,CAAEiC,EAAY,EAAM,CACnC,EAAG,CAACF,CAAK,CAAC,EACNA,IAAU,WAAmBlV,MAAC,KAAE,UAAWiD,GAAO,SAAU,KAAK,SAAS,mDAAuC,EACjHiS,IAAU,kBACLlV,MAAC0V,IAAY,QAAQ,yBAAyB,QAAQ,cAAc,QAAQ,cAAc,cAAa,GAAC,SAG9GC,GAAA,CACC,UAAA3V,MAAC4V,GAAA,EAAc,QACd,OAAI,UAAW3S,GAAO,MAAO,SAAAjD,MAACmS,KAAS,EAAE,GAC5C,CAEJ","names":["DESKTOP_COMMAND_EVENT","COMMANDS","resolveTheme","preference","bridge","reportThemeToShell","isDesktopCommand","value","subscribeDesktopCommands","handler","onCommand","event","command","Icon","size","title","children","rest","jsxs","jsx","IconChat","p","IconCpu","IconInbox","IconCheck","IconCheckCircle","IconX","IconGauge","IconSliders","IconAlert","IconInfo","IconPlus","IconSearch","IconCopy","IconChevronDown","IconChevronRight","IconTrash","IconExternalLink","IconLock","IconSun","IconMoon","IconMonitor","ChatIcon","AutonomyIcon","ApprovalsIcon","UsageIcon","SettingsIcon","SearchIcon","PlusIcon","TrashIcon","ArrowDownIcon","ChevronIcon","PanelIcon","props","SidebarIcon","VerseMark","SECTION_ICON","Button","variant","icon","trailingIcon","block","busy","iconOnly","className","disabled","type","classes","styles","ENGINE_COLOR","Tag","engine","mono","dot","showDot","VERSE_SECTIONS","SECTION_IDS","s","VERSE_SIDEBAR","VERSE_RESOURCES","STORAGE_KEY","DEFAULTS","clampWidth","range","n","read","raw","parsed","state","nonce","listeners","persist","next","payload","patch","delta","k","shouldPersist","l","subscribeVerseUi","listener","getVerseUiState","setVerseSection","section","setVerseSidebarWidth","width","setVerseSidebarCollapsed","collapsed","setVerseResourcesOpen","open","setVerseResourcesWidth","setVersePendingApprovals","count","requestVerseCommand","name","clearVerseCommand","SEAT_STORAGE_KEY","SEAT_MEMORY_LIMIT","seatMemory","readSeatMemory","out","path","seatId","model","lastVerseSeat","projectPath","memory","exact","keys","newest","rememberVerseSeat","seat","stale","CLAUDE_VERSION_REASON","CLAUDE_USAGE_PINNED_VERSION","record","str","source","key","v","num","bool","fallback","list","FORBIDDEN_COMMAND","sanitizeCommand","trimmed","clampPercent","projectWindow","r","id","native","limitReached","measuredRaw","projectCredits","balance","PROVIDERS","projectAccount","provider","windows","w","auth","unsupportedRaw","projectUnsupported","explicit","reason","projectCollectorNote","root","flat","collector","projectAccountsSnapshot","rawAccounts","a","projectDay","day","projectUsageSeries","requested","rawDays","windowValue","d","b","c","projectLocalModel","runtime","caps","supportsTools","nativeContext","configuredContext","placement","projectRuntimeReport","rawModels","models","m","projectLocalModels","ollama","lmStudio","reports","x","reachable","machine","USAGE_FRONTIER_KEY","USAGE_VERSE_CONTROL_KEY","frontierUsageQuery","signal","apiGet","describeControlFailure","err","ApiError","verseControlQuery","USAGE_ACCOUNTS_KEY","USAGE_LOCAL_MODELS_KEY","USAGE_SERIES_KEY_PREFIX","describeOptionalFailure","optionalGet","verseAccountsQuery","LOCAL_MODELS_RETRY_DELAYS_MS","readLocalModels","reportsNothingReachable","snapshot","sleep","ms","resolve","reject","onAbort","timer","verseLocalModelsQuery","delayMs","SERIES_QUERIES","usageSeriesQuery","window","ONBOARDING_STEPS","clampStep","step","PROVIDER_RECONNECT","accountFinding","account","label","base","binding","limited","spendable","percent","buildAccountsFindings","input","findings","signedOut","f","usable","summary","LOCAL_MEANING_AVAILABLE","LOCAL_MEANING_ABSENT","buildLocalFinding","toolCapable","STOP_CONTROLS","VERSE_ONBOARDING_STORAGE_KEY","EMPTY","readRecord","isFirstRun","initialRecord","subscribeOnboarding","getOnboardingState","setOnboardingStep","dismissOnboarding","completeOnboarding","replayOnboarding","useOnboarding","useSyncExternalStore","ToneMark","tone","Glyph","StepBody","SECTION_BLURB","WelcomeStep","entry","index","AccountsStep","useQuery","useMemo","finding","LocalStep","StopsStep","control","FinishStep","STEP_COMPONENTS","OnboardingFlow","meta","Step","last","close","useCallback","cardRef","useRef","useEffect","onKey","card","i","useVerseUi","SECTION_MODULES","__vitePreload","MissingSection","moduleName","detail","sectionLoader","importer","mod","exported","SECTION_COMPONENTS","lazy","PENDING_APPROVALS_QUERY","inboxListQuery","VerseApp","ui","theme","useTheme","Section","pendingCount","themeTitle","IconComponent","pending","active","ThemeGlyph","RouteErrorBoundary","Suspense","SectionFallback","VERSE_BOOTSTRAP_KEY","VERSE_SESSIONS_KEY","verseBootstrapQuery","verseSessionsQuery","verseSessionPath","sessionId","suffix","fetchVerseSessionDetail","VerseMutationLockedError","post","body","token","getMutationToken","result","apiPost","touchMutationHold","invalidateVerseLists","invalidate","createVerseSession","req","session","sendVerseTurn","text","response","cancelVerseTurn","deleteVerseSession","renameVerseSession","VERSE_WORKSPACES_KEY","VERSE_AUTONOMY_SCOPE_KEY","verseWorkspacesQuery","verseAutonomyScopeQuery","fetchVerseSessionRoots","VerseConsoleApp","phase","useAuthPhase","cancelled","adoptInjectedTokens","adopted","runQuery","markCheckComplete","getQuerySnapshot","SessionGate","ToastProvider","SkipToContent"],"ignoreList":[],"sources":["../../../../../../src/web-ui/app/desktop-shell.ts","../../../../../../src/web-ui/components/primitives/icons.tsx","../../../../../../src/web-ui/routes/verse/verse-icons.tsx","../../../../../../src/web-ui/components/primitives/Button.tsx","../../../../../../src/web-ui/components/primitives/Tag.tsx","../../../../../../src/web-ui/routes/verse/verse-ui-store.ts","../../../../../../src/web-ui/routes/verse/usage/usage-contract.ts","../../../../../../src/web-ui/routes/verse/usage/usage-queries.ts","../../../../../../src/web-ui/routes/verse/onboarding/onboarding-model.ts","../../../../../../src/web-ui/routes/verse/onboarding/onboarding-store.ts","../../../../../../src/web-ui/routes/verse/onboarding/useOnboarding.ts","../../../../../../src/web-ui/routes/verse/onboarding/OnboardingFlow.tsx","../../../../../../src/web-ui/routes/verse/useVerseUi.ts","../../../../../../src/web-ui/routes/verse/VerseApp.tsx","../../../../../../src/web-ui/routes/verse/verse-queries.ts","../../../../../../src/web-ui/app/VerseConsoleApp.tsx"],"sourcesContent":["/**\n * app/desktop-shell.ts — the web half of the desktop shell contract.\n *\n * The native side (`desktop/src-tauri/src/shell_contract.{rs,js}`, documented\n * in `desktop/README.md` → \"Desktop shell contract\") injects markers, CSS\n * variables, a drag-region mirror, a menu-command event, and one optional\n * page→native call. This module is the ONLY place the web UI touches any of\n * it, so the console keeps exactly one seam to the desktop app and never\n * references Tauri.\n *\n * Everything here is inert in a browser: the markers are absent, the global\n * is undefined, and the event is never dispatched. No caller needs a\n * conditional build or a feature flag.\n */\nimport type { ThemePreference } from '../data/theme-store.js';\n\n/** Commands the native menu bar can send the page. */\nexport type DesktopCommand = 'open-settings' | 'toggle-theme';\n\nconst DESKTOP_COMMAND_EVENT = 'ashlr:desktop-command';\nconst COMMANDS: readonly DesktopCommand[] = ['open-settings', 'toggle-theme'];\n\n/**\n * True only inside the Tauri window, where `shell_contract.js` has stamped\n * `data-app-shell=\"desktop\"` on `<html>`. Layout does NOT branch on this —\n * the CSS reads `--app-titlebar-height` / `--app-traffic-light-inset` with a\n * `0px` fallback instead, so there is one layout, not two.\n */\nexport function isDesktopShell(): boolean {\n try {\n return document.documentElement.getAttribute('data-app-shell') === 'desktop';\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve a three-state preference down to what is actually painted, which is\n * what the native side needs: it stores the value and paints the window\n * background with the matching canvas colour on the NEXT launch, before the\n * webview has painted. 'system' therefore has to become a concrete answer\n * here, not be passed through.\n */\nexport function resolveTheme(preference: ThemePreference): 'light' | 'dark' {\n if (preference === 'light' || preference === 'dark') return preference;\n try {\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n } catch {\n // jsdom and old webviews without matchMedia: light is the token default.\n return 'light';\n }\n}\n\ninterface DesktopBridge {\n reportTheme?: (theme: 'light' | 'dark') => void;\n}\n\nfunction bridge(): DesktopBridge | undefined {\n return (window as unknown as { __ASHLR_DESKTOP__?: DesktopBridge }).__ASHLR_DESKTOP__;\n}\n\n/**\n * Tell the native window which theme is painted, so the next cold launch does\n * not flash white. Optional by contract, best-effort by implementation: a\n * browser has no bridge, and a throwing bridge must never break a render.\n * Repeat calls with the same value are dropped on the native side.\n */\nexport function reportThemeToShell(preference: ThemePreference): void {\n try {\n bridge()?.reportTheme?.(resolveTheme(preference));\n } catch {\n /* the shell is an enhancement; never let it fail the page */\n }\n}\n\nfunction isDesktopCommand(value: unknown): value is DesktopCommand {\n return typeof value === 'string' && (COMMANDS as readonly string[]).includes(value);\n}\n\n/**\n * Listen for menu commands. Returns an unsubscribe function, so a component\n * can register it from an effect.\n *\n * Unknown commands are ignored rather than forwarded: the native menu can\n * grow ahead of the web UI, and an unhandled command is specified to be inert\n * rather than an error.\n */\nexport function subscribeDesktopCommands(handler: (command: DesktopCommand) => void): () => void {\n function onCommand(event: Event): void {\n const detail = (event as CustomEvent<{ command?: unknown }>).detail;\n const command = detail?.command;\n if (isDesktopCommand(command)) handler(command);\n }\n window.addEventListener(DESKTOP_COMMAND_EVENT, onCommand);\n return () => window.removeEventListener(DESKTOP_COMMAND_EVENT, onCommand);\n}\n","/**\n * components/primitives/icons.tsx — the console's icon set.\n *\n * Hand-drawn inline SVG rather than an icon package: the design language\n * fixes one geometry (16px box, 1.5px stroke, round caps/joins, currentColor)\n * and the app ships zero runtime dependencies for presentation. Adding a\n * library here would import hundreds of icons drawn to someone else's stroke\n * weight for the six we actually need per section.\n *\n * Every icon is decorative by default (`aria-hidden`), because it sits next\n * to a label or inside a control that already has an accessible name. Pass\n * `title` ONLY when the icon is the sole carrier of meaning; it then becomes\n * `role=\"img\"` with an accessible name.\n */\nimport type { ReactNode, SVGProps } from 'react';\n\nexport interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'children' | 'viewBox'> {\n /** Edge length in px. Defaults to 16 — the design language's icon size. */\n size?: number;\n /** Accessible name. Omit for decorative icons (the default). */\n title?: string;\n}\n\nfunction Icon({ size = 16, title, children, ...rest }: IconProps & { children: ReactNode }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n focusable=\"false\"\n {...(title ? { role: 'img' } : { 'aria-hidden': true })}\n {...rest}\n >\n {title ? <title>{title}</title> : null}\n {children}\n </svg>\n );\n}\n\n/** Chat — the transcript section. */\nexport const IconChat = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M2.5 11.5V4.25A1.75 1.75 0 0 1 4.25 2.5h7.5a1.75 1.75 0 0 1 1.75 1.75v4.5a1.75 1.75 0 0 1-1.75 1.75H5.5L2.5 13.5v-2Z\" />\n </Icon>\n);\n\n/** CPU — autonomy / the daemon loop. */\nexport const IconCpu = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"4.5\" y=\"4.5\" width=\"7\" height=\"7\" rx=\"1.5\" />\n <path d=\"M6.5 1.5v3M9.5 1.5v3M6.5 11.5v3M9.5 11.5v3M1.5 6.5h3M1.5 9.5h3M11.5 6.5h3M11.5 9.5h3\" />\n </Icon>\n);\n\n/** Inbox — approvals. */\nexport const IconInbox = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M2 9.5 3.6 3.4A1.5 1.5 0 0 1 5.05 2.3h5.9a1.5 1.5 0 0 1 1.45 1.1L14 9.5\" />\n <path d=\"M2 9.5h3l.8 1.6h4.4l.8-1.6h3v2.6A1.9 1.9 0 0 1 12.1 14H3.9A1.9 1.9 0 0 1 2 12.1V9.5Z\" />\n </Icon>\n);\n\nexport const IconCheck = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"m3 8.5 3.2 3.2L13 5\" />\n </Icon>\n);\n\nexport const IconCheckCircle = (p: IconProps) => (\n <Icon {...p}>\n <circle cx=\"8\" cy=\"8\" r=\"6\" />\n <path d=\"m5.2 8.2 1.9 1.9 3.7-4\" />\n </Icon>\n);\n\nexport const IconX = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"m4 4 8 8M12 4l-8 8\" />\n </Icon>\n);\n\n/** Gauge — usage / spend. */\nexport const IconGauge = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M2.2 11.5a6.4 6.4 0 1 1 11.6 0\" />\n <path d=\"M8 11 10.8 6.6\" />\n <circle cx=\"8\" cy=\"11.6\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n </Icon>\n);\n\n/** Sliders — settings. */\nexport const IconSliders = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M2.5 4.5h4M9.5 4.5h4M2.5 11.5h2M7.5 11.5h6\" />\n <circle cx=\"8\" cy=\"4.5\" r=\"1.6\" />\n <circle cx=\"6\" cy=\"11.5\" r=\"1.6\" />\n </Icon>\n);\n\nexport const IconPlay = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M5.5 3.4 12 8l-6.5 4.6V3.4Z\" />\n </Icon>\n);\n\nexport const IconStop = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1.2\" />\n </Icon>\n);\n\nexport const IconPause = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M6 3.5v9M10 3.5v9\" />\n </Icon>\n);\n\n/** Alert — a warning that is paired with text, never used alone for state. */\nexport const IconAlert = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M8 2.6 14.2 13H1.8L8 2.6Z\" />\n <path d=\"M8 6.6v3\" />\n <circle cx=\"8\" cy=\"11.3\" r=\"0.75\" fill=\"currentColor\" stroke=\"none\" />\n </Icon>\n);\n\nexport const IconInfo = (p: IconProps) => (\n <Icon {...p}>\n <circle cx=\"8\" cy=\"8\" r=\"6\" />\n <path d=\"M8 7.4v3.4\" />\n <circle cx=\"8\" cy=\"5.4\" r=\"0.75\" fill=\"currentColor\" stroke=\"none\" />\n </Icon>\n);\n\nexport const IconPlus = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M8 3.2v9.6M3.2 8h9.6\" />\n </Icon>\n);\n\nexport const IconSearch = (p: IconProps) => (\n <Icon {...p}>\n <circle cx=\"7.2\" cy=\"7.2\" r=\"4.2\" />\n <path d=\"m10.4 10.4 3.1 3.1\" />\n </Icon>\n);\n\nexport const IconCopy = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <path d=\"M10.5 3.5a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 3.5v5A1.5 1.5 0 0 0 4 10\" />\n </Icon>\n);\n\nexport const IconChevronDown = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"m4 6.2 4 4 4-4\" />\n </Icon>\n);\n\nexport const IconChevronUp = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"m4 9.8 4-4 4 4\" />\n </Icon>\n);\n\nexport const IconChevronRight = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"m6.2 4 4 4-4 4\" />\n </Icon>\n);\n\nexport const IconChevronLeft = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"m9.8 4-4 4 4 4\" />\n </Icon>\n);\n\nexport const IconMic = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"6\" y=\"1.8\" width=\"4\" height=\"7.4\" rx=\"2\" />\n <path d=\"M3.6 7.6a4.4 4.4 0 0 0 8.8 0M8 11.9v2.3\" />\n </Icon>\n);\n\nexport const IconSend = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M14 2 7.2 8.8M14 2l-4.4 12-2.4-5.2L2 6.4 14 2Z\" />\n </Icon>\n);\n\nexport const IconTrash = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M2.8 4.2h10.4M6.4 4.2V2.8h3.2v1.4M4.2 4.2l.6 8.2a1.3 1.3 0 0 0 1.3 1.2h3.8a1.3 1.3 0 0 0 1.3-1.2l.6-8.2\" />\n </Icon>\n);\n\nexport const IconExternalLink = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M9.5 2.5H13.5v4M13.5 2.5 7.8 8.2\" />\n <path d=\"M12.5 9.6v2.9a1.5 1.5 0 0 1-1.5 1.5H3.5A1.5 1.5 0 0 1 2 12.5V5a1.5 1.5 0 0 1 1.5-1.5h2.9\" />\n </Icon>\n);\n\nexport const IconFolder = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M2 4.6A1.6 1.6 0 0 1 3.6 3h2.3l1.4 1.8h5.1A1.6 1.6 0 0 1 14 6.4v5A1.6 1.6 0 0 1 12.4 13H3.6A1.6 1.6 0 0 1 2 11.4V4.6Z\" />\n </Icon>\n);\n\nexport const IconRefresh = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M13.2 7.2a5.2 5.2 0 1 0-.7 3.5\" />\n <path d=\"M13.5 3.4v3.9h-3.9\" />\n </Icon>\n);\n\nexport const IconLock = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"3\" y=\"7\" width=\"10\" height=\"6.5\" rx=\"1.5\" />\n <path d=\"M5.5 7V5.2a2.5 2.5 0 0 1 5 0V7\" />\n </Icon>\n);\n\nexport const IconKey = (p: IconProps) => (\n <Icon {...p}>\n <circle cx=\"5.4\" cy=\"10.6\" r=\"2.6\" />\n <path d=\"m7.4 8.7 5.3-5.3M10.6 5.5l1.4 1.4M12.2 3.9l1.4 1.4\" />\n </Icon>\n);\n\nexport const IconSun = (p: IconProps) => (\n <Icon {...p}>\n <circle cx=\"8\" cy=\"8\" r=\"3.1\" />\n <path d=\"M8 1.5v1.6M8 12.9v1.6M1.5 8h1.6M12.9 8h1.6M3.4 3.4l1.1 1.1M11.5 11.5l1.1 1.1M12.6 3.4l-1.1 1.1M4.5 11.5l-1.1 1.1\" />\n </Icon>\n);\n\nexport const IconMoon = (p: IconProps) => (\n <Icon {...p}>\n <path d=\"M13 9.8A5.6 5.6 0 0 1 6.2 3a5.6 5.6 0 1 0 6.8 6.8Z\" />\n </Icon>\n);\n\nexport const IconMonitor = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"1.8\" y=\"2.8\" width=\"12.4\" height=\"8.4\" rx=\"1.5\" />\n <path d=\"M5.8 14h4.4M8 11.2V14\" />\n </Icon>\n);\n\nexport const IconDrag = (p: IconProps) => (\n <Icon {...p}>\n <circle cx=\"6\" cy=\"4\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"10\" cy=\"4\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"6\" cy=\"8\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"10\" cy=\"8\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"6\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"10\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n </Icon>\n);\n\nexport const IconKeyboard = (p: IconProps) => (\n <Icon {...p}>\n <rect x=\"1.5\" y=\"4\" width=\"13\" height=\"8\" rx=\"1.5\" />\n <path d=\"M4.2 6.6h.01M6.8 6.6h.01M9.4 6.6h.01M12 6.6h.01M4.2 9.4h.01M12 9.4h.01M6.4 9.4h3.2\" />\n </Icon>\n);\n","/**\n * routes/verse/verse-icons.tsx — the icons the shell rail and the chat chrome\n * use, under the names the Verse surfaces already import.\n *\n * Owner A's `components/primitives/icons.tsx` is now the drawing authority:\n * one geometry (16px box, 1.5px stroke, round caps/joins, currentColor), one\n * stroke weight, one accessibility convention. Everything below that has an\n * equivalent there is an ALIAS of it, so the rail and the inbox cannot drift\n * to two different chat glyphs.\n *\n * Three icons stay drawn here because the shared set has no equivalent and\n * they are Verse-specific chrome, not general console vocabulary:\n * `PanelIcon` / `SidebarIcon` (the two pane toggles, which must read as\n * mirror images of each other) and `VerseMark` (the brand mark in the rail\n * head, which is 32px and never takes a color state).\n */\nimport type { ComponentType, ReactNode } from 'react';\nimport {\n IconChat,\n IconChevronDown,\n IconChevronRight,\n IconCpu,\n IconGauge,\n IconInbox,\n IconMoon,\n IconPlus,\n IconSearch,\n IconSliders,\n IconTrash,\n type IconProps,\n} from '../../components/primitives/icons.js';\nimport type { VerseSectionId } from './verse-ui-store.js';\n\nexport type { IconProps };\n\n/**\n * Aliases onto the shared set. The names are the ones the Verse rail, sidebar\n * and composer already import — keeping them means this reconciliation\n * touched no call site.\n */\nexport const ChatIcon = IconChat;\nexport const AutonomyIcon = IconCpu;\nexport const ApprovalsIcon = IconInbox;\nexport const UsageIcon = IconGauge;\nexport const SettingsIcon = IconSliders;\nexport const SearchIcon = IconSearch;\nexport const PlusIcon = IconPlus;\nexport const TrashIcon = IconTrash;\nexport const ArrowDownIcon = IconChevronDown;\nexport const ChevronIcon = IconChevronRight;\n/** The rail's theme quick-toggle. One glyph for the control, not per-theme. */\nexport const ThemeIcon = IconMoon;\n\n/** Local shell chrome — see the header note for why these three stay here. */\nfunction Icon({ size = 16, children, ...rest }: IconProps & { children: ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 16 16\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport function PanelIcon(props: IconProps) {\n return <Icon {...props}><rect x=\"2.5\" y=\"3\" width=\"11\" height=\"10\" rx=\"1.5\" /><path d=\"M10 3v10\" /></Icon>;\n}\n\nexport function SidebarIcon(props: IconProps) {\n return <Icon {...props}><rect x=\"2.5\" y=\"3\" width=\"11\" height=\"10\" rx=\"1.5\" /><path d=\"M6 3v10\" /></Icon>;\n}\n\n/** The mark in the rail head. Not a section icon — it never gets a color state. */\nexport function VerseMark(props: IconProps) {\n const { size = 20, ...rest } = props;\n return (\n <svg viewBox=\"0 0 32 32\" width={size} height={size} fill=\"none\" stroke=\"currentColor\" strokeWidth={1.8}\n strokeLinejoin=\"round\" strokeLinecap=\"round\" aria-hidden=\"true\" focusable=\"false\" {...rest}>\n <path d=\"m5 11 11-6 11 6-11 6Z M5 16l11 6 11-6 M5 21l11 6 11-6\" />\n </svg>\n );\n}\n\nexport const SECTION_ICON: Record<VerseSectionId, ComponentType<IconProps>> = {\n chat: ChatIcon,\n autonomy: AutonomyIcon,\n approvals: ApprovalsIcon,\n usage: UsageIcon,\n settings: SettingsIcon,\n};\n","/**\n * components/primitives/Button.tsx — every clickable action in the console.\n *\n * Four variants, and they are a hierarchy, not a palette (design doc §1):\n * ghost — the default in dense chrome. No border, no fill. Header strips\n * contain only these.\n * subtle — hairline border, no fill. The ordinary form button.\n * primary — the ONE accent-filled action on a surface. If a screen has two,\n * one of them is wrong.\n * danger — destructive. Outlined, never filled, and always paired with a\n * confirm step at the call site (approve/emergency-stop/delete).\n *\n * Heights come from the density tokens, never from a literal px, so compact\n * mode moves every control together.\n *\n * Icon-only buttons are a TYPE-LEVEL contract: `iconOnly` requires\n * `aria-label`, because an icon with no text has no accessible name and the\n * operator's screen reader would announce \"button\". Use <IconButton> for the\n * common case.\n */\nimport type { ButtonHTMLAttributes, ReactNode, Ref } from 'react';\nimport styles from './Button.module.css';\n\nexport type ButtonVariant = 'ghost' | 'subtle' | 'primary' | 'danger';\nexport type ButtonSize = 'sm' | 'md';\n\ninterface ButtonBase extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Leading glyph (16px icon from ./icons.tsx). */\n icon?: ReactNode;\n /** Trailing glyph — chevrons, external-link marks. */\n trailingIcon?: ReactNode;\n /** Stretch to the container's width (forms, sheets). */\n block?: boolean;\n /** In-flight: disables the control and announces aria-busy. */\n busy?: boolean;\n /** Escape hatch for layout-only classes from a parent module. */\n className?: string;\n /** React 19 takes `ref` as an ordinary prop — no forwardRef wrapper needed. */\n ref?: Ref<HTMLButtonElement>;\n children?: ReactNode;\n}\n\nexport type ButtonProps = ButtonBase &\n (\n | {\n /** Square control with no visible label — an accessible name is mandatory. */\n iconOnly: true;\n 'aria-label': string;\n children?: never;\n }\n | { iconOnly?: false }\n );\n\nexport function Button({\n variant = 'subtle',\n size = 'md',\n icon,\n trailingIcon,\n block = false,\n busy = false,\n iconOnly = false,\n className,\n children,\n disabled,\n type = 'button',\n ...rest\n}: ButtonProps) {\n const classes = [\n styles.button,\n styles[variant],\n styles[size],\n iconOnly ? styles.iconOnly : '',\n block ? styles.block : '',\n className ?? '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button\n type={type}\n className={classes}\n disabled={disabled || busy}\n aria-busy={busy || undefined}\n {...rest}\n >\n {icon ? <span className={styles.glyph}>{icon}</span> : null}\n {iconOnly ? null : children}\n {trailingIcon ? <span className={styles.glyph}>{trailingIcon}</span> : null}\n </button>\n );\n}\n\nexport interface IconButtonProps extends Omit<ButtonBase, 'icon' | 'children' | 'trailingIcon'> {\n icon: ReactNode;\n /** Mandatory: the icon is the whole control. */\n 'aria-label': string;\n}\n\n/** Square, label-less button. Same variants and sizing as <Button>. */\nexport function IconButton({ icon, ...rest }: IconButtonProps) {\n return <Button {...rest} iconOnly icon={icon} />;\n}\n","/**\n * components/primitives/Tag.tsx — a small, quiet label: a seat pill, a model\n * name, a repo, a risk class. NOT a status badge (that is StatusBadge, which\n * owns the status-color mapping) and not a button.\n *\n * `engine` tints the leading dot with that provider's identity hue. Identity\n * hues are never used for the text itself (design doc §2) — the tag's label\n * stays in the normal text color so it keeps its contrast in both themes.\n */\nimport type { ReactNode } from 'react';\nimport type { VerseEngine } from '../../data/api-types.js';\nimport styles from './Tag.module.css';\n\nconst ENGINE_COLOR: Record<VerseEngine, string> = {\n claude: 'var(--engine-claude)',\n codex: 'var(--engine-codex)',\n grok: 'var(--engine-grok)',\n local: 'var(--engine-local)',\n};\n\nexport interface TagProps {\n children: ReactNode;\n /** Provider identity: tints the leading dot and the pill's edge. */\n engine?: VerseEngine;\n /** Monospace for ids, paths and model names. */\n mono?: boolean;\n size?: 'sm' | 'md';\n /** Show a leading dot even without an engine. */\n dot?: boolean;\n title?: string;\n className?: string;\n}\n\nexport function Tag({ children, engine, mono = false, size = 'md', dot = false, title, className }: TagProps) {\n const showDot = dot || engine !== undefined;\n return (\n <span\n className={`${styles.tag} ${styles[size]} ${mono ? styles.mono : ''} ${className ?? ''}`}\n title={title}\n data-engine={engine}\n >\n {showDot ? (\n <span\n className={styles.dot}\n style={engine ? { background: ENGINE_COLOR[engine] } : undefined}\n aria-hidden=\"true\"\n />\n ) : null}\n {children}\n </span>\n );\n}\n\n/** The 2px identity marker used on session rows and seat pills. */\nexport function EngineMarker({ engine, className }: { engine: VerseEngine; className?: string }) {\n return <span className={`${styles.marker} ${className ?? ''}`} style={{ background: ENGINE_COLOR[engine] }} aria-hidden=\"true\" />;\n}\n\nexport function engineColor(engine: VerseEngine): string {\n return ENGINE_COLOR[engine];\n}\n","/**\n * routes/verse/verse-ui-store.ts — the shell's own state: which of the five\n * rail sections is mounted, the chat sidebar's width / collapsed flag, and\n * the resources panel. Framework-free (one `useSyncExternalStore` hook at\n * the bottom), same split as verse-store.ts + useVerseSession.ts.\n *\n * Persisted under `ashlr.verse.ui.v2` (VERSE-CONTRACT-V2 \"Shell contract\").\n * Two fields are deliberately NOT persisted:\n *\n * - `pendingApprovals` — evidence, not preference. The Approvals rail item\n * shows its dot from whatever the Approvals/Autonomy section last\n * published via `setVersePendingApprovals`; a stale count restored from\n * localStorage would claim work is waiting when it is not.\n * - `command` — the ⌘N / ⌘K hand-off. The rail owns the global shortcuts,\n * but the section that can act on them is lazily mounted and takes no\n * props (contract), so the shell raises a one-shot command here and the\n * section consumes it by nonce.\n */\n\nexport type VerseSectionId = 'chat' | 'autonomy' | 'approvals' | 'usage' | 'settings';\n\n/** Rail order is the ⌘1–⌘5 order. */\nexport const VERSE_SECTIONS: readonly { id: VerseSectionId; label: string; module: string }[] = [\n { id: 'chat', label: 'Chat', module: 'ChatSection' },\n { id: 'autonomy', label: 'Autonomy', module: 'AutonomySection' },\n { id: 'approvals', label: 'Approvals', module: 'ApprovalsSection' },\n { id: 'usage', label: 'Usage', module: 'UsageSection' },\n { id: 'settings', label: 'Settings', module: 'SettingsSection' },\n];\n\nconst SECTION_IDS = new Set<string>(VERSE_SECTIONS.map((s) => s.id));\n\n/** One-shot shell → section requests. */\nexport type VerseCommandName = 'new-chat' | 'quick-switcher';\n\nexport interface VerseCommand {\n name: VerseCommandName;\n /** Monotonic; a section reacts when it sees a nonce it has not handled. */\n nonce: number;\n}\n\nexport interface VerseUiState {\n section: VerseSectionId;\n sidebarWidth: number;\n sidebarCollapsed: boolean;\n resourcesOpen: boolean;\n resourcesWidth: number;\n pendingApprovals: number;\n command: VerseCommand | null;\n}\n\nexport const VERSE_SIDEBAR = { min: 240, max: 360, def: 264 } as const;\nexport const VERSE_RESOURCES = { min: 260, max: 480, def: 320 } as const;\n\nconst STORAGE_KEY = 'ashlr.verse.ui.v2';\n\nconst DEFAULTS: VerseUiState = {\n section: 'chat',\n sidebarWidth: VERSE_SIDEBAR.def,\n sidebarCollapsed: false,\n resourcesOpen: true,\n resourcesWidth: VERSE_RESOURCES.def,\n pendingApprovals: 0,\n command: null,\n};\n\nexport function clampWidth(value: unknown, range: { min: number; max: number; def: number }): number {\n const n = Number(value);\n if (!Number.isFinite(n) || n <= 0) return range.def;\n return Math.max(range.min, Math.min(range.max, Math.round(n)));\n}\n\n/** Persisted subset. `pendingApprovals`/`command` never round-trip. */\ntype Persisted = Pick<VerseUiState, 'section' | 'sidebarWidth' | 'sidebarCollapsed' | 'resourcesOpen' | 'resourcesWidth'>;\n\nfunction read(): VerseUiState {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return DEFAULTS;\n const parsed = JSON.parse(raw) as Partial<Persisted>;\n return {\n ...DEFAULTS,\n section: typeof parsed.section === 'string' && SECTION_IDS.has(parsed.section) ? (parsed.section as VerseSectionId) : DEFAULTS.section,\n sidebarWidth: clampWidth(parsed.sidebarWidth, VERSE_SIDEBAR),\n sidebarCollapsed: parsed.sidebarCollapsed === true,\n resourcesOpen: parsed.resourcesOpen !== false,\n resourcesWidth: clampWidth(parsed.resourcesWidth, VERSE_RESOURCES),\n };\n } catch {\n return DEFAULTS;\n }\n}\n\nlet state: VerseUiState = read();\nlet nonce = 0;\nconst listeners = new Set<() => void>();\n\nfunction persist(next: VerseUiState): void {\n const payload: Persisted = {\n section: next.section,\n sidebarWidth: next.sidebarWidth,\n sidebarCollapsed: next.sidebarCollapsed,\n resourcesOpen: next.resourcesOpen,\n resourcesWidth: next.resourcesWidth,\n };\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n } catch {\n /* best-effort: a private window without storage still runs the app */\n }\n}\n\n/** Snapshot identity only changes when something actually changed. */\nfunction patch(delta: Partial<VerseUiState>): void {\n const next = { ...state, ...delta };\n if ((Object.keys(delta) as (keyof VerseUiState)[]).every((k) => Object.is(state[k], next[k]))) return;\n const shouldPersist = (['section', 'sidebarWidth', 'sidebarCollapsed', 'resourcesOpen', 'resourcesWidth'] as const)\n .some((k) => !Object.is(state[k], next[k]));\n state = next;\n if (shouldPersist) persist(next);\n for (const l of listeners) l();\n}\n\nexport function subscribeVerseUi(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function getVerseUiState(): VerseUiState {\n return state;\n}\n\nexport function setVerseSection(section: VerseSectionId): void {\n patch({ section });\n}\n\nexport function setVerseSidebarWidth(width: number): void {\n patch({ sidebarWidth: clampWidth(width, VERSE_SIDEBAR) });\n}\n\nexport function setVerseSidebarCollapsed(collapsed: boolean): void {\n patch({ sidebarCollapsed: collapsed });\n}\n\nexport function toggleVerseSidebar(): void {\n patch({ sidebarCollapsed: !state.sidebarCollapsed });\n}\n\nexport function setVerseResourcesOpen(open: boolean): void {\n patch({ resourcesOpen: open });\n}\n\nexport function setVerseResourcesWidth(width: number): void {\n patch({ resourcesWidth: clampWidth(width, VERSE_RESOURCES) });\n}\n\n/**\n * Published by whichever section knows the real number (Approvals reads\n * `GET /api/inbox`, Autonomy reads `VerseControlSnapshot.pendingCount`).\n * Unknown stays 0 — the rail shows no dot rather than inventing one.\n */\nexport function setVersePendingApprovals(count: number): void {\n const n = Number.isFinite(count) ? Math.max(0, Math.trunc(count)) : 0;\n patch({ pendingApprovals: n });\n}\n\n/** ⌘N / ⌘K: switch to Chat and hand the section a one-shot request. */\nexport function requestVerseCommand(name: VerseCommandName): void {\n nonce += 1;\n patch({ section: 'chat', command: { name, nonce } });\n}\n\nexport function clearVerseCommand(): void {\n patch({ command: null });\n}\n\n/** Test hygiene. */\nexport function resetVerseUi(): void {\n state = DEFAULTS;\n nonce = 0;\n seatMemory = null;\n try {\n localStorage.removeItem(STORAGE_KEY);\n localStorage.removeItem(SEAT_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n for (const l of listeners) l();\n}\n\nexport const VERSE_UI_STORAGE_KEY = STORAGE_KEY;\n\n// ---------------------------------------------------------------------------\n// Last-used seat, per project\n// ---------------------------------------------------------------------------\n\n/**\n * Which seat + model a project's last chat was started on.\n *\n * WHY THIS IS PERSISTED. A new chat is seat-bound at creation, and the two\n * ways to start one — the sidebar \"+\" and ⌘N — both carry the CURRENT\n * session's seat forward. That works right up until there is no current\n * session (first load, or after deleting the last chat), where both fall\n * through to `defaultSeatChoice()`, which walks ENGINE_ORDER and lands on\n * Claude: the scarcest and most expensive account, chosen by alphabet rather\n * than by intent. Remembering the last seat per project makes \"New chat\" mean\n * the same thing across a reload as it does within one.\n *\n * NOT part of `VerseUiState`. This is a per-project memory, not shell state:\n * nothing re-renders when it changes, `VERSE-CONTRACT-V2` pins the shape\n * stored under `ashlr.verse.ui.v2`, and a map that grows with the project list\n * has no business in a snapshot compared by identity on every render.\n */\nexport interface VerseSeatMemory {\n seatId: string;\n model: string;\n}\n\nconst SEAT_STORAGE_KEY = 'ashlr.verse.seats.v1';\n/** Bounded so a long-lived browser cannot accumulate an unbounded map. */\nconst SEAT_MEMORY_LIMIT = 50;\n\n/** Lazily read, then held in memory; `null` means \"not read yet\". */\nlet seatMemory: Record<string, VerseSeatMemory> | null = null;\n\nfunction readSeatMemory(): Record<string, VerseSeatMemory> {\n if (seatMemory) return seatMemory;\n const out: Record<string, VerseSeatMemory> = {};\n try {\n const raw = localStorage.getItem(SEAT_STORAGE_KEY);\n const parsed = raw ? (JSON.parse(raw) as unknown) : null;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n for (const [path, value] of Object.entries(parsed as Record<string, unknown>)) {\n if (!value || typeof value !== 'object' || Array.isArray(value)) continue;\n const { seatId, model } = value as Record<string, unknown>;\n if (typeof seatId !== 'string' || seatId.length === 0) continue;\n if (typeof model !== 'string' || model.length === 0) continue;\n out[path] = { seatId, model };\n }\n }\n } catch {\n /* a private window without storage still runs the app */\n }\n seatMemory = out;\n return out;\n}\n\n/**\n * The seat a chat on `projectPath` was last started with, or the most recent\n * seat on any project when that project has no record yet — a brand-new\n * project inherits the operator's current working habit rather than resetting\n * to the default engine. Null only when nothing has ever been started.\n */\nexport function lastVerseSeat(projectPath?: string | null): VerseSeatMemory | null {\n const memory = readSeatMemory();\n if (projectPath) {\n const exact = memory[projectPath];\n if (exact) return exact;\n }\n // Insertion order is recency order: rememberVerseSeat re-inserts on write.\n const keys = Object.keys(memory);\n const newest = keys[keys.length - 1];\n return newest ? memory[newest] ?? null : null;\n}\n\n/** Record the seat a chat was just created with. Never throws. */\nexport function rememberVerseSeat(projectPath: string, seat: VerseSeatMemory): void {\n if (!projectPath || !seat.seatId || !seat.model) return;\n const memory = readSeatMemory();\n // Delete before re-inserting so key order stays newest-last.\n delete memory[projectPath];\n memory[projectPath] = { seatId: seat.seatId, model: seat.model };\n const keys = Object.keys(memory);\n for (const stale of keys.slice(0, Math.max(0, keys.length - SEAT_MEMORY_LIMIT))) {\n delete memory[stale];\n }\n try {\n localStorage.setItem(SEAT_STORAGE_KEY, JSON.stringify(memory));\n } catch {\n /* best-effort */\n }\n}\n\nexport const VERSE_SEAT_STORAGE_KEY = SEAT_STORAGE_KEY;\n","/**\n * routes/verse/usage/usage-contract.ts\n *\n * ┌───────────────────────────────────────────────────────────────────────┐\n * │ INTEGRATION — RECONCILED AGAINST OWNER T'S REAL ROUTES (V2.1) │\n * │ │\n * │ GET /api/verse/accounts → VerseAccountsSnapshot │\n * │ GET /api/verse/usage-series → {window, byDay, estimated, caveats} │\n * │ GET /api/verse/local-models → VerseLocalModelsSnapshot │\n * │ │\n * │ T's types now exist and are imported below as the WIRE shapes. The │\n * │ interfaces in this file are no longer stand-ins for them: they are │\n * │ the DISPLAY shapes this section renders, and they differ from the │\n * │ wire on purpose in three places the seam actually required — │\n * │ │\n * │ 1. local-models arrives as TWO runtime reports (ollama, lmStudio) │\n * │ plus a `machine` budget. This section shows one list of models │\n * │ against one budget, so `projectLocalModels` flattens them. │\n * │ 2. usage-series arrives as `{byDay}`, not `{days}` (T's documented │\n * │ deviation 1). The projector reads `byDay` and still accepts │\n * │ `days`/a bare array so an older server degrades rather than dies. │\n * │ 3. `unsupported` is not a wire field. T reports the version-pin │\n * │ failure in `reason` as the verbatim probe code, so it is DERIVED │\n * │ here from that code plus T's exported pin constant rather than │\n * │ being added to T's contract late in the run. │\n * │ │\n * │ The `WIRE_*_KEYS` blocks below are the executable seam contract: │\n * │ every canonical field name this module reads is pinned to `keyof` the │\n * │ corresponding core type, so a rename in src/core/verse breaks THIS │\n * │ build instead of silently degrading the panel to \"unknown\" at run │\n * │ time — which is exactly how this seam was broken when integration │\n * │ started. │\n * └───────────────────────────────────────────────────────────────────────┘\n *\n * Why every read goes through a structural narrower instead of a cast:\n *\n * - This section must render correctly against a server that does NOT have\n * T's routes (404) and against one that has an earlier spelling of them.\n * A cast would turn a field-name drift into `undefined.something` at\n * render time; a narrower turns it into an honest \"unknown\" with a reason.\n * - Nothing here is ever coerced. A missing percentage stays `null`, never\n * 0 — `usedPercent: 0` and \"no reading\" are different facts and the UI\n * draws them differently (docs/VERSE-TELEMETRY-V2.md, closing rules).\n *\n * SECURITY (docs/VERSE-CONTRACT-V2.md ground rules): a native-profile\n * launcher command must never reach a surface. `sanitizeCommand` below is a\n * client-side backstop on top of the server's own stripping — if a payload\n * ever carries a launcher path, this module drops it rather than printing it.\n *\n * Pure: no React, no I/O.\n */\n// EVERY import from src/core here MUST be type-only.\n//\n// `core/verse/accounts.ts` is the server's collector: it pulls node:fs,\n// node:child_process, the quota lease and the connection monitor. A VALUE\n// import of even a one-word constant from it drags that entire graph into the\n// browser bundle — `vite build` externalizes the node built-ins and the build\n// fails. Type-only imports are erased, so the seam guards below cost nothing\n// at runtime. The two constants this module needs are therefore re-declared\n// locally and PINNED TO CORE'S LITERAL TYPES (see below), which gives the same\n// drift protection with no emitted import.\nimport type {\n VerseAccountRecord,\n VerseAccountWindow,\n VerseAccountsCollectorStatus,\n VerseAccountsSnapshot,\n VerseCodexCredits,\n} from '../../../../core/verse/accounts.js';\nimport type {\n VerseLocalModel,\n VerseLocalModelsSnapshot,\n VerseLocalRuntimeReport,\n} from '../../../../core/verse/local-models.js';\nimport type { DailyUsage as CoreDailyUsage } from '../../../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Seam contract — compile-time only, zero runtime cost.\n//\n// Each entry pins a field name this module reads off the wire to `keyof` the\n// core type that produces it. Renaming a field in src/core/verse now fails\n// `npm run typecheck:web` here, at the seam, rather than turning a live panel\n// into a silent \"unknown\".\n// ---------------------------------------------------------------------------\n\nconst WIRE_ACCOUNT_KEYS = {\n id: 'id',\n label: 'label',\n provider: 'provider',\n state: 'state',\n authentication: 'authentication',\n health: 'health',\n planType: 'planType',\n observedAt: 'observedAt',\n windows: 'windows',\n binding: 'binding',\n credits: 'credits',\n reason: 'reason',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountRecord>;\n\nconst WIRE_WINDOW_KEYS = {\n id: 'id',\n usedPercent: 'usedPercent',\n resetsAt: 'resetsAt',\n nativeReport: 'nativeReport',\n limitReached: 'limitReached',\n measured: 'measured',\n} as const satisfies Record<string, keyof VerseAccountWindow>;\n\nconst WIRE_CREDITS_KEYS = {\n hasCredits: 'hasCredits',\n unlimited: 'unlimited',\n balance: 'balance',\n} as const satisfies Record<string, keyof VerseCodexCredits>;\n\nconst WIRE_ACCOUNTS_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n refreshing: 'refreshing',\n accounts: 'accounts',\n collector: 'collector',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountsSnapshot>;\n\nconst WIRE_COLLECTOR_KEYS = {\n owner: 'owner',\n note: 'note',\n} as const satisfies Record<string, keyof VerseAccountsCollectorStatus>;\n\nconst WIRE_LOCAL_SNAPSHOT_KEYS = {\n machine: 'machine',\n ollama: 'ollama',\n lmStudio: 'lmStudio',\n} as const satisfies Record<string, keyof VerseLocalModelsSnapshot>;\n\nconst WIRE_LOCAL_RUNTIME_KEYS = {\n reachable: 'reachable',\n models: 'models',\n reason: 'reason',\n // V2.1: a RETAINED known-good reading rather than a fresh probe. Both must\n // be projected — a stale reading presented as fresh is the exact failure\n // this seam exists to prevent.\n stale: 'stale',\n staleForMs: 'staleForMs',\n} as const satisfies Record<string, keyof VerseLocalRuntimeReport>;\n\nconst WIRE_LOCAL_MODEL_KEYS = {\n id: 'id',\n label: 'label',\n state: 'state',\n sizeBytes: 'sizeBytes',\n sizeVramBytes: 'sizeVramBytes',\n placement: 'placement',\n gpuPercent: 'gpuPercent',\n memoryPercent: 'memoryPercent',\n family: 'family',\n arch: 'arch',\n expiresAt: 'expiresAt',\n contextLength: 'contextLength',\n nativeContextLength: 'nativeContextLength',\n parameterSize: 'parameterSize',\n quantization: 'quantization',\n capabilities: 'capabilities',\n supportsTools: 'supportsTools',\n} as const satisfies Record<string, keyof VerseLocalModel>;\n\n/**\n * Claude's version-pin constants, re-declared rather than imported.\n *\n * The annotations are the drift guard: `typeof import(...)` is a TYPE position,\n * so it is erased at build time, but it resolves to core's literal type\n * (`'2.1.257'`, `'usage-version-unsupported'`). Change either constant in\n * `core/verse/accounts.ts` and this file stops compiling — the same protection\n * a value import would give, without pulling node:fs into the browser.\n */\ntype CoreAccountsModule = typeof import('../../../../core/verse/accounts.js');\n\nexport const CLAUDE_VERSION_REASON: CoreAccountsModule['VERSE_CLAUDE_VERSION_REASON'] =\n 'usage-version-unsupported';\n\nexport const CLAUDE_USAGE_PINNED_VERSION: CoreAccountsModule['VERSE_CLAUDE_USAGE_PINNED_VERSION'] =\n '2.1.257';\n\n/** `byDay` is the wire key (T's deviation 1); `DailyUsage` below mirrors core. */\nconst WIRE_DAILY_USAGE_KEYS = {\n day: 'day',\n tokensIn: 'tokensIn',\n tokensOut: 'tokensOut',\n estCostUsd: 'estCostUsd',\n sessions: 'sessions',\n cacheRead: 'cacheRead',\n cacheWrite: 'cacheWrite',\n cacheHitRate: 'cacheHitRate',\n} as const satisfies Record<string, keyof CoreDailyUsage>;\n\n// Referenced so the guards are not dead code under `noUnusedLocals`.\nexport const WIRE_CONTRACT_KEYS = {\n account: WIRE_ACCOUNT_KEYS,\n window: WIRE_WINDOW_KEYS,\n credits: WIRE_CREDITS_KEYS,\n accountsSnapshot: WIRE_ACCOUNTS_SNAPSHOT_KEYS,\n collector: WIRE_COLLECTOR_KEYS,\n localSnapshot: WIRE_LOCAL_SNAPSHOT_KEYS,\n localRuntime: WIRE_LOCAL_RUNTIME_KEYS,\n localModel: WIRE_LOCAL_MODEL_KEYS,\n dailyUsage: WIRE_DAILY_USAGE_KEYS,\n} as const;\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/accounts\n// ---------------------------------------------------------------------------\n\n/** Provider ids this surface knows how to describe. */\nexport type AccountProvider = 'claude' | 'codex' | 'grok';\n\n/**\n * One quota window on an account.\n *\n * `resetsAt` is an ISO string when the provider gave a real timestamp (Codex\n * publishes an epoch the server normalizes). Claude's is STRUCTURALLY always\n * null and the human sentence lives in `nativeReport.resetDescription`, which\n * is rendered verbatim and never turned into a countdown.\n */\nexport interface AccountWindow {\n id: string;\n /** Human label when the server supplies one; otherwise `id` is shown. */\n label: string | null;\n /** 0–100. `null` is \"no reading\", never 0. */\n usedPercent: number | null;\n /** ISO 8601, or null. */\n resetsAt: string | null;\n /** Verbatim provider prose, e.g. \"resets Sep 25 at 7pm (America/New_York)\". */\n resetDescription: string | null;\n /**\n * True when the provider signalled `rateLimitReachedType` — the upstream\n * writes the SENTINEL 100, which is a flag, not a measurement. Rendered as\n * \"limit reached\", never as \"100% used\".\n */\n limitReached: boolean;\n /**\n * False when `usedPercent` is a FLAGGED SENTINEL rather than a reading.\n *\n * Codex writes `rateLimitReachedType` upstream as the value 100, so a bare\n * 100 is indistinguishable from a genuinely measured 100 by the time it\n * arrives. The server distinguishes them; this surface must not collapse\n * them back together. Absent on the wire → assumed measured UNLESS the\n * limit flag is set, which is the only case where the sentinel is written.\n */\n measured: boolean;\n}\n\n/**\n * Codex credits. Independent of the window: a 100%-used week with a spendable\n * balance is NOT blocked, and this surface must not say it is.\n */\nexport interface AccountCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Raw decimal string from the provider, kept verbatim for the title text. */\n balance: string | null;\n /** `balance` parsed, or null when it was absent/unparseable. */\n balanceValue: number | null;\n}\n\nexport interface Account {\n id: string;\n label: string;\n provider: AccountProvider;\n state: 'checking' | 'observed' | 'signed-out' | 'unavailable';\n authentication: 'signed-in' | 'signed-out' | 'unknown';\n /**\n * The connection monitor's own health verdict. Claude's is ALWAYS `unknown`\n * by construction (docs/VERSE-TELEMETRY-V2.md) — that is not a fault and is\n * never rendered as one.\n */\n health: string | null;\n planType: string | null;\n observedAt: string | null;\n windows: AccountWindow[];\n /**\n * The server's computed binding window (highest used percent). Kept as its\n * own field rather than recomputed blindly, but `accounts-model.ts` verifies\n * it against `windows` and falls back to computing it when absent.\n */\n binding: AccountWindow | null;\n credits: AccountCredits | null;\n /** Plain-language reason for a non-observed state. */\n reason: string | null;\n /**\n * Present when a probe failed CLOSED on a version pin (Claude's probe is\n * pinned to a specific Claude Code build). The fix is a one-line constant\n * bump, so the UI names it instead of showing a silent \"unknown\".\n */\n unsupported: { code: string; pinnedVersion: string | null } | null;\n /** Already sanitized — see `sanitizeCommand`. Null when nothing safe to show. */\n reconnectCommand: string | null;\n /**\n * The server's plain-language facts for this account (`VerseAccountRecord.\n * notes`). Grok's \"reconnect through `ashlr resources`, profile path withheld\n * on purpose\" lives here, which is why this surface shows notes rather than\n * only the machine-readable `reason`.\n */\n notes: string[];\n}\n\nexport interface AccountsSnapshot {\n sampledAt: string | null;\n refreshing: boolean;\n accounts: Account[];\n /**\n * Set when another collector process owns the quota-refresh lease, so these\n * readings are read-only and may be staler than this server's poll interval.\n */\n collectorNote: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/usage-series?window=7d|30d\n// ---------------------------------------------------------------------------\n\nexport type SeriesWindow = '7d' | '30d';\n\n/** `buildRollup(window, cfg).byDay` — see docs/VERSE-TELEMETRY-V2.md. */\nexport interface DailyUsage {\n /** YYYY-MM-DD. */\n day: string;\n tokensIn: number;\n tokensOut: number;\n /** ESTIMATED from a static price table. Never a billed figure. */\n estCostUsd: number;\n sessions: number;\n /** Optional: absent means the rollup carried no cache columns for that day. */\n cacheRead: number | null;\n cacheWrite: number | null;\n /** 0–1 fraction, or null. */\n cacheHitRate: number | null;\n}\n\nexport interface UsageSeries {\n window: SeriesWindow;\n days: DailyUsage[];\n generatedAt: string | null;\n /**\n * The server states outright that every cost column here is estimated.\n * Carried through rather than re-asserted locally so the disclosure the UI\n * prints is the one the producer actually made.\n */\n estimated: boolean;\n /** The server's own caveats, rendered verbatim beside the charts. */\n caveats: string[];\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models\n// ---------------------------------------------------------------------------\n\nexport interface LocalModel {\n name: string;\n /** Which runtime reported it, so a flattened list stays attributable. */\n runtime: 'ollama' | 'lmstudio' | null;\n /** Resident in memory right now (Ollama /api/ps), vs merely installed. */\n loaded: boolean;\n /** Total resident bytes, or null when not reported. */\n sizeBytes: number | null;\n /** Of `sizeBytes`, how much sits in VRAM. null = not reported. */\n sizeVramBytes: number | null;\n /**\n * Where the weights actually sit. `split` is the one that matters: a model\n * that only half-fits the GPU runs at a fraction of the speed of one that\n * fits, and that is the difference between usable and not.\n */\n placement: 'gpu' | 'cpu' | 'split' | 'unknown';\n /** The runtime's own GPU share, 0–100. Preferred over recomputing it. */\n gpuPercent: number | null;\n /** Resident size against total machine memory, 0–100, else null. */\n memoryPercent: number | null;\n family: string | null;\n arch: string | null;\n /** Keep-alive expiry (ISO). Only meaningful while `loaded`. */\n expiresAt: string | null;\n /** e.g. \"79.7B\". Provider string, never parsed into a number for display. */\n parameterSize: string | null;\n /** e.g. \"Q4_K_M\". */\n quantization: string | null;\n /** Native context from model_info[\"<arch>.context_length\"]. */\n nativeContext: number | null;\n /** Context Ashlr actually configures for this seat, when it differs. */\n configuredContext: number | null;\n /**\n * `capabilities` from /api/show. `null` means the capability list was not\n * reported — which is NOT the same as \"does not support tools\".\n */\n capabilities: string[] | null;\n /**\n * The runtime's own answer to \"can this drive an agentic session\", which is\n * AUTHORITATIVE over `capabilities` and must be preferred when non-null.\n *\n * This matters: owner T sends `capabilities: []` when a runtime reported no\n * capability list, and reading that array alone would render \"no tools\" —\n * a hard, wrong gate — where T's `supportsTools: null` correctly means\n * \"unknown\". Deriving tool support from the array alone was a real defect\n * at this seam, not a cosmetic one.\n */\n supportsTools: boolean | null;\n}\n\n/**\n * One runtime's own reachability, kept per-runtime rather than folded into the\n * flattened list, because STALENESS is per-runtime and must be stated.\n *\n * `stale` means the server served a RETAINED known-good reading after a probe\n * TIMED OUT (core `VERSE_LOCAL_LAST_GOOD_TTL_MS`). That is the honest choice\n * server-side — a timeout is \"no answer yet\", not \"the runtime is gone\" — but\n * it obliges this surface to say plainly that the numbers are N seconds old\n * rather than presenting them as fresh.\n */\nexport interface LocalRuntimeStatus {\n runtime: 'ollama' | 'lmstudio';\n reachable: boolean;\n /** Machine-readable degradation code; never rendered as a sentence. */\n reason: string | null;\n /** True when this report is a retained reading rather than a fresh probe. */\n stale: boolean;\n /** Age of that retained reading in ms. Null when `stale` is false. */\n staleForMs: number | null;\n modelCount: number;\n}\n\nexport interface LocalModelsSnapshot {\n reachable: boolean;\n models: LocalModel[];\n /** Machine memory budget in bytes, or null when the server did not say. */\n memoryBudgetBytes: number | null;\n /** Machine memory reported free right now, or null. */\n freeMemoryBytes: number | null;\n reason: string | null;\n /** Per-runtime reachability and staleness. Empty on a flat legacy body. */\n runtimes: LocalRuntimeStatus[];\n /** The server's own plain-language caveats for this snapshot. */\n notes: string[];\n sampledAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Narrowing helpers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction str(source: Record<string, unknown>, key: string): string | null {\n const v = source[key];\n return typeof v === 'string' && v.length > 0 ? v : null;\n}\n\nfunction num(source: Record<string, unknown>, key: string): number | null {\n const v = source[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n}\n\nfunction bool(source: Record<string, unknown>, key: string, fallback = false): boolean {\n const v = source[key];\n return typeof v === 'boolean' ? v : fallback;\n}\n\nfunction list(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\n/**\n * Drop anything that looks like a native-profile launcher invocation or an\n * absolute path into the private account store. The server is supposed to\n * strip these; this is the client-side backstop, because the cost of printing\n * one is unacceptable and the cost of showing \"no command\" is a sentence.\n */\nconst FORBIDDEN_COMMAND = /(launcher\\.mjs|native-profiles|account-connections|console-startup|\\/\\.ashlr\\b|Bearer\\s|--token\\b)/i;\n\nexport function sanitizeCommand(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 200) return null;\n if (FORBIDDEN_COMMAND.test(trimmed)) return null;\n // A newline would let a payload smuggle a second command onto the surface.\n if (/[\\r\\n]/.test(trimmed)) return null;\n return trimmed;\n}\n\nfunction clampPercent(value: number | null): number | null {\n if (value === null) return null;\n return Math.max(0, Math.min(100, value));\n}\n\nfunction projectWindow(raw: unknown): AccountWindow | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id') ?? str(r, 'label');\n if (id === null) return null;\n const native = record(r['nativeReport']);\n const limitReached = bool(r, 'limitReached') || bool(r, 'rateLimitReached');\n const measuredRaw = r['measured'];\n return {\n id,\n label: str(r, 'label'),\n usedPercent: clampPercent(num(r, 'usedPercent') ?? num(r, 'used_percent')),\n resetsAt: str(r, 'resetsAt') ?? str(r, 'resets_at'),\n resetDescription:\n (native ? str(native, 'resetDescription') : null) ?? str(r, 'resetDescription'),\n limitReached,\n // Absent → measured, EXCEPT under a limit flag, which is the one case the\n // upstream writes the sentinel 100. Defaulting a flagged window to\n // `measured: true` would let a denial print as \"100% used\".\n measured: typeof measuredRaw === 'boolean' ? measuredRaw : !limitReached,\n };\n}\n\nfunction projectCredits(raw: unknown): AccountCredits | null {\n const r = record(raw);\n if (!r) return null;\n const balance = str(r, 'balance');\n const parsed = balance === null ? num(r, 'balance') : Number.parseFloat(balance);\n return {\n hasCredits: bool(r, 'hasCredits') || bool(r, 'has_credits'),\n unlimited: bool(r, 'unlimited'),\n balance,\n balanceValue: typeof parsed === 'number' && Number.isFinite(parsed) ? parsed : null,\n };\n}\n\nconst PROVIDERS: readonly string[] = ['claude', 'codex', 'grok'];\n\nfunction projectAccount(raw: unknown): Account | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id');\n const provider = str(r, 'provider');\n if (id === null || provider === null || !PROVIDERS.includes(provider)) return null;\n\n const windows = list(r['windows'])\n .map(projectWindow)\n .filter((w): w is AccountWindow => w !== null);\n\n const state = str(r, 'state');\n const auth = str(r, 'authentication');\n const unsupportedRaw = record(r['unsupported']);\n\n return {\n id,\n label: str(r, 'label') ?? id,\n provider: provider as AccountProvider,\n state:\n state === 'checking' || state === 'observed' || state === 'signed-out' || state === 'unavailable'\n ? state\n : 'unavailable',\n authentication: auth === 'signed-in' || auth === 'signed-out' ? auth : 'unknown',\n health: str(r, 'health'),\n planType: str(r, 'planType') ?? str(r, 'plan_type'),\n observedAt: str(r, 'observedAt'),\n windows,\n binding: projectWindow(r['binding']),\n credits: projectCredits(r['credits']),\n reason: str(r, 'reason'),\n unsupported: projectUnsupported(r, unsupportedRaw),\n reconnectCommand: sanitizeCommand(r['reconnectCommand']),\n notes: list(r['notes']).filter((n): n is string => typeof n === 'string'),\n };\n}\n\n/**\n * A version-pinned probe that failed CLOSED, named rather than swallowed.\n *\n * `unsupported` is not a field on the wire. Owner T reports the failure as the\n * verbatim probe code in `reason` (`usage-version-unsupported`) and states the\n * pin in `notes`, so this derives the structured form from those rather than\n * requiring a late contract change. An explicit `unsupported` object is still\n * honoured first, so a server that grows one later wins without a client edit.\n */\nfunction projectUnsupported(\n r: Record<string, unknown>,\n explicit: Record<string, unknown> | null,\n): Account['unsupported'] {\n if (explicit) {\n return {\n code: str(explicit, 'code') ?? CLAUDE_VERSION_REASON,\n pinnedVersion: str(explicit, 'pinnedVersion') ?? str(explicit, 'version'),\n };\n }\n const reason = str(r, 'reason');\n if (reason !== CLAUDE_VERSION_REASON) return null;\n return { code: reason, pinnedVersion: CLAUDE_USAGE_PINNED_VERSION };\n}\n\n/**\n * The read-only banner. Owner T reports lease ownership as a structured\n * `collector` status, not a flat `collectorNote`, so the note is derived from\n * it — and ONLY when another process owns the lease, because that is the one\n * case where these readings may be staler than this server's poll interval.\n * A stray `collectorNote` string is still accepted for forward compatibility.\n */\nfunction projectCollectorNote(root: Record<string, unknown>): string | null {\n const flat = str(root, 'collectorNote');\n if (flat) return flat;\n const collector = record(root['collector']);\n if (!collector) return null;\n if (str(collector, 'owner') !== 'another-collector') return null;\n return (\n str(collector, 'note') ??\n 'Another collector process owns the quota-refresh lease, so these readings are read-only and may be staler than this server’s poll interval.'\n );\n}\n\nexport function projectAccountsSnapshot(raw: unknown): AccountsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n const rawAccounts = Array.isArray(root['accounts']) ? root['accounts'] : Array.isArray(raw) ? raw : null;\n if (rawAccounts === null) return null;\n return {\n sampledAt: str(root, 'sampledAt'),\n refreshing: bool(root, 'refreshing'),\n accounts: rawAccounts.map(projectAccount).filter((a): a is Account => a !== null),\n collectorNote: projectCollectorNote(root),\n };\n}\n\nfunction projectDay(raw: unknown): DailyUsage | null {\n const r = record(raw);\n if (!r) return null;\n const day = str(r, 'day');\n if (day === null || !/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return null;\n return {\n day,\n tokensIn: num(r, 'tokensIn') ?? 0,\n tokensOut: num(r, 'tokensOut') ?? 0,\n estCostUsd: num(r, 'estCostUsd') ?? 0,\n sessions: num(r, 'sessions') ?? 0,\n cacheRead: num(r, 'cacheRead'),\n cacheWrite: num(r, 'cacheWrite'),\n cacheHitRate: num(r, 'cacheHitRate'),\n };\n}\n\n/**\n * `byDay` is the wire key. Owner T wraps the series as\n * `{window, byDay, estimated, caveats}` rather than returning a bare array\n * (documented deviation 1), so `byDay` is read FIRST. `days` and a bare array\n * remain accepted so an older or differently-shaped server degrades to a\n * rendered series instead of a dead panel.\n */\nexport function projectUsageSeries(raw: unknown, requested: SeriesWindow): UsageSeries | null {\n const root = record(raw);\n const rawDays = root\n ? Array.isArray(root['byDay'])\n ? root['byDay']\n : Array.isArray(root['days'])\n ? root['days']\n : null\n : Array.isArray(raw)\n ? raw\n : null;\n if (rawDays === null) return null;\n const windowValue = root ? str(root, 'window') : null;\n return {\n window: windowValue === '7d' || windowValue === '30d' ? windowValue : requested,\n days: rawDays\n .map(projectDay)\n .filter((d): d is DailyUsage => d !== null)\n .sort((a, b) => a.day.localeCompare(b.day)),\n generatedAt: root ? str(root, 'generatedAt') : null,\n // The producer asserts estimation explicitly. Absent → still true: every\n // cost column on this route is price-table derived, and defaulting the\n // disclosure OFF would drop it exactly when the server is older.\n estimated: root ? bool(root, 'estimated', true) : true,\n caveats: root ? list(root['caveats']).filter((c): c is string => typeof c === 'string') : [],\n };\n}\n\nfunction projectLocalModel(raw: unknown, runtime: LocalModel['runtime']): LocalModel | null {\n const r = record(raw);\n if (!r) return null;\n // `label`/`id` are owner T's spellings; `name`/`model` are the Ollama-native\n // ones a differently-shaped server might send.\n const name = str(r, 'label') ?? str(r, 'id') ?? str(r, 'name') ?? str(r, 'model');\n if (name === null) return null;\n const caps = r['capabilities'];\n const state = str(r, 'state');\n const supportsTools = r['supportsTools'];\n\n // `nativeContextLength` is the architecture maximum; `contextLength` is what\n // the runtime actually configured for the loaded instance. They are two\n // different facts and the panel shows the gap between them, so they must not\n // collapse onto one field.\n const nativeContext = num(r, 'nativeContextLength') ?? num(r, 'nativeContext');\n const configuredContext = num(r, 'contextLength') ?? num(r, 'configuredContext');\n\n const placement = str(r, 'placement');\n\n return {\n name,\n runtime,\n loaded: state !== null ? state === 'loaded' : bool(r, 'loaded') || bool(r, 'resident'),\n sizeBytes: num(r, 'sizeBytes') ?? num(r, 'size'),\n sizeVramBytes: num(r, 'sizeVramBytes') ?? num(r, 'size_vram'),\n placement:\n placement === 'gpu' || placement === 'cpu' || placement === 'split' ? placement : 'unknown',\n gpuPercent: clampPercent(num(r, 'gpuPercent')),\n memoryPercent: clampPercent(num(r, 'memoryPercent')),\n family: str(r, 'family'),\n arch: str(r, 'arch'),\n expiresAt: str(r, 'expiresAt') ?? str(r, 'expires_at'),\n parameterSize: str(r, 'parameterSize') ?? str(r, 'parameter_size'),\n quantization: str(r, 'quantization') ?? str(r, 'quantization_level'),\n nativeContext,\n // Only a genuine narrowing is worth showing. When the runtime reports the\n // same number twice there is no truncation to report.\n configuredContext:\n configuredContext !== null && nativeContext !== null && configuredContext === nativeContext\n ? null\n : configuredContext,\n capabilities: Array.isArray(caps) ? caps.filter((c): c is string => typeof c === 'string') : null,\n supportsTools: typeof supportsTools === 'boolean' ? supportsTools : null,\n };\n}\n\nfunction projectRuntimeReport(\n raw: unknown,\n runtime: NonNullable<LocalModel['runtime']>,\n): { status: LocalRuntimeStatus; models: LocalModel[] } | null {\n const r = record(raw);\n if (!r) return null;\n const rawModels = Array.isArray(r['models']) ? r['models'] : null;\n if (rawModels === null) return null;\n const models = rawModels\n .map((m) => projectLocalModel(m, runtime))\n .filter((m): m is LocalModel => m !== null);\n const stale = bool(r, 'stale');\n return {\n models,\n status: {\n runtime,\n reachable: bool(r, 'reachable'),\n reason: str(r, 'reason'),\n stale,\n // Only meaningful under `stale`. A staleForMs on a fresh report would be\n // a contradiction, and printing it would age a current reading.\n staleForMs: stale ? num(r, 'staleForMs') : null,\n modelCount: models.length,\n },\n };\n}\n\n/**\n * Owner T reports local availability per RUNTIME (`ollama`, `lmStudio`) with a\n * shared `machine` budget. This panel answers one question — \"what can I run\n * right now, and against how much memory\" — so the runtimes are flattened into\n * one list, each row keeping its `runtime` so it stays attributable.\n *\n * Reachability is the OR of the runtimes: one dead runtime is not an unreachable\n * local stack. `reason` is only carried when NOTHING is reachable, because a\n * degradation note beside a working list would misdescribe what is on screen.\n *\n * A flat `{reachable, models, memoryBudgetBytes}` body is still accepted, so an\n * older or differently-shaped server degrades rather than rendering nothing.\n */\nexport function projectLocalModels(raw: unknown): LocalModelsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n\n const ollama = projectRuntimeReport(root['ollama'], 'ollama');\n const lmStudio = projectRuntimeReport(root['lmStudio'] ?? root['lmstudio'], 'lmstudio');\n\n if (ollama !== null || lmStudio !== null) {\n const reports = [ollama, lmStudio].filter((x): x is NonNullable<typeof x> => x !== null);\n const reachable = reports.some((x) => x.status.reachable);\n const machine = record(root['machine']);\n return {\n reachable,\n models: reports.flatMap((x) => x.models),\n memoryBudgetBytes:\n (machine ? num(machine, 'totalMemoryBytes') : null) ??\n num(root, 'memoryBudgetBytes') ??\n num(root, 'memoryBudget'),\n freeMemoryBytes: machine ? num(machine, 'freeMemoryBytes') : null,\n reason: reachable\n ? null\n : (reports.map((x) => x.status.reason).find((x) => x !== null) ?? null),\n runtimes: reports.map((x) => x.status),\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n }\n\n const rawModels = Array.isArray(root['models']) ? root['models'] : null;\n if (rawModels === null) return null;\n return {\n reachable: bool(root, 'reachable', true),\n models: rawModels.map((m) => projectLocalModel(m, null)).filter((m): m is LocalModel => m !== null),\n memoryBudgetBytes: num(root, 'memoryBudgetBytes') ?? num(root, 'memoryBudget'),\n freeMemoryBytes: num(root, 'freeMemoryBytes'),\n reason: str(root, 'reason'),\n // A flat legacy body carries no per-runtime reachability, so there is\n // nothing to attribute and nothing to call stale. An empty list says that\n // honestly; a fabricated entry would not.\n runtimes: [],\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n}\n","/**\n * routes/verse/usage/usage-queries.ts — the reads behind the Usage section.\n *\n * `/api/control` is fetched through the shared `controlSnapshotQuery` so this\n * section rides the same cache (and the same SSE invalidation) as every other\n * view rather than opening a second copy of a large snapshot.\n *\n * `/api/verse/control` is owner B's new route. It is fetched through a\n * NON-throwing wrapper because this section must still render when the route\n * is absent (server started without --allow-dispatch, or B's route not landed\n * yet): a missing configured-caps source is a degraded panel, not a dead\n * section. 401 is the one error that still propagates — an expired read\n * session is an unauthorized state for the whole surface, not a degraded one.\n *\n * The cache key is deliberately NOT shared with the Autonomy section's own\n * read of the same route: this module stores a wrapper shape, and two owners\n * writing different value types under one key would be a real bug.\n */\nimport type { FrontierUsage } from '../../../../core/usage/frontier-usage.js';\nimport { ApiError, apiGet } from '../../../data/client.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { projectLocalModels, type SeriesWindow } from './usage-contract.js';\n\nexport const USAGE_FRONTIER_KEY = 'verse-usage-frontier';\nexport const USAGE_VERSE_CONTROL_KEY = 'verse-usage-control';\n\n/** GET /api/usage — per-engine frontier usage (see core/usage/frontier-usage.ts). */\nexport const frontierUsageQuery: QueryDef<FrontierUsage> = {\n key: USAGE_FRONTIER_KEY,\n fetch: (signal) => apiGet<FrontierUsage>('/api/usage', signal),\n};\n\nexport interface VerseControlRead {\n /** Raw body; narrowed by `projectVerseControl` (owner B's types are not landed). */\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeControlFailure(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return 'This server does not expose /api/verse/control, so configured caps and today’s spend are unavailable here.';\n }\n return `Configured caps unavailable (HTTP ${err.status}).`;\n }\n return 'Configured caps unavailable: the request failed.';\n}\n\nexport const verseControlQuery: QueryDef<VerseControlRead> = {\n key: USAGE_VERSE_CONTROL_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>('/api/verse/control', signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeControlFailure(err) };\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Owner T's routes (GET /api/verse/{accounts,usage-series,local-models})\n// ---------------------------------------------------------------------------\n//\n// These three are fetched through the SAME non-throwing wrapper pattern as\n// /api/verse/control, for the same reason and one more: they are landing in\n// parallel with this section. A server that predates them answers 404, and a\n// 404 here means \"this panel is degraded\", not \"the Usage view is broken\".\n// 401 still propagates, because an expired read session is an unauthorized\n// state for the whole surface.\n//\n// The bodies are narrowed structurally by usage-contract.ts rather than cast,\n// so a field-name drift between T's route and this client degrades to an\n// honest \"unknown\" instead of throwing at render time.\n\nexport const USAGE_ACCOUNTS_KEY = 'verse-usage-accounts';\nexport const USAGE_LOCAL_MODELS_KEY = 'verse-usage-local-models';\nexport const USAGE_SERIES_KEY_PREFIX = 'verse-usage-series';\n\n/** A read that is allowed to be absent. `raw` is null when it was. */\nexport interface OptionalRead {\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeOptionalFailure(path: string, err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This server does not expose ${path} yet, so this panel has no source.`;\n }\n return `${path} answered HTTP ${err.status}.`;\n }\n return `${path} could not be reached.`;\n}\n\nfunction optionalGet(path: string): (signal?: AbortSignal) => Promise<OptionalRead> {\n return async (signal) => {\n try {\n const raw = await apiGet<unknown>(path, signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeOptionalFailure(path, err) };\n }\n };\n}\n\n/** GET /api/verse/accounts — per-account state, windows, credits, plan. */\nexport const verseAccountsQuery: QueryDef<OptionalRead> = {\n key: USAGE_ACCOUNTS_KEY,\n fetch: optionalGet('/api/verse/accounts'),\n};\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models — and why this one read retries\n// ---------------------------------------------------------------------------\n//\n// `/api/verse/local-models` probes the runtimes live on every request, with a\n// 2s per-probe timeout (core/verse/local-models.ts\n// VERSE_LOCAL_PROBE_TIMEOUT_MS). A probe that times out is reported as\n// `{reachable: false, reason: 'ollama-unreachable'}` in a perfectly ordinary\n// HTTP 200 — which is correct on the server's terms (it genuinely did not get\n// an answer) but is NOT the same fact as \"Ollama is not running\", and nothing\n// in the payload distinguishes the two.\n//\n// That distinction matters here because this section is the thing that causes\n// the timeout. Mounting Usage, and every press of its Refresh button, fires\n// seven reads at once, several of which spawn short-lived account-probe\n// processes server-side; measured against a live Ollama with twelve models,\n// roughly one burst in ten starves the 2s probe and comes back\n// `ollama-unreachable`. Nothing re-reads this route afterwards — it has no SSE\n// invalidation key — so that one false negative is what the operator stares\n// at, and pressing Refresh re-creates the very burst that produced it.\n//\n// So a reported-unreachable local stack is RE-READ, up to twice, with a short\n// gap for the burst to drain. This is not \"ignore the failure\": the retries\n// are bounded, each one is a real request, and whatever the last read says is\n// what this section renders — a runtime that is genuinely down answers fast\n// (connection refused, not a timeout) and still reports unreachable, three\n// times, in well under a second.\n//\n// Only an AVAILABLE read is retried. A 404/500 (`available: false`) is a\n// statement about the route, not about the runtime, and re-asking cannot\n// change it.\n\n/** Two extra reads at most, spaced so the section's own request burst drains. */\nconst LOCAL_MODELS_RETRY_DELAYS_MS = [350, 1200] as const;\n\nconst readLocalModels = optionalGet('/api/verse/local-models');\n\nfunction reportsNothingReachable(read: OptionalRead): boolean {\n if (!read.available) return false;\n const snapshot = projectLocalModels(read.raw);\n return snapshot !== null && !snapshot.reachable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** GET /api/verse/local-models — resident vs installed, VRAM split, tools. */\nexport const verseLocalModelsQuery: QueryDef<OptionalRead> = {\n key: USAGE_LOCAL_MODELS_KEY,\n fetch: async (signal) => {\n let read = await readLocalModels(signal);\n for (const delayMs of LOCAL_MODELS_RETRY_DELAYS_MS) {\n if (!reportsNothingReachable(read)) return read;\n await sleep(delayMs, signal);\n read = await readLocalModels(signal);\n }\n return read;\n },\n};\n\n// One QueryDef per window, created once at module scope: useQuery keys on\n// `def.key`, and minting a fresh object per render would be harmless but\n// useRefresh/useRefetch's useCallback deps would churn for no reason.\nconst SERIES_QUERIES: Record<SeriesWindow, QueryDef<OptionalRead>> = {\n '7d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:7d`,\n fetch: optionalGet('/api/verse/usage-series?window=7d'),\n },\n '30d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:30d`,\n fetch: optionalGet('/api/verse/usage-series?window=30d'),\n },\n};\n\nexport function usageSeriesQuery(window: SeriesWindow): QueryDef<OptionalRead> {\n return SERIES_QUERIES[window];\n}\n","/**\n * routes/verse/onboarding/onboarding-model.ts — the first-run tour's facts,\n * derived from the same reads the Usage section uses, with the same honesty\n * rules (docs/VERSE-TELEMETRY-V2.md).\n *\n * Pure: no React, no I/O. Everything the tour asserts about the machine is\n * computed here so it can be tested without a DOM, and so the one rule that\n * matters is enforced in one place:\n *\n * AN ABSENT READ IS \"UNKNOWN\", NEVER \"FINE\" AND NEVER \"BROKEN\".\n *\n * A first-run screen is exactly where a confident lie does the most damage —\n * it is the operator's first and only calibration of how much this app's\n * claims can be trusted. So a route that 404s, a payload that does not\n * narrow, and a probe that could not reach a runtime each produce their own\n * sentence, and none of them produces a green check.\n *\n * The tour NEVER renders a reconnect command it invented. `Account.\n * reconnectCommand` is already sanitized by usage-contract.ts's\n * `sanitizeCommand` (which is itself a backstop on the server's stripping),\n * and a native-profile launcher argv is withheld on purpose — where that is\n * the case the server says so in `notes`, and the tour shows the note rather\n * than a command.\n */\nimport type { Account, AccountsSnapshot, LocalModelsSnapshot } from '../usage/usage-contract.js';\n\n// ---------------------------------------------------------------------------\n// Steps\n// ---------------------------------------------------------------------------\n\nexport type OnboardingStepId = 'welcome' | 'accounts' | 'local' | 'stops' | 'finish';\n\nexport interface OnboardingStepMeta {\n id: OnboardingStepId;\n /** Shown as the card's heading. */\n title: string;\n /** One line under the heading. */\n subtitle: string;\n}\n\nexport const ONBOARDING_STEPS: readonly OnboardingStepMeta[] = [\n {\n id: 'welcome',\n title: 'Welcome to Verse',\n subtitle: 'Five sections, one rail. Two minutes and you will know what each one does.',\n },\n {\n id: 'accounts',\n title: 'Your seats',\n subtitle: 'Which provider accounts this machine can actually dispatch to right now.',\n },\n {\n id: 'local',\n title: 'Local runtime',\n subtitle: 'Whether there is a model on this machine, and what that changes.',\n },\n {\n id: 'stops',\n title: 'Three ways to stop',\n subtitle: 'They do not have the same blast radius. This is the one screen that says so.',\n },\n {\n id: 'finish',\n title: 'Make it yours',\n subtitle: 'Theme, accent, density and font live in Settings. Then start a chat.',\n },\n];\n\nexport function clampStep(step: number): number {\n if (!Number.isFinite(step)) return 0;\n return Math.min(ONBOARDING_STEPS.length - 1, Math.max(0, Math.trunc(step)));\n}\n\n// ---------------------------------------------------------------------------\n// Accounts\n// ---------------------------------------------------------------------------\n\nexport type FindingTone = 'ok' | 'attention' | 'unknown';\n\nexport interface AccountFinding {\n id: string;\n label: string;\n provider: Account['provider'];\n tone: FindingTone;\n /** Short state word shown next to the label. Never a colour on its own. */\n state: string;\n /** One plain sentence: what is true, and when it is not ok, what to do. */\n detail: string;\n /** A sanitized command the operator can run, when the server offered one. */\n fix: string | null;\n}\n\nexport interface AccountsFindings {\n /** Null when the read has not resolved or the route is absent. */\n findings: AccountFinding[] | null;\n /** Headline sentence for the step. Always present. */\n summary: string;\n /** Set when the roster itself is not trustworthy. */\n caveat: string | null;\n signedOutCount: number;\n}\n\nconst PROVIDER_RECONNECT: Record<Account['provider'], string> = {\n claude: 'Sign back in with the Claude CLI on this machine, then reopen Verse.',\n codex: 'Sign back in with the Codex CLI on this machine, then reopen Verse.',\n grok: 'Reconnect the Grok seat through `ashlr resources`.',\n};\n\nfunction accountFinding(account: Account): AccountFinding {\n const label = account.label || account.id;\n const base = { id: account.id, label, provider: account.provider };\n\n if (account.authentication === 'signed-out' || account.state === 'signed-out') {\n return {\n ...base,\n tone: 'attention',\n state: 'signed out',\n detail:\n account.reason ??\n account.notes[0] ??\n `Verse cannot dispatch to ${label} until this seat is signed in again.`,\n fix: account.reconnectCommand ?? PROVIDER_RECONNECT[account.provider],\n };\n }\n\n if (account.unsupported) {\n return {\n ...base,\n tone: 'attention',\n state: 'probe blocked',\n detail:\n `The usage probe for ${label} is pinned to a specific CLI build` +\n (account.unsupported.pinnedVersion ? ` (${account.unsupported.pinnedVersion})` : '') +\n ' and this machine is running a different one, so its quota is unreadable. The seat itself still works.',\n fix: null,\n };\n }\n\n if (account.state === 'unavailable') {\n return {\n ...base,\n tone: 'unknown',\n state: 'no reading',\n detail: account.reason ?? `No usage reading came back for ${label}. That is not the same as a limit.`,\n fix: null,\n };\n }\n\n if (account.state === 'checking') {\n return { ...base, tone: 'unknown', state: 'checking', detail: `Still probing ${label}.`, fix: null };\n }\n\n const binding = account.binding;\n const limited = binding?.limitReached === true;\n const spendable = account.credits?.hasCredits === true || account.credits?.unlimited === true;\n\n if (limited && !spendable) {\n return {\n ...base,\n tone: 'attention',\n state: 'limit reached',\n detail: `${label} reported its limit reached. Pick another seat, or wait for the window to reset.`,\n fix: null,\n };\n }\n\n if (limited && spendable) {\n // The trap this surface must not fall into: a used-up window on an\n // account that still has a spendable balance is NOT blocked.\n return {\n ...base,\n tone: 'ok',\n state: 'usable on credits',\n detail: `${label} has used up its included window but still has a spendable balance, so it can still dispatch.`,\n fix: null,\n };\n }\n\n const percent = binding?.measured === true && typeof binding.usedPercent === 'number' ? binding.usedPercent : null;\n return {\n ...base,\n tone: 'ok',\n state: 'connected',\n detail:\n percent === null\n ? `${label} is signed in. No local utilization signal for this provider — that is expected, not a fault.`\n : `${label} is signed in, ${Math.round(percent)}% through its binding window.`,\n fix: null,\n };\n}\n\nexport interface AccountsInput {\n /** Narrowed snapshot, or null when the route was absent or did not narrow. */\n snapshot: AccountsSnapshot | null;\n /** True while the read has produced nothing at all yet. */\n loading: boolean;\n /** Why the read could not be used, when the server or the client said. */\n unavailableReason: string | null;\n}\n\nexport function buildAccountsFindings(input: AccountsInput): AccountsFindings {\n if (input.loading) {\n return { findings: null, summary: 'Checking which accounts this machine can reach…', caveat: null, signedOutCount: 0 };\n }\n if (!input.snapshot) {\n return {\n findings: null,\n summary: 'This server did not report a per-account roster, so Verse cannot say which seats are connected.',\n caveat: input.unavailableReason,\n signedOutCount: 0,\n };\n }\n\n const findings = input.snapshot.accounts.map(accountFinding);\n if (findings.length === 0) {\n return {\n findings,\n summary: 'No provider accounts are connected on this machine yet. Verse will still run local models.',\n caveat: input.snapshot.collectorNote,\n signedOutCount: 0,\n };\n }\n\n const signedOut = findings.filter((f) => f.state === 'signed out');\n const usable = findings.filter((f) => f.tone === 'ok');\n const summary =\n signedOut.length === 0\n ? `${usable.length} of ${findings.length} ${findings.length === 1 ? 'seat is' : 'seats are'} ready to dispatch.`\n : `${signedOut.length} ${signedOut.length === 1 ? 'seat is' : 'seats are'} signed out. Each one below says how to get it back.`;\n\n return { findings, summary, caveat: input.snapshot.collectorNote, signedOutCount: signedOut.length };\n}\n\n// ---------------------------------------------------------------------------\n// Local runtime\n// ---------------------------------------------------------------------------\n\nexport interface LocalFinding {\n tone: FindingTone;\n state: string;\n summary: string;\n /** What having (or not having) a local runtime means for the operator. */\n meaning: string;\n /** Present only when there is something to do about it. */\n fix: string | null;\n modelCount: number;\n toolCapableCount: number;\n /** True when this reading was retained from an earlier probe. */\n stale: boolean;\n}\n\nexport interface LocalInput {\n snapshot: LocalModelsSnapshot | null;\n loading: boolean;\n unavailableReason: string | null;\n}\n\nconst LOCAL_MEANING_AVAILABLE =\n 'Local seats cost nothing and consume no provider quota, so the autonomous loop can keep working after a cloud window is used up.';\nconst LOCAL_MEANING_ABSENT =\n 'Without one, every turn and every autonomous tick spends a provider account, and a used-up window stops the work.';\n\nexport function buildLocalFinding(input: LocalInput): LocalFinding {\n if (input.loading) {\n return {\n tone: 'unknown',\n state: 'checking',\n summary: 'Probing the local runtimes on this machine…',\n meaning: LOCAL_MEANING_AVAILABLE,\n fix: null,\n modelCount: 0,\n toolCapableCount: 0,\n stale: false,\n };\n }\n\n if (!input.snapshot) {\n return {\n tone: 'unknown',\n state: 'not reported',\n summary: 'This server does not report local runtimes, so Verse cannot say whether one is available here.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: input.unavailableReason,\n modelCount: 0,\n toolCapableCount: 0,\n stale: false,\n };\n }\n\n const models = input.snapshot.models;\n const toolCapable = models.filter((m) => m.supportsTools === true).length;\n const stale = input.snapshot.runtimes.some((r) => r.stale);\n\n if (!input.snapshot.reachable) {\n return {\n tone: 'attention',\n state: 'unreachable',\n // \"Not reachable\" and \"not installed\" are different facts and the probe\n // cannot tell them apart — so this does not claim either one.\n summary:\n 'No local runtime answered. Verse cannot tell whether one is not running or not installed — the probe only knows it got no answer.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: 'Start Ollama (or LM Studio) and press Refresh in Usage. If neither is installed, everything still works — it all runs on the cloud seats.',\n modelCount: 0,\n toolCapableCount: 0,\n stale,\n };\n }\n\n if (models.length === 0) {\n return {\n tone: 'attention',\n state: 'no models',\n summary: 'A local runtime answered, but it has no models installed.',\n meaning: LOCAL_MEANING_ABSENT,\n fix: 'Pull a model into the runtime, then press Refresh in Usage.',\n modelCount: 0,\n toolCapableCount: 0,\n stale,\n };\n }\n\n return {\n tone: 'ok',\n state: stale ? 'available (retained reading)' : 'available',\n summary:\n `${models.length} local ${models.length === 1 ? 'model' : 'models'} available` +\n (toolCapable > 0 ? `, ${toolCapable} of them tool-capable.` : ', none of them tool-capable.') +\n (stale ? ' This is a retained reading, not a fresh probe.' : ''),\n meaning: toolCapable > 0\n ? LOCAL_MEANING_AVAILABLE\n : `${LOCAL_MEANING_AVAILABLE} A model that cannot call tools can answer, but cannot run an agentic turn.`,\n fix: null,\n modelCount: models.length,\n toolCapableCount: toolCapable,\n stale,\n };\n}\n\n// ---------------------------------------------------------------------------\n// The three stops\n// ---------------------------------------------------------------------------\n\nexport interface StopControl {\n name: string;\n /** What it halts. */\n scope: string;\n /** What it does NOT halt — the half people get wrong. */\n limit: string;\n reversible: string;\n tone: FindingTone;\n}\n\n/**\n * Verbatim against docs/VERSE-CONTRACT-V2.md's two footguns and the V2.1\n * amendment. The kill switch is never called a pause, and \"Stop loop\" is\n * stated as engaging the same global sentinel as the emergency control,\n * because it does (`stopDaemon()` is `setKill(true)`).\n */\nexport const STOP_CONTROLS: readonly StopControl[] = [\n {\n name: 'Pause',\n scope: 'Halts autonomous dispatch only. A running loop parks instead of exiting.',\n limit: 'Your own chats and the agent’s write tools keep working.',\n reversible: 'Reversible in one click, with no restart and no confirmation.',\n tone: 'ok',\n },\n {\n name: 'Stop loop',\n scope: 'Stops the daemon — and engages the GLOBAL kill switch while doing it.',\n limit: 'That means it also refuses the agent’s own write tools, exactly like the emergency control.',\n reversible: 'Reversible, but confirm-guarded. For an ordinary halt, use Pause.',\n tone: 'attention',\n },\n {\n name: 'Emergency stop',\n scope: 'Engages the global kill switch (~/.ashlr/KILL) directly.',\n limit: 'Every mutating path refuses: the loop, dispatch, and the agent’s own write tools.',\n reversible: 'Reversible, confirm-guarded, and deliberately separated from the other two.',\n tone: 'attention',\n },\n];\n","/**\n * routes/verse/onboarding/onboarding-store.ts — whether the first-run tour\n * is showing, and whether it has already been answered.\n *\n * Framework-free, same shape as verse-ui-store.ts: a module-level snapshot,\n * a listener set, and one `useSyncExternalStore` hook in ./useOnboarding.ts.\n *\n * Persisted under `ashlr.verse.onboarding.v1`. Two facts are stored and they\n * are deliberately different:\n *\n * - `completedAt` — the operator walked to the end.\n * - `dismissedAt` — the operator skipped, or closed it part-way.\n *\n * Either one silences the tour for good; storing which happened means a\n * later build can tell \"has seen it\" from \"chose not to\", and it makes the\n * Settings replay affordance honest about what it is replaying.\n *\n * SHOWING IT IS FAIL-SAFE IN THE QUIET DIRECTION. A storage read that throws\n * (private window, storage disabled) or returns something malformed resolves\n * to NOT showing the tour. A first-run flow that reappears on every launch\n * because storage is unavailable would be worse than one that never appears:\n * the app is fully usable without it, and it is reachable from Settings.\n */\n\nexport interface OnboardingRecord {\n /** ISO timestamp of the run that reached the last step. */\n completedAt: string | null;\n /** ISO timestamp of a skip or an early close. */\n dismissedAt: string | null;\n}\n\nexport interface OnboardingState extends OnboardingRecord {\n /** Is the flow on screen right now? */\n open: boolean;\n /** 0-based index into the step list (./onboarding-model.ts ONBOARDING_STEPS). */\n step: number;\n}\n\nexport const VERSE_ONBOARDING_STORAGE_KEY = 'ashlr.verse.onboarding.v1';\n\nconst EMPTY: OnboardingRecord = { completedAt: null, dismissedAt: null };\n\nfunction readRecord(): OnboardingRecord {\n try {\n const raw = localStorage.getItem(VERSE_ONBOARDING_STORAGE_KEY);\n if (!raw) return EMPTY;\n const parsed = JSON.parse(raw) as Partial<OnboardingRecord>;\n return {\n completedAt: typeof parsed.completedAt === 'string' ? parsed.completedAt : null,\n dismissedAt: typeof parsed.dismissedAt === 'string' ? parsed.dismissedAt : null,\n };\n } catch {\n // Unreadable storage means \"answered\" — see the fail-safe note above.\n return { completedAt: null, dismissedAt: new Date(0).toISOString() };\n }\n}\n\nfunction persist(record: OnboardingRecord): void {\n try {\n localStorage.setItem(VERSE_ONBOARDING_STORAGE_KEY, JSON.stringify(record));\n } catch {\n /* best-effort: a private window without storage still runs the app */\n }\n}\n\n/** True when neither answer has been recorded yet. */\nexport function isFirstRun(record: OnboardingRecord): boolean {\n return record.completedAt === null && record.dismissedAt === null;\n}\n\nconst initialRecord = readRecord();\n\nlet state: OnboardingState = {\n ...initialRecord,\n open: isFirstRun(initialRecord),\n step: 0,\n};\n\nconst listeners = new Set<() => void>();\n\nfunction patch(delta: Partial<OnboardingState>): void {\n const next = { ...state, ...delta };\n if ((Object.keys(delta) as (keyof OnboardingState)[]).every((k) => Object.is(state[k], next[k]))) return;\n state = next;\n for (const l of listeners) l();\n}\n\nexport function subscribeOnboarding(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function getOnboardingState(): OnboardingState {\n return state;\n}\n\nexport function setOnboardingStep(step: number): void {\n patch({ step: Math.max(0, Math.trunc(step)) });\n}\n\n/** Skip, Escape, or the close button — all the same answer. */\nexport function dismissOnboarding(): void {\n const record: OnboardingRecord = { completedAt: state.completedAt, dismissedAt: new Date().toISOString() };\n persist(record);\n patch({ ...record, open: false });\n}\n\n/** Walked to the end. */\nexport function completeOnboarding(): void {\n const record: OnboardingRecord = { completedAt: new Date().toISOString(), dismissedAt: state.dismissedAt };\n persist(record);\n patch({ ...record, open: false });\n}\n\n/** Settings → \"Replay onboarding\". Reopens at the first step; the stored\n * answer is kept, so closing the replay does not re-arm the first run. */\nexport function replayOnboarding(): void {\n patch({ open: true, step: 0 });\n}\n\n/** Test hygiene — forgets the stored answer and re-arms the first run. */\nexport function resetOnboarding(): void {\n try {\n localStorage.removeItem(VERSE_ONBOARDING_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n state = { completedAt: null, dismissedAt: null, open: true, step: 0 };\n for (const l of listeners) l();\n}\n","/**\n * routes/verse/onboarding/useOnboarding.ts — the single React binding over\n * onboarding-store.ts, kept in its own file for the same reason\n * useVerseUi.ts is: the store stays framework-free and unit-testable\n * without a DOM.\n */\nimport { useSyncExternalStore } from 'react';\nimport { getOnboardingState, subscribeOnboarding, type OnboardingState } from './onboarding-store.js';\n\nexport function useOnboarding(): OnboardingState {\n return useSyncExternalStore(subscribeOnboarding, getOnboardingState, getOnboardingState);\n}\n","/**\n * routes/verse/onboarding/OnboardingFlow.tsx — the first-run tour.\n *\n * A first-time operator opens Verse to five unlabelled rail icons and no\n * guidance. This is five short steps that answer the questions that actually\n * block someone on day one: which of my accounts can this thing use, is\n * there anything local, what do the three stop buttons really do, where do I\n * change how it looks, and how do I start.\n *\n * THREE RULES IT IS BUILT AROUND:\n *\n * 1. It never blocks the app. This is NOT a modal — no backdrop, no focus\n * trap, no `aria-modal`. It is a docked card over the section area; every\n * rail button, shortcut and section behind it stays clickable while it is\n * open. Escape closes it, so does Skip, so does the close button, and any\n * of those three silences it for good.\n *\n * 2. It never asserts more than it read. Steps 2 and 3 show real state from\n * the same two routes the Usage section reads, through the same\n * narrowers, with the same honesty rules — a 404 is \"not reported\", an\n * unanswered probe is \"no answer\", and neither is a green check. All of\n * that logic is in ./onboarding-model.ts, tested without a DOM.\n *\n * 3. It costs no extra requests on the common path. Each data step mounts\n * its own query only when the operator reaches it, and those queries are\n * the Usage section's own cache entries — so a first-run user who walks\n * the tour and then opens Usage finds both reads already in cache and\n * within the freshness window (data/hooks.ts DEFAULT_QUERY_FRESH_MS).\n */\nimport { useCallback, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport { Button, Tag } from '../../../components/primitives/index.js';\nimport {\n IconAlert,\n IconCheckCircle,\n IconChat,\n IconCpu,\n IconInfo,\n IconSliders,\n IconX,\n} from '../../../components/primitives/icons.js';\nimport { useQuery } from '../../../data/hooks.js';\nimport { SECTION_ICON } from '../verse-icons.js';\nimport { requestVerseCommand, setVerseSection, VERSE_SECTIONS } from '../verse-ui-store.js';\nimport { verseAccountsQuery, verseLocalModelsQuery } from '../usage/usage-queries.js';\nimport { projectAccountsSnapshot, projectLocalModels } from '../usage/usage-contract.js';\nimport {\n ONBOARDING_STEPS,\n STOP_CONTROLS,\n buildAccountsFindings,\n buildLocalFinding,\n clampStep,\n type FindingTone,\n} from './onboarding-model.js';\nimport {\n completeOnboarding,\n dismissOnboarding,\n setOnboardingStep,\n} from './onboarding-store.js';\nimport { useOnboarding } from './useOnboarding.js';\nimport styles from './onboarding.module.css';\n\n/**\n * Tone is paired with a glyph everywhere it appears, never carried by colour\n * alone (DESIGN-V2 §6).\n */\nfunction ToneMark({ tone, label }: { tone: FindingTone; label: string }) {\n const Glyph = tone === 'ok' ? IconCheckCircle : tone === 'attention' ? IconAlert : IconInfo;\n return (\n <span className={styles.tone} data-tone={tone}>\n <Glyph size={13} aria-hidden=\"true\" focusable=\"false\" />\n <span className={styles.toneLabel}>{label}</span>\n </span>\n );\n}\n\nfunction StepBody({ children }: { children: ReactNode }) {\n return <div className={styles.body}>{children}</div>;\n}\n\n// ---------------------------------------------------------------------------\n// Step 1 — what the rail is\n// ---------------------------------------------------------------------------\n\nconst SECTION_BLURB: Record<string, string> = {\n chat: 'Talk to a seat. Sessions are grouped by project and resume where they stopped.',\n autonomy: 'The human-out-of-the-loop cockpit: the loop, its budget, its scope, and what it did while you were away.',\n approvals: 'Everything the loop produced that is waiting on you. Approving a PR proposal pushes a branch.',\n usage: 'Which account you can actually use right now, and what it costs.',\n settings: 'Theme, accent, density, font — and this tour again whenever you want it.',\n};\n\nfunction WelcomeStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Verse is the desktop surface over this machine’s agentic fleet. Everything it shows comes from one local\n server — no session, token or artifact leaves this machine.\n </p>\n <ul className={styles.sections}>\n {VERSE_SECTIONS.map((entry, index) => {\n const Icon = SECTION_ICON[entry.id];\n return (\n <li key={entry.id} className={styles.sectionRow}>\n <span className={styles.sectionIcon} aria-hidden=\"true\">\n <Icon />\n </span>\n <span className={styles.sectionText}>\n <span className={styles.sectionName}>\n {entry.label} <kbd className={styles.kbd}>⌘{index + 1}</kbd>\n </span>\n <span className={styles.sectionBlurb}>{SECTION_BLURB[entry.id]}</span>\n </span>\n </li>\n );\n })}\n </ul>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 2 — seats\n// ---------------------------------------------------------------------------\n\nfunction AccountsStep() {\n const read = useQuery(verseAccountsQuery);\n const findings = useMemo(\n () =>\n buildAccountsFindings({\n snapshot: read.data?.available ? projectAccountsSnapshot(read.data.raw) : null,\n loading: read.data === undefined && read.status !== 'error',\n unavailableReason: read.data?.reason ?? read.error?.message ?? null,\n }),\n [read.data, read.status, read.error],\n );\n\n return (\n <StepBody>\n <p className={styles.lead}>{findings.summary}</p>\n {findings.findings === null ? null : (\n <ul className={styles.findings}>\n {findings.findings.map((finding) => (\n <li key={finding.id} className={styles.finding}>\n <div className={styles.findingHead}>\n <Tag engine={finding.provider}>{finding.label}</Tag>\n <ToneMark tone={finding.tone} label={finding.state} />\n </div>\n <p className={styles.findingDetail}>{finding.detail}</p>\n {finding.fix ? (\n <p className={styles.findingFix}>\n <span className={styles.fixLabel}>Fix</span>\n <code className={styles.code}>{finding.fix}</code>\n </p>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n {findings.caveat ? <p className={styles.caveat}>{findings.caveat}</p> : null}\n <p className={styles.aside}>\n The full per-window picture — resets, credits, limits — lives in Usage{' '}\n <kbd className={styles.kbd}>⌘4</kbd>.\n </p>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 3 — local runtime\n// ---------------------------------------------------------------------------\n\nfunction LocalStep() {\n const read = useQuery(verseLocalModelsQuery);\n const finding = useMemo(\n () =>\n buildLocalFinding({\n snapshot: read.data?.available ? projectLocalModels(read.data.raw) : null,\n loading: read.data === undefined && read.status !== 'error',\n unavailableReason: read.data?.reason ?? read.error?.message ?? null,\n }),\n [read.data, read.status, read.error],\n );\n\n return (\n <StepBody>\n <div className={styles.findingHead}>\n <span className={styles.localIcon} aria-hidden=\"true\">\n <IconCpu size={15} />\n </span>\n <ToneMark tone={finding.tone} label={finding.state} />\n </div>\n <p className={styles.lead}>{finding.summary}</p>\n <p className={styles.findingDetail}>{finding.meaning}</p>\n {finding.fix ? (\n <p className={styles.findingFix}>\n <span className={styles.fixLabel}>Fix</span>\n <span className={styles.fixText}>{finding.fix}</span>\n </p>\n ) : null}\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 4 — the three stops\n// ---------------------------------------------------------------------------\n\nfunction StopsStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Autonomy <kbd className={styles.kbd}>⌘2</kbd> has three stop controls. They are not interchangeable, and the\n difference is the most important thing on this screen.\n </p>\n <ul className={styles.findings}>\n {STOP_CONTROLS.map((control) => (\n <li key={control.name} className={styles.finding}>\n <div className={styles.findingHead}>\n <span className={styles.stopName}>{control.name}</span>\n <ToneMark tone={control.tone} label={control.tone === 'ok' ? 'narrow' : 'global'} />\n </div>\n <p className={styles.findingDetail}>{control.scope}</p>\n <p className={styles.findingDetail}>{control.limit}</p>\n <p className={styles.findingNote}>{control.reversible}</p>\n </li>\n ))}\n </ul>\n </StepBody>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Step 5 — appearance, then go\n// ---------------------------------------------------------------------------\n\nfunction FinishStep() {\n return (\n <StepBody>\n <p className={styles.lead}>\n Settings <kbd className={styles.kbd}>⌘,</kbd> carries theme, accent hue, density, display font, corner radius\n and reduced motion. Every change applies as you make it — there is no save button.\n </p>\n <Button\n variant=\"subtle\"\n icon={<IconSliders size={14} />}\n onClick={() => setVerseSection('settings')}\n >\n Open Settings\n </Button>\n <p className={styles.aside}>\n You can replay this tour any time from Settings → Onboarding.\n </p>\n </StepBody>\n );\n}\n\nconst STEP_COMPONENTS = [WelcomeStep, AccountsStep, LocalStep, StopsStep, FinishStep] as const;\n\n// ---------------------------------------------------------------------------\n// The card\n// ---------------------------------------------------------------------------\n\nexport function OnboardingFlow() {\n const { open, step } = useOnboarding();\n const index = clampStep(step);\n const meta = ONBOARDING_STEPS[index]!;\n const Step = STEP_COMPONENTS[index]!;\n const last = index === ONBOARDING_STEPS.length - 1;\n\n const close = useCallback(() => dismissOnboarding(), []);\n const cardRef = useRef<HTMLElement>(null);\n\n // Escape dismisses the tour — but ONLY when the focus is inside the card.\n //\n // This card is deliberately not a modal (rule 1 above): the operator works\n // behind it, and every Escape they press for something else — closing the\n // command palette, backing out of a seat menu, stopping dictation — used to\n // land here too and permanently dismiss the tour, writing `dismissedAt` with\n // no confirmation and no undo short of Settings → Replay. It also swallowed\n // the default Escape behaviour of whatever they were actually trying to\n // close. Scoped to the card, both problems go away and the shortcut still\n // works where the operator would expect it to.\n useEffect(() => {\n if (!open) return undefined;\n function onKey(event: globalThis.KeyboardEvent) {\n if (event.key !== 'Escape') return;\n const card = cardRef.current;\n if (!card || !(event.target instanceof Node) || !card.contains(event.target)) return;\n event.preventDefault();\n dismissOnboarding();\n }\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [open]);\n\n if (!open) return null;\n\n return (\n <aside ref={cardRef} className={styles.card} aria-labelledby=\"verse-onboarding-title\" role=\"region\">\n <header className={styles.head}>\n <div className={styles.headText}>\n <p className={styles.eyebrow}>\n Getting started · {index + 1} of {ONBOARDING_STEPS.length}\n </p>\n <h2 id=\"verse-onboarding-title\" className={styles.title}>\n {meta.title}\n </h2>\n <p className={styles.subtitle}>{meta.subtitle}</p>\n </div>\n <Button\n iconOnly\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Close getting started\"\n icon={<IconX size={14} />}\n onClick={close}\n />\n </header>\n\n <Step />\n\n <footer className={styles.foot}>\n <ol className={styles.pips} aria-hidden=\"true\">\n {ONBOARDING_STEPS.map((s, i) => (\n <li key={s.id} className={styles.pip} data-state={i === index ? 'current' : i < index ? 'done' : 'todo'} />\n ))}\n </ol>\n <div className={styles.actions}>\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>\n Skip setup\n </Button>\n {index > 0 ? (\n <Button variant=\"subtle\" size=\"sm\" onClick={() => setOnboardingStep(index - 1)}>\n Back\n </Button>\n ) : null}\n {last ? (\n <Button\n variant=\"primary\"\n size=\"sm\"\n icon={<IconChat size={14} />}\n onClick={() => {\n completeOnboarding();\n // Switches to Chat and raises the one-shot ⌘N command the\n // chat section consumes by nonce (verse-ui-store.ts).\n requestVerseCommand('new-chat');\n }}\n >\n Start a first chat\n </Button>\n ) : (\n <Button variant=\"primary\" size=\"sm\" onClick={() => setOnboardingStep(index + 1)}>\n Next\n </Button>\n )}\n </div>\n </footer>\n </aside>\n );\n}\n","/**\n * routes/verse/useVerseUi.ts — the React glue over verse-ui-store.ts (same\n * split as useVerseSession.ts over verse-store.ts: the store stays\n * framework-free, this file is the only place that knows about React).\n */\nimport { useSyncExternalStore } from 'react';\nimport { getVerseUiState, subscribeVerseUi, type VerseUiState } from './verse-ui-store.js';\n\nexport function useVerseUi(): VerseUiState {\n return useSyncExternalStore(subscribeVerseUi, getVerseUiState, getVerseUiState);\n}\n","/**\n * routes/verse/VerseApp.tsx — the Verse shell (VERSE-CONTRACT-V2 \"Shell\n * contract\"): a 56px icon rail down the left, and exactly one of the five\n * section modules lazily mounted beside it.\n *\n * Chat · Autonomy · Approvals · Usage · Settings\n * ⌘1–⌘5 switch · ⌘K quick switcher · ⌘N new chat · ⌘, Settings\n *\n * Each section module exports a named component taking NO props and owns\n * its own data; the shell knows nothing about chat, caps or inboxes. That\n * is why the two chat shortcuts the rail owns (⌘N, ⌘K) are raised as\n * one-shot commands through verse-ui-store instead of being passed down.\n *\n * Section modules are resolved through `import.meta.glob` rather than a\n * static `import()` per section, for one deliberate reason: the four\n * non-chat modules are written by other owners and land at different times.\n * A glob yields real per-section code splitting when a module is present\n * and a designed \"not built yet\" state when it is not, instead of a build\n * that cannot compile until every owner has finished.\n */\nimport { Suspense, lazy, useEffect, useMemo, type ComponentType } from 'react';\nimport { RouteErrorBoundary } from '../../components/primitives/RouteErrorBoundary.js';\nimport { reportThemeToShell, subscribeDesktopCommands } from '../../app/desktop-shell.js';\nimport { useQuery, useTheme } from '../../data/hooks.js';\nimport { inboxListQuery } from '../../data/queries.js';\nimport { SECTION_ICON, VerseMark } from './verse-icons.js';\nimport { OnboardingFlow } from './onboarding/OnboardingFlow.js';\nimport { useVerseUi } from './useVerseUi.js';\nimport {\n requestVerseCommand,\n setVerseSection,\n setVersePendingApprovals,\n VERSE_SECTIONS,\n type VerseSectionId,\n} from './verse-ui-store.js';\nimport styles from './VerseApp.module.css';\n\n/**\n * Every `sections/*Section.tsx` that exists at build time, lazily. Vite\n * resolves this at build time (one chunk per match, `{}` when there are no\n * matches), so a module that has not been written yet is a missing key, not\n * an unresolved import.\n */\nconst SECTION_MODULES = import.meta.glob('./sections/*Section.tsx');\n\n/**\n * The designed state for a rail slot whose module has not landed (or failed\n * to load). Exported so it can be tested directly: which sections exist\n * changes as the other owners land theirs, and a test that depends on one\n * being absent would rot the day it arrives.\n */\nexport function MissingSection({ label, moduleName, detail }: { label: string; moduleName: string; detail?: string }) {\n return (\n <div className={styles.missing} role=\"status\">\n <h1 className={styles.missingTitle}>{label} is not wired up yet</h1>\n <p className={styles.missingBody}>\n This build has no <code>routes/verse/sections/{moduleName}.tsx</code>. The rail keeps the slot so the\n section appears the moment that module lands — nothing here is broken, and the other sections still work.\n </p>\n {detail ? <p className={styles.missingDetail}>{detail}</p> : null}\n </div>\n );\n}\n\n/**\n * Resolve one rail section to a lazy component. A module that is absent, or\n * that throws while loading, resolves to the honest missing state rather\n * than tearing down the shell.\n */\nfunction sectionLoader(id: VerseSectionId): () => Promise<{ default: ComponentType }> {\n const entry = VERSE_SECTIONS.find((s) => s.id === id)!;\n const importer = SECTION_MODULES[`./sections/${entry.module}.tsx`];\n return async () => {\n if (!importer) return { default: () => <MissingSection label={entry.label} moduleName={entry.module} /> };\n try {\n const mod = (await importer()) as Record<string, unknown>;\n const exported = mod[entry.module] ?? mod.default;\n if (typeof exported !== 'function') {\n return {\n default: () => (\n <MissingSection label={entry.label} moduleName={entry.module}\n detail={`The module loaded but exports no \\`${entry.module}\\` component.`} />\n ),\n };\n }\n return { default: exported as ComponentType };\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n return { default: () => <MissingSection label={entry.label} moduleName={entry.module} detail={detail} /> };\n }\n };\n}\n\n/** One lazy component per section, created once for the life of the tab. */\nconst SECTION_COMPONENTS = new Map<VerseSectionId, ComponentType>(\n VERSE_SECTIONS.map((s) => [s.id, lazy(sectionLoader(s.id))] as const),\n);\n\n/**\n * The rail's Approvals badge has to be right whichever section is mounted —\n * that is the whole point of a badge — so the count is published from the\n * SHELL, not from ApprovalsSection. It rides the exact QueryDef the section\n * itself uses, so the two share one cache entry and one request rather than\n * each fetching the inbox.\n */\nconst PENDING_APPROVALS_QUERY = inboxListQuery({ status: 'pending', limit: 500 });\n\nexport function VerseApp() {\n const ui = useVerseUi();\n const theme = useTheme();\n const Section = SECTION_COMPONENTS.get(ui.section)!;\n\n const pendingApprovals = useQuery(PENDING_APPROVALS_QUERY);\n const pendingCount = pendingApprovals.data?.pending;\n useEffect(() => {\n // Only publish an observed number. While the read is in flight or has\n // failed the badge stays as it was rather than flashing to zero, which\n // would read as \"nothing is waiting for you\" — a false all-clear.\n if (typeof pendingCount === 'number') setVersePendingApprovals(pendingCount);\n }, [pendingCount]);\n\n // ⌘1–⌘5 sections · ⌘K quick switcher · ⌘N new chat · ⌘, Settings.\n // Held at the document so they work wherever focus is, except inside a\n // dialog's own text field where the browser's own editing shortcuts win.\n useEffect(() => {\n function onKey(event: globalThis.KeyboardEvent) {\n if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey) return;\n const index = Number.parseInt(event.key, 10);\n if (Number.isInteger(index) && index >= 1 && index <= VERSE_SECTIONS.length) {\n event.preventDefault();\n setVerseSection(VERSE_SECTIONS[index - 1]!.id);\n return;\n }\n switch (event.key.toLowerCase()) {\n case 'k':\n event.preventDefault();\n requestVerseCommand('quick-switcher');\n break;\n case 'n':\n event.preventDefault();\n requestVerseCommand('new-chat');\n break;\n case ',':\n event.preventDefault();\n setVerseSection('settings');\n break;\n default:\n break;\n }\n }\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, []);\n\n // Desktop shell: the native menu bar owns ⌘, and ⇧⌘L and forwards them as a\n // window event rather than IPC, so this is inert in a browser. ⌘, is also\n // bound above for the browser; the native menu swallows it in the app, which\n // is why the menu has to hand it back.\n useEffect(() => subscribeDesktopCommands((command) => {\n if (command === 'open-settings') setVerseSection('settings');\n else if (command === 'toggle-theme') theme.cycle();\n }), [theme]);\n\n // Report the PAINTED theme so the native window can pre-paint its background\n // on the next cold launch instead of flashing white. No-op in a browser.\n useEffect(() => { reportThemeToShell(theme.theme); }, [theme.theme]);\n\n const themeTitle = useMemo(() => `Theme: ${theme.theme} — click to cycle`, [theme.theme]);\n\n return (\n <div className={styles.shell}>\n <nav className={styles.rail} aria-label=\"Verse sections\">\n {/*\n Desktop shell: the window's top 48px is overlaid by the OS title bar\n and the traffic lights. The rail clears it in CSS; this strip makes\n the cleared space drag the window. It is 0px tall in a browser, where\n `--app-titlebar-height` is not set, so it is inert there.\n See desktop/README.md → \"Desktop shell contract\".\n */}\n <span className={styles.railDragStrip} data-app-region=\"drag\" aria-hidden=\"true\" />\n <span className={styles.mark} title=\"Ashlr Verse\">\n <VerseMark />\n <span className=\"visually-hidden\">Ashlr Verse</span>\n </span>\n <ul className={styles.railList}>\n {VERSE_SECTIONS.map((entry, index) => {\n const IconComponent = SECTION_ICON[entry.id];\n const pending = entry.id === 'approvals' ? ui.pendingApprovals : 0;\n const active = ui.section === entry.id;\n return (\n <li key={entry.id}>\n <button type=\"button\" className={styles.railButton} aria-current={active ? 'page' : undefined}\n data-section={entry.id} title={`${entry.label} (⌘${index + 1})`}\n aria-label={pending > 0 ? `${entry.label}, ${pending} pending` : entry.label}\n onClick={() => setVerseSection(entry.id)}>\n <IconComponent />\n {pending > 0 ? <span className={styles.railDot} data-pending={pending} aria-hidden=\"true\" /> : null}\n </button>\n </li>\n );\n })}\n </ul>\n <div className={styles.railFoot}>\n <button type=\"button\" className={styles.railButton} onClick={theme.cycle} title={themeTitle}\n aria-label={themeTitle} data-theme-toggle={theme.theme}>\n <ThemeGlyph preference={theme.theme} />\n </button>\n </div>\n </nav>\n {/*\n The ONE <main id=\"main-content\"> for the whole Verse shell. SkipToContent\n imperatively focuses that id, and it used to live inside ChatSection — so\n \"Skip to content\" worked in Chat and silently did nothing in Autonomy,\n Approvals, Usage and Settings, leaving the keyboard user on <body> with the\n rail still ahead of them. Owning it here makes the landmark section-\n independent: every lazy-mounted section inherits a real skip target, and\n there is exactly one <main> on the page instead of zero or one.\n */}\n <main className={styles.section} data-section={ui.section} id=\"main-content\" tabIndex={-1}>\n <RouteErrorBoundary resetKey={ui.section}>\n <Suspense fallback={<SectionFallback />}>\n <Section />\n </Suspense>\n </RouteErrorBoundary>\n </main>\n {/*\n First run only, and OUTSIDE the error boundary's subtree on purpose:\n it is a docked card, not a modal — no backdrop, no focus trap — so the\n rail and the mounted section stay fully usable while it is open, and a\n section that throws does not take the guidance down with it. It renders\n nothing at all once the operator has skipped or finished it\n (onboarding/onboarding-store.ts).\n */}\n <OnboardingFlow />\n </div>\n );\n}\n\n/**\n * Theme is a three-state preference, so the glyph says which — a half-moon\n * for the two explicit choices and a ring for \"follow the system\" (never\n * color alone, DESIGN §6).\n */\nfunction ThemeGlyph({ preference }: { preference: string }) {\n return (\n <svg viewBox=\"0 0 16 16\" width={16} height={16} fill=\"none\" stroke=\"currentColor\" strokeWidth={1.4}\n strokeLinejoin=\"round\" strokeLinecap=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"8\" cy=\"8\" r=\"4.2\" />\n {preference === 'dark' ? <path d=\"M8 3.8a4.2 4.2 0 0 0 0 8.4Z\" fill=\"currentColor\" stroke=\"none\" /> : null}\n {preference === 'light' ? <path d=\"M8 1.6v1M8 13.4v1M14.4 8h-1M2.6 8h-1M12.5 3.5l-.7.7M4.2 11.8l-.7.7M12.5 12.5l-.7-.7M4.2 4.2l-.7-.7\" /> : null}\n </svg>\n );\n}\n\nfunction SectionFallback() {\n return <div className={styles.loading} role=\"status\" aria-live=\"polite\">Loading…</div>;\n}\n","/**\n * routes/verse/verse-queries.ts — every /api/verse/* call the Verse console\n * makes. Reads are QueryDefs consumed through useQuery (cache-backed, so a\n * sidebar refresh never blanks the list); writes are wrapped like\n * data/mutations.ts's helpers — they pull the held mutation token from\n * auth-store, touch the hold on success, and invalidate the cache keys they\n * obviously affect. Nothing here ever sees launcher commands or env: the\n * server strips those before any payload leaves it (docs/VERSE-CONTRACT-V1).\n */\nimport type {\n VerseAutonomyScopeView,\n VerseBootstrap,\n VerseCreateSessionRequest,\n VerseRootPriority,\n VerseSession,\n VerseSessionDetail,\n VerseSessionRootsResponse,\n VerseTurnRequest,\n VerseTurnResponse,\n VerseWorkspace,\n VerseWorkspaceCreateRequest,\n VerseWorkspacesResponse,\n VerseWorkspaceUpdateRequest,\n} from '../../data/api-types.js';\nimport { getMutationToken, touchMutationHold } from '../../data/auth-store.js';\nimport { apiGet, apiPost } from '../../data/client.js';\nimport { invalidate } from '../../data/cache.js';\nimport type { QueryDef } from '../../data/queries.js';\n\nexport const VERSE_BOOTSTRAP_KEY = 'verse-bootstrap';\nexport const VERSE_SESSIONS_KEY = 'verse-sessions';\n\nexport const verseBootstrapQuery: QueryDef<VerseBootstrap> = {\n key: VERSE_BOOTSTRAP_KEY,\n fetch: (signal) => apiGet<VerseBootstrap>('/api/verse/bootstrap', signal),\n};\n\nexport const verseSessionsQuery: QueryDef<VerseSession[]> = {\n key: VERSE_SESSIONS_KEY,\n fetch: (signal) => apiGet<VerseSession[]>('/api/verse/sessions', signal),\n};\n\nexport function verseSessionPath(sessionId: string, suffix = ''): string {\n return `/api/verse/sessions/${encodeURIComponent(sessionId)}${suffix}`;\n}\n\nexport function fetchVerseSessionDetail(sessionId: string, signal?: AbortSignal): Promise<VerseSessionDetail> {\n return apiGet<VerseSessionDetail>(verseSessionPath(sessionId), signal);\n}\n\nexport class VerseMutationLockedError extends Error {\n constructor() {\n super('Unlock actions with the mutation token before chatting.');\n this.name = 'VerseMutationLockedError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseMutationLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\n/** Sidebar + resources panel both read these; refresh them after any write. */\nexport function invalidateVerseLists(): void {\n invalidate(VERSE_SESSIONS_KEY);\n invalidate(VERSE_BOOTSTRAP_KEY);\n}\n\nexport async function createVerseSession(req: VerseCreateSessionRequest): Promise<VerseSession> {\n const session = await post<VerseSession>('/api/verse/sessions', req);\n invalidateVerseLists();\n return session;\n}\n\nexport async function sendVerseTurn(sessionId: string, text: string): Promise<VerseTurnResponse> {\n const body: VerseTurnRequest = { text };\n const response = await post<VerseTurnResponse>(verseSessionPath(sessionId, '/turns'), body);\n invalidate(VERSE_SESSIONS_KEY);\n return response;\n}\n\nexport async function cancelVerseTurn(sessionId: string): Promise<void> {\n await post<{ ok: true }>(verseSessionPath(sessionId, '/cancel'), {});\n invalidate(VERSE_SESSIONS_KEY);\n}\n\nexport async function deleteVerseSession(sessionId: string): Promise<void> {\n await post<{ ok: true }>(verseSessionPath(sessionId, '/delete'), {});\n invalidateVerseLists();\n}\n\nexport async function renameVerseSession(sessionId: string, title: string): Promise<VerseSession> {\n const session = await post<VerseSession>(verseSessionPath(sessionId, '/rename'), { title });\n invalidate(VERSE_SESSIONS_KEY);\n return session;\n}\n\n// ---------------------------------------------------------------------------\n// Workspaces (V2.2)\n// ---------------------------------------------------------------------------\n\nexport const VERSE_WORKSPACES_KEY = 'verse-workspaces';\nexport const VERSE_AUTONOMY_SCOPE_KEY = 'verse-autonomy-scope';\n\nexport const verseWorkspacesQuery: QueryDef<VerseWorkspacesResponse> = {\n key: VERSE_WORKSPACES_KEY,\n fetch: (signal) => apiGet<VerseWorkspacesResponse>('/api/verse/workspaces', signal),\n};\n\n/**\n * Enrolled repos, ordered by section focus and priority. Kept on its own key\n * from `verseScopeQuery` (which is the raw registry) so a re-rank refreshes\n * the ORDER without re-reading enrollment — and so it is obvious in the cache\n * that these are two different facts.\n */\nexport const verseAutonomyScopeQuery: QueryDef<VerseAutonomyScopeView> = {\n key: VERSE_AUTONOMY_SCOPE_KEY,\n fetch: (signal) => apiGet<VerseAutonomyScopeView>('/api/verse/autonomy-scope', signal),\n};\n\n/**\n * Per-root identity for one session: branch, dirty state, remote, whether the\n * engine can reach each root and whether the autonomous lane would.\n *\n * Deliberately NOT cached by session id alone at module scope — a branch goes\n * stale the moment a turn commits, so the panel refetches it per open.\n */\nexport function fetchVerseSessionRoots(sessionId: string, signal?: AbortSignal): Promise<VerseSessionRootsResponse> {\n return apiGet<VerseSessionRootsResponse>(verseSessionPath(sessionId, '/roots'), signal);\n}\n\nfunction invalidateWorkspaces(): void {\n invalidate(VERSE_WORKSPACES_KEY);\n invalidate(VERSE_AUTONOMY_SCOPE_KEY);\n invalidate(VERSE_BOOTSTRAP_KEY);\n}\n\nexport async function createVerseWorkspace(req: VerseWorkspaceCreateRequest): Promise<VerseWorkspace> {\n const workspace = await post<VerseWorkspace>('/api/verse/workspaces', req);\n invalidateWorkspaces();\n return workspace;\n}\n\nexport async function updateVerseWorkspace(id: string, patch: VerseWorkspaceUpdateRequest): Promise<VerseWorkspace> {\n const workspace = await post<VerseWorkspace>(`/api/verse/workspaces/${encodeURIComponent(id)}/update`, patch);\n invalidateWorkspaces();\n return workspace;\n}\n\nexport async function deleteVerseWorkspace(id: string): Promise<void> {\n await post<{ ok: true }>(`/api/verse/workspaces/${encodeURIComponent(id)}/delete`, {});\n invalidateWorkspaces();\n}\n\nexport async function setVerseRootPriority(path: string, priority: VerseRootPriority): Promise<void> {\n await post<unknown>('/api/verse/workspaces/priority', { path, priority });\n invalidateWorkspaces();\n}\n\nexport async function setVerseFocusSection(sectionId: string | null): Promise<void> {\n await post<unknown>('/api/verse/workspaces/focus', { sectionId });\n invalidateWorkspaces();\n}\n","/**\n * app/VerseConsoleApp.tsx — isolated bootstrap for /verse (pattern:\n * ResourcePoolConsoleApp). No global dashboard shell, router, or observer\n * stream: the read session is probed against /api/verse/bootstrap, host-\n * injected tokens (desktop wrapper) are adopted before that probe, and the\n * full-bleed VerseApp takes over once authenticated.\n */\nimport { useEffect } from 'react';\nimport { SessionGate } from '../components/auth/SessionGate.js';\nimport { ToastProvider } from '../components/primitives/Toast.js';\nimport { adoptInjectedTokens, markCheckComplete } from '../data/auth-store.js';\nimport { getQuerySnapshot, runQuery } from '../data/cache.js';\nimport { useAuthPhase } from '../data/hooks.js';\nimport { VerseApp } from '../routes/verse/VerseApp.js';\nimport { verseBootstrapQuery } from '../routes/verse/verse-queries.js';\nimport { SkipToContent } from './SkipToContent.js';\nimport styles from './VerseConsoleApp.module.css';\nimport '../design/global.css';\n\nexport function VerseConsoleApp() {\n const phase = useAuthPhase();\n useEffect(() => {\n if (phase !== 'checking') return;\n let cancelled = false;\n void adoptInjectedTokens().then((adopted) => {\n if (cancelled || adopted) return;\n return runQuery(verseBootstrapQuery.key, verseBootstrapQuery.fetch).then(() => {\n if (!cancelled) markCheckComplete(getQuerySnapshot(verseBootstrapQuery.key).status === 'success');\n });\n });\n return () => { cancelled = true; };\n }, [phase]);\n if (phase === 'checking') return <p className={styles.checking} role=\"status\">Checking for an existing Verse session…</p>;\n if (phase === 'unauthenticated') {\n return <SessionGate heading=\"Connect to Ashlr Verse\" command=\"ashlr verse\" subject=\"Ashlr Verse\" mutationField />;\n }\n return (\n <ToastProvider>\n <SkipToContent />\n <div className={styles.shell}><VerseApp /></div>\n </ToastProvider>\n );\n}\n"],"file":"assets/VerseConsoleApp-Cu5aG6J6.js"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._button_12qr7_1{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);height:var(--density-row);padding:0 var(--density-pad);border:1px solid transparent;border-radius:var(--radius-sm);background:transparent;color:var(--text-primary);font-family:var(--font-ui);font-size:var(--text-sm-size);line-height:1;font-weight:var(--font-weight-medium);white-space:nowrap;cursor:pointer;transition:background-color var(--duration-fast) var(--ease-standard),border-color var(--duration-fast) var(--ease-standard),color var(--duration-fast) var(--ease-standard),opacity var(--duration-fast) var(--ease-standard)}._button_12qr7_1:disabled{cursor:not-allowed;opacity:.55}._glyph_12qr7_30{display:inline-flex;flex:none;align-items:center;justify-content:center}._sm_12qr7_37{height:var(--density-row-sm);padding:0 var(--space-2);font-size:var(--text-xs-size)}._block_12qr7_43{width:100%}._iconOnly_12qr7_48{width:var(--density-row);padding:0}._sm_12qr7_37._iconOnly_12qr7_48{width:var(--density-row-sm)}._ghost_12qr7_60{color:var(--text-secondary)}._ghost_12qr7_60:hover:not(:disabled){background:var(--bg-hover);color:var(--text-primary)}._ghost_12qr7_60:active:not(:disabled){background:var(--bg-active)}._subtle_12qr7_71{border-color:var(--border-default);background:var(--bg-surface);color:var(--text-primary)}._subtle_12qr7_71:hover:not(:disabled){background:var(--bg-hover);border-color:var(--border-strong)}._subtle_12qr7_71:active:not(:disabled){background:var(--bg-active)}._primary_12qr7_84{background:var(--accent-600);border-color:var(--accent-600);color:var(--text-on-accent)}._primary_12qr7_84:hover:not(:disabled){background:var(--accent-700);border-color:var(--accent-700)}._primary_12qr7_84:active:not(:disabled){background:var(--accent-700)}._danger_12qr7_99{border-color:var(--border-default);color:var(--status-danger-fg)}._danger_12qr7_99:hover:not(:disabled){background:var(--status-danger-bg);border-color:var(--status-danger-solid)}._danger_12qr7_99:active:not(:disabled){background:var(--status-danger-bg)}._button_12qr7_1[aria-pressed=true],._button_12qr7_1[aria-expanded=true]{background:var(--bg-selected);color:var(--text-primary)}._tag_2eqdv_1{display:inline-flex;align-items:center;gap:var(--space-1);max-width:100%;height:var(--density-row-sm);padding:0 var(--space-2);border:1px solid var(--border-subtle);border-radius:var(--radius-xs);background:var(--bg-hover);color:var(--text-secondary);font-size:var(--text-xs-size);line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._sm_2eqdv_19{height:calc(var(--density-row-sm) - var(--space-2));padding:0 var(--space-1);font-size:var(--text-2xs-size)}._mono_2eqdv_25{font-family:var(--font-mono);font-size:var(--text-2xs-size)}._dot_2eqdv_30{flex:none;width:6px;height:6px;border-radius:var(--radius-full);background:var(--status-neutral-solid)}._marker_2eqdv_38{display:inline-block;flex:none;width:2px;height:100%;min-height:var(--engine-marker-h);border-radius:var(--radius-full)}._card_13g9r_14{position:fixed;z-index:var(--z-dialog);left:calc(var(--rail-width) + var(--space-5));right:auto;bottom:calc(var(--space-5) + env(safe-area-inset-bottom,0px));width:min(420px,calc(100vw - var(--rail-width) - var(--space-5) * 2));max-height:min(640px,calc(100vh - var(--space-8)));display:flex;flex-direction:column;overflow:hidden;background:var(--bg-surface-raised);border:1px solid var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-dialog)}._card_13g9r_14{animation:_onboarding-in_13g9r_1 var(--duration-base) var(--ease-decelerate)}@keyframes _onboarding-in_13g9r_1{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}._head_13g9r_56{display:flex;align-items:flex-start;gap:var(--space-2);padding:var(--space-4) var(--space-4) var(--space-3);border-bottom:1px solid var(--border-subtle)}._headText_13g9r_64{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}._eyebrow_13g9r_72{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary)}._title_13g9r_80{font-family:var(--font-display);font-size:var(--text-md-size);font-weight:var(--font-weight-semibold);letter-spacing:var(--tracking-display);color:var(--text-primary)}._subtitle_13g9r_88{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._body_13g9r_96{flex:1;min-height:0;overflow-y:auto;padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-3);align-items:flex-start}._lead_13g9r_107{font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed);color:var(--text-primary)}._aside_13g9r_113,._caveat_13g9r_114{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-tertiary)}._caveat_13g9r_114{border-left:2px solid var(--border-strong);padding-left:var(--space-3)}._kbd_13g9r_125{font-family:var(--font-mono);font-size:var(--text-2xs-size);padding:1px 5px;border:1px solid var(--border-default);border-radius:var(--radius-xs);background:var(--bg-surface);color:var(--text-secondary);white-space:nowrap}._sections_13g9r_138,._findings_13g9r_139{list-style:none;margin:0;padding:0;width:100%;display:flex;flex-direction:column}._sectionRow_13g9r_148{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-2) 0;border-top:1px solid var(--border-subtle)}._sectionRow_13g9r_148:first-child{border-top:none}._sectionIcon_13g9r_160,._localIcon_13g9r_161{flex:none;display:inline-flex;align-items:center;justify-content:center;width:var(--control-h-xs);height:var(--control-h-xs);color:var(--text-tertiary)}._sectionText_13g9r_173{display:flex;flex-direction:column;gap:2px;min-width:0}._sectionName_13g9r_180{font-family:var(--font-display);font-size:var(--text-xs-size);font-weight:var(--font-weight-semibold);color:var(--text-primary);display:inline-flex;align-items:center;gap:var(--space-2)}._sectionBlurb_13g9r_190{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._finding_13g9r_139{display:flex;flex-direction:column;gap:var(--space-1);padding:var(--space-3) 0;border-top:1px solid var(--border-subtle)}._finding_13g9r_139:first-child{border-top:none}._findingHead_13g9r_210{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);flex-wrap:wrap}._stopName_13g9r_218{font-family:var(--font-display);font-size:var(--text-sm-size);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._findingDetail_13g9r_225{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._findingNote_13g9r_231{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-tertiary)}._findingFix_13g9r_237{display:flex;align-items:baseline;gap:var(--space-2);flex-wrap:wrap;margin-top:2px}._fixLabel_13g9r_245{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary);flex:none}._fixText_13g9r_254{font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary)}._code_13g9r_260{font-family:var(--font-mono);font-size:var(--text-xs-size);padding:2px 6px;border:1px solid var(--border-subtle);border-radius:var(--radius-xs);background:var(--bg-code, var(--bg-surface));color:var(--text-primary);overflow-wrap:anywhere}._tone_13g9r_276{display:inline-flex;align-items:center;gap:5px;flex:none}._toneLabel_13g9r_283{font-family:var(--font-display);font-size:var(--text-2xs-size);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-secondary)}._tone_13g9r_276[data-tone=ok]{color:var(--status-success-fg, var(--text-secondary))}._tone_13g9r_276[data-tone=attention]{color:var(--status-warning-fg, var(--text-secondary))}._tone_13g9r_276[data-tone=unknown]{color:var(--text-tertiary)}._foot_13g9r_305{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-top:1px solid var(--border-subtle);background:var(--bg-surface)}._pips_13g9r_315{list-style:none;margin:0;padding:0;display:flex;gap:5px}._pip_13g9r_315{width:14px;height:2px;border-radius:1px;background:var(--border-default)}._pip_13g9r_315[data-state=current]{background:var(--accent-500)}._pip_13g9r_315[data-state=done]{background:var(--border-strong)}._actions_13g9r_338{display:flex;align-items:center;gap:var(--space-2)}@media(max-width:900px){._card_13g9r_14{left:calc(var(--rail-width) + var(--space-3));right:auto;width:min(420px,calc(100vw - var(--rail-width) - var(--space-3) * 2))}}._shell_tbse1_5{display:grid;grid-template-columns:var(--rail-width) minmax(0,1fr);height:100%;min-height:0;background:var(--bg-canvas);color:var(--text-primary);font-family:var(--font-ui)}._shell_tbse1_5>*{min-width:0;min-height:0}._rail_tbse1_21{position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--space-2);padding:var(--space-3) 0;border-right:1px solid var(--border-subtle);background:var(--bg-canvas)}._rail_tbse1_21{padding-top:calc(var(--space-3) + var(--app-titlebar-height, 0px))}._railDragStrip_tbse1_44{position:absolute;top:0;left:0;width:100%;height:var(--app-titlebar-height, 0px)}._mark_tbse1_52{display:flex;align-items:center;justify-content:center;width:32px;height:32px;margin-bottom:var(--space-2);color:var(--accent-500)}._railList_tbse1_62{display:flex;flex-direction:column;align-items:center;gap:2px;list-style:none;margin:0;padding:0}._railFoot_tbse1_71{margin-top:auto}._railButton_tbse1_73{position:relative;display:flex;align-items:center;justify-content:center;width:calc(var(--control-h) + var(--space-1));height:calc(var(--control-h) + var(--space-1));border-radius:var(--radius-sm);color:var(--text-tertiary);transition:color var(--duration-fast) var(--ease-standard),background var(--duration-fast) var(--ease-standard)}._railButton_tbse1_73:hover{color:var(--text-primary);background:var(--bg-hover)}._railButton_tbse1_73:active{background:var(--bg-active)}._railButton_tbse1_73[aria-current]{color:var(--text-primary)}._railButton_tbse1_73[aria-current]:before{content:"";position:absolute;left:-10px;top:50%;height:56%;transform:translateY(-50%);width:2px;border-radius:1px;background:var(--accent-500)}._railDot_tbse1_104{position:absolute;top:6px;right:6px;width:6px;height:6px;border-radius:var(--radius-full);background:var(--status-warning-solid);box-shadow:0 0 0 2px var(--bg-canvas)}._section_tbse1_116{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:var(--bg-surface)}._section_tbse1_116>*{min-height:0}._loading_tbse1_126{flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-secondary);font-size:var(--text-sm-size)}._missing_tbse1_135{max-width:56ch;margin:clamp(32px,12vh,120px) auto 0;padding:0 var(--space-6);display:grid;gap:var(--space-3)}._missingTitle_tbse1_142{font-family:var(--font-display);font-size:var(--text-xl-size);line-height:var(--text-xl-line);font-weight:var(--font-weight-medium);letter-spacing:var(--tracking-display, -.02em)}._missingBody_tbse1_149,._missingDetail_tbse1_150{color:var(--text-secondary);font-size:var(--text-sm-size);line-height:var(--text-sm-line)}._missingBody_tbse1_149 code{font-size:var(--text-xs-size);color:var(--text-primary)}._missingDetail_tbse1_150{padding-left:var(--space-3);border-left:2px solid var(--border-strong);color:var(--text-tertiary);font-family:var(--font-mono);font-size:var(--text-xs-size);overflow-wrap:anywhere}._shell_k4nf7_1{height:100dvh;min-height:100%;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-canvas);color:var(--text-primary)}._checking_k4nf7_2{padding:var(--space-8);color:var(--text-secondary)}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{U as d,l as $}from"./format-fggwu_Rs.js";function u(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:null}function r(n,e){const t=n[e];return typeof t=="string"&&t.length>0?t:null}function v(n,e){const t=n[e];return typeof t=="number"&&Number.isFinite(t)?t:null}function a(n,e){const t=v(n,e);return t===null?null:Math.max(0,Math.round(t))}function f(n,e){const t=n[e];return typeof t=="boolean"?t:null}function A(n,e){const t=n[e];return Array.isArray(t)?t.filter(s=>typeof s=="string"):[]}const S=["llama-server","ollama","vllm","unknown"],q=["running","starting","stopping","stopped","unknown"],T=["queued","running","finishing"],E=["off","config","env","config+env","latch","unknown"];function h(n,e,t,s){const o=n[e];return typeof o=="string"&&t.includes(o)?o:s}function C(n){const e=u(n);return e?{capable:f(e,"capable"),refusal:r(e,"refusal"),slots:a(e,"slots")}:{capable:null,refusal:null,slots:null}}const y={up:"running",down:"stopped",loading:"starting",unknown:"unknown"};function R(n){const e=n.state;if(typeof e!="string"||!(e in y))return null;const t=u(n.slots),s=r(n,"host"),o=a(n,"port"),i=t?a(t,"configured"):null,l=t?a(t,"busy"):null,m=t?r(t,"source"):null,g=m!==null&&m!=="unknown",c=g?i:null,w=r(n,"parallelRefusal"),b=r(n,"runtimeKind"),k=a(n,"contextPerSlot"),p=a(n,"contextTotal");return{kind:b==="ollama"?"ollama":b==="unknown"?"unknown":"llama-server",state:y[e]??"unknown",endpoint:s!==null&&o!==null?`${s}:${o}`:r(n,"origin")??null,model:N(r(n,"modelName"))??N(r(n,"model")),slotsTotal:c,slotsBusy:g?l:null,contextTokens:k??(c!==null&&c>0&&p!==null&&p>0?Math.floor(p/c):null),startedAt:r(n,"startedAt"),parallel:{capable:w!==null?!1:g&&c!==null?!0:null,refusal:w,slots:c},reason:r(n,"lastError"),supervised:f(n,"managed")??!1,sampledAt:r(n,"checkedAt")}}function N(n){if(n===null||n.length===0)return null;const e=n.split("/").pop()??n;return e.length===0||/^sha256[-:][0-9a-f]{16,}$/i.test(e)?null:e}function _(n){const e=u(n);if(!e)return null;if(!("kind"in e)&&"slots"in e&&"state"in e){const t=R(e);if(t!==null)return t}return{kind:h(e,"kind",S,"unknown"),state:h(e,"state",q,"unknown"),endpoint:r(e,"endpoint"),model:r(e,"model"),slotsTotal:a(e,"slotsTotal"),slotsBusy:a(e,"slotsBusy"),contextTokens:a(e,"contextTokens"),startedAt:r(e,"startedAt"),parallel:C(e.parallel),reason:r(e,"reason"),supervised:f(e,"supervised")??!1,sampledAt:r(e,"sampledAt")}}function x(n){const e=u(n);if(!e)return null;const t=r(e,"id");return t===null?null:{id:t,task:r(e,"task"),repo:r(e,"repo"),engine:r(e,"engine"),model:r(e,"model"),state:h(e,"state",T,"running"),startedAt:r(e,"startedAt"),slot:a(e,"slot")}}function j(n){const e=u(n);return e?{agents:(Array.isArray(e.agents)?e.agents:[]).map(x).filter(s=>s!==null),queueDepth:a(e,"queueDepth"),slotsTotal:a(e,"slotsTotal"),slotsBusy:a(e,"slotsBusy"),notes:A(e,"notes"),sampledAt:r(e,"sampledAt")}:null}function M(n){const e=u(n);if(!e)return null;const t=r(e,"engine");return t===null?null:{engine:t,reason:r(e,"reason")??"The dispatcher refuses this engine while local-only is on."}}const D=new Set(["env","config+env","latch","unknown"]);function F(n){const e=u(n);if(!e)return null;const t=Array.isArray(e.refuses)?e.refuses:[],s=h(e,"source",E,"unknown");return{enabled:f(e,"enabled")??!1,source:s,refuses:t.map(M).filter(o=>o!==null),mutable:D.has(s)?!1:f(e,"mutable")??!1,detail:r(e,"detail"),sampledAt:r(e,"sampledAt")??r(e,"checkedAt")}}function L(n){switch(n){case"llama-server":return"llama-server";case"ollama":return"Ollama";case"vllm":return"vLLM";default:return"the serving runtime"}}function B(n){if(n===null)return{verdict:"unknown",effectiveConcurrency:null,configuredSlots:null,overstated:!1,headline:"No serving runtime reported",detail:"Nothing answered for the serving runtime, so how many agents can run at once is unknown. That is a missing reading, not an idle machine.",tone:"unknown"};const e=n.slotsTotal??n.parallel.slots,t=L(n.kind);if(n.state!=="running")return{verdict:"offline",effectiveConcurrency:null,configuredSlots:e,overstated:!1,headline:n.state==="stopped"?"Not serving":`Serving runtime is ${n.state}`,detail:n.state==="stopped"?`${t} is not running, so no local agent can take a turn. Start it before dispatching a fleet.`:`${t} is ${n.state}; capacity is not settled until it reports running.`,tone:n.state==="stopped"?"neutral":"warning"};if(n.parallel.capable===!1){const s=e!==null&&e>1;return{verdict:"serialized",effectiveConcurrency:1,configuredSlots:e,overstated:s,headline:`${t} serializes requests`,detail:s?`${t} has ${e} slots configured but runs one request at a time for this model, so the real capacity is one agent. The other ${e-1} would queue, and a queue looks like slowness rather than a wait.`:`${t} runs one request at a time for this model. A second agent waits for the first to finish.`,tone:"danger"}}return n.parallel.capable===null?{verdict:"unknown",effectiveConcurrency:null,configuredSlots:e,overstated:!1,headline:"Batching not confirmed",detail:`${t} is running${e===null?"":` with ${e} slots configured`}, but it has not reported whether it batches concurrent requests for this model. Until it does, this panel will not quote a concurrency it cannot stand behind.`,tone:"unknown"}:e===null?{verdict:"batched",effectiveConcurrency:null,configuredSlots:null,overstated:!1,headline:`${t} batches concurrent requests`,detail:`${t} batches, but reported no slot count, so the ceiling on concurrent agents is unknown.`,tone:"unknown"}:{verdict:"batched",effectiveConcurrency:e,configuredSlots:e,overstated:!1,headline:`${e} agent${e===1?"":"s"} in parallel`,detail:`${t} batches across ${e} slot${e===1?"":"s"} sharing one copy of the weights, so ${e} agent${e===1?"":"s"} can be mid-turn at once.`,tone:"success"}}const I=[{runtime:"Ollama",perRequestSeconds:[3.7,7.6,11.4,15.2],wallSeconds:15.2,verdict:"staggered — the requests queued"},{runtime:"llama-server",perRequestSeconds:[8.6,8.9,9,9],wallSeconds:9.1,verdict:"together — the requests batched"}];function P(n,e){if(n===null||e===null||e<=0)return{busy:n,total:e,percent:null,saturated:!1,label:n===null?"Slot occupancy is not reported.":`${n} in flight; the number of slots is not known, so occupancy cannot be drawn.`};const t=Math.min(n,e),s=Math.round(t/e*100),o=n>=e;return{busy:n,total:e,percent:s,saturated:o,label:o?`All ${e} slot${e===1?"":"s"} busy — new turns wait for one to free up.`:`${n} of ${e} slot${e===1?"":"s"} busy.`}}function z(n,e,t){if(n===null)return{state:"unknown",headline:"Fleet not reported",detail:"No fleet snapshot answered, so what is in flight cannot be listed. That is a missing reading, not an empty fleet.",tone:"unknown"};const s=n.agents.filter(i=>i.state!=="queued").length,o=n.queueDepth??n.agents.filter(i=>i.state==="queued").length;return o>0?{state:"queued",headline:`${o} waiting for a slot`,detail:t.verdict==="serialized"?`${s} turn${s===1?"":"s"} in flight and ${o} queued. This runtime serializes, so the queue drains one at a time — the wait is a wait, not slow inference.`:`${s} turn${s===1?"":"s"} in flight and ${o} queued behind ${e.total===null?"the available slots":`${e.total} slots`}. Queued turns have not started; their wall time is queueing, not work.`,tone:"warning"}:s===0?{state:"idle",headline:"Nothing in flight",detail:"No agent is mid-turn. The fleet is idle, not stuck.",tone:"neutral"}:e.saturated?{state:"saturated",headline:`All slots busy · ${s} in flight`,detail:"Every slot is working and nothing is queued behind them. The next turn will wait, but none is waiting yet.",tone:"running"}:{state:"working",headline:`${s} in flight`,detail:e.label,tone:"running"}}const O="Refused: local-only is on and this engine is not local.";function K(n,e){const t=e.filter(l=>l.engine!=="local"),s=e.filter(l=>l.engine==="local"),o=new Map;for(const l of n?.refuses??[])o.set(l.engine,l.reason);const i=e.length===0?"No seats are configured, so there is nothing for this policy to block yet.":t.length===0?`Every one of your ${e.length} seat${e.length===1?"":"s"} is local, so this policy would block nothing today.`:`${t.length} of ${e.length} seat${e.length===1?"":"s"} would become unreachable; ${s.length} local seat${s.length===1?"":"s"} would keep working.`;return{blocked:t,allowed:s,refusalFor:l=>o.get(l)??O,summary:i}}function Y(n){if(n===null)return null;if(n.detail!==null)return n.detail;switch(n.source){case"env":case"config+env":return"This policy is pinned by an environment variable on the server process, so it cannot be changed from here — restart the server without it to take the switch back.";case"latch":return"This process already observed a persisted local-only and has pinned it for its own lifetime, so turning it off takes effect for new dispatches but not for the seams that latched. Restart the server to clear it.";case"config":return"Stored in the hub config and applied on the next dispatch.";case"off":return"Not configured; cloud engines are reachable.";default:return"The server did not say where this setting came from."}}function G(n,e){if(!n)return d;const t=Date.parse(n);return Number.isNaN(t)?d:$(Math.max(0,e-t))}function Q(n,e){if(!n)return d;const t=Date.parse(n);return Number.isNaN(t)?d:`up ${$(Math.max(0,e-t))}`}function V(n){return n===null||!Number.isFinite(n)?d:n>=1024?`${Math.round(n/1024)}k`:String(n)}function W(n){const e={running:0,finishing:1,queued:2};return[...n].sort((t,s)=>{const o=e[t.state]-e[s.state];if(o!==0)return o;const i=t.startedAt?Date.parse(t.startedAt):Number.NaN,l=s.startedAt?Date.parse(s.startedAt):Number.NaN;return Number.isNaN(i)&&Number.isNaN(l)?t.id.localeCompare(s.id):Number.isNaN(i)?1:Number.isNaN(l)?-1:i-l})}export{I as C,j as a,F as b,Y as c,L as d,G as e,z as f,V as g,Q as h,K as l,W as o,_ as p,B as r,P as s};
|
|
2
|
-
//# sourceMappingURL=fleet-model-DXCfVtNW.js.map
|