@ashlr/hub 3.11.0 → 3.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/authority-surface.json +12 -7
  3. package/dist/build-identity.json +2 -2
  4. package/dist/core/universe/builtins/preparation/manifest.json +1 -1
  5. package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +5 -4
  6. package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +4 -3
  7. package/dist/core/universe/campaign.js +9 -1
  8. package/dist/core/universe/campaign.js.map +1 -1
  9. package/dist/core/universe/runner.d.ts +3 -0
  10. package/dist/core/universe/runner.js +7 -3
  11. package/dist/core/universe/runner.js.map +1 -1
  12. package/dist/core/verse/compaction-point.d.ts +55 -0
  13. package/dist/core/verse/compaction-point.js +75 -0
  14. package/dist/core/verse/compaction-point.js.map +1 -0
  15. package/dist/core/verse/context-math.d.ts +1 -38
  16. package/dist/core/verse/context-math.js +5 -59
  17. package/dist/core/verse/context-math.js.map +1 -1
  18. package/dist/core/web/public/next/assets/{ActionMenu-CQvNJvHY.js → ActionMenu-FxXeRbPx.js} +2 -2
  19. package/dist/core/web/public/next/assets/{ActionMenu-CQvNJvHY.js.map → ActionMenu-FxXeRbPx.js.map} +1 -1
  20. package/dist/core/web/public/next/assets/Advanced-D_eS4472.js +2 -0
  21. package/dist/core/web/public/next/assets/{Advanced-DEM93sKI.js.map → Advanced-D_eS4472.js.map} +1 -1
  22. package/dist/core/web/public/next/assets/App-Cj4zKbG3.js +7 -0
  23. package/dist/core/web/public/next/assets/{App-CimXmK0L.js.map → App-Cj4zKbG3.js.map} +1 -1
  24. package/dist/core/web/public/next/assets/AppsSection-Ddu_RCQE.js +2 -0
  25. package/dist/core/web/public/next/assets/{AppsSection-D6U-dSj6.js.map → AppsSection-Ddu_RCQE.js.map} +1 -1
  26. package/dist/core/web/public/next/assets/{AreaTrend-LD9lCPkT.js → AreaTrend-CDxrQU4b.js} +2 -2
  27. package/dist/core/web/public/next/assets/{AreaTrend-LD9lCPkT.js.map → AreaTrend-CDxrQU4b.js.map} +1 -1
  28. package/dist/core/web/public/next/assets/AutonomySection-DuQkHGD_.js +2 -0
  29. package/dist/core/web/public/next/assets/{AutonomySection-3V9pUyxm.js.map → AutonomySection-DuQkHGD_.js.map} +1 -1
  30. package/dist/core/web/public/next/assets/BranchBar-CLsvOcyK.js +2 -0
  31. package/dist/core/web/public/next/assets/{BranchBar-U8UdpfEB.js.map → BranchBar-CLsvOcyK.js.map} +1 -1
  32. package/dist/core/web/public/next/assets/{BudgetControl-DOTlMSmW.js → BudgetControl-TL3FeZ1D.js} +2 -2
  33. package/dist/core/web/public/next/assets/{BudgetControl-DOTlMSmW.js.map → BudgetControl-TL3FeZ1D.js.map} +1 -1
  34. package/dist/core/web/public/next/assets/{BurnDown-x4PWH9JF.js → BurnDown-sFXkUGdB.js} +2 -2
  35. package/dist/core/web/public/next/assets/{BurnDown-x4PWH9JF.js.map → BurnDown-sFXkUGdB.js.map} +1 -1
  36. package/dist/core/web/public/next/assets/{Button-DYv_KKxr.js → Button-HHXgoXGr.js} +2 -2
  37. package/dist/core/web/public/next/assets/{Button-DYv_KKxr.js.map → Button-HHXgoXGr.js.map} +1 -1
  38. package/dist/core/web/public/next/assets/CapacityStrip-qReu0RaF.js +2 -0
  39. package/dist/core/web/public/next/assets/CapacityStrip-qReu0RaF.js.map +1 -0
  40. package/dist/core/web/public/next/assets/ChatSection-DZuZfTaC.js +3 -0
  41. package/dist/core/web/public/next/assets/ChatSection-DZuZfTaC.js.map +1 -0
  42. package/dist/core/web/public/next/assets/{CloudBudgetForm-DJeJvBEu.js → CloudBudgetForm-DJbiT1wi.js} +2 -2
  43. package/dist/core/web/public/next/assets/{CloudBudgetForm-DJeJvBEu.js.map → CloudBudgetForm-DJbiT1wi.js.map} +1 -1
  44. package/dist/core/web/public/next/assets/CommandPalette-zYLFZRnj.js +2 -0
  45. package/dist/core/web/public/next/assets/{CommandPalette-FiD4N8XD.js.map → CommandPalette-zYLFZRnj.js.map} +1 -1
  46. package/dist/core/web/public/next/assets/CommandSection-rIeMK5Ch.js +2 -0
  47. package/dist/core/web/public/next/assets/{CommandSection-DN8KwH-X.js.map → CommandSection-rIeMK5Ch.js.map} +1 -1
  48. package/dist/core/web/public/next/assets/ConfirmDialog-DLrLKM0c.js +2 -0
  49. package/dist/core/web/public/next/assets/ConfirmDialog-DLrLKM0c.js.map +1 -0
  50. package/dist/core/web/public/next/assets/ConfirmDialog-Dx15x0Ho.css +1 -0
  51. package/dist/core/web/public/next/assets/Dialog-BS9Dxi3G.js +2 -0
  52. package/dist/core/web/public/next/assets/Dialog-BS9Dxi3G.js.map +1 -0
  53. package/dist/core/web/public/next/assets/Dialog-tQ8kFulD.css +1 -0
  54. package/dist/core/web/public/next/assets/{DiffPane-DLJ3gGGK.js → DiffPane-TOmUf3b2.js} +2 -2
  55. package/dist/core/web/public/next/assets/{DiffPane-DLJ3gGGK.js.map → DiffPane-TOmUf3b2.js.map} +1 -1
  56. package/dist/core/web/public/next/assets/{DiffViewer-B7NWPjIO.js → DiffViewer-BpH56302.js} +2 -2
  57. package/dist/core/web/public/next/assets/{DiffViewer-B7NWPjIO.js.map → DiffViewer-BpH56302.js.map} +1 -1
  58. package/dist/core/web/public/next/assets/DockHost-DzkzR-HD.js +2 -0
  59. package/dist/core/web/public/next/assets/{DockHost-DvR-hPhZ.js.map → DockHost-DzkzR-HD.js.map} +1 -1
  60. package/dist/core/web/public/next/assets/{EmptyState-DhNgDDrF.js → EmptyState-BqR5YAmf.js} +2 -2
  61. package/dist/core/web/public/next/assets/{EmptyState-DhNgDDrF.js.map → EmptyState-BqR5YAmf.js.map} +1 -1
  62. package/dist/core/web/public/next/assets/{Epistemic-uARPnx9x.js → Epistemic-dhvDTwAZ.js} +2 -2
  63. package/dist/core/web/public/next/assets/{Epistemic-uARPnx9x.js.map → Epistemic-dhvDTwAZ.js.map} +1 -1
  64. package/dist/core/web/public/next/assets/FleetSection-ViAb549H.js +3 -0
  65. package/dist/core/web/public/next/assets/{FleetSection-D_zRBCub.js.map → FleetSection-ViAb549H.js.map} +1 -1
  66. package/dist/core/web/public/next/assets/{Funnel-CL8uHONq.js → Funnel-D2u7Wlzc.js} +2 -2
  67. package/dist/core/web/public/next/assets/{Funnel-CL8uHONq.js.map → Funnel-D2u7Wlzc.js.map} +1 -1
  68. package/dist/core/web/public/next/assets/GearTray-Cb2npoxM.js +2 -0
  69. package/dist/core/web/public/next/assets/{GearTray-C7k4l_BW.js.map → GearTray-Cb2npoxM.js.map} +1 -1
  70. package/dist/core/web/public/next/assets/{GrowthSection-DwdNSGj8.js → GrowthSection-C5aDPs8B.js} +2 -2
  71. package/dist/core/web/public/next/assets/{GrowthSection-DwdNSGj8.js.map → GrowthSection-C5aDPs8B.js.map} +1 -1
  72. package/dist/core/web/public/next/assets/HandoffDialog-BF3AYg-X.js +2 -0
  73. package/dist/core/web/public/next/assets/{HandoffDialog-FPVOqOMN.js.map → HandoffDialog-BF3AYg-X.js.map} +1 -1
  74. package/dist/core/web/public/next/assets/{Input-B9-VLcHS.js → Input-B5dmGLZx.js} +2 -2
  75. package/dist/core/web/public/next/assets/{Input-B9-VLcHS.js.map → Input-B5dmGLZx.js.map} +1 -1
  76. package/dist/core/web/public/next/assets/LeaderCard-DZrmjDbI.js +2 -0
  77. package/dist/core/web/public/next/assets/{LeaderCard-4R0BhDzT.js.map → LeaderCard-DZrmjDbI.js.map} +1 -1
  78. package/dist/core/web/public/next/assets/{MatrixHeatmap-DiuushcS.js → MatrixHeatmap-BgEUs2Eu.js} +2 -2
  79. package/dist/core/web/public/next/assets/{MatrixHeatmap-DiuushcS.js.map → MatrixHeatmap-BgEUs2Eu.js.map} +1 -1
  80. package/dist/core/web/public/next/assets/McpSection-DZkiOuoq.js +2 -0
  81. package/dist/core/web/public/next/assets/{McpSection-CJ__OJKl.js.map → McpSection-DZkiOuoq.js.map} +1 -1
  82. package/dist/core/web/public/next/assets/{MessageMarkdown-qWKyJvAQ.js → MessageMarkdown-BauY8ZTY.js} +3 -3
  83. package/dist/core/web/public/next/assets/{MessageMarkdown-qWKyJvAQ.js.map → MessageMarkdown-BauY8ZTY.js.map} +1 -1
  84. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-x05TrsrW.js → MessageMarkdownRenderer-DLBNLfsn.js} +2 -2
  85. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-x05TrsrW.js.map → MessageMarkdownRenderer-DLBNLfsn.js.map} +1 -1
  86. package/dist/core/web/public/next/assets/{Meter-D-hncpkO.js → Meter-DNeocJnD.js} +2 -2
  87. package/dist/core/web/public/next/assets/{Meter-D-hncpkO.js.map → Meter-DNeocJnD.js.map} +1 -1
  88. package/dist/core/web/public/next/assets/MindSection-BvJXFjyX.js +2 -0
  89. package/dist/core/web/public/next/assets/{MindSection-BjXHkQPS.js.map → MindSection-BvJXFjyX.js.map} +1 -1
  90. package/dist/core/web/public/next/assets/MutationTokenDialog-CrfJ0PdD.css +1 -0
  91. package/dist/core/web/public/next/assets/MutationTokenDialog-mxrw0Yvy.js +2 -0
  92. package/dist/core/web/public/next/assets/MutationTokenDialog-mxrw0Yvy.js.map +1 -0
  93. package/dist/core/web/public/next/assets/NeedsYouDrawer-CO-Balfp.js +2 -0
  94. package/dist/core/web/public/next/assets/{NeedsYouDrawer-rSd1ZHAR.js.map → NeedsYouDrawer-CO-Balfp.js.map} +1 -1
  95. package/dist/core/web/public/next/assets/{NeedsYouList-CG-nB1tr.js → NeedsYouList-CzDZbzRD.js} +2 -2
  96. package/dist/core/web/public/next/assets/{NeedsYouList-CG-nB1tr.js.map → NeedsYouList-CzDZbzRD.js.map} +1 -1
  97. package/dist/core/web/public/next/assets/NewChatDialog-B8eJjlFf.js +3 -0
  98. package/dist/core/web/public/next/assets/{NewChatDialog-BeDQ1eW3.js.map → NewChatDialog-B8eJjlFf.js.map} +1 -1
  99. package/dist/core/web/public/next/assets/OnboardingFlow-Cij6KWat.js +2 -0
  100. package/dist/core/web/public/next/assets/{OnboardingFlow-CkTZtt-m.js.map → OnboardingFlow-Cij6KWat.js.map} +1 -1
  101. package/dist/core/web/public/next/assets/PreviewPane-BS-CleCd.js +2 -0
  102. package/dist/core/web/public/next/assets/{PreviewPane-kzbbSK4u.js.map → PreviewPane-BS-CleCd.js.map} +1 -1
  103. package/dist/core/web/public/next/assets/ProviderLogo-C5mBg8i0.js +2 -0
  104. package/dist/core/web/public/next/assets/ProviderLogo-C5mBg8i0.js.map +1 -0
  105. package/dist/core/web/public/next/assets/{RailStatus-D-t2gPae.js → RailStatus-cPRyOmrk.js} +2 -2
  106. package/dist/core/web/public/next/assets/{RailStatus-D-t2gPae.js.map → RailStatus-cPRyOmrk.js.map} +1 -1
  107. package/dist/core/web/public/next/assets/{RefreshIndicator-BLnr9IOM.js → RefreshIndicator-CMwSCiz5.js} +2 -2
  108. package/dist/core/web/public/next/assets/{RefreshIndicator-BLnr9IOM.js.map → RefreshIndicator-CMwSCiz5.js.map} +1 -1
  109. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BeG0gBif.js → ResourcePoolConsoleApp-BFi1opsC.js} +5 -5
  110. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BeG0gBif.js.map → ResourcePoolConsoleApp-BFi1opsC.js.map} +1 -1
  111. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-CM_8pJs6.css → ResourcePoolConsoleApp-BX9JLkT4.css} +1 -1
  112. package/dist/core/web/public/next/assets/ResourcesChrome-BJCauW_t.js +3 -0
  113. package/dist/core/web/public/next/assets/ResourcesChrome-BJCauW_t.js.map +1 -0
  114. package/dist/core/web/public/next/assets/ResourcesChrome-uZEqC2EM.css +1 -0
  115. package/dist/core/web/public/next/assets/ResourcesDrawer-BDecg6nO.js +2 -0
  116. package/dist/core/web/public/next/assets/ResourcesDrawer-BDecg6nO.js.map +1 -0
  117. package/dist/core/web/public/next/assets/RouteErrorBoundary-DYtwc2ja.js +2 -0
  118. package/dist/core/web/public/next/assets/RouteErrorBoundary-DYtwc2ja.js.map +1 -0
  119. package/dist/core/web/public/next/assets/RouteErrorBoundary-DdxhTdZ6.css +1 -0
  120. package/dist/core/web/public/next/assets/{RunInCloudAction-C3LBp7C4.js → RunInCloudAction-BEGEEM8O.js} +2 -2
  121. package/dist/core/web/public/next/assets/{RunInCloudAction-C3LBp7C4.js.map → RunInCloudAction-BEGEEM8O.js.map} +1 -1
  122. package/dist/core/web/public/next/assets/SeatSelector-CYHRR7Wp.js +3 -0
  123. package/dist/core/web/public/next/assets/{SeatSelector-DpvvbjNm.js.map → SeatSelector-CYHRR7Wp.js.map} +1 -1
  124. package/dist/core/web/public/next/assets/{Segmented-BL40udoO.js → Segmented-BE53BenI.js} +2 -2
  125. package/dist/core/web/public/next/assets/{Segmented-BL40udoO.js.map → Segmented-BE53BenI.js.map} +1 -1
  126. package/dist/core/web/public/next/assets/{Select-FWLnAw_j.js → Select-BwSGkHCS.js} +2 -2
  127. package/dist/core/web/public/next/assets/{Select-FWLnAw_j.js.map → Select-BwSGkHCS.js.map} +1 -1
  128. package/dist/core/web/public/next/assets/SessionGate-DvMpXNpJ.css +1 -0
  129. package/dist/core/web/public/next/assets/SessionGate-e0dFJm9d.js +2 -0
  130. package/dist/core/web/public/next/assets/SessionGate-e0dFJm9d.js.map +1 -0
  131. package/dist/core/web/public/next/assets/SessionInsightChip-CxlSyueJ.js +2 -0
  132. package/dist/core/web/public/next/assets/{SessionInsightChip-CWye87Ju.js.map → SessionInsightChip-CxlSyueJ.js.map} +1 -1
  133. package/dist/core/web/public/next/assets/{SessionSearch-YvCHFUuN.js → SessionSearch-_yp7S2TP.js} +2 -2
  134. package/dist/core/web/public/next/assets/{SessionSearch-YvCHFUuN.js.map → SessionSearch-_yp7S2TP.js.map} +1 -1
  135. package/dist/core/web/public/next/assets/SettingsSection-wGnpWeGW.js +2 -0
  136. package/dist/core/web/public/next/assets/SettingsSection-wGnpWeGW.js.map +1 -0
  137. package/dist/core/web/public/next/assets/Sheet-DVP2Mgy6.js +2 -0
  138. package/dist/core/web/public/next/assets/{Sheet-DZKcQXQg.js.map → Sheet-DVP2Mgy6.js.map} +1 -1
  139. package/dist/core/web/public/next/assets/ShortcutsOverlay-BcIcoClX.js +2 -0
  140. package/dist/core/web/public/next/assets/{ShortcutsOverlay-BpDimdPq.js.map → ShortcutsOverlay-BcIcoClX.js.map} +1 -1
  141. package/dist/core/web/public/next/assets/Sidebar-DjQOqPbm.js +3 -0
  142. package/dist/core/web/public/next/assets/{Sidebar-BoBzBEFX.js.map → Sidebar-DjQOqPbm.js.map} +1 -1
  143. package/dist/core/web/public/next/assets/{Slider-DUMo9HDD.js → Slider-BypUWjpH.js} +2 -2
  144. package/dist/core/web/public/next/assets/{Slider-DUMo9HDD.js.map → Slider-BypUWjpH.js.map} +1 -1
  145. package/dist/core/web/public/next/assets/{StatusBadge-BwnBNFQr.js → StatusBadge-HCZp416_.js} +2 -2
  146. package/dist/core/web/public/next/assets/{StatusBadge-BwnBNFQr.js.map → StatusBadge-HCZp416_.js.map} +1 -1
  147. package/dist/core/web/public/next/assets/{StepBand-PDXMIlRk.js → StepBand-Duz1PUes.js} +2 -2
  148. package/dist/core/web/public/next/assets/{StepBand-PDXMIlRk.js.map → StepBand-Duz1PUes.js.map} +1 -1
  149. package/dist/core/web/public/next/assets/{Surface-B3TZVoER.js → Surface-B75lVfzm.js} +2 -2
  150. package/dist/core/web/public/next/assets/{Surface-B3TZVoER.js.map → Surface-B75lVfzm.js.map} +1 -1
  151. package/dist/core/web/public/next/assets/{Swimlane-DR4OgON_.js → Swimlane-DGcIcnNA.js} +2 -2
  152. package/dist/core/web/public/next/assets/{Swimlane-DR4OgON_.js.map → Swimlane-DGcIcnNA.js.map} +1 -1
  153. package/dist/core/web/public/next/assets/{Switch-CcR5Llk5.js → Switch-iveI-8NY.js} +2 -2
  154. package/dist/core/web/public/next/assets/{Switch-CcR5Llk5.js.map → Switch-iveI-8NY.js.map} +1 -1
  155. package/dist/core/web/public/next/assets/{Tag-_-K1h7Hk.js → Tag-DH15CUJp.js} +2 -2
  156. package/dist/core/web/public/next/assets/{Tag-_-K1h7Hk.js.map → Tag-DH15CUJp.js.map} +1 -1
  157. package/dist/core/web/public/next/assets/TerminalPane-MQT-veKZ.js +7 -0
  158. package/dist/core/web/public/next/assets/{TerminalPane-_1aH4ndN.js.map → TerminalPane-MQT-veKZ.js.map} +1 -1
  159. package/dist/core/web/public/next/assets/UniverseConsoleApp-C8yQ0AaR.js +2 -0
  160. package/dist/core/web/public/next/assets/{UniverseConsoleApp-BUsq-inZ.js.map → UniverseConsoleApp-C8yQ0AaR.js.map} +1 -1
  161. package/dist/core/web/public/next/assets/{UniverseConsoleApp-Dh7A-hLD.css → UniverseConsoleApp-DfuT-wFw.css} +1 -1
  162. package/dist/core/web/public/next/assets/{UniverseView-Dogy_dsB.js → UniverseView-_nPURPqe.js} +4 -4
  163. package/dist/core/web/public/next/assets/{UniverseView-Dogy_dsB.js.map → UniverseView-_nPURPqe.js.map} +1 -1
  164. package/dist/core/web/public/next/assets/UsageSection-CqxRGJ40.js +2 -0
  165. package/dist/core/web/public/next/assets/{UsageSection-DiX_dTyo.js.map → UsageSection-CqxRGJ40.js.map} +1 -1
  166. package/dist/core/web/public/next/assets/VerseConsoleApp-DTjDpGCd.js +3 -0
  167. package/dist/core/web/public/next/assets/VerseConsoleApp-DTjDpGCd.js.map +1 -0
  168. package/dist/core/web/public/next/assets/Workspace-DfcFGzME.js +10 -0
  169. package/dist/core/web/public/next/assets/Workspace-DfcFGzME.js.map +1 -0
  170. package/dist/core/web/public/next/assets/Workspace-Dwri2jFJ.css +1 -0
  171. package/dist/core/web/public/next/assets/actions-tWevL9HV.js +2 -0
  172. package/dist/core/web/public/next/assets/{actions-s2lfm_5k.js.map → actions-tWevL9HV.js.map} +1 -1
  173. package/dist/core/web/public/next/assets/budget-queries-V3wcJVK_.js +2 -0
  174. package/dist/core/web/public/next/assets/{budget-queries-wUshcovN.js.map → budget-queries-V3wcJVK_.js.map} +1 -1
  175. package/dist/core/web/public/next/assets/{capacity-strip-model-Bj_9ztzs.js → capacity-strip-model-BDbmQ3e3.js} +2 -2
  176. package/dist/core/web/public/next/assets/{capacity-strip-model-Bj_9ztzs.js.map → capacity-strip-model-BDbmQ3e3.js.map} +1 -1
  177. package/dist/core/web/public/next/assets/{charts-CMSgAUKn.js → charts-CfAjuKMv.js} +2 -2
  178. package/dist/core/web/public/next/assets/{charts-CMSgAUKn.js.map → charts-CfAjuKMv.js.map} +1 -1
  179. package/dist/core/web/public/next/assets/cloud-queries-Br_r0UAz.js +2 -0
  180. package/dist/core/web/public/next/assets/{cloud-queries-CnV1yaNG.js.map → cloud-queries-Br_r0UAz.js.map} +1 -1
  181. package/dist/core/web/public/next/assets/{cloud.module-CiwatLj3.js → cloud.module-ascz58c3.js} +2 -2
  182. package/dist/core/web/public/next/assets/{cloud.module-CiwatLj3.js.map → cloud.module-ascz58c3.js.map} +1 -1
  183. package/dist/core/web/public/next/assets/{command-bus-DqimKCUY.js → command-bus-xYZoK9nQ.js} +2 -2
  184. package/dist/core/web/public/next/assets/{command-bus-DqimKCUY.js.map → command-bus-xYZoK9nQ.js.map} +1 -1
  185. package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js +2 -0
  186. package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js.map +1 -0
  187. package/dist/core/web/public/next/assets/compaction-point-VL9oegWS.js +2 -0
  188. package/dist/core/web/public/next/assets/compaction-point-VL9oegWS.js.map +1 -0
  189. package/dist/core/web/public/next/assets/{composer-keys-DBRymxQn.js → composer-keys-su0g1h9o.js} +2 -2
  190. package/dist/core/web/public/next/assets/{composer-keys-DBRymxQn.js.map → composer-keys-su0g1h9o.js.map} +1 -1
  191. package/dist/core/web/public/next/assets/context-model-BC-HOmPo.js +2 -0
  192. package/dist/core/web/public/next/assets/{context-model-Dwd49-dp.js.map → context-model-BC-HOmPo.js.map} +1 -1
  193. package/dist/core/web/public/next/assets/context-model-CIBmSugV.js +2 -0
  194. package/dist/core/web/public/next/assets/{context-model-MT17V86_.js.map → context-model-CIBmSugV.js.map} +1 -1
  195. package/dist/core/web/public/next/assets/context-queries-CrPcHWTz.js +2 -0
  196. package/dist/core/web/public/next/assets/{context-queries-xVKIeynP.js.map → context-queries-CrPcHWTz.js.map} +1 -1
  197. package/dist/core/web/public/next/assets/control-queries-CmgBgKV7.js +2 -0
  198. package/dist/core/web/public/next/assets/{control-queries-DOZR-D8G.js.map → control-queries-CmgBgKV7.js.map} +1 -1
  199. package/dist/core/web/public/next/assets/{dock-icons-8EtARwUm.js → dock-icons-CUh8dOxJ.js} +2 -2
  200. package/dist/core/web/public/next/assets/{dock-icons-8EtARwUm.js.map → dock-icons-CUh8dOxJ.js.map} +1 -1
  201. package/dist/core/web/public/next/assets/{dock-store-BA1cHOYA.js → dock-store-B2vlxqPu.js} +2 -2
  202. package/dist/core/web/public/next/assets/{dock-store-BA1cHOYA.js.map → dock-store-B2vlxqPu.js.map} +1 -1
  203. package/dist/core/web/public/next/assets/{fleet-model-CNe8Wh-s.js → fleet-model-7i-FbzKI.js} +2 -2
  204. package/dist/core/web/public/next/assets/{fleet-model-CNe8Wh-s.js.map → fleet-model-7i-FbzKI.js.map} +1 -1
  205. package/dist/core/web/public/next/assets/fleet-queries-DzGoqq8X.js +2 -0
  206. package/dist/core/web/public/next/assets/{fleet-queries-BSdRlUwJ.js.map → fleet-queries-DzGoqq8X.js.map} +1 -1
  207. package/dist/core/web/public/next/assets/focus-trap-HtcoXeEq.js +2 -0
  208. package/dist/core/web/public/next/assets/focus-trap-HtcoXeEq.js.map +1 -0
  209. package/dist/core/web/public/next/assets/{format-B8DAVcn2.js → format-BkWdOQDL.js} +2 -2
  210. package/dist/core/web/public/next/assets/{format-B8DAVcn2.js.map → format-BkWdOQDL.js.map} +1 -1
  211. package/dist/core/web/public/next/assets/git-model-bk_RXh3y.js +5 -0
  212. package/dist/core/web/public/next/assets/{git-model-CivuBY_D.js.map → git-model-bk_RXh3y.js.map} +1 -1
  213. package/dist/core/web/public/next/assets/global-BlI2BYa1.css +1 -0
  214. package/dist/core/web/public/next/assets/global-oEl9Qj8u.js +2 -0
  215. package/dist/core/web/public/next/assets/global-oEl9Qj8u.js.map +1 -0
  216. package/dist/core/web/public/next/assets/guarded-action-OzqcPjmh.js +3 -0
  217. package/dist/core/web/public/next/assets/guarded-action-OzqcPjmh.js.map +1 -0
  218. package/dist/core/web/public/next/assets/guarded-runners-LHLXmXIk.js +2 -0
  219. package/dist/core/web/public/next/assets/guarded-runners-LHLXmXIk.js.map +1 -0
  220. package/dist/core/web/public/next/assets/icon-base-DvM1eI5V.js +2 -0
  221. package/dist/core/web/public/next/assets/icon-base-DvM1eI5V.js.map +1 -0
  222. package/dist/core/web/public/next/assets/icons-DEQa2rTx.js +2 -0
  223. package/dist/core/web/public/next/assets/icons-DEQa2rTx.js.map +1 -0
  224. package/dist/core/web/public/next/assets/{index-oAAq8XJa.js → index-BVxOlseC.js} +3 -3
  225. package/dist/core/web/public/next/assets/{index-oAAq8XJa.js.map → index-BVxOlseC.js.map} +1 -1
  226. package/dist/core/web/public/next/assets/{live-model-DCw_IFRI.js → live-model-bmsJgnYD.js} +2 -2
  227. package/dist/core/web/public/next/assets/{live-model-DCw_IFRI.js.map → live-model-bmsJgnYD.js.map} +1 -1
  228. package/dist/core/web/public/next/assets/{mind.module-vnuJcwvD.js → mind.module-gTGAuJt1.js} +2 -2
  229. package/dist/core/web/public/next/assets/{mind.module-vnuJcwvD.js.map → mind.module-gTGAuJt1.js.map} +1 -1
  230. package/dist/core/web/public/next/assets/mutations-C5S7okTW.js +2 -0
  231. package/dist/core/web/public/next/assets/{mutations-Dpsql5t7.js.map → mutations-C5S7okTW.js.map} +1 -1
  232. package/dist/core/web/public/next/assets/nav-NVtnuG7A.js +2 -0
  233. package/dist/core/web/public/next/assets/nav-NVtnuG7A.js.map +1 -0
  234. package/dist/core/web/public/next/assets/overnight-queries-DGm3qL1b.js +2 -0
  235. package/dist/core/web/public/next/assets/{overnight-queries-X-44Gsw5.js.map → overnight-queries-DGm3qL1b.js.map} +1 -1
  236. package/dist/core/web/public/next/assets/preloaded-Cwf9rsnZ.js +2 -0
  237. package/dist/core/web/public/next/assets/preloaded-Cwf9rsnZ.js.map +1 -0
  238. package/dist/core/web/public/next/assets/primitives-DyCKYSBG.js +1 -0
  239. package/dist/core/web/public/next/assets/{queries-BA4rNGD-.js → queries-CYisSAAB.js} +2 -2
  240. package/dist/core/web/public/next/assets/{queries-BA4rNGD-.js.map → queries-CYisSAAB.js.map} +1 -1
  241. package/dist/core/web/public/next/assets/reasoning-pref-BUcFF_5G.js +2 -0
  242. package/dist/core/web/public/next/assets/{reasoning-pref-B9-DJUXP.js.map → reasoning-pref-BUcFF_5G.js.map} +1 -1
  243. package/dist/core/web/public/next/assets/reveal-anchor-D-tV8xau.js +2 -0
  244. package/dist/core/web/public/next/assets/reveal-anchor-D-tV8xau.js.map +1 -0
  245. package/dist/core/web/public/next/assets/seat-subscription-B-f9ViU2.js +2 -0
  246. package/dist/core/web/public/next/assets/{seat-subscription-CH6fW4fJ.js.map → seat-subscription-B-f9ViU2.js.map} +1 -1
  247. package/dist/core/web/public/next/assets/{section-visibility-qFqc_d4Z.js → section-visibility-Yctxu-if.js} +2 -2
  248. package/dist/core/web/public/next/assets/{section-visibility-qFqc_d4Z.js.map → section-visibility-Yctxu-if.js.map} +1 -1
  249. package/dist/core/web/public/next/assets/{sidebar-model-M1GaQU5l.js → sidebar-model-DQ-FyBHW.js} +2 -2
  250. package/dist/core/web/public/next/assets/{sidebar-model-M1GaQU5l.js.map → sidebar-model-DQ-FyBHW.js.map} +1 -1
  251. package/dist/core/web/public/next/assets/slots-BhP8b8tf.js +3 -0
  252. package/dist/core/web/public/next/assets/{slots-Ds9ZIqUL.js.map → slots-BhP8b8tf.js.map} +1 -1
  253. package/dist/core/web/public/next/assets/surface-data-DTI7LjvH.js +2 -0
  254. package/dist/core/web/public/next/assets/{surface-data-J52iIGMD.js.map → surface-data-DTI7LjvH.js.map} +1 -1
  255. package/dist/core/web/public/next/assets/surface-prefetch-CdUEBFrl.js +2 -0
  256. package/dist/core/web/public/next/assets/{surface-prefetch-CgZ-LEJK.js.map → surface-prefetch-CdUEBFrl.js.map} +1 -1
  257. package/dist/core/web/public/next/assets/{tasks-model-ent8f0jZ.js → tasks-model-BKDNqmmt.js} +2 -2
  258. package/dist/core/web/public/next/assets/{tasks-model-ent8f0jZ.js.map → tasks-model-BKDNqmmt.js.map} +1 -1
  259. package/dist/core/web/public/next/assets/{terminal-icons-DJTK7QpR.js → terminal-icons-D2xe-aM1.js} +2 -2
  260. package/dist/core/web/public/next/assets/{terminal-icons-DJTK7QpR.js.map → terminal-icons-D2xe-aM1.js.map} +1 -1
  261. package/dist/core/web/public/next/assets/{usage-queries-Bn8ccqyN.js → usage-queries-BZuAANlI.js} +2 -2
  262. package/dist/core/web/public/next/assets/{usage-queries-Bn8ccqyN.js.map → usage-queries-BZuAANlI.js.map} +1 -1
  263. package/dist/core/web/public/next/assets/use-guarded-action-Cf4MeNBa.js +2 -0
  264. package/dist/core/web/public/next/assets/{use-guarded-action-C2HlSzkz.js.map → use-guarded-action-Cf4MeNBa.js.map} +1 -1
  265. package/dist/core/web/public/next/assets/{use-ticker-BNc1H4ZC.js → use-ticker-D9yi49my.js} +2 -2
  266. package/dist/core/web/public/next/assets/{use-ticker-BNc1H4ZC.js.map → use-ticker-D9yi49my.js.map} +1 -1
  267. package/dist/core/web/public/next/assets/use-token-gate-DqrSXdX6.js +2 -0
  268. package/dist/core/web/public/next/assets/{use-token-gate-B3IJL6bf.js.map → use-token-gate-DqrSXdX6.js.map} +1 -1
  269. package/dist/core/web/public/next/assets/useChartWidth-BW6SwYIK.css +1 -0
  270. package/dist/core/web/public/next/assets/useChartWidth-owwodNVz.js +2 -0
  271. package/dist/core/web/public/next/assets/{useChartWidth-lZ9PrQn0.js.map → useChartWidth-owwodNVz.js.map} +1 -1
  272. package/dist/core/web/public/next/assets/{useSeatsRefresh-CG4jczeL.js → useSeatsRefresh-DgFy-Ph4.js} +2 -2
  273. package/dist/core/web/public/next/assets/{useSeatsRefresh-CG4jczeL.js.map → useSeatsRefresh-DgFy-Ph4.js.map} +1 -1
  274. package/dist/core/web/public/next/assets/useVerseTranscript-CDYrrWOO.js +2 -0
  275. package/dist/core/web/public/next/assets/useVerseTranscript-CDYrrWOO.js.map +1 -0
  276. package/dist/core/web/public/next/assets/verse-icons-F9VwX07_.js +2 -0
  277. package/dist/core/web/public/next/assets/verse-icons-F9VwX07_.js.map +1 -0
  278. package/dist/core/web/public/next/assets/verse-model-DyCwZF-M.js +2 -0
  279. package/dist/core/web/public/next/assets/verse-model-DyCwZF-M.js.map +1 -0
  280. package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js +3 -0
  281. package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js.map +1 -0
  282. package/dist/core/web/public/next/assets/verse-ui-store-62DxpVHS.js +3 -0
  283. package/dist/core/web/public/next/assets/{verse-ui-store-zafyzXKD.js.map → verse-ui-store-62DxpVHS.js.map} +1 -1
  284. package/dist/core/web/public/next/assets/{viewport-BEqGUoTA.js → viewport-nTubFCwf.js} +2 -2
  285. package/dist/core/web/public/next/assets/{viewport-BEqGUoTA.js.map → viewport-nTubFCwf.js.map} +1 -1
  286. package/dist/core/web/public/next/assets/warmup-HG5vYbsN.js +3 -0
  287. package/dist/core/web/public/next/assets/{warmup-BR6pxAKs.js.map → warmup-HG5vYbsN.js.map} +1 -1
  288. package/dist/core/web/public/next/assets/{workspace-model-D_tWD5Wt.js → workspace-model-CbhdPhei.js} +2 -2
  289. package/dist/core/web/public/next/assets/{workspace-model-D_tWD5Wt.js.map → workspace-model-CbhdPhei.js.map} +1 -1
  290. package/dist/core/web/public/next/index.html +1 -1
  291. package/dist/release-dependency-inventory.json +1 -1
  292. package/package.json +5 -2
  293. package/dist/cli/activation.d.ts +0 -41
  294. package/dist/cli/activation.js +0 -485
  295. package/dist/cli/activation.js.map +0 -1
  296. package/dist/core/fleet/generated-repair-resolution.d.ts +0 -36
  297. package/dist/core/fleet/generated-repair-resolution.js +0 -245
  298. package/dist/core/fleet/generated-repair-resolution.js.map +0 -1
  299. package/dist/core/local-runtime/llama/port.d.ts +0 -17
  300. package/dist/core/local-runtime/llama/port.js +0 -47
  301. package/dist/core/local-runtime/llama/port.js.map +0 -1
  302. package/dist/core/local-runtime/llama/proxy-host.d.ts +0 -54
  303. package/dist/core/local-runtime/llama/proxy-host.js +0 -159
  304. package/dist/core/local-runtime/llama/proxy-host.js.map +0 -1
  305. package/dist/core/local-runtime/llama/proxy-process.d.ts +0 -148
  306. package/dist/core/local-runtime/llama/proxy-process.js +0 -250
  307. package/dist/core/local-runtime/llama/proxy-process.js.map +0 -1
  308. package/dist/core/local-runtime/llama/proxy-record.d.ts +0 -40
  309. package/dist/core/local-runtime/llama/proxy-record.js +0 -133
  310. package/dist/core/local-runtime/llama/proxy-record.js.map +0 -1
  311. package/dist/core/local-runtime/llama/proxy-supervisor.d.ts +0 -118
  312. package/dist/core/local-runtime/llama/proxy-supervisor.js +0 -511
  313. package/dist/core/local-runtime/llama/proxy-supervisor.js.map +0 -1
  314. package/dist/core/web/public/next/assets/Advanced-DEM93sKI.js +0 -2
  315. package/dist/core/web/public/next/assets/App-CimXmK0L.js +0 -7
  316. package/dist/core/web/public/next/assets/AppsSection-D6U-dSj6.js +0 -2
  317. package/dist/core/web/public/next/assets/AutonomySection-3V9pUyxm.js +0 -2
  318. package/dist/core/web/public/next/assets/BranchBar-U8UdpfEB.js +0 -2
  319. package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js +0 -2
  320. package/dist/core/web/public/next/assets/CapacityStrip-C667yQe8.js.map +0 -1
  321. package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js +0 -3
  322. package/dist/core/web/public/next/assets/ChatSection-CCcIPpOq.js.map +0 -1
  323. package/dist/core/web/public/next/assets/CommandPalette-FiD4N8XD.js +0 -2
  324. package/dist/core/web/public/next/assets/CommandSection-DN8KwH-X.js +0 -2
  325. package/dist/core/web/public/next/assets/DockHost-DvR-hPhZ.js +0 -2
  326. package/dist/core/web/public/next/assets/FleetSection-D_zRBCub.js +0 -3
  327. package/dist/core/web/public/next/assets/GearTray-C7k4l_BW.js +0 -2
  328. package/dist/core/web/public/next/assets/HandoffDialog-FPVOqOMN.js +0 -2
  329. package/dist/core/web/public/next/assets/LeaderCard-4R0BhDzT.js +0 -2
  330. package/dist/core/web/public/next/assets/McpSection-CJ__OJKl.js +0 -2
  331. package/dist/core/web/public/next/assets/MindSection-BjXHkQPS.js +0 -2
  332. package/dist/core/web/public/next/assets/MutationTokenDialog-Cum_DqQZ.css +0 -1
  333. package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js +0 -2
  334. package/dist/core/web/public/next/assets/MutationTokenDialog-SkRxqV_I.js.map +0 -1
  335. package/dist/core/web/public/next/assets/NeedsYouDrawer-rSd1ZHAR.js +0 -2
  336. package/dist/core/web/public/next/assets/NewChatDialog-BeDQ1eW3.js +0 -3
  337. package/dist/core/web/public/next/assets/OnboardingFlow-CkTZtt-m.js +0 -2
  338. package/dist/core/web/public/next/assets/PreviewPane-kzbbSK4u.js +0 -2
  339. package/dist/core/web/public/next/assets/ResourcesChrome-B3Z3O98t.css +0 -1
  340. package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js +0 -3
  341. package/dist/core/web/public/next/assets/ResourcesChrome-BzV6bkIa.js.map +0 -1
  342. package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js +0 -2
  343. package/dist/core/web/public/next/assets/ResourcesDrawer-o4ILHdep.js.map +0 -1
  344. package/dist/core/web/public/next/assets/RouteErrorBoundary-6RMd_aZg.css +0 -1
  345. package/dist/core/web/public/next/assets/RouteErrorBoundary-C5SxA2Dg.js +0 -2
  346. package/dist/core/web/public/next/assets/RouteErrorBoundary-C5SxA2Dg.js.map +0 -1
  347. package/dist/core/web/public/next/assets/SeatSelector-DpvvbjNm.js +0 -3
  348. package/dist/core/web/public/next/assets/SessionInsightChip-CWye87Ju.js +0 -2
  349. package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js +0 -2
  350. package/dist/core/web/public/next/assets/SettingsSection-Dr18upeE.js.map +0 -1
  351. package/dist/core/web/public/next/assets/Sheet-DZKcQXQg.js +0 -2
  352. package/dist/core/web/public/next/assets/ShortcutsOverlay-BpDimdPq.js +0 -2
  353. package/dist/core/web/public/next/assets/Sidebar-BoBzBEFX.js +0 -3
  354. package/dist/core/web/public/next/assets/TerminalPane-_1aH4ndN.js +0 -7
  355. package/dist/core/web/public/next/assets/UniverseConsoleApp-BUsq-inZ.js +0 -2
  356. package/dist/core/web/public/next/assets/UsageSection-DiX_dTyo.js +0 -2
  357. package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js +0 -3
  358. package/dist/core/web/public/next/assets/VerseConsoleApp-WVeyJnW7.js.map +0 -1
  359. package/dist/core/web/public/next/assets/Workspace-BYW9dm90.css +0 -1
  360. package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js +0 -10
  361. package/dist/core/web/public/next/assets/Workspace-BbxZHwQd.js.map +0 -1
  362. package/dist/core/web/public/next/assets/actions-s2lfm_5k.js +0 -2
  363. package/dist/core/web/public/next/assets/budget-queries-wUshcovN.js +0 -2
  364. package/dist/core/web/public/next/assets/cloud-queries-CnV1yaNG.js +0 -2
  365. package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js +0 -2
  366. package/dist/core/web/public/next/assets/command-catalog-BdtDH93o.js.map +0 -1
  367. package/dist/core/web/public/next/assets/context-model-Dwd49-dp.js +0 -2
  368. package/dist/core/web/public/next/assets/context-model-MT17V86_.js +0 -2
  369. package/dist/core/web/public/next/assets/context-queries-xVKIeynP.js +0 -2
  370. package/dist/core/web/public/next/assets/control-queries-DOZR-D8G.js +0 -2
  371. package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js +0 -2
  372. package/dist/core/web/public/next/assets/dock-panes-UKS-mXhr.js.map +0 -1
  373. package/dist/core/web/public/next/assets/fleet-queries-BSdRlUwJ.js +0 -2
  374. package/dist/core/web/public/next/assets/git-model-CivuBY_D.js +0 -5
  375. package/dist/core/web/public/next/assets/global-Di2PUgj4.js +0 -2
  376. package/dist/core/web/public/next/assets/global-Di2PUgj4.js.map +0 -1
  377. package/dist/core/web/public/next/assets/global-_tOCFt9y.css +0 -1
  378. package/dist/core/web/public/next/assets/guarded-action-CvOHcqyH.js +0 -2
  379. package/dist/core/web/public/next/assets/guarded-action-CvOHcqyH.js.map +0 -1
  380. package/dist/core/web/public/next/assets/icons-B_yuAgdN.js +0 -2
  381. package/dist/core/web/public/next/assets/icons-B_yuAgdN.js.map +0 -1
  382. package/dist/core/web/public/next/assets/mutations-Dpsql5t7.js +0 -2
  383. package/dist/core/web/public/next/assets/overnight-queries-X-44Gsw5.js +0 -2
  384. package/dist/core/web/public/next/assets/primitives-BDIcUvob.js +0 -1
  385. package/dist/core/web/public/next/assets/reasoning-pref-B9-DJUXP.js +0 -2
  386. package/dist/core/web/public/next/assets/seat-subscription-CH6fW4fJ.js +0 -2
  387. package/dist/core/web/public/next/assets/slots-Ds9ZIqUL.js +0 -3
  388. package/dist/core/web/public/next/assets/surface-data-J52iIGMD.js +0 -2
  389. package/dist/core/web/public/next/assets/surface-prefetch-CgZ-LEJK.js +0 -2
  390. package/dist/core/web/public/next/assets/use-guarded-action-C2HlSzkz.js +0 -2
  391. package/dist/core/web/public/next/assets/use-token-gate-B3IJL6bf.js +0 -2
  392. package/dist/core/web/public/next/assets/useActivity-Bk3XgXjL.js +0 -2
  393. package/dist/core/web/public/next/assets/useActivity-Bk3XgXjL.js.map +0 -1
  394. package/dist/core/web/public/next/assets/useChartWidth-BAtVgn2n.css +0 -1
  395. package/dist/core/web/public/next/assets/useChartWidth-lZ9PrQn0.js +0 -2
  396. package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js +0 -2
  397. package/dist/core/web/public/next/assets/verse-model-D7NZQFAR.js.map +0 -1
  398. package/dist/core/web/public/next/assets/verse-queries-DvIJcn6Z.js +0 -2
  399. package/dist/core/web/public/next/assets/verse-queries-DvIJcn6Z.js.map +0 -1
  400. package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js +0 -3
  401. package/dist/core/web/public/next/assets/verse-store-DjBWj04q.js.map +0 -1
  402. package/dist/core/web/public/next/assets/verse-ui-store-zafyzXKD.js +0 -3
  403. package/dist/core/web/public/next/assets/warmup-BR6pxAKs.js +0 -3
@@ -0,0 +1,2 @@
1
+ import{a as e,i as t,n,s as r}from"./index-BVxOlseC.js";import{m as i,p as a}from"./global-oEl9Qj8u.js";import{t as o}from"./focus-trap-HtcoXeEq.js";import{c as s,s as c}from"./command-catalog-Bb_PxC5w.js";import{i as l,r as u}from"./guarded-action-OzqcPjmh.js";import{C as d}from"./verse-ui-store-62DxpVHS.js";import{r as f}from"./section-visibility-Yctxu-if.js";import{E as p,G as m,H as h,U as g,Z as _,z as v}from"./VerseConsoleApp-DTjDpGCd.js";import{v as y}from"./format-BkWdOQDL.js";import{a as b,i as x,t as S}from"./CapacityStrip-qReu0RaF.js";import{a as C,i as ee,o as te}from"./useSeatsRefresh-DgFy-Ph4.js";import{l as w,n as ne,o as re,r as ie,t as T}from"./capacity-strip-model-BDbmQ3e3.js";import{n as E,t as D}from"./Button-HHXgoXGr.js";import{c as O,g as ae,x as oe}from"./icons-DEQa2rTx.js";import{a as k,i as A}from"./fleet-queries-DzGoqq8X.js";import{a as j,s as M}from"./usage-queries-BZuAANlI.js";import{t as N}from"./local-model-DFyjKX0b.js";import{a as P,i as F,n as I,o as L,r as R}from"./ResourcesChrome-BJCauW_t.js";import{t as z}from"./apps-model-CDFvmsQV.js";var B=r(e(),1),se=r(t(),1),V={backdrop:`_backdrop_ldzh8_8`,fade:`_fade_ldzh8_1`,panel:`_panel_ldzh8_18`,slide:`_slide_ldzh8_1`,head:`_head_ldzh8_49`,headText:`_headText_ldzh8_60`,title:`_title_ldzh8_67`,headline:`_headline_ldzh8_76`,headActions:`_headActions_ldzh8_83`,body:`_body_ldzh8_92`,group:`_group_ldzh8_100`,groupTitle:`_groupTitle_ldzh8_102`,cards:`_cards_ldzh8_113`,card:`_card_ldzh8_113`,cardHead:`_cardHead_ldzh8_138`,cardName:`_cardName_ldzh8_145`,plan:`_plan_ldzh8_157`,status:`_status_ldzh8_165`,statusDot:`_statusDot_ldzh8_180`,statusLabel:`_statusLabel_ldzh8_192`,statusDetail:`_statusDetail_ldzh8_197`,stamp:`_stamp_ldzh8_199`,subtle:`_subtle_ldzh8_200`,fine:`_fine_ldzh8_201`,reserveLine:`_reserveLine_ldzh8_202`,meters:`_meters_ldzh8_214`,meter:`_meter_ldzh8_214`,meterLabel:`_meterLabel_ldzh8_236`,meterTrack:`_meterTrack_ldzh8_243`,meterFill:`_meterFill_ldzh8_257`,meterReserve:`_meterReserve_ldzh8_266`,meterTick:`_meterTick_ldzh8_276`,meterValue:`_meterValue_ldzh8_284`,meterReset:`_meterReset_ldzh8_293`,cardActions:`_cardActions_ldzh8_301`,note:`_note_ldzh8_308`,pill:`_pill_ldzh8_316`,runtime:`_runtime_ldzh8_334`,runtimeHead:`_runtimeHead_ldzh8_343`,runtimeName:`_runtimeName_ldzh8_351`,models:`_models_ldzh8_353`,model:`_model_ldzh8_353`,modelName:`_modelName_ldzh8_373`,modelFacts:`_modelFacts_ldzh8_380`,creditsHead:`_creditsHead_ldzh8_392`,creditsAmount:`_creditsAmount_ldzh8_400`,external:`_external_ldzh8_410`,foot:`_foot_ldzh8_428`,linkButton:`_linkButton_ldzh8_435`,visuallyHidden:`_visuallyHidden_ldzh8_450`},H=n(),U=20;function W({credits:e}){let t=e.remainingPercent,n=t<=0?`limit`:t<U?`tight`:`ok`,r=`${F(e.remainingUsd)} of ${F(e.totalUsd)} left`,i=[`${e.running} running`,e.maxSessionsPerDay===null?`${e.sessionsToday} today`:`${e.sessionsToday} of ${e.maxSessionsPerDay} today`].join(` · `),a=e.seatReady?e.canLaunch?null:e.canLaunchReason:e.seatReason;return(0,H.jsxs)(H.Fragment,{children:[(0,H.jsxs)(`p`,{className:V.creditsHead,children:[(0,H.jsx)(`span`,{className:V.creditsAmount,children:r}),(0,H.jsx)(`span`,{className:V.pill,"data-tone":`neutral`,title:e.estimateNote,children:`estimate`})]}),(0,H.jsxs)(`div`,{className:V.meter,"data-level":n,"data-single":!0,children:[(0,H.jsx)(`span`,{className:V.meterTrack,role:`img`,"aria-label":`Cloud credits: an estimated ${F(e.remainingUsd)} of ${F(e.totalUsd)} left, ${p(t)}`,children:(0,H.jsx)(`span`,{className:V.meterFill,"data-kind":`left`,style:{width:`${Math.round(t)}%`}})}),(0,H.jsxs)(`span`,{className:V.meterValue,"aria-hidden":`true`,children:[p(t),` left`]})]}),(0,H.jsx)(`p`,{className:V.subtle,children:i}),a===null?null:(0,H.jsxs)(`p`,{className:V.status,"data-tone":`warning`,children:[(0,H.jsx)(`span`,{className:V.statusDot,"aria-hidden":`true`}),(0,H.jsx)(`span`,{children:a})]}),(0,H.jsx)(`p`,{className:V.fine,children:e.estimateNote}),(0,H.jsxs)(`a`,{className:V.external,href:e.balanceUrl,target:`_blank`,rel:`noopener noreferrer`,children:[`Real balance on claude.ai`,(0,H.jsx)(O,{}),(0,H.jsx)(`span`,{className:V.visuallyHidden,children:` (opens in a new tab)`})]})]})}function ce(){let e=a(R),t=i(R);f(t,I.cloud);let n=e.data===void 0&&e.status!==`error`,r=e.data?.available??!1,o=e.data?.credits??null;return(0,H.jsxs)(`li`,{className:V.card,"data-resource":`cloud`,"data-cloud":n?`loading`:r?o?`ready`:`unrecognised`:`unavailable`,children:[(0,H.jsxs)(`div`,{className:V.cardHead,children:[(0,H.jsx)(b,{monogram:`C`,engine:`claude`,size:`sm`}),(0,H.jsxs)(`h4`,{className:V.cardName,children:[(0,H.jsx)(`span`,{children:`Claude cloud credits`}),(0,H.jsx)(`span`,{className:V.plan,children:`claude.ai`})]})]}),n?(0,H.jsx)(`p`,{className:V.subtle,"aria-busy":`true`,children:`Reading cloud credits…`}):r?o===null?(0,H.jsx)(`p`,{className:V.subtle,children:`The cloud lane answered in a shape this drawer does not recognise, so nothing is shown rather than guessed.`}):(0,H.jsx)(W,{credits:o}):(0,H.jsxs)(H.Fragment,{children:[(0,H.jsxs)(`p`,{className:V.status,"data-tone":`neutral`,children:[(0,H.jsx)(`span`,{className:V.statusDot,"aria-hidden":`true`}),(0,H.jsx)(`span`,{className:V.statusLabel,children:`Cloud lane not available yet`})]}),(0,H.jsx)(`p`,{className:V.fine,children:`Credits show here once this build has the cloud lane.`})]})]})}var G=90,K={"all-in":`all-in mode`,balanced:`balanced mode`,reserve:`reserve mode`};function q(e){return Math.max(0,Math.min(100,Math.round(e)))}function J({status:e}){let t=[e.detail,e.usableAgain].filter(e=>e!==null&&e.length>0),n=[e.label,...t].join(` · `);return(0,H.jsxs)(`p`,{className:V.status,"data-tone":e.tone,"data-status":e.kind,title:n,children:[(0,H.jsx)(`span`,{className:V.statusDot,"aria-hidden":`true`}),(0,H.jsxs)(`span`,{children:[(0,H.jsx)(`span`,{className:V.statusLabel,children:e.label}),t.map(e=>(0,H.jsx)(`span`,{className:V.statusDetail,children:` · ${e}`},e))]})]})}function Y({row:e,w:t,reservePercent:n}){let r=w(e,t,t.binding?n:null),i=t.binding&&n!==null&&n>0?100-q(n):null,a=t.label.replace(/ window$/,``),o,s,c=0;return t.limitReached?(o=`limit`,s=`limit reached`,c=100):t.usedPercent===null?(o=`unknown`,s=`no reading`):(c=q(t.usedPercent),o=c>=G?`tight`:`ok`,s=p(t.usedPercent)),(0,H.jsxs)(`div`,{className:V.meter,"data-binding":t.binding||void 0,"data-level":o,children:[(0,H.jsx)(`span`,{className:V.meterLabel,title:t.label,children:a.charAt(0).toUpperCase()+a.slice(1)}),(0,H.jsxs)(`span`,{className:V.meterTrack,role:`img`,"aria-label":r,"data-unknown":o===`unknown`||void 0,children:[i===null?null:(0,H.jsx)(`span`,{className:V.meterReserve,style:{left:`${i}%`,width:`${100-i}%`}}),o===`unknown`?null:(0,H.jsx)(`span`,{className:V.meterFill,style:{width:`${c}%`}}),i===null?null:(0,H.jsx)(`span`,{className:V.meterTick,style:{left:`${i}%`}})]}),(0,H.jsx)(`span`,{className:V.meterValue,"aria-hidden":`true`,children:s}),t.resetText===null?null:(0,H.jsx)(`span`,{className:V.meterReset,title:t.resetText,"aria-hidden":`true`,children:t.resetText})]})}function le({row:e,status:t,settled:n,mode:r,busy:i,onAction:a}){let o=z(e,n).filter(e=>e.kind!==`edit-budget`),s=e.reserve,c=s===null?null:s.percent!==null&&r!==null?`${s.label} · ${K[r]}`:s.label;return(0,H.jsxs)(`li`,{className:V.card,"data-status":t.kind,"data-seat":e.seatId,"data-verse-anchor":`resources:${e.seatId}`,children:[(0,H.jsxs)(`div`,{className:V.cardHead,children:[(0,H.jsx)(b,{monogram:e.monogram,engine:e.engine,size:`sm`}),(0,H.jsxs)(`h4`,{className:V.cardName,children:[(0,H.jsx)(`span`,{title:e.label,children:e.label}),e.plan===null?null:(0,H.jsx)(`span`,{className:V.plan,children:e.plan})]})]}),(0,H.jsx)(J,{status:t}),t.checked===null?null:(0,H.jsx)(`p`,{className:V.stamp,title:t.checkedTitle??void 0,children:t.checked}),e.windows.length>0?(0,H.jsx)(`div`,{className:V.meters,children:e.windows.map(t=>(0,H.jsx)(Y,{row:e,w:t,reservePercent:s?.percent??null},t.id))}):null,c!==null||e.credits!==null?(0,H.jsxs)(`p`,{className:V.reserveLine,children:[c===null?null:(0,H.jsx)(`span`,{title:s?.why,children:c}),c!==null&&e.credits!==null?` · `:null,e.credits===null?null:(0,H.jsx)(`span`,{children:e.credits})]}):null,o.length>0?(0,H.jsx)(`div`,{className:V.cardActions,children:o.map(t=>(0,H.jsx)(D,{size:`sm`,variant:t.primary?`primary`:`ghost`,busy:i?.seatId===e.seatId&&i.kind===t.kind,"aria-label":`${t.kind===`fix`?`Fix in Apps`:t.label}: ${e.label}`,onClick:()=>a(e,t),children:t.kind===`fix`?`Fix in Apps`:t.label},t.kind))}):null]})}var X=`Every local agent turn in flight is answered by this process. Stopping it ends those turns — nothing in flight is rolled back, and no local seat can take a new turn until it is running again.`;function ue({status:e,onOpenUsage:t,now:n}){let r=a(j),o=a(k),s=i(j),c=i(k);f(s,I.local),f(c,I.runtime);let[u,d]=(0,B.useState)(null),[p,m]=(0,B.useState)(null),h=r.data?.available?N(M(r.data.raw),n):null,g=L(o.data?.value??null),_=r.data===void 0&&r.status!==`error`,v=h?.rows??[],x=v.slice(0,6),S=v.length-x.length,C=e=>{let t=e===`start`?`Start`:`Stop`;d(null),l({title:`Stop the serving runtime?`,body:X,confirmLabel:`Stop runtime`,destructive:!0,skipConfirm:e===`start`,token:!0,tokenReason:`${t===`Start`?`Starting`:`Stopping`} the serving runtime requires the dispatch token.`,run:async()=>{m(e);try{let t=await A(e);d({tone:`neutral`,text:(t.note?y(t.note):``)||(e===`start`?`Runtime starting.`:`Runtime stopped.`)})}finally{m(null)}},onError:e=>d({tone:`danger`,text:e})})};return(0,H.jsxs)(`li`,{className:V.card,"data-resource":`local`,"data-status":e?.kind,children:[(0,H.jsxs)(`div`,{className:V.cardHead,children:[(0,H.jsx)(b,{monogram:`L`,engine:`local`,size:`sm`}),(0,H.jsxs)(`h4`,{className:V.cardName,children:[(0,H.jsx)(`span`,{children:`Local models`}),(0,H.jsx)(`span`,{className:V.plan,children:`this machine`})]})]}),e===null?h!==null&&!h.reachable?(0,H.jsxs)(`p`,{className:V.status,"data-tone":`neutral`,children:[(0,H.jsx)(`span`,{className:V.statusDot,"aria-hidden":`true`}),(0,H.jsx)(`span`,{className:V.statusLabel,children:`No local runtime answering`})]}):null:(0,H.jsx)(J,{status:e}),g===null?null:(0,H.jsxs)(`div`,{className:V.runtime,"data-runtime-state":g.state,children:[(0,H.jsxs)(`p`,{className:V.runtimeHead,children:[(0,H.jsx)(`span`,{className:V.runtimeName,children:g.name}),(0,H.jsx)(`span`,{className:V.pill,"data-tone":g.tone,children:g.word})]}),g.detail===null?null:(0,H.jsx)(`p`,{className:V.subtle,title:g.detail,children:g.detail}),g.canStart||g.canStop?(0,H.jsxs)(`div`,{className:V.cardActions,children:[g.canStart?(0,H.jsx)(D,{size:`sm`,variant:`primary`,busy:p===`start`,"aria-label":`Start ${g.name}`,onClick:()=>C(`start`),children:`Start`}):null,g.canStop?(0,H.jsx)(D,{size:`sm`,variant:`subtle`,busy:p===`stop`,"aria-label":`Stop ${g.name}`,onClick:()=>C(`stop`),children:`Stop`}):null]}):g.managedElsewhere?(0,H.jsx)(`p`,{className:V.subtle,children:`Started and stopped outside Verse.`}):null]}),_?(0,H.jsx)(`p`,{className:V.subtle,"aria-busy":`true`,children:`Reading local models…`}):r.data?.available?h===null||v.length===0?(0,H.jsx)(`p`,{className:V.subtle,children:h?.reachable?`No models installed.`:`Start Ollama or llama-server to use local models.`}):(0,H.jsx)(`ul`,{className:V.models,"aria-label":`Local models`,children:x.map(e=>{let t=P(e);return(0,H.jsxs)(`li`,{className:V.model,"data-resident":e.resident||void 0,children:[(0,H.jsx)(`span`,{className:V.modelName,title:e.name,children:e.name}),(0,H.jsxs)(`span`,{className:V.modelFacts,children:[e.resident?(0,H.jsx)(`span`,{className:V.pill,"data-tone":`success`,children:`Loaded`}):null,t===null?null:(0,H.jsx)(`span`,{title:e.contextTruncated?`Configured below the model’s native window`:void 0,children:t})]})]},`${e.runtime??`local`}:${e.name}`)})}):(0,H.jsx)(`p`,{className:V.subtle,children:`Local model details are not available from this server yet.`}),S>0?(0,H.jsx)(`button`,{type:`button`,className:V.linkButton,onClick:t,children:`${S} more in Usage`}):null,(0,H.jsx)(`p`,{className:u?V.note:V.visuallyHidden,"data-tone":u?.tone,role:`status`,"aria-live":`polite`,children:u?.text??``})]})}var Z=`No accounts connected yet. Sign in to Claude Code, Codex or Grok in a terminal — they show up here within a minute.`;function de({pinned:e}){return(0,H.jsxs)(`svg`,{width:`16`,height:`16`,viewBox:`0 0 16 16`,fill:e?`currentColor`:`none`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinejoin:`round`,strokeLinecap:`round`,"aria-hidden":`true`,focusable:`false`,children:[(0,H.jsx)(`path`,{d:`M6 2.5h4l-.5 4 2.25 2.25H4.25L6.5 6.5z`}),(0,H.jsx)(`path`,{d:`M8 8.75v4.75`,fill:`none`})]})}function Q({mode:e,compact:t=!1,now:n}){let r=(0,B.useId)(),a=(0,B.useRef)(null),p=e===`overlay`,m=x(),[h,y]=(0,B.useState)(()=>Date.now());f(()=>y(Date.now()),S,{enabled:n===void 0});let b=n??h,w=m.health!==null,[D,O]=(0,B.useState)(null),[A,M]=(0,B.useState)(null),N=i(te),P=i(j),F=i(k),I=i(R),L=(0,B.useMemo)(()=>ne(m.seats,{health:m.health,budget:m.budget,now:b}),[m.seats,m.health,m.budget,b]),z=(0,B.useMemo)(()=>re(L.filter(e=>e.kind===`subscription`),{healthRead:w,now:b}),[L,w,b]),U=L.find(e=>e.kind===`local`)??null,W=m.budget?.mode??null,G=(0,B.useCallback)(()=>{v()},[]),K=(0,B.useCallback)(()=>{u()||document.querySelector(`[aria-modal="true"]:not([data-verse-overlay])`)||v()},[]);o({open:p,containerRef:a,onClose:K}),(0,B.useEffect)(()=>{if(p)return()=>{window.setTimeout(()=>{let e=document.activeElement;(e===null||e===document.body)&&document.querySelector(`[data-resources-handle]`)?.focus({preventScroll:!0})},0)}},[p]);let q=(e,t=null)=>{p&&v(),d(e,t)},J=(e,t)=>{if(M(null),t.kind===`fix`||t.kind===`edit-budget`){q(`apps`,`seat:${e.seatId}`);return}let n=t.kind===`reconnect`;l({title:n?`Reconnect ${e.label}?`:`Check ${e.label} again?`,body:``,confirmLabel:t.label,destructive:!1,skipConfirm:!0,token:!0,tokenReason:n?`Open the sign-in for ${e.label} in Terminal`:`Check ${e.label} again (status commands only — nothing is spent)`,run:async()=>{O({seatId:e.seatId,kind:t.kind});try{n?await ee(e.seatId):await C()}finally{O(null)}},onDone:()=>M({tone:`neutral`,text:n?`Opened the sign-in for ${e.label} in Terminal. Finish it there; this drawer picks it up.`:`Checked ${e.label} again.`}),onError:e=>M({tone:`danger`,text:e})})},Y=()=>{M(null),N(),P(),F(),I(),y(Date.now())},X=c(`resources.toggle`)?.keys[0],Q=X?s(X):void 0,pe=!t,$=e===`docked`,me=(0,H.jsxs)(`div`,{ref:a,className:V.panel,"data-mode":e,"data-presentation":t?`full`:`side`,"data-verse-overlay":`resources`,...p?{role:`dialog`,"aria-modal":!0,"aria-labelledby":r,tabIndex:-1}:{role:`complementary`,"aria-labelledby":r},children:[(0,H.jsxs)(`header`,{className:V.head,children:[(0,H.jsxs)(`div`,{className:V.headText,children:[(0,H.jsx)(`h2`,{id:r,className:V.title,children:`Resources`}),!m.loading&&L.length>0?(0,H.jsx)(`p`,{className:V.headline,children:ie(L)}):null]}),(0,H.jsxs)(`div`,{className:V.headActions,children:[(0,H.jsx)(_,{label:`Read everything again`,placement:`bottom`,children:(0,H.jsx)(E,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(ae,{}),"aria-label":`Read everything again`,onClick:Y})}),pe?(0,H.jsx)(_,{label:$?`Unpin — float over the page`:`Pin beside the page`,placement:`bottom`,children:(0,H.jsx)(E,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(de,{pinned:$}),"aria-label":$?`Unpin resources`:`Pin resources beside the page`,"aria-pressed":$,"data-resources-pin":!0,onClick:()=>g(!$)})}):null,(0,H.jsx)(_,{label:`Close resources`,shortcut:Q,placement:`bottom`,children:(0,H.jsx)(E,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(oe,{}),"aria-label":`Close resources`,onClick:G})})]})]}),(0,H.jsxs)(`div`,{className:V.body,children:[(0,H.jsxs)(`section`,{className:V.group,"aria-labelledby":`${r}-accounts`,children:[(0,H.jsx)(`h3`,{id:`${r}-accounts`,className:V.groupTitle,children:`Accounts`}),m.loading?(0,H.jsx)(`p`,{className:V.subtle,"aria-busy":`true`,children:`Reading accounts…`}):z.length===0?(0,H.jsx)(`p`,{className:V.subtle,children:Z}):(0,H.jsx)(`ul`,{className:V.cards,children:z.map(e=>{let t=T(e,{healthRead:w,now:b}),n=D?.seatId===e.seatId&&D.kind===`check-again`?T(e,{healthRead:w,now:b,checking:!0}):t;return(0,H.jsx)(le,{row:e,status:n,settled:t,mode:W,busy:D,onAction:J},e.seatId)})}),(0,H.jsx)(`p`,{className:A?V.note:V.visuallyHidden,"data-tone":A?.tone,role:`status`,"aria-live":`polite`,children:A?.text??``})]}),(0,H.jsxs)(`section`,{className:V.group,"aria-labelledby":`${r}-local`,children:[(0,H.jsx)(`h3`,{id:`${r}-local`,className:V.groupTitle,children:`Local`}),(0,H.jsx)(`ul`,{className:V.cards,children:(0,H.jsx)(ue,{status:U?T(U,{healthRead:w,now:b}):null,onOpenUsage:()=>q(`usage`),now:b})})]}),(0,H.jsxs)(`section`,{className:V.group,"aria-labelledby":`${r}-cloud`,children:[(0,H.jsx)(`h3`,{id:`${r}-cloud`,className:V.groupTitle,children:`Cloud`}),(0,H.jsx)(`ul`,{className:V.cards,children:(0,H.jsx)(ce,{})})]})]}),(0,H.jsxs)(`footer`,{className:V.foot,children:[(0,H.jsx)(`button`,{type:`button`,className:V.linkButton,onClick:()=>q(`apps`),children:`Apps & Accounts`}),(0,H.jsx)(`button`,{type:`button`,className:V.linkButton,onClick:()=>q(`usage`),children:`Usage`}),(0,H.jsx)(fe,{})]})]});return p?(0,se.createPortal)((0,H.jsx)(`div`,{className:V.backdrop,"data-presentation":t?`full`:`side`,onMouseDown:e=>e.target===e.currentTarget&&G(),children:me}),document.body):me}function fe(){let{bar:e}=m();return(0,H.jsx)(`button`,{type:`button`,className:V.linkButton,style:{marginLeft:`auto`},"aria-pressed":e,onClick:()=>h(!e),children:e?`Hide resource bar`:`Show resource bar`})}export{Z as RESOURCES_EMPTY_TEXT,Q as ResourcesDrawer};
2
+ //# sourceMappingURL=ResourcesDrawer-BDecg6nO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourcesDrawer-BDecg6nO.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/resources/ResourcesDrawer.module.css","../../../../../../src/web-ui/routes/verse/resources/CloudCredits.tsx","../../../../../../src/web-ui/routes/verse/resources/ResourceCard.tsx","../../../../../../src/web-ui/routes/verse/resources/LocalResources.tsx","../../../../../../src/web-ui/routes/verse/resources/ResourcesDrawer.tsx"],"sourcesContent":["/* Resources — a 360px right-hand panel: over the surface (overlay) or beside\n it (docked). Tokens only, so light and dark follow the theme. Cards are\n hairline-separated blocks on the surface; state is a WORD first, a shape\n second, colour last. */\n\n/* ── Overlay chrome ─────────────────────────────────────────────────── */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: var(--z-overlay);\n display: flex;\n justify-content: flex-end;\n background: color-mix(in srgb, var(--bg-overlay) 55%, transparent);\n animation: fade var(--duration-fast) var(--ease-standard);\n}\n\n.panel {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n background: var(--bg-surface);\n color: var(--text-primary);\n font-family: var(--font-ui);\n outline: none;\n}\n\n.panel[data-mode='overlay'] {\n width: min(360px, calc(100vw - var(--space-8)));\n border-left: 1px solid var(--border-default);\n box-shadow: var(--shadow-dialog);\n animation: slide var(--duration-base) var(--ease-decelerate);\n}\n\n.panel[data-mode='overlay'][data-presentation='full'] {\n width: 100%;\n border-left: 0;\n}\n\n/* Docked: the shell gives it a grid track; it fills that track. */\n.panel[data-mode='docked'] {\n width: 100%;\n border-left: 1px solid var(--border-subtle);\n}\n\n/* ── Head ───────────────────────────────────────────────────────────── */\n\n.head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--space-3);\n min-height: var(--strip-height);\n /* Clear the desktop title bar (0px in a browser), like the rail. */\n padding: calc(var(--space-3) + var(--app-titlebar-height, 0px)) var(--space-3) var(--space-3) var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.headText {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-display);\n}\n\n.headline {\n margin: 0;\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.headActions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex: none;\n}\n\n/* ── Body ───────────────────────────────────────────────────────────── */\n\n.body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--space-2) var(--space-3) var(--space-4);\n}\n\n.group + .group { margin-top: var(--space-4); }\n\n.groupTitle {\n margin: var(--space-2) var(--space-1) var(--space-2);\n color: var(--text-tertiary);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n}\n\n.cards {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n padding: var(--space-3);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n /* The panel's own ground: tertiary text is certified AA on --bg-surface in\n both themes (tokens-contrast.test.ts), not on the raised ground. */\n background: var(--bg-surface);\n /* Never break inside a word; long names wrap at spaces and carry a tooltip. */\n overflow-wrap: normal;\n word-break: normal;\n hyphens: none;\n}\n\n.cardHead {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n}\n\n.cardName {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: var(--space-2);\n min-width: 0;\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n}\n\n.plan {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-regular);\n}\n\n/* ── Status ─────────────────────────────────────────────────────────── */\n\n.status {\n --tone: var(--status-neutral-solid);\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n margin: var(--space-1) 0 0;\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.status[data-tone='success'] { --tone: var(--status-success-solid); }\n.status[data-tone='warning'] { --tone: var(--status-warning-solid); }\n.status[data-tone='danger'] { --tone: var(--status-danger-solid); }\n\n/* Shape follows the tone: a disc when fine, a ring when tight, a diamond when blocked. */\n.statusDot {\n flex: none;\n width: 7px;\n height: 7px;\n border-radius: var(--radius-full);\n background: var(--tone);\n transform: translateY(-1px);\n}\n.status[data-tone='warning'] .statusDot { background: transparent; border: 2px solid var(--tone); }\n.status[data-tone='danger'] .statusDot { border-radius: 1px; transform: translateY(-1px) rotate(45deg) scale(0.9); }\n.status[data-tone='neutral'] .statusDot { background: transparent; border: 1.5px dashed var(--text-tertiary); }\n\n.statusLabel {\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n\n.statusDetail { white-space: normal; }\n\n.stamp,\n.subtle,\n.fine,\n.reserveLine {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n.stamp { padding-left: calc(7px + var(--space-2)); }\n.subtle { color: var(--text-secondary); }\n.reserveLine { margin-top: var(--space-1); color: var(--text-secondary); }\n\n/* ── Window meters ──────────────────────────────────────────────────── */\n\n.meters,\n.meter[data-single] {\n display: grid;\n align-items: center;\n column-gap: var(--space-2);\n row-gap: 2px;\n margin-top: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n/* One grid for all of a card's windows, so the tracks line up under the\n longest label (\"Weekly fable\") instead of wrapping it. */\n.meters { grid-template-columns: max-content minmax(0, 1fr) auto; }\n.meter[data-single] { grid-template-columns: minmax(0, 1fr) auto; }\n\n.meter {\n --fill: var(--data-seq-5);\n display: contents;\n}\n.meter[data-level='tight'] { --fill: var(--status-warning-solid); }\n.meter[data-level='limit'] { --fill: var(--status-danger-solid); }\n\n.meterLabel {\n grid-column: 1;\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.meter[data-binding] .meterLabel { color: var(--text-primary); font-weight: var(--font-weight-medium); }\n\n.meterTrack {\n position: relative;\n display: block;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--meter-track);\n overflow: hidden;\n}\n/* No reading: absence drawn as absence (a dashed outline), never a 0% bar. */\n.meterTrack[data-unknown] {\n background: transparent;\n border: 1px dashed var(--border-strong);\n}\n\n.meterFill {\n position: absolute;\n inset: 0 auto 0 0;\n border-radius: inherit;\n background: var(--fill);\n transition: width var(--duration-slow) var(--ease-standard);\n}\n\n/* The band kept for the operator, past a tick at 100 − reserve. */\n.meterReserve {\n position: absolute;\n top: 0;\n bottom: 0;\n background: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--text-tertiary) 30%, transparent) 0 2px,\n transparent 2px 4px\n );\n}\n.meterTick {\n position: absolute;\n top: -1px;\n bottom: -1px;\n width: 1.5px;\n background: var(--text-secondary);\n}\n\n.meterValue {\n color: var(--text-primary);\n font-variant-numeric: tabular-nums;\n text-align: right;\n white-space: nowrap;\n}\n.meter[data-level='limit'] .meterValue { font-weight: var(--font-weight-semibold); }\n.meter[data-level='unknown'] .meterValue { color: var(--text-tertiary); }\n\n.meterReset {\n grid-column: 2 / 4;\n margin-bottom: var(--space-1);\n color: var(--text-tertiary);\n}\n\n/* ── Actions and notes ──────────────────────────────────────────────── */\n\n.cardActions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2);\n margin-top: var(--space-2);\n}\n\n.note {\n margin: var(--space-2) var(--space-1) 0;\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n.note[data-tone='danger'] { color: var(--text-primary); font-weight: var(--font-weight-medium); }\n\n.pill {\n display: inline-flex;\n align-items: center;\n flex: none;\n padding: 0 var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-neutral-bg);\n color: var(--status-neutral-fg);\n font-size: var(--text-2xs-size);\n line-height: 18px;\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n}\n.pill[data-tone='success'] { background: var(--status-success-bg); color: var(--status-success-fg); }\n.pill[data-tone='warning'] { background: var(--status-warning-bg); color: var(--status-warning-fg); }\n\n/* ── Local ──────────────────────────────────────────────────────────── */\n\n.runtime {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: var(--space-2);\n padding-top: var(--space-2);\n border-top: 1px solid var(--border-subtle);\n}\n\n.runtimeHead {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n margin: 0;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.runtimeName { font-weight: var(--font-weight-medium); }\n\n.models {\n display: flex;\n flex-direction: column;\n margin: var(--space-2) 0 0;\n padding: var(--space-1) 0 0;\n border-top: 1px solid var(--border-subtle);\n list-style: none;\n}\n\n.model {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n column-gap: var(--space-3);\n padding: var(--space-1) 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.modelName {\n min-width: 0;\n font-family: var(--font-mono);\n color: var(--text-primary);\n overflow-wrap: anywhere; /* model tags have no spaces; break at any point rather than overflow */\n}\n\n.modelFacts {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n margin-left: auto;\n color: var(--text-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n/* ── Cloud ──────────────────────────────────────────────────────────── */\n\n.creditsHead {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n margin: var(--space-1) 0 0;\n}\n\n.creditsAmount {\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n font-variant-numeric: tabular-nums;\n}\n\n.meterFill[data-kind='left'] { background: var(--fill); }\n\n.external {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n align-self: flex-start;\n margin-top: var(--space-1);\n color: var(--text-link);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n text-decoration: none;\n border-radius: var(--radius-xs);\n}\n.external:hover { text-decoration: underline; }\n.external:focus-visible { outline: none; box-shadow: var(--shadow-focus-ring); }\n.external svg { width: 12px; height: 12px; }\n\n/* ── Foot ───────────────────────────────────────────────────────────── */\n\n.foot {\n display: flex;\n gap: var(--space-4);\n padding: var(--space-2) var(--space-4);\n border-top: 1px solid var(--border-subtle);\n}\n\n.linkButton {\n align-self: flex-start;\n padding: 2px 0;\n border: 0;\n border-radius: var(--radius-xs);\n background: none;\n color: var(--text-link);\n font: inherit;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n cursor: pointer;\n}\n.linkButton:hover { text-decoration: underline; }\n.linkButton:focus-visible { outline: none; box-shadow: var(--shadow-focus-ring); }\n\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* ── Motion ─────────────────────────────────────────────────────────── */\n\n@keyframes fade { from { opacity: 0; } }\n@keyframes slide { from { transform: translateX(100%); } }\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion='full']) .backdrop,\n :root:not([data-motion='full']) .panel { animation: none; }\n :root:not([data-motion='full']) .meterFill { transition: none; }\n}\n:root[data-motion='reduce'] .backdrop,\n:root[data-motion='reduce'] .panel { animation: none; }\n:root[data-motion='reduce'] .meterFill { transition: none; }\n","/**\n * routes/verse/resources/CloudCredits.tsx — Claude cloud credits in the\n * Resources drawer (unit 3.11 C6): estimated remaining of the total, the\n * sessions running now and launched today, and the link to the real balance\n * on claude.ai. The balance is not readable programmatically (core/cloud\n * types.ts), so every figure is labelled an ESTIMATE, with the server's own\n * note beside it.\n *\n * GET /api/verse/cloud lands with another unit; until it does, this card says\n * \"Cloud lane not available yet\" — a designed state, not an error.\n */\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { IconExternalLink } from '../../../components/primitives/icons.js';\nimport { MonogramTile } from '../apps/MonogramTile.js';\nimport { usePollWhileVisible } from '../shell/section-visibility.js';\nimport { usedPercentText } from '../percent-text.js';\nimport { formatUsd, type CloudCreditsView } from './resources-model.js';\nimport { cloudCreditsQuery, RESOURCES_POLL_MS } from './resources-queries.js';\nimport styles from './ResourcesDrawer.module.css';\n\n/** Below this share of the total left, the meter turns amber. */\nconst LOW_AT = 20;\n\nfunction Credits({ credits }: { credits: CloudCreditsView }) {\n const left = credits.remainingPercent;\n const level = left <= 0 ? 'limit' : left < LOW_AT ? 'tight' : 'ok';\n const headline = `${formatUsd(credits.remainingUsd)} of ${formatUsd(credits.totalUsd)} left`;\n const sessions = [\n `${credits.running} running`,\n credits.maxSessionsPerDay !== null ? `${credits.sessionsToday} of ${credits.maxSessionsPerDay} today` : `${credits.sessionsToday} today`,\n ].join(' · ');\n const blocker = !credits.seatReady ? credits.seatReason : !credits.canLaunch ? credits.canLaunchReason : null;\n return (\n <>\n <p className={styles.creditsHead}>\n <span className={styles.creditsAmount}>{headline}</span>\n <span className={styles.pill} data-tone=\"neutral\" title={credits.estimateNote}>estimate</span>\n </p>\n <div className={styles.meter} data-level={level} data-single>\n <span\n className={styles.meterTrack}\n role=\"img\"\n aria-label={`Cloud credits: an estimated ${formatUsd(credits.remainingUsd)} of ${formatUsd(credits.totalUsd)} left, ${usedPercentText(left)}`}\n >\n <span className={styles.meterFill} data-kind=\"left\" style={{ width: `${Math.round(left)}%` }} />\n </span>\n <span className={styles.meterValue} aria-hidden=\"true\">{usedPercentText(left)} left</span>\n </div>\n <p className={styles.subtle}>{sessions}</p>\n {blocker !== null ? (\n <p className={styles.status} data-tone=\"warning\"><span className={styles.statusDot} aria-hidden=\"true\" /><span>{blocker}</span></p>\n ) : null}\n <p className={styles.fine}>{credits.estimateNote}</p>\n <a className={styles.external} href={credits.balanceUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Real balance on claude.ai\n <IconExternalLink />\n <span className={styles.visuallyHidden}> (opens in a new tab)</span>\n </a>\n </>\n );\n}\n\nexport function CloudCredits() {\n const read = useQuery(cloudCreditsQuery);\n const refetch = useRefetch(cloudCreditsQuery);\n usePollWhileVisible(refetch, RESOURCES_POLL_MS.cloud);\n const loading = read.data === undefined && read.status !== 'error';\n const available = read.data?.available ?? false;\n const credits = read.data?.credits ?? null;\n return (\n <li className={styles.card} data-resource=\"cloud\" data-cloud={loading ? 'loading' : !available ? 'unavailable' : credits ? 'ready' : 'unrecognised'}>\n <div className={styles.cardHead}>\n <MonogramTile monogram=\"C\" engine=\"claude\" size=\"sm\" />\n <h4 className={styles.cardName}>\n <span>Claude cloud credits</span>\n <span className={styles.plan}>claude.ai</span>\n </h4>\n </div>\n {loading ? (\n <p className={styles.subtle} aria-busy=\"true\">Reading cloud credits…</p>\n ) : !available ? (\n <>\n <p className={styles.status} data-tone=\"neutral\">\n <span className={styles.statusDot} aria-hidden=\"true\" />\n <span className={styles.statusLabel}>Cloud lane not available yet</span>\n </p>\n <p className={styles.fine}>Credits show here once this build has the cloud lane.</p>\n </>\n ) : credits === null ? (\n <p className={styles.subtle}>The cloud lane answered in a shape this drawer does not recognise, so nothing is shown rather than guessed.</p>\n ) : (\n <Credits credits={credits} />\n )}\n </li>\n );\n}\n","/**\n * routes/verse/resources/ResourceCard.tsx — one paid account in the Resources\n * drawer (unit 3.11 C6):\n *\n * [C] Claude Max · max\n * ● Spent · resets Sat 11:46 PM · usable again in 1d 7h\n * checked 2m ago\n * 5-hour ▇▇▇▇▇▇▇▇▇▇▇▇│▨▨ limit reached\n * resets Sat 11:46 PM\n * Weekly ▇▇▇▇░░░░░░░░ 40%\n * Reserved for you 40% · balanced mode\n * [Check again]\n *\n * Every word comes from the shared capacity projection — `accountStatus` for\n * the status line, the row's windows for the meters (resets already worded by\n * `describeResetAt`), `usedPercentText` for every percent, `accountActions`\n * for what the account needs — so this card and Apps & Accounts can never\n * disagree about one seat. Text wraps at word boundaries; anything long also\n * carries its full text as a tooltip.\n */\nimport type { BudgetMode } from '../../../../core/routing/types.js';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { accountActions, type AccountAction } from '../apps/apps-model.js';\nimport { MonogramTile } from '../apps/MonogramTile.js';\nimport { usedPercentText } from '../percent-text.js';\nimport { windowSentence, type AccountStatus, type CapacityRow, type CapacityWindowRow } from '../usage/capacity-strip-model.js';\nimport styles from './ResourcesDrawer.module.css';\n\n/** Above this share of a window the meter turns amber (the capacity strip's own line). */\nconst TIGHT_AT = 90;\n\nconst MODE_WORD: Readonly<Record<BudgetMode, string>> = {\n 'all-in': 'all-in mode',\n balanced: 'balanced mode',\n reserve: 'reserve mode',\n};\n\nfunction clamp(n: number): number {\n return Math.max(0, Math.min(100, Math.round(n)));\n}\n\nexport function StatusLine({ status }: { status: AccountStatus }) {\n const parts = [status.detail, status.usableAgain].filter((p): p is string => p !== null && p.length > 0);\n const full = [status.label, ...parts].join(' · ');\n return (\n <p className={styles.status} data-tone={status.tone} data-status={status.kind} title={full}>\n <span className={styles.statusDot} aria-hidden=\"true\" />\n <span>\n <span className={styles.statusLabel}>{status.label}</span>\n {parts.map((p) => (\n <span key={p} className={styles.statusDetail}>{` · ${p}`}</span>\n ))}\n </span>\n </p>\n );\n}\n\nfunction WindowMeter({ row, w, reservePercent }: { row: CapacityRow; w: CapacityWindowRow; reservePercent: number | null }) {\n const sentence = windowSentence(row, w, w.binding ? reservePercent : null);\n const ceiling = w.binding && reservePercent !== null && reservePercent > 0 ? 100 - clamp(reservePercent) : null;\n const label = w.label.replace(/ window$/, '');\n let level: 'ok' | 'tight' | 'limit' | 'unknown';\n let value: string;\n let used = 0;\n if (w.limitReached) {\n level = 'limit';\n value = 'limit reached';\n used = 100;\n } else if (w.usedPercent === null) {\n level = 'unknown';\n value = 'no reading';\n } else {\n used = clamp(w.usedPercent);\n level = used >= TIGHT_AT ? 'tight' : 'ok';\n value = usedPercentText(w.usedPercent);\n }\n return (\n <div className={styles.meter} data-binding={w.binding || undefined} data-level={level}>\n <span className={styles.meterLabel} title={w.label}>{label.charAt(0).toUpperCase() + label.slice(1)}</span>\n <span className={styles.meterTrack} role=\"img\" aria-label={sentence} data-unknown={level === 'unknown' || undefined}>\n {ceiling !== null ? <span className={styles.meterReserve} style={{ left: `${ceiling}%`, width: `${100 - ceiling}%` }} /> : null}\n {level !== 'unknown' ? <span className={styles.meterFill} style={{ width: `${used}%` }} /> : null}\n {ceiling !== null ? <span className={styles.meterTick} style={{ left: `${ceiling}%` }} /> : null}\n </span>\n <span className={styles.meterValue} aria-hidden=\"true\">{value}</span>\n {w.resetText !== null ? <span className={styles.meterReset} title={w.resetText} aria-hidden=\"true\">{w.resetText}</span> : null}\n </div>\n );\n}\n\nexport interface ResourceCardProps {\n row: CapacityRow;\n /** Worded against the drawer's clock, with any running check applied. */\n status: AccountStatus;\n /** The status with no check applied, so a button does not vanish while its own check runs. */\n settled: AccountStatus;\n mode: BudgetMode | null;\n busy: { seatId: string; kind: AccountAction['kind'] } | null;\n onAction: (row: CapacityRow, action: AccountAction) => void;\n}\n\nexport function ResourceCard({ row, status, settled, mode, busy, onAction }: ResourceCardProps) {\n // Budget editing lives in Apps & Accounts; the drawer offers what the seat needs now.\n const actions = accountActions(row, settled).filter((a) => a.kind !== 'edit-budget');\n const reserve = row.reserve;\n const reserveText = reserve === null ? null : reserve.percent !== null && mode !== null ? `${reserve.label} · ${MODE_WORD[mode]}` : reserve.label;\n return (\n <li className={styles.card} data-status={status.kind} data-seat={row.seatId} data-verse-anchor={`resources:${row.seatId}`}>\n <div className={styles.cardHead}>\n <MonogramTile monogram={row.monogram} engine={row.engine} size=\"sm\" />\n <h4 className={styles.cardName}>\n <span title={row.label}>{row.label}</span>\n {row.plan !== null ? <span className={styles.plan}>{row.plan}</span> : null}\n </h4>\n </div>\n <StatusLine status={status} />\n {status.checked !== null ? (\n <p className={styles.stamp} title={status.checkedTitle ?? undefined}>{status.checked}</p>\n ) : null}\n {row.windows.length > 0 ? (\n <div className={styles.meters}>\n {row.windows.map((w) => (\n <WindowMeter key={w.id} row={row} w={w} reservePercent={reserve?.percent ?? null} />\n ))}\n </div>\n ) : null}\n {reserveText !== null || row.credits !== null ? (\n <p className={styles.reserveLine}>\n {reserveText !== null ? <span title={reserve?.why}>{reserveText}</span> : null}\n {reserveText !== null && row.credits !== null ? ' · ' : null}\n {row.credits !== null ? <span>{row.credits}</span> : null}\n </p>\n ) : null}\n {actions.length > 0 ? (\n <div className={styles.cardActions}>\n {actions.map((action) => (\n <Button\n key={action.kind}\n size=\"sm\"\n variant={action.primary ? 'primary' : 'ghost'}\n busy={busy?.seatId === row.seatId && busy.kind === action.kind}\n aria-label={`${action.kind === 'fix' ? 'Fix in Apps' : action.label}: ${row.label}`}\n onClick={() => onAction(row, action)}\n >\n {action.kind === 'fix' ? 'Fix in Apps' : action.label}\n </Button>\n ))}\n </div>\n ) : null}\n </li>\n );\n}\n","/**\n * routes/verse/resources/LocalResources.tsx — local compute in the Resources\n * drawer (unit 3.11 C6): the local seat's readiness (the shared capacity\n * projection's word), the serving runtime (llama-server / Ollama: state,\n * loaded model, per-agent context, slots) with Start / Stop when THIS server\n * supervises it, and the installed models with the context each one really\n * runs at.\n *\n * Reads are the owners' own QueryDefs — `/api/verse/local-models`\n * (usage-queries, with its burst retry) and `/api/verse/runtime`\n * (autonomy/fleet-queries) — polled only while the drawer is mounted, which\n * is only while it is open. Start / Stop go through the shell's guard (Stop\n * confirms first, both ask for the token), with the same words as the Fleet\n * runtime panel.\n */\nimport { useState } from 'react';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { runRuntimeAction, servingRuntimeQuery } from '../autonomy/fleet-queries.js';\nimport { MonogramTile } from '../apps/MonogramTile.js';\nimport { tidyProse } from '../autonomy/format.js';\nimport { requestGuarded } from '../shell/guarded-action.js';\nimport { usePollWhileVisible } from '../shell/section-visibility.js';\nimport type { AccountStatus } from '../usage/capacity-strip-model.js';\nimport { buildLocalModelsView } from '../usage/local-model.js';\nimport { projectLocalModels } from '../usage/usage-contract.js';\nimport { verseLocalModelsQuery } from '../usage/usage-queries.js';\nimport { LOCAL_MODELS_SHOWN, modelContextText, runtimeView } from './resources-model.js';\nimport { RESOURCES_POLL_MS } from './resources-queries.js';\nimport { StatusLine } from './ResourceCard.js';\nimport styles from './ResourcesDrawer.module.css';\n\nconst STOP_BODY =\n 'Every local agent turn in flight is answered by this process. Stopping it ends those turns — nothing in flight is rolled back, and no local seat can take a new turn until it is running again.';\n\nexport function LocalResources({ status, onOpenUsage, now }: { status: AccountStatus | null; onOpenUsage: () => void; now: number }) {\n const models = useQuery(verseLocalModelsQuery);\n const runtimeRead = useQuery(servingRuntimeQuery);\n const refetchModels = useRefetch(verseLocalModelsQuery);\n const refetchRuntime = useRefetch(servingRuntimeQuery);\n usePollWhileVisible(refetchModels, RESOURCES_POLL_MS.local);\n usePollWhileVisible(refetchRuntime, RESOURCES_POLL_MS.runtime);\n const [note, setNote] = useState<{ tone: 'neutral' | 'danger'; text: string } | null>(null);\n const [busy, setBusy] = useState<'start' | 'stop' | null>(null);\n\n const view = models.data?.available ? buildLocalModelsView(projectLocalModels(models.data.raw), now) : null;\n const runtime = runtimeView(runtimeRead.data?.value ?? null);\n const modelsLoading = models.data === undefined && models.status !== 'error';\n const rows = view?.rows ?? [];\n const shown = rows.slice(0, LOCAL_MODELS_SHOWN);\n const more = rows.length - shown.length;\n\n const act = (action: 'start' | 'stop') => {\n const label = action === 'start' ? 'Start' : 'Stop';\n setNote(null);\n requestGuarded({\n title: 'Stop the serving runtime?',\n body: STOP_BODY,\n confirmLabel: 'Stop runtime',\n destructive: true,\n skipConfirm: action === 'start',\n token: true,\n tokenReason: `${label === 'Start' ? 'Starting' : 'Stopping'} the serving runtime requires the dispatch token.`,\n run: async () => {\n setBusy(action);\n try {\n const result = await runRuntimeAction(action);\n setNote({ tone: 'neutral', text: (result.note ? tidyProse(result.note) : '') || (action === 'start' ? 'Runtime starting.' : 'Runtime stopped.') });\n } finally {\n setBusy(null);\n }\n },\n onError: (message) => setNote({ tone: 'danger', text: message }),\n });\n };\n\n return (\n <li className={styles.card} data-resource=\"local\" data-status={status?.kind}>\n <div className={styles.cardHead}>\n <MonogramTile monogram=\"L\" engine=\"local\" size=\"sm\" />\n <h4 className={styles.cardName}>\n <span>Local models</span>\n <span className={styles.plan}>this machine</span>\n </h4>\n </div>\n {status !== null ? (\n <StatusLine status={status} />\n ) : view !== null && !view.reachable ? (\n <p className={styles.status} data-tone=\"neutral\"><span className={styles.statusDot} aria-hidden=\"true\" /><span className={styles.statusLabel}>No local runtime answering</span></p>\n ) : null}\n\n {runtime !== null ? (\n <div className={styles.runtime} data-runtime-state={runtime.state}>\n <p className={styles.runtimeHead}>\n <span className={styles.runtimeName}>{runtime.name}</span>\n <span className={styles.pill} data-tone={runtime.tone}>{runtime.word}</span>\n </p>\n {runtime.detail !== null ? <p className={styles.subtle} title={runtime.detail}>{runtime.detail}</p> : null}\n {runtime.canStart || runtime.canStop ? (\n <div className={styles.cardActions}>\n {runtime.canStart ? (\n <Button size=\"sm\" variant=\"primary\" busy={busy === 'start'} aria-label={`Start ${runtime.name}`} onClick={() => act('start')}>Start</Button>\n ) : null}\n {runtime.canStop ? (\n <Button size=\"sm\" variant=\"subtle\" busy={busy === 'stop'} aria-label={`Stop ${runtime.name}`} onClick={() => act('stop')}>Stop</Button>\n ) : null}\n </div>\n ) : runtime.managedElsewhere ? (\n <p className={styles.subtle}>Started and stopped outside Verse.</p>\n ) : null}\n </div>\n ) : null}\n\n {modelsLoading ? (\n <p className={styles.subtle} aria-busy=\"true\">Reading local models…</p>\n ) : !models.data?.available ? (\n <p className={styles.subtle}>Local model details are not available from this server yet.</p>\n ) : view === null || rows.length === 0 ? (\n <p className={styles.subtle}>\n {view?.reachable ? 'No models installed.' : 'Start Ollama or llama-server to use local models.'}\n </p>\n ) : (\n <ul className={styles.models} aria-label=\"Local models\">\n {shown.map((m) => {\n const context = modelContextText(m);\n return (\n <li key={`${m.runtime ?? 'local'}:${m.name}`} className={styles.model} data-resident={m.resident || undefined}>\n <span className={styles.modelName} title={m.name}>{m.name}</span>\n <span className={styles.modelFacts}>\n {m.resident ? <span className={styles.pill} data-tone=\"success\">Loaded</span> : null}\n {context !== null ? <span title={m.contextTruncated ? 'Configured below the model’s native window' : undefined}>{context}</span> : null}\n </span>\n </li>\n );\n })}\n </ul>\n )}\n {more > 0 ? (\n <button type=\"button\" className={styles.linkButton} onClick={onOpenUsage}>\n {`${more} more in Usage`}\n </button>\n ) : null}\n <p className={note ? styles.note : styles.visuallyHidden} data-tone={note?.tone} role=\"status\" aria-live=\"polite\">{note?.text ?? ''}</p>\n </li>\n );\n}\n","/**\n * routes/verse/resources/ResourcesDrawer.tsx — RESOURCES: every account,\n * local runtime and cloud credit the operator can spend, on every surface\n * (unit 3.11 C6). A lazy chunk: the shell mounts it only while open.\n *\n * overlay ~360px from the right edge over the surface. Esc, a click\n * outside or ⌘. closes it; focus is trapped inside and returned\n * to whatever opened it.\n * docked PINNED: a right-hand column beside the surface (the shell gives\n * it a grid track, so the surface shrinks rather than hides).\n * Not modal — no trap, no backdrop, Esc is the surface's.\n *\n * Accounts one card per paid seat, usable first (orderAccountRows)\n * Local models the local seat, the serving runtime, installed models\n * Cloud credits GET /api/verse/cloud, or \"Cloud lane not available yet\"\n *\n * Data is the app-wide caches (useCapacityData: bootstrap seats, /health,\n * /budget) plus the owners' local and cloud reads — nothing polls unless the\n * drawer is open, because nothing here is mounted unless it is.\n *\n * Writes go through the shell's guard (confirm where the regular UI confirms,\n * then the mutation token): Reconnect opens the provider's own sign-in in\n * Terminal, Check again is the zero-cost health sweep.\n */\nimport { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { IconButton } from '../../../components/primitives/Button.js';\nimport { useFocusTrap } from '../../../components/primitives/focus-trap.js';\nimport { IconRefresh, IconX } from '../../../components/primitives/icons.js';\nimport { Tooltip } from '../../../components/primitives/Tooltip.js';\nimport { useRefetch } from '../../../data/hooks.js';\nimport type { AccountAction } from '../apps/apps-model.js';\nimport { servingRuntimeQuery } from '../autonomy/fleet-queries.js';\nimport { reconnectSeat, refreshSeatHealth, verseHealthQuery } from '../health/health-queries.js';\nimport { findCommand, formatChord } from '../shell/command-catalog.js';\nimport { isGuardOpen, requestGuarded } from '../shell/guarded-action.js';\nimport { usePollWhileVisible } from '../shell/section-visibility.js';\nimport { ACCOUNT_CLOCK_MS, useCapacityData } from '../usage/CapacityStrip.js';\nimport { accountStatus, buildCapacityRows, capacityHeadline, orderAccountRows, type CapacityRow } from '../usage/capacity-strip-model.js';\nimport { verseLocalModelsQuery } from '../usage/usage-queries.js';\nimport { setVerseSection, type VerseSectionId } from '../verse-ui-store.js';\nimport { CloudCredits } from './CloudCredits.js';\nimport { LocalResources } from './LocalResources.js';\nimport { ResourceCard } from './ResourceCard.js';\nimport { cloudCreditsQuery } from './resources-queries.js';\nimport { closeResources, setResourcesBar, setResourcesPinned, useResourcesUi } from './resources-store.js';\nimport styles from './ResourcesDrawer.module.css';\n\nexport const RESOURCES_EMPTY_TEXT =\n 'No accounts connected yet. Sign in to Claude Code, Codex or Grok in a terminal — they show up here within a minute.';\n\nfunction PinIcon({ pinned }: { pinned: boolean }) {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill={pinned ? 'currentColor' : 'none'} stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinejoin=\"round\" strokeLinecap=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M6 2.5h4l-.5 4 2.25 2.25H4.25L6.5 6.5z\" />\n <path d=\"M8 8.75v4.75\" fill=\"none\" />\n </svg>\n );\n}\n\ntype Note = { tone: 'neutral' | 'danger'; text: string } | null;\n\nexport interface ResourcesDrawerProps {\n mode: 'overlay' | 'docked';\n /** Phone-width window: the overlay takes the whole screen and cannot be pinned. */\n compact?: boolean;\n /** Injected clock for tests; otherwise the drawer re-reads the clock every ACCOUNT_CLOCK_MS. */\n now?: number;\n}\n\nexport function ResourcesDrawer({ mode, compact = false, now: fixedNow }: ResourcesDrawerProps) {\n const titleId = useId();\n const panelRef = useRef<HTMLDivElement>(null);\n const overlay = mode === 'overlay';\n const data = useCapacityData();\n const [tick, setTick] = useState(() => Date.now());\n usePollWhileVisible(() => setTick(Date.now()), ACCOUNT_CLOCK_MS, { enabled: fixedNow === undefined });\n const now = fixedNow ?? tick;\n const healthRead = data.health !== null;\n const [busy, setBusy] = useState<{ seatId: string; kind: AccountAction['kind'] } | null>(null);\n const [note, setNote] = useState<Note>(null);\n\n const refetchHealth = useRefetch(verseHealthQuery);\n const refetchLocal = useRefetch(verseLocalModelsQuery);\n const refetchRuntime = useRefetch(servingRuntimeQuery);\n const refetchCloud = useRefetch(cloudCreditsQuery);\n\n const rows = useMemo(\n () => buildCapacityRows(data.seats, { health: data.health, budget: data.budget, now }),\n [data.seats, data.health, data.budget, now],\n );\n const paid = useMemo(() => orderAccountRows(rows.filter((r) => r.kind === 'subscription'), { healthRead, now }), [rows, healthRead, now]);\n const localRow = rows.find((r) => r.kind === 'local') ?? null;\n const mode_ = data.budget?.mode ?? null;\n\n // ── close: Esc (overlay), outside click, the close button, ⌘. ─────────\n const close = useCallback(() => {\n closeResources();\n }, []);\n const trapClose = useCallback(() => {\n // Esc in a dialog opened FROM the drawer (a confirmation, the token\n // prompt) belongs to that dialog: every trap hears Escape, and this one\n // registered first.\n if (isGuardOpen() || document.querySelector('[aria-modal=\"true\"]:not([data-verse-overlay])')) return;\n closeResources();\n }, []);\n useFocusTrap({ open: overlay, containerRef: panelRef, onClose: trapClose });\n // Focus goes back to whatever opened the drawer (the trap does that). When\n // that is gone — the palette that ran \"Show resources\" unmounts — it lands\n // on the edge handle rather than on <body>.\n useEffect(() => {\n if (!overlay) return undefined;\n return () => {\n window.setTimeout(() => {\n const active = document.activeElement;\n if (active === null || active === document.body) document.querySelector<HTMLElement>('[data-resources-handle]')?.focus({ preventScroll: true });\n }, 0);\n };\n }, [overlay]);\n\n const go = (section: VerseSectionId, anchor: string | null = null) => {\n if (overlay) closeResources();\n setVerseSection(section, anchor);\n };\n\n const onAction = (row: CapacityRow, action: AccountAction) => {\n setNote(null);\n if (action.kind === 'fix' || action.kind === 'edit-budget') {\n go('apps', `seat:${row.seatId}`);\n return;\n }\n const reconnect = action.kind === 'reconnect';\n requestGuarded({\n title: reconnect ? `Reconnect ${row.label}?` : `Check ${row.label} again?`,\n body: '',\n confirmLabel: action.label,\n destructive: false,\n skipConfirm: true,\n token: true,\n tokenReason: reconnect\n ? `Open the sign-in for ${row.label} in Terminal`\n : `Check ${row.label} again (status commands only — nothing is spent)`,\n run: async () => {\n setBusy({ seatId: row.seatId, kind: action.kind });\n try {\n if (reconnect) await reconnectSeat(row.seatId);\n else await refreshSeatHealth();\n } finally {\n setBusy(null);\n }\n },\n onDone: () =>\n setNote({\n tone: 'neutral',\n text: reconnect\n ? `Opened the sign-in for ${row.label} in Terminal. Finish it there; this drawer picks it up.`\n : `Checked ${row.label} again.`,\n }),\n onError: (message) => setNote({ tone: 'danger', text: message }),\n });\n };\n\n const refreshAll = () => {\n setNote(null);\n refetchHealth();\n refetchLocal();\n refetchRuntime();\n refetchCloud();\n setTick(Date.now());\n };\n\n const chord = findCommand('resources.toggle')?.keys[0];\n const shortcut = chord ? formatChord(chord) : undefined;\n const canPin = !compact;\n const pinned = mode === 'docked';\n\n const panel = (\n <div\n ref={panelRef}\n className={styles.panel}\n data-mode={mode}\n data-presentation={compact ? 'full' : 'side'}\n data-verse-overlay=\"resources\"\n {...(overlay\n ? { role: 'dialog', 'aria-modal': true, 'aria-labelledby': titleId, tabIndex: -1 }\n : { role: 'complementary', 'aria-labelledby': titleId })}\n >\n <header className={styles.head}>\n <div className={styles.headText}>\n <h2 id={titleId} className={styles.title}>Resources</h2>\n {!data.loading && rows.length > 0 ? <p className={styles.headline}>{capacityHeadline(rows)}</p> : null}\n </div>\n <div className={styles.headActions}>\n <Tooltip label=\"Read everything again\" placement=\"bottom\">\n <IconButton variant=\"ghost\" size=\"sm\" icon={<IconRefresh />} aria-label=\"Read everything again\" onClick={refreshAll} />\n </Tooltip>\n {canPin ? (\n <Tooltip label={pinned ? 'Unpin — float over the page' : 'Pin beside the page'} placement=\"bottom\">\n <IconButton\n variant=\"ghost\"\n size=\"sm\"\n icon={<PinIcon pinned={pinned} />}\n aria-label={pinned ? 'Unpin resources' : 'Pin resources beside the page'}\n aria-pressed={pinned}\n data-resources-pin\n onClick={() => setResourcesPinned(!pinned)}\n />\n </Tooltip>\n ) : null}\n <Tooltip label=\"Close resources\" shortcut={shortcut} placement=\"bottom\">\n <IconButton variant=\"ghost\" size=\"sm\" icon={<IconX />} aria-label=\"Close resources\" onClick={close} />\n </Tooltip>\n </div>\n </header>\n\n <div className={styles.body}>\n <section className={styles.group} aria-labelledby={`${titleId}-accounts`}>\n <h3 id={`${titleId}-accounts`} className={styles.groupTitle}>Accounts</h3>\n {data.loading ? (\n <p className={styles.subtle} aria-busy=\"true\">Reading accounts…</p>\n ) : paid.length === 0 ? (\n <p className={styles.subtle}>{RESOURCES_EMPTY_TEXT}</p>\n ) : (\n <ul className={styles.cards}>\n {paid.map((row) => {\n const settled = accountStatus(row, { healthRead, now });\n const checking = busy?.seatId === row.seatId && busy.kind === 'check-again';\n const status = checking ? accountStatus(row, { healthRead, now, checking: true }) : settled;\n return <ResourceCard key={row.seatId} row={row} status={status} settled={settled} mode={mode_} busy={busy} onAction={onAction} />;\n })}\n </ul>\n )}\n <p className={note ? styles.note : styles.visuallyHidden} data-tone={note?.tone} role=\"status\" aria-live=\"polite\">{note?.text ?? ''}</p>\n </section>\n\n <section className={styles.group} aria-labelledby={`${titleId}-local`}>\n <h3 id={`${titleId}-local`} className={styles.groupTitle}>Local</h3>\n <ul className={styles.cards}>\n <LocalResources status={localRow ? accountStatus(localRow, { healthRead, now }) : null} onOpenUsage={() => go('usage')} now={now} />\n </ul>\n </section>\n\n <section className={styles.group} aria-labelledby={`${titleId}-cloud`}>\n <h3 id={`${titleId}-cloud`} className={styles.groupTitle}>Cloud</h3>\n <ul className={styles.cards}>\n <CloudCredits />\n </ul>\n </section>\n </div>\n\n <footer className={styles.foot}>\n <button type=\"button\" className={styles.linkButton} onClick={() => go('apps')}>Apps &amp; Accounts</button>\n <button type=\"button\" className={styles.linkButton} onClick={() => go('usage')}>Usage</button>\n <BarToggle />\n </footer>\n </div>\n );\n\n if (!overlay) return panel;\n return createPortal(\n <div className={styles.backdrop} data-presentation={compact ? 'full' : 'side'} onMouseDown={(e) => e.target === e.currentTarget && close()}>\n {panel}\n </div>,\n document.body,\n );\n}\n\n/** Footer switch for the always-on resource bar in the rail (3.11.1). */\nfunction BarToggle() {\n const { bar } = useResourcesUi();\n return (\n <button\n type=\"button\"\n className={styles.linkButton}\n style={{ marginLeft: 'auto' }}\n aria-pressed={bar}\n onClick={() => setResourcesBar(!bar)}\n >\n {bar ? 'Hide resource bar' : 'Show resource bar'}\n </button>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";var r=n(e(),1),i={region:`_region_1818x_1`,toast:`_toast_1818x_12`,"slide-in":`_slide-in_1818x_1`,success:`_success_1818x_27`,danger:`_danger_1818x_30`,dismiss:`_dismiss_1818x_34`},a=t(),o=(0,r.createContext)(null);function s(){let e=(0,r.useContext)(o);if(!e)throw Error(`useToast() called outside <ToastProvider>`);return e}var c=5e3;function l({children:e}){let[t,n]=(0,r.useState)([]),s=(0,r.useRef)(0),l=(0,r.useCallback)(e=>{n(t=>t.filter(t=>t.id!==e))},[]),u=(0,r.useCallback)((e,t=`neutral`)=>{let r=s.current++;n(n=>[...n,{id:r,message:e,tone:t}]),setTimeout(()=>l(r),c)},[l]),d=(0,r.useMemo)(()=>({show:u}),[u]);return(0,a.jsxs)(o.Provider,{value:d,children:[e,(0,a.jsx)(`div`,{className:i.region,role:`status`,"aria-live":`polite`,children:t.map(e=>(0,a.jsxs)(`div`,{className:`${i.toast} ${i[e.tone]}`,children:[(0,a.jsx)(`span`,{children:e.message}),(0,a.jsx)(`button`,{type:`button`,className:i.dismiss,onClick:()=>l(e.id),"aria-label":`Dismiss`,children:`×`})]},e.id))})]})}var u={wrap:`_wrap_1759l_1`,title:`_title_1759l_14`,detail:`_detail_1759l_21`,retry:`_retry_1759l_27`},d=class extends r.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){console.error(`[ashlr] view crashed while rendering`,e,t.componentStack)}componentDidUpdate(e){this.state.error&&e.resetKey!==this.props.resetKey&&this.setState({error:null})}render(){return this.state.error?(0,a.jsxs)(`div`,{className:u.wrap,role:`alert`,children:[(0,a.jsx)(`p`,{className:u.title,children:`This view hit an error and couldn't render.`}),(0,a.jsxs)(`p`,{className:u.detail,children:[this.state.error.message||`Unknown error.`,` — the rest of ashlr is still working; pick another view from the sidebar, or retry this one.`]}),(0,a.jsx)(`button`,{type:`button`,className:u.retry,onClick:()=>this.setState({error:null}),children:`Retry this view`})]}):this.props.children}};export{l as n,s as r,d as t};
2
+ //# sourceMappingURL=RouteErrorBoundary-DYtwc2ja.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouteErrorBoundary-DYtwc2ja.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Toast.module.css","../../../../../../src/web-ui/components/primitives/Toast.tsx","../../../../../../src/web-ui/components/primitives/RouteErrorBoundary.module.css","../../../../../../src/web-ui/components/primitives/RouteErrorBoundary.tsx"],"sourcesContent":[".region {\n position: fixed;\n bottom: var(--space-6);\n right: var(--space-6);\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n z-index: var(--z-toast);\n max-width: 360px;\n}\n\n.toast {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n padding: var(--space-3) var(--space-4);\n border-radius: var(--radius-md);\n box-shadow: var(--shadow-toast);\n font-size: var(--text-sm-size);\n animation: slide-in var(--duration-base) var(--ease-decelerate);\n border: 1px solid var(--border-default);\n background: var(--bg-surface-raised);\n color: var(--text-primary);\n}\n\n.success {\n border-color: var(--status-success-solid);\n}\n.danger {\n border-color: var(--status-danger-solid);\n}\n\n.dismiss {\n color: var(--text-tertiary);\n border-radius: var(--radius-xs);\n font-size: var(--text-lg-size);\n line-height: 1;\n padding: var(--space-1);\n}\n.dismiss {\n transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.dismiss:hover {\n color: var(--text-primary);\n background: var(--bg-hover);\n}\n.dismiss:active {\n background: var(--bg-active);\n}\n\n@keyframes slide-in {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .toast {\n animation: none;\n }\n}\n\n:root[data-motion=\"reduce\"] .toast {\n animation: none;\n}\n","/**\n * components/primitives/Toast.tsx — app-wide notifications. A single\n * aria-live region so screen readers announce toasts once, not per-toast\n * duplicate regions.\n */\nimport { createContext, useCallback, useContext, useMemo, useRef, useState, type ReactNode } from 'react';\nimport styles from './Toast.module.css';\n\nexport type ToastTone = 'neutral' | 'success' | 'danger';\n\ninterface ToastItem {\n id: number;\n message: string;\n tone: ToastTone;\n}\n\ninterface ToastContextValue {\n show: (message: string, tone?: ToastTone) => void;\n}\n\nconst ToastContext = createContext<ToastContextValue | null>(null);\n\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error('useToast() called outside <ToastProvider>');\n return ctx;\n}\n\nconst AUTO_DISMISS_MS = 5000;\n\nexport function ToastProvider({ children }: { children: ReactNode }) {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const nextId = useRef(0);\n\n const dismiss = useCallback((id: number) => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, []);\n\n const show = useCallback(\n (message: string, tone: ToastTone = 'neutral') => {\n const id = nextId.current++;\n setToasts((prev) => [...prev, { id, message, tone }]);\n setTimeout(() => dismiss(id), AUTO_DISMISS_MS);\n },\n [dismiss],\n );\n\n const value = useMemo(() => ({ show }), [show]);\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n <div className={styles.region} role=\"status\" aria-live=\"polite\">\n {toasts.map((t) => (\n <div key={t.id} className={`${styles.toast} ${styles[t.tone]}`}>\n <span>{t.message}</span>\n <button type=\"button\" className={styles.dismiss} onClick={() => dismiss(t.id)} aria-label=\"Dismiss\">\n ×\n </button>\n </div>\n ))}\n </div>\n </ToastContext.Provider>\n );\n}\n",".wrap {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--space-3);\n max-width: 640px;\n margin: var(--space-8) auto;\n padding: var(--space-6);\n border: 1px solid var(--status-danger-solid);\n border-radius: var(--radius-lg);\n background: var(--status-danger-bg);\n}\n\n.title {\n font-size: var(--text-md-size);\n line-height: var(--text-md-line);\n font-weight: var(--font-weight-semibold);\n color: var(--status-danger-fg);\n}\n\n.detail {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n}\n\n.retry {\n padding: var(--space-2) var(--space-4);\n border: 1px solid var(--status-danger-solid);\n border-radius: var(--radius-sm);\n background: var(--bg-surface);\n color: var(--status-danger-fg);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n cursor: pointer;\n}\n\n.retry:hover {\n background: var(--bg-hover);\n}\n","/**\n * components/primitives/RouteErrorBoundary.tsx — the last line of defense\n * against a view crashing on real-world data that doesn't match its\n * expected shape (see SwarmsView.tsx's `plan?.tasks` guard for a concrete\n * example: 2 of 80 real swarm records on this machine predate the `plan`\n * field entirely).\n *\n * React error boundaries can only be class components — there is no hook\n * equivalent. Wraps `<Outlet/>` in Shell.tsx, not the whole app: if one\n * routed view throws during render, the sidebar/topbar/command palette\n * survive and the operator can navigate to a working view instead of being\n * stuck on a permanently blank screen (DESIGN.md §11 point 4 — \"never a\n * full-page error, the shell stays usable\" — extended here to cover\n * uncaught render exceptions, not just query-status `'error'`).\n */\nimport { Component, type ErrorInfo, type ReactNode } from 'react';\nimport styles from './RouteErrorBoundary.module.css';\n\ninterface Props {\n children: ReactNode;\n /** Identity that, when changed, resets the boundary — pass the route pathname. */\n resetKey: string;\n}\n\ninterface State {\n error: Error | null;\n}\n\nexport class RouteErrorBoundary extends Component<Props, State> {\n override state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo) {\n console.error('[ashlr] view crashed while rendering', error, info.componentStack);\n }\n\n override componentDidUpdate(prevProps: Props) {\n if (this.state.error && prevProps.resetKey !== this.props.resetKey) {\n this.setState({ error: null });\n }\n }\n\n override render() {\n if (this.state.error) {\n return (\n <div className={styles.wrap} role=\"alert\">\n <p className={styles.title}>This view hit an error and couldn&apos;t render.</p>\n <p className={styles.detail}>\n {this.state.error.message || 'Unknown error.'} — the rest of ashlr is still working; pick another view\n from the sidebar, or retry this one.\n </p>\n <button type=\"button\" className={styles.retry} onClick={() => this.setState({ error: null })}>\n Retry this view\n </button>\n </div>\n );\n }\n return this.props.children;\n }\n}\n"],"mappings":"iPCoBM,GAAA,EAAe,EAAA,cAAA,CAAwC,IAAI,EAEjE,SAAgB,GAA8B,CAC5C,IAAM,GAAA,EAAM,EAAA,WAAA,CAAW,CAAY,EACnC,GAAI,CAAC,EAAK,MAAU,MAAM,2CAA2C,EACrE,OAAO,CACT,CAEA,IAAM,EAAkB,IAExB,SAAgB,EAAc,CAAE,YAAqC,CACnE,GAAM,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAAsB,CAAC,CAAC,EAC9C,GAAA,EAAS,EAAA,OAAA,CAAO,CAAC,EAEjB,GAAA,EAAU,EAAA,YAAA,CAAa,GAAe,CAC1C,EAAW,GAAS,EAAK,OAAQ,GAAM,EAAE,KAAO,CAAE,CAAC,CACrD,EAAG,CAAC,CAAC,EAEC,GAAA,EAAO,EAAA,YAAA,EACV,EAAiB,EAAkB,YAAc,CAChD,IAAM,EAAK,EAAO,UAClB,EAAW,GAAS,CAAC,GAAG,EAAM,CAAE,KAAI,UAAS,MAAK,CAAC,CAAC,EACpD,eAAiB,EAAQ,CAAE,EAAG,CAAe,CAC/C,EACA,CAAC,CAAO,CACV,EAEM,GAAA,EAAQ,EAAA,QAAA,MAAe,CAAE,MAAK,GAAI,CAAC,CAAI,CAAC,EAE9C,OACE,EAAA,EAAA,KAAA,CAAC,EAAa,SAAd,CAA8B,QAA9B,SAAA,CACG,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,OAAQ,KAAK,SAAS,YAAU,SACpD,SAAA,EAAO,IAAK,IACX,EAAA,EAAA,KAAA,CAAC,MAAD,CAAgB,UAAW,GAAG,EAAO,MAAM,GAAG,EAAO,EAAE,QAAvD,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,EAAE,OAAc,CAAA,GACvB,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,KAAK,SAAS,UAAW,EAAO,QAAS,YAAe,EAAQ,EAAE,EAAE,EAAG,aAAW,UAAU,SAAA,GAE5F,CAAA,CACL,CALK,EAAA,EAAE,EAKP,CACN,CACE,CAAA,CACgB,GAE3B,wGEpCa,EAAb,cAAwC,EAAA,SAAwB,CAC9D,MAAwB,CAAE,MAAO,IAAK,EAEtC,OAAO,yBAAyB,EAAqB,CACnD,MAAO,CAAE,OAAM,CACjB,CAEA,kBAA2B,EAAc,EAAiB,CACxD,QAAQ,MAAM,uCAAwC,EAAO,EAAK,cAAc,CAClF,CAEA,mBAA4B,EAAkB,CACxC,KAAK,MAAM,OAAS,EAAU,WAAa,KAAK,MAAM,UACxD,KAAK,SAAS,CAAE,MAAO,IAAK,CAAC,CAEjC,CAEA,QAAkB,CAehB,OAdI,KAAK,MAAM,OAEX,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAO,KAAM,KAAK,QAAlC,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAO,MAAO,SAAA,6CAAmD,CAAA,GAC/E,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,UAAW,EAAO,OAArB,SAAA,CACG,KAAK,MAAM,MAAM,SAAW,iBAAiB,+FAE7C,KACH,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,KAAK,SAAS,UAAW,EAAO,MAAO,YAAe,KAAK,SAAS,CAAE,MAAO,IAAK,CAAC,EAAG,SAAA,iBAEtF,CAAA,CACL,IAGF,KAAK,MAAM,QACpB,CACF"}
@@ -0,0 +1 @@
1
+ ._region_1818x_1{bottom:var(--space-6);right:var(--space-6);gap:var(--space-2);z-index:var(--z-toast);flex-direction:column;max-width:360px;display:flex;position:fixed}._toast_1818x_12{justify-content:space-between;align-items:center;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-radius:var(--radius-md);box-shadow:var(--shadow-toast);font-size:var(--text-sm-size);animation:_slide-in_1818x_1 var(--duration-base) var(--ease-decelerate);border:1px solid var(--border-default);background:var(--bg-surface-raised);color:var(--text-primary);display:flex}._success_1818x_27{border-color:var(--status-success-solid)}._danger_1818x_30{border-color:var(--status-danger-solid)}._dismiss_1818x_34{color:var(--text-tertiary);border-radius:var(--radius-xs);font-size:var(--text-lg-size);padding:var(--space-1);transition:color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);line-height:1}._dismiss_1818x_34:hover{color:var(--text-primary);background:var(--bg-hover)}._dismiss_1818x_34:active{background:var(--bg-active)}@keyframes _slide-in_1818x_1{0%{opacity:0;transform:translateY(8px)}}@media (prefers-reduced-motion:reduce){:root:not([data-motion=full]) ._toast_1818x_12{animation:none}}:root[data-motion=reduce] ._toast_1818x_12{animation:none}._wrap_1759l_1{align-items:flex-start;gap:var(--space-3);max-width:640px;margin:var(--space-8) auto;padding:var(--space-6);border:1px solid var(--status-danger-solid);border-radius:var(--radius-lg);background:var(--status-danger-bg);flex-direction:column;display:flex}._title_1759l_14{font-size:var(--text-md-size);line-height:var(--text-md-line);font-weight:var(--font-weight-semibold);color:var(--status-danger-fg)}._detail_1759l_21{font-size:var(--text-sm-size);line-height:var(--text-sm-line);color:var(--text-secondary)}._retry_1759l_27{padding:var(--space-2) var(--space-4);border:1px solid var(--status-danger-solid);border-radius:var(--radius-sm);background:var(--bg-surface);color:var(--status-danger-fg);font-size:var(--text-sm-size);font-weight:var(--font-weight-medium);cursor:pointer}._retry_1759l_27:hover{background:var(--bg-hover)}
@@ -1,2 +1,2 @@
1
- import{a as e,n as t,s as n}from"./index-oAAq8XJa.js";import{m as r}from"./global-Di2PUgj4.js";import{t as i}from"./MutationTokenDialog-SkRxqV_I.js";import{r as a}from"./RouteErrorBoundary-C5SxA2Dg.js";import{l as o}from"./icons-B_yuAgdN.js";import{j as s,m as c}from"./VerseConsoleApp-WVeyJnW7.js";import{a as l,h as u}from"./verse-store-DjBWj04q.js";import{t as d}from"./Button-DYv_KKxr.js";import{n as f,t as p}from"./use-token-gate-B3IJL6bf.js";import{h as m,m as h,t as g,u as _}from"./cloud.module-CiwatLj3.js";import{i as v,n as y}from"./cloud-queries-CnV1yaNG.js";import{c as b}from"./ChatSection-CCcIPpOq.js";var x=n(e(),1);function S(e=document){let t=e.querySelector(`textarea[aria-label="Message"]`);return t instanceof HTMLTextAreaElement?t:null}function C(e){return S(e)?.value??``}function w(e){let t=S(e);if(!t)return!1;let n=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,`value`)?.set;return n?n.call(t,``):t.value=``,t.dispatchEvent(new Event(`input`,{bubbles:!0})),!0}var T=t(),E=()=>()=>{};function D(){try{return a()}catch{return null}}function O({root:e}={}){let{activeSessionId:t}=c(),n=(0,x.useSyncExternalStore)((0,x.useCallback)(e=>t?u(t,e):E(),[t]),()=>l(t),()=>l(t)),a=b(n.session),S=r(y,{freshMs:15e3}),O=f(),k=D(),[A,j]=(0,x.useState)(``);(0,x.useLayoutEffect)(()=>j(C(e)),[e]);let[M,N]=(0,x.useState)(!1),[P,F]=(0,x.useState)(null),[I,L]=(0,x.useState)(null),R=a.data?.roots.find(e=>e.primary)??a.data?.roots[0]??null,z=R?.git?.remote??null,B=R?.git?.branch??null,V=S.data?.value??null,H=h({overview:V,overviewReason:S.data?S.data.reason:`Reading the cloud lane…`,repo:z,rootsLoading:n.session!==null&&a.data===null&&a.error===null,prompt:A}),U=V?.budget.budget.estimatedCostPerSessionUsd??null,W=async()=>{let t=C(e).trim()||A.trim();if(z&&t){N(!0),F(null);try{let n=await O.run(`Run this message as a Claude Code cloud session on your Claude account.`,()=>v({repo:z,...B?{baseBranch:B}:{},prompt:t,origin:`chat`}));if(n===null)return;w(e),L(n.task);let r=m(n.task.sessionUrl,`claude.ai`);k?.show(`Cloud task started: ${n.task.title}.${r?` ${r}`:``}`,`success`)}catch(e){F(p(e))}finally{N(!1)}}},G=I?m(I.sessionUrl,`claude.ai`):null;return(0,T.jsxs)(`div`,{className:g.sheetAction,children:[I?(0,T.jsxs)(`p`,{className:g.notice,"data-tone":`success`,role:`status`,children:[`Started “`,I.title,`” in the cloud. The draft was cleared.`,` `,G?(0,T.jsxs)(`a`,{className:g.link,href:G,target:`_blank`,rel:`noreferrer noopener`,children:[`Open in Claude `,(0,T.jsx)(o,{width:12,height:12,"aria-hidden":`true`})]}):`Its session link appears on Command once the session is created.`]}):(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(s,{label:H??`Launch this message as a cloud session on ${z}${B?` from ${B}`:``}`,children:(0,T.jsx)(d,{block:!0,disabled:H!==null,busy:M,onClick:()=>void W(),children:`Run in cloud`})}),(0,T.jsx)(`p`,{className:g.muted,children:H??`Runs on ${z} from ${B??`its default branch`} as a Claude Code cloud session and delivers a draft PR.${U===null?``:` Estimated at ${_(U)}.`}`})]}),P?(0,T.jsx)(`p`,{className:g.notice,"data-tone":`danger`,role:`alert`,children:P}):null,(0,T.jsx)(i,{...O.dialog,tokenLabel:`Mutation token`,tokenHelp:`the mutation token ashlr verse printed`})]})}export{O as RunInCloudAction};
2
- //# sourceMappingURL=RunInCloudAction-C3LBp7C4.js.map
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{p as r}from"./global-oEl9Qj8u.js";import{t as i}from"./MutationTokenDialog-mxrw0Yvy.js";import{r as a}from"./RouteErrorBoundary-DYtwc2ja.js";import{N as o,Z as s}from"./VerseConsoleApp-DTjDpGCd.js";import{a as c,m as l}from"./verse-store-b_Lek_c5.js";import{t as u}from"./Button-HHXgoXGr.js";import{c as d}from"./icons-DEQa2rTx.js";import{n as f,t as p}from"./use-token-gate-DqrSXdX6.js";import{h as m,m as h,t as g,u as _}from"./cloud.module-ascz58c3.js";import{i as v,n as y}from"./cloud-queries-Br_r0UAz.js";import{c as b}from"./ChatSection-DZuZfTaC.js";var x=n(e(),1);function S(e=document){let t=e.querySelector(`textarea[aria-label="Message"]`);return t instanceof HTMLTextAreaElement?t:null}function C(e){return S(e)?.value??``}function w(e){let t=S(e);if(!t)return!1;let n=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,`value`)?.set;return n?n.call(t,``):t.value=``,t.dispatchEvent(new Event(`input`,{bubbles:!0})),!0}var T=t(),E=()=>()=>{};function D(){try{return a()}catch{return null}}function O({root:e}={}){let{activeSessionId:t}=o(),n=(0,x.useSyncExternalStore)((0,x.useCallback)(e=>t?l(t,e):E(),[t]),()=>c(t),()=>c(t)),a=b(n.session),S=r(y,{freshMs:15e3}),O=f(),k=D(),[A,j]=(0,x.useState)(``);(0,x.useLayoutEffect)(()=>j(C(e)),[e]);let[M,N]=(0,x.useState)(!1),[P,F]=(0,x.useState)(null),[I,L]=(0,x.useState)(null),R=a.data?.roots.find(e=>e.primary)??a.data?.roots[0]??null,z=R?.git?.remote??null,B=R?.git?.branch??null,V=S.data?.value??null,H=h({overview:V,overviewReason:S.data?S.data.reason:`Reading the cloud lane…`,repo:z,rootsLoading:n.session!==null&&a.data===null&&a.error===null,prompt:A}),U=V?.budget.budget.estimatedCostPerSessionUsd??null,W=async()=>{let t=C(e).trim()||A.trim();if(z&&t){N(!0),F(null);try{let n=await O.run(`Run this message as a Claude Code cloud session on your Claude account.`,()=>v({repo:z,...B?{baseBranch:B}:{},prompt:t,origin:`chat`}));if(n===null)return;w(e),L(n.task);let r=m(n.task.sessionUrl,`claude.ai`);k?.show(`Cloud task started: ${n.task.title}.${r?` ${r}`:``}`,`success`)}catch(e){F(p(e))}finally{N(!1)}}},G=I?m(I.sessionUrl,`claude.ai`):null;return(0,T.jsxs)(`div`,{className:g.sheetAction,children:[I?(0,T.jsxs)(`p`,{className:g.notice,"data-tone":`success`,role:`status`,children:[`Started “`,I.title,`” in the cloud. The draft was cleared.`,` `,G?(0,T.jsxs)(`a`,{className:g.link,href:G,target:`_blank`,rel:`noreferrer noopener`,children:[`Open in Claude `,(0,T.jsx)(d,{width:12,height:12,"aria-hidden":`true`})]}):`Its session link appears on Command once the session is created.`]}):(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(s,{label:H??`Launch this message as a cloud session on ${z}${B?` from ${B}`:``}`,children:(0,T.jsx)(u,{block:!0,disabled:H!==null,busy:M,onClick:()=>void W(),children:`Run in cloud`})}),(0,T.jsx)(`p`,{className:g.muted,children:H??`Runs on ${z} from ${B??`its default branch`} as a Claude Code cloud session and delivers a draft PR.${U===null?``:` Estimated at ${_(U)}.`}`})]}),P?(0,T.jsx)(`p`,{className:g.notice,"data-tone":`danger`,role:`alert`,children:P}):null,(0,T.jsx)(i,{...O.dialog,tokenLabel:`Mutation token`,tokenHelp:`the mutation token ashlr verse printed`})]})}export{O as RunInCloudAction};
2
+ //# sourceMappingURL=RunInCloudAction-BEGEEM8O.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RunInCloudAction-C3LBp7C4.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/cloud/composer-draft.ts","../../../../../../src/web-ui/routes/verse/cloud/RunInCloudAction.tsx"],"sourcesContent":["/**\n * routes/verse/cloud/composer-draft.ts — read and clear the chat composer's\n * draft from outside the Composer (3.11 unit C3, for \"Run in cloud\").\n *\n * The composer owns its text state and takes no cloud props: the ⋯ sheet is\n * the one place the cloud lane may add to it (SPEC 3.11 C3). So, like the\n * dock's \"Send selection to chat\" fallback (chat/composer-bridge.ts), this\n * goes through the box itself: read its value, and clear it with the native\n * setter plus an `input` event, which React's controlled textarea treats as\n * the operator's own edit — its draft persistence sees the empty box too, so\n * a reload does not bring the launched text back.\n */\n\n/** The chat composer's message box (the Composer's `aria-label=\"Message\"`). */\nexport function findComposerBox(root: ParentNode = document): HTMLTextAreaElement | null {\n const node = root.querySelector('textarea[aria-label=\"Message\"]');\n return node instanceof HTMLTextAreaElement ? node : null;\n}\n\nexport function readComposerDraft(root?: ParentNode): string {\n return findComposerBox(root)?.value ?? '';\n}\n\n/** Empty the box as a person would. False when there is no box to clear. */\nexport function clearComposerDraft(root?: ParentNode): boolean {\n const box = findComposerBox(root);\n if (!box) return false;\n const setter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;\n if (setter) setter.call(box, '');\n else box.value = '';\n box.dispatchEvent(new Event('input', { bubbles: true }));\n return true;\n}\n","/**\n * routes/verse/cloud/RunInCloudAction.tsx — \"Run in cloud\" in the composer's\n * ⋯ sheet (3.11 unit C3; lazy-loaded by composer/ControlsSheet.tsx the first\n * time the sheet opens, so none of this is chat first-paint).\n *\n * It launches the message typed in the box as a cloud task on the chat\n * project's GitHub origin, from the branch the chat is on. Both come from the\n * chat's roots read (chat/use-session-roots — the read behind the header's\n * `repo › branch` and the Branch bar), which is already in the cache when the\n * chat is open. After a launch the draft is cleared, a toast confirms it, and\n * the sheet shows the session link in place of the button.\n *\n * Disabled — with the reason as its tooltip AND as a line under it (a\n * disabled button takes no focus, so a keyboard user would never see the\n * tooltip) — when the project has no GitHub origin, the Claude seat is not\n * ready, the budget gate is closed, or the box is empty.\n */\nimport { useCallback, useLayoutEffect, useState, useSyncExternalStore } from 'react';\nimport type { CloudTaskV1 } from '../../../../core/cloud/types.js';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { IconExternalLink } from '../../../components/primitives/icons.js';\nimport { useToast } from '../../../components/primitives/Toast.js';\nimport { Tooltip } from '../../../components/primitives/Tooltip.js';\nimport { useQuery } from '../../../data/hooks.js';\nimport { useSessionRoots } from '../chat/use-session-roots.js';\nimport { describeContextError, useTokenGate } from '../context/use-token-gate.js';\nimport { useVerseUi } from '../useVerseUi.js';\nimport { getVerseSessionHead, subscribeVerseSession } from '../verse-store.js';\nimport { formatDollars, runInCloudBlock, safeHref } from './cloud-model.js';\nimport { cloudQuery, launchCloudTask } from './cloud-queries.js';\nimport { clearComposerDraft, readComposerDraft } from './composer-draft.js';\nimport styles from './cloud.module.css';\n\nconst NO_SUBSCRIPTION = () => () => {};\n\n/** The shell's toast when there is one; tests and bare mounts have none, and a launch must not throw for want of it. */\nfunction useOptionalToast(): ReturnType<typeof useToast> | null {\n try {\n return useToast();\n } catch {\n return null;\n }\n}\n\nexport function RunInCloudAction({ root }: { root?: ParentNode } = {}) {\n const { activeSessionId } = useVerseUi();\n const head = useSyncExternalStore(\n useCallback((listener: () => void) => (activeSessionId ? subscribeVerseSession(activeSessionId, listener) : NO_SUBSCRIPTION()), [activeSessionId]),\n () => getVerseSessionHead(activeSessionId),\n () => getVerseSessionHead(activeSessionId),\n );\n const roots = useSessionRoots(head.session);\n const read = useQuery(cloudQuery, { freshMs: 15_000 });\n const gate = useTokenGate();\n const toast = useOptionalToast();\n // The sheet is modal, so the box cannot change while it is open: one read\n // once mounted (after commit, never during render) is the draft this\n // button launches — and it is re-read on press anyway.\n const [prompt, setPrompt] = useState('');\n useLayoutEffect(() => setPrompt(readComposerDraft(root)), [root]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [launched, setLaunched] = useState<CloudTaskV1 | null>(null);\n\n const primary = roots.data?.roots.find((r) => r.primary) ?? roots.data?.roots[0] ?? null;\n const repo = primary?.git?.remote ?? null;\n const branch = primary?.git?.branch ?? null;\n const overview = read.data?.value ?? null;\n const block = runInCloudBlock({\n overview,\n overviewReason: read.data ? read.data.reason : 'Reading the cloud lane…',\n repo,\n rootsLoading: head.session !== null && roots.data === null && roots.error === null,\n prompt,\n });\n const estimate = overview?.budget.budget.estimatedCostPerSessionUsd ?? null;\n\n const launch = async () => {\n const text = readComposerDraft(root).trim() || prompt.trim();\n if (!repo || !text) return;\n setBusy(true);\n setError(null);\n try {\n const response = await gate.run('Run this message as a Claude Code cloud session on your Claude account.', () =>\n launchCloudTask({ repo, ...(branch ? { baseBranch: branch } : {}), prompt: text, origin: 'chat' }),\n );\n if (response === null) return; // the unlock dialog was dismissed: nothing was sent\n clearComposerDraft(root);\n setLaunched(response.task);\n const link = safeHref(response.task.sessionUrl, 'claude.ai');\n toast?.show(`Cloud task started: ${response.task.title}.${link ? ` ${link}` : ''}`, 'success');\n } catch (err) {\n setError(describeContextError(err));\n } finally {\n setBusy(false);\n }\n };\n\n const session = launched ? safeHref(launched.sessionUrl, 'claude.ai') : null;\n return (\n <div className={styles.sheetAction}>\n {launched ? (\n <p className={styles.notice} data-tone=\"success\" role=\"status\">\n Started “{launched.title}” in the cloud. The draft was cleared.{' '}\n {session ? (\n <a className={styles.link} href={session} target=\"_blank\" rel=\"noreferrer noopener\">\n Open in Claude <IconExternalLink width={12} height={12} aria-hidden=\"true\" />\n </a>\n ) : (\n 'Its session link appears on Command once the session is created.'\n )}\n </p>\n ) : (\n <>\n <Tooltip label={block ?? `Launch this message as a cloud session on ${repo}${branch ? ` from ${branch}` : ''}`}>\n <Button block disabled={block !== null} busy={busy} onClick={() => void launch()}>\n Run in cloud\n </Button>\n </Tooltip>\n <p className={styles.muted}>\n {block ??\n `Runs on ${repo} from ${branch ?? 'its default branch'} as a Claude Code cloud session and delivers a draft PR.${estimate !== null ? ` Estimated at ${formatDollars(estimate)}.` : ''}`}\n </p>\n </>\n )}\n {error ? <p className={styles.notice} data-tone=\"danger\" role=\"alert\">{error}</p> : null}\n <MutationTokenDialog {...gate.dialog} tokenLabel=\"Mutation token\" tokenHelp=\"the mutation token ashlr verse printed\" />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"RunInCloudAction-BEGEEM8O.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/cloud/composer-draft.ts","../../../../../../src/web-ui/routes/verse/cloud/RunInCloudAction.tsx"],"sourcesContent":["/**\n * routes/verse/cloud/composer-draft.ts — read and clear the chat composer's\n * draft from outside the Composer (3.11 unit C3, for \"Run in cloud\").\n *\n * The composer owns its text state and takes no cloud props: the ⋯ sheet is\n * the one place the cloud lane may add to it (SPEC 3.11 C3). So, like the\n * dock's \"Send selection to chat\" fallback (chat/composer-bridge.ts), this\n * goes through the box itself: read its value, and clear it with the native\n * setter plus an `input` event, which React's controlled textarea treats as\n * the operator's own edit — its draft persistence sees the empty box too, so\n * a reload does not bring the launched text back.\n */\n\n/** The chat composer's message box (the Composer's `aria-label=\"Message\"`). */\nexport function findComposerBox(root: ParentNode = document): HTMLTextAreaElement | null {\n const node = root.querySelector('textarea[aria-label=\"Message\"]');\n return node instanceof HTMLTextAreaElement ? node : null;\n}\n\nexport function readComposerDraft(root?: ParentNode): string {\n return findComposerBox(root)?.value ?? '';\n}\n\n/** Empty the box as a person would. False when there is no box to clear. */\nexport function clearComposerDraft(root?: ParentNode): boolean {\n const box = findComposerBox(root);\n if (!box) return false;\n const setter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;\n if (setter) setter.call(box, '');\n else box.value = '';\n box.dispatchEvent(new Event('input', { bubbles: true }));\n return true;\n}\n","/**\n * routes/verse/cloud/RunInCloudAction.tsx — \"Run in cloud\" in the composer's\n * ⋯ sheet (3.11 unit C3; lazy-loaded by composer/ControlsSheet.tsx the first\n * time the sheet opens, so none of this is chat first-paint).\n *\n * It launches the message typed in the box as a cloud task on the chat\n * project's GitHub origin, from the branch the chat is on. Both come from the\n * chat's roots read (chat/use-session-roots — the read behind the header's\n * `repo › branch` and the Branch bar), which is already in the cache when the\n * chat is open. After a launch the draft is cleared, a toast confirms it, and\n * the sheet shows the session link in place of the button.\n *\n * Disabled — with the reason as its tooltip AND as a line under it (a\n * disabled button takes no focus, so a keyboard user would never see the\n * tooltip) — when the project has no GitHub origin, the Claude seat is not\n * ready, the budget gate is closed, or the box is empty.\n */\nimport { useCallback, useLayoutEffect, useState, useSyncExternalStore } from 'react';\nimport type { CloudTaskV1 } from '../../../../core/cloud/types.js';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { IconExternalLink } from '../../../components/primitives/icons.js';\nimport { useToast } from '../../../components/primitives/Toast.js';\nimport { Tooltip } from '../../../components/primitives/Tooltip.js';\nimport { useQuery } from '../../../data/hooks.js';\nimport { useSessionRoots } from '../chat/use-session-roots.js';\nimport { describeContextError, useTokenGate } from '../context/use-token-gate.js';\nimport { useVerseUi } from '../useVerseUi.js';\nimport { getVerseSessionHead, subscribeVerseSession } from '../verse-store.js';\nimport { formatDollars, runInCloudBlock, safeHref } from './cloud-model.js';\nimport { cloudQuery, launchCloudTask } from './cloud-queries.js';\nimport { clearComposerDraft, readComposerDraft } from './composer-draft.js';\nimport styles from './cloud.module.css';\n\nconst NO_SUBSCRIPTION = () => () => {};\n\n/** The shell's toast when there is one; tests and bare mounts have none, and a launch must not throw for want of it. */\nfunction useOptionalToast(): ReturnType<typeof useToast> | null {\n try {\n return useToast();\n } catch {\n return null;\n }\n}\n\nexport function RunInCloudAction({ root }: { root?: ParentNode } = {}) {\n const { activeSessionId } = useVerseUi();\n const head = useSyncExternalStore(\n useCallback((listener: () => void) => (activeSessionId ? subscribeVerseSession(activeSessionId, listener) : NO_SUBSCRIPTION()), [activeSessionId]),\n () => getVerseSessionHead(activeSessionId),\n () => getVerseSessionHead(activeSessionId),\n );\n const roots = useSessionRoots(head.session);\n const read = useQuery(cloudQuery, { freshMs: 15_000 });\n const gate = useTokenGate();\n const toast = useOptionalToast();\n // The sheet is modal, so the box cannot change while it is open: one read\n // once mounted (after commit, never during render) is the draft this\n // button launches — and it is re-read on press anyway.\n const [prompt, setPrompt] = useState('');\n useLayoutEffect(() => setPrompt(readComposerDraft(root)), [root]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [launched, setLaunched] = useState<CloudTaskV1 | null>(null);\n\n const primary = roots.data?.roots.find((r) => r.primary) ?? roots.data?.roots[0] ?? null;\n const repo = primary?.git?.remote ?? null;\n const branch = primary?.git?.branch ?? null;\n const overview = read.data?.value ?? null;\n const block = runInCloudBlock({\n overview,\n overviewReason: read.data ? read.data.reason : 'Reading the cloud lane…',\n repo,\n rootsLoading: head.session !== null && roots.data === null && roots.error === null,\n prompt,\n });\n const estimate = overview?.budget.budget.estimatedCostPerSessionUsd ?? null;\n\n const launch = async () => {\n const text = readComposerDraft(root).trim() || prompt.trim();\n if (!repo || !text) return;\n setBusy(true);\n setError(null);\n try {\n const response = await gate.run('Run this message as a Claude Code cloud session on your Claude account.', () =>\n launchCloudTask({ repo, ...(branch ? { baseBranch: branch } : {}), prompt: text, origin: 'chat' }),\n );\n if (response === null) return; // the unlock dialog was dismissed: nothing was sent\n clearComposerDraft(root);\n setLaunched(response.task);\n const link = safeHref(response.task.sessionUrl, 'claude.ai');\n toast?.show(`Cloud task started: ${response.task.title}.${link ? ` ${link}` : ''}`, 'success');\n } catch (err) {\n setError(describeContextError(err));\n } finally {\n setBusy(false);\n }\n };\n\n const session = launched ? safeHref(launched.sessionUrl, 'claude.ai') : null;\n return (\n <div className={styles.sheetAction}>\n {launched ? (\n <p className={styles.notice} data-tone=\"success\" role=\"status\">\n Started “{launched.title}” in the cloud. The draft was cleared.{' '}\n {session ? (\n <a className={styles.link} href={session} target=\"_blank\" rel=\"noreferrer noopener\">\n Open in Claude <IconExternalLink width={12} height={12} aria-hidden=\"true\" />\n </a>\n ) : (\n 'Its session link appears on Command once the session is created.'\n )}\n </p>\n ) : (\n <>\n <Tooltip label={block ?? `Launch this message as a cloud session on ${repo}${branch ? ` from ${branch}` : ''}`}>\n <Button block disabled={block !== null} busy={busy} onClick={() => void launch()}>\n Run in cloud\n </Button>\n </Tooltip>\n <p className={styles.muted}>\n {block ??\n `Runs on ${repo} from ${branch ?? 'its default branch'} as a Claude Code cloud session and delivers a draft PR.${estimate !== null ? ` Estimated at ${formatDollars(estimate)}.` : ''}`}\n </p>\n </>\n )}\n {error ? <p className={styles.notice} data-tone=\"danger\" role=\"alert\">{error}</p> : null}\n <MutationTokenDialog {...gate.dialog} tokenLabel=\"Mutation token\" tokenHelp=\"the mutation token ashlr verse printed\" />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{b as r,l as i,n as a}from"./verse-model-DyCwZF-M.js";import{b as o,x as s}from"./format-BkWdOQDL.js";import{n as c}from"./seat-subscription-B-f9ViU2.js";import{b as l,g as u,h as d,m as f,p,r as m,x as h}from"./context-model-CIBmSugV.js";import{t as g}from"./Composer.module-C8U73KdQ.js";var _=n(e(),1),v=t();function y(e){return JSON.stringify([e.seatId,e.model])}function b(e){try{let t=JSON.parse(e);if(!Array.isArray(t)||t.length!==2)return null;let[n,r]=t;return typeof n!=`string`||typeof r!=`string`?null:{seatId:n,model:r}}catch{return null}}function x(e,t=null){for(let n of i(e))for(let e of n.seats){if(e.health.state===`unavailable`||s(e,S(t,e.id))!==null)continue;let n=e.models.find(t=>u(e,t)===null);if(n)return{seatId:e.id,model:n.id}}return null}function S(e,t){return e?.find(e=>e.seatId===t)??null}function C(e,t,n=null,r=Date.now()){let i=s(e,S(n,e.id),r);if(i===null)return null;let a=i.reason.replace(`${e.label} is `,``).replace(/ to use this seat\.$/,``).replace(/\.$/,``),c=o(e.id,t,n,r)[0],l=c===void 0?null:t.find(e=>e.id===c)?.label??null;return l===null?a:`${a} · try ${l}`}function w(e){let t=d(e.workingSetTokens,e.model,e.mode,e.seat.engine),n=t===null?``:` · ${m[t]}`,r=e.note===null?``:` (${e.note})`;return`${e.seat.label} — ${e.model.label} · ${p(e.model,e.mode)}${n}${r}`}function T(e,t,n){let r=[];n!==null&&r.push(n.charAt(0).toUpperCase()+n.slice(1)),r.push(f(t));let i=l(e);return i!==null&&r.push(`Runs ${i}.`),r.push(...h(e)),r.join(`
2
+ `)}function E({seats:e,value:t,onChange:n,disabled:o=!1,label:s=`Seat and model`,id:l,compact:d=!1,workingSetTokens:f=null,modeFor:p,healthReports:m=null}){let h=(0,_.useId)(),x=l??h,S=i(e),E=t?y(t):``,D=t&&e.some(e=>e.id===t.seatId&&e.models.some(e=>e.id===t.model));return(0,v.jsxs)(`label`,{className:`${g.seatField} ${d?g.seatFieldCompact:``}`,htmlFor:x,children:[(0,v.jsx)(`span`,{className:d?`visually-hidden`:g.fieldLabel,children:s}),(0,v.jsxs)(`select`,{id:x,className:g.seatSelect,value:D?E:``,disabled:o||S.length===0,"aria-label":d?s:void 0,onChange:e=>{let t=b(e.target.value);t&&n(t)},children:[D?null:(0,v.jsx)(`option`,{value:``,disabled:!0,children:S.length===0?`No seats discovered`:`Choose a seat…`}),S.map(t=>(0,v.jsx)(`optgroup`,{label:a[t.engine],children:t.seats.flatMap(t=>{let n=r(t)??C(t,e,m),i=c(t),a=i.cls===`unread`||i.kind===`local`?null:`${i.plan===null?``:`${i.plan} · `}${i.word} · ${i.summary}`;return t.models.map(e=>{let r=n??u(t,e),i=r===null?a:`unavailable: ${r}`,o=p?.(t,e)??`standard`,s=y({seatId:t.id,model:e.id});return(0,v.jsx)(`option`,{value:s,disabled:r!==null,title:T(t,e,i),children:w({seat:t,model:e,mode:o,workingSetTokens:f,note:i})},s)})})},t.engine))]})]})}export{x as n,E as t};
3
+ //# sourceMappingURL=SeatSelector-CYHRR7Wp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SeatSelector-DpvvbjNm.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/SeatSelector.tsx"],"sourcesContent":["/**\n * routes/verse/SeatSelector.tsx — grouped seat/model picker. A native\n * <select> with one <optgroup> per engine (Claude · Codex · Grok · Local)\n * and one option per seat×model; seats whose health is `unavailable` are\n * disabled with the reason in the label (and `title`), so the operator sees\n * why rather than just a greyed row. Value is `[seatId, modelId]` JSON so\n * ids containing ':' or '/' can never collide.\n *\n * Every option also carries its seat's CAPACITY (`seat-subscription.ts`).\n * Without it an exhausted seat was indistinguishable from a fresh one here:\n * the only annotation was `seatUnavailableReason`, which fires solely on\n * `health.state === 'unavailable'`, and Claude's health is `unknown` BY\n * CONSTRUCTION (docs/VERSE-TELEMETRY-V2.md). A Claude seat whose binding\n * weekly window read 100% used therefore appeared as an ordinary, enabled,\n * unannotated choice, and the exhaustion was discovered at turn time — the\n * exact failure the Usage section exists to prevent.\n *\n * The annotation reads `plan · word · binding phrase` — the plan tier only\n * when the provider published one, so nothing is invented for a seat whose\n * subscription was never read.\n *\n * A `blocked` seat is MARKED but stays selectable: a used-up window can\n * coexist with a spendable credit balance, so refusing the choice would be a\n * stronger claim than the data supports.\n *\n * V3.10 — EXCEPT when the server's verdict IS a refusal. The session engine now\n * refuses a turn on a seat whose `capacity.usability` is `exhausted` (every\n * read window spent, no credits) or `signed-out` — the same rule, from the same\n * function (core/verse/seat-readiness.ts `seatBlock`). Offering such a seat\n * here would only move the failure from the picker to the first send, so its\n * rows are disabled and say why, when it resets, and where to go instead\n * (\"unavailable: out of usage — resets Fri 2:25 PM · try Grok\"). A seat that is\n * merely `tight` (a spent window beside spendable credits, or a spent per-model\n * window beside healthy account-wide ones) stays selectable, as before.\n *\n * V3.9 — EVERY ROW SAYS WHAT CONTEXT IT BUYS. A row used to read \"Claude Max —\n * Opus 5\", and the only window anywhere near the picker was the seat's DEFAULT\n * model's (so \"200k\" for every 1M Claude model). Now each row carries its own\n * model's window and compaction point in the mode that row would run in\n * (\"1M ctx · compacts ≈367k\"), and — when the dialog has sized the chosen\n * folders — whether that code would fit. A model the seat's pinned CLI cannot\n * run (Opus 5.5 on a 2.1.257 seat) is LISTED, disabled, with its reason, so\n * the operator learns why it is missing instead of wondering. The option's\n * tooltip carries the long form: the window's provenance, the pinned CLI\n * version and the seat's own notes. The new-chat dialog repeats those for the\n * chosen seat in visible text, because WebKit's native menus never show an\n * option's title.\n */\nimport { useId } from 'react';\nimport type { VerseModelOption, VerseSeat } from '../../data/api-types.js';\nimport type { VerseContextMode } from '../../../core/verse/types.js';\nimport type { SeatHealthReport } from '../../../core/verse/health-types.js';\nimport { rankSeatAlternatives, seatBlock } from '../../../core/verse/seat-readiness.js';\nimport { seatSubscription } from './seat-subscription.js';\nimport {\n FIT_SHORT,\n modelContextPhrase,\n modelContextSentence,\n modelFit,\n modelUnavailableReason,\n seatCliLine,\n seatContextNotes,\n} from './usage/context-model.js';\nimport { ENGINE_LABEL, groupSeats, seatUnavailableReason } from './verse-model.js';\nimport styles from './Composer.module.css';\n\nexport interface SeatChoice {\n seatId: string;\n model: string;\n}\n\nexport interface SeatSelectorProps {\n seats: readonly VerseSeat[];\n value: SeatChoice | null;\n onChange: (choice: SeatChoice) => void;\n disabled?: boolean;\n label?: string;\n id?: string;\n compact?: boolean;\n /**\n * Estimated tokens of the chosen folders' tracked code (GET /context-fit).\n * When present every row also says whether that code fits the model. Null\n * or absent: nothing is claimed.\n */\n workingSetTokens?: number | null;\n /**\n * The context mode each row would run in, so its compaction point is the\n * one the operator would actually get. Absent → standard for every row.\n */\n modeFor?: (seat: VerseSeat, model: VerseModelOption) => VerseContextMode;\n /**\n * V3.10. Live seat health (GET /api/verse/health). Optional: without it the\n * seat's own `capacity.usability` still decides which seats are blocked.\n */\n healthReports?: readonly SeatHealthReport[] | null;\n}\n\nexport function encodeSeatChoice(choice: SeatChoice): string {\n return JSON.stringify([choice.seatId, choice.model]);\n}\n\nexport function decodeSeatChoice(value: string): SeatChoice | null {\n try {\n const parsed = JSON.parse(value) as unknown;\n if (!Array.isArray(parsed) || parsed.length !== 2) return null;\n const [seatId, model] = parsed as [unknown, unknown];\n if (typeof seatId !== 'string' || typeof model !== 'string') return null;\n return { seatId, model };\n } catch {\n return null;\n }\n}\n\n/**\n * First selectable seat (ready/degraded/unknown) with its first RUNNABLE\n * model. The seat catalog already puts a runnable model first; skipping an\n * unavailable one here as well means a stale or hand-built roster can never\n * make \"Start chat\" land on a model the pinned CLI would reject.\n */\nexport function defaultSeatChoice(\n seats: readonly VerseSeat[],\n healthReports: readonly SeatHealthReport[] | null = null,\n): SeatChoice | null {\n for (const group of groupSeats(seats)) {\n for (const seat of group.seats) {\n if (seat.health.state === 'unavailable') continue;\n // A seat the engine would refuse is never the default (V3.10).\n if (seatBlock(seat, reportFor(healthReports, seat.id)) !== null) continue;\n const model = seat.models.find((m) => modelUnavailableReason(seat, m) === null);\n if (model) return { seatId: seat.id, model: model.id };\n }\n }\n return null;\n}\n\nfunction reportFor(reports: readonly SeatHealthReport[] | null | undefined, seatId: string): SeatHealthReport | null {\n return reports?.find((report) => report.seatId === seatId) ?? null;\n}\n\n/**\n * Why a seat is refused, as an inline note — \"out of usage — resets Fri\n * 2:25 PM · try Grok\" / \"signed out — reconnect it · try Grok\" — or null when\n * the engine would accept it. The seat's label is dropped (the row already\n * leads with it) and the best alternative is named, so the row says where to\n * go instead.\n */\nexport function seatBlockedNote(\n seat: VerseSeat,\n seats: readonly VerseSeat[],\n healthReports: readonly SeatHealthReport[] | null = null,\n now: number = Date.now(),\n): string | null {\n const block = seatBlock(seat, reportFor(healthReports, seat.id), now);\n if (block === null) return null;\n const phrase = block.reason\n .replace(`${seat.label} is `, '')\n .replace(/ to use this seat\\.$/, '')\n .replace(/\\.$/, '');\n const best = rankSeatAlternatives(seat.id, seats, healthReports, now)[0];\n const bestLabel = best === undefined ? null : seats.find((candidate) => candidate.id === best)?.label ?? null;\n return bestLabel === null ? phrase : `${phrase} · try ${bestLabel}`;\n}\n\n/**\n * The option's text, which is also its accessible name:\n * \"Claude Max — Opus 5.5 · 1M ctx · compacts ≈367k · code fits (usable · …)\".\n * Seat and model lead so the CLOSED select still says what was chosen.\n */\nexport function seatOptionText(input: {\n seat: VerseSeat;\n model: VerseModelOption;\n mode: VerseContextMode;\n workingSetTokens?: number | null;\n note: string | null;\n}): string {\n // The seat's own engine: the fit adds THAT CLI's estimated fixed prompt.\n const verdict = modelFit(input.workingSetTokens, input.model, input.mode, input.seat.engine);\n const fit = verdict === null ? '' : ` · ${FIT_SHORT[verdict]}`;\n const note = input.note === null ? '' : ` (${input.note})`;\n return `${input.seat.label} — ${input.model.label} · ${modelContextPhrase(input.model, input.mode)}${fit}${note}`;\n}\n\n/**\n * The option's tooltip: the note first (it is why the row is marked), then the\n * model's full context sentence, then the seat facts no row has room for.\n */\nexport function seatOptionTitle(seat: VerseSeat, model: VerseModelOption, note: string | null): string {\n const lines: string[] = [];\n if (note !== null) lines.push(note.charAt(0).toUpperCase() + note.slice(1));\n lines.push(modelContextSentence(model));\n const cli = seatCliLine(seat);\n if (cli !== null) lines.push(`Runs ${cli}.`);\n lines.push(...seatContextNotes(seat));\n return lines.join('\\n');\n}\n\nexport function SeatSelector({\n seats,\n value,\n onChange,\n disabled = false,\n label = 'Seat and model',\n id,\n compact = false,\n workingSetTokens = null,\n modeFor,\n healthReports = null,\n}: SeatSelectorProps) {\n const generated = useId();\n const selectId = id ?? generated;\n const groups = groupSeats(seats);\n const current = value ? encodeSeatChoice(value) : '';\n const known = value && seats.some((s) => s.id === value.seatId && s.models.some((m) => m.id === value.model));\n return (\n <label className={`${styles.seatField} ${compact ? styles.seatFieldCompact : ''}`} htmlFor={selectId}>\n <span className={compact ? 'visually-hidden' : styles.fieldLabel}>{label}</span>\n <select id={selectId} className={styles.seatSelect} value={known ? current : ''} disabled={disabled || groups.length === 0}\n aria-label={compact ? label : undefined}\n onChange={(event) => {\n const choice = decodeSeatChoice(event.target.value);\n if (choice) onChange(choice);\n }}>\n {!known ? <option value=\"\" disabled>{groups.length === 0 ? 'No seats discovered' : 'Choose a seat…'}</option> : null}\n {groups.map((group) => (\n <optgroup key={group.engine} label={ENGINE_LABEL[group.engine]}>\n {group.seats.flatMap((seat) => {\n // Reachability first, then the engine's own refusal (V3.10).\n const seatReason = seatUnavailableReason(seat) ?? seatBlockedNote(seat, seats, healthReports);\n const capacity = seatSubscription(seat);\n // `unread` is left unsaid: \"no reading\" on every Claude row\n // would be noise, and the absent figure already says it. A local\n // seat is left unsaid too — it has no subscription to report,\n // and its readiness is already carried by the disabled state.\n const capacityNote =\n capacity.cls === 'unread' || capacity.kind === 'local'\n ? null\n : `${capacity.plan === null ? '' : `${capacity.plan} · `}${capacity.word} · ${capacity.summary}`;\n return seat.models.map((model) => {\n // The seat's outage outranks the model's own reason: nothing\n // on an unreachable seat runs, whatever its CLI version.\n const reason = seatReason ?? modelUnavailableReason(seat, model);\n // The label reads inline after the model name, so it stays\n // lowercase; the tooltip stands alone, so it is sentence case.\n const note = reason !== null ? `unavailable: ${reason}` : capacityNote;\n const mode = modeFor?.(seat, model) ?? 'standard';\n const optionValue = encodeSeatChoice({ seatId: seat.id, model: model.id });\n return (\n <option key={optionValue} value={optionValue} disabled={reason !== null}\n title={seatOptionTitle(seat, model, note)}>\n {seatOptionText({ seat, model, mode, workingSetTokens, note })}\n </option>\n );\n });\n })}\n </optgroup>\n ))}\n </select>\n </label>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SeatSelector-CYHRR7Wp.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/SeatSelector.tsx"],"sourcesContent":["/**\n * routes/verse/SeatSelector.tsx — grouped seat/model picker. A native\n * <select> with one <optgroup> per engine (Claude · Codex · Grok · Local)\n * and one option per seat×model; seats whose health is `unavailable` are\n * disabled with the reason in the label (and `title`), so the operator sees\n * why rather than just a greyed row. Value is `[seatId, modelId]` JSON so\n * ids containing ':' or '/' can never collide.\n *\n * Every option also carries its seat's CAPACITY (`seat-subscription.ts`).\n * Without it an exhausted seat was indistinguishable from a fresh one here:\n * the only annotation was `seatUnavailableReason`, which fires solely on\n * `health.state === 'unavailable'`, and Claude's health is `unknown` BY\n * CONSTRUCTION (docs/VERSE-TELEMETRY-V2.md). A Claude seat whose binding\n * weekly window read 100% used therefore appeared as an ordinary, enabled,\n * unannotated choice, and the exhaustion was discovered at turn time — the\n * exact failure the Usage section exists to prevent.\n *\n * The annotation reads `plan · word · binding phrase` — the plan tier only\n * when the provider published one, so nothing is invented for a seat whose\n * subscription was never read.\n *\n * A `blocked` seat is MARKED but stays selectable: a used-up window can\n * coexist with a spendable credit balance, so refusing the choice would be a\n * stronger claim than the data supports.\n *\n * V3.10 — EXCEPT when the server's verdict IS a refusal. The session engine now\n * refuses a turn on a seat whose `capacity.usability` is `exhausted` (every\n * read window spent, no credits) or `signed-out` — the same rule, from the same\n * function (core/verse/seat-readiness.ts `seatBlock`). Offering such a seat\n * here would only move the failure from the picker to the first send, so its\n * rows are disabled and say why, when it resets, and where to go instead\n * (\"unavailable: out of usage — resets Fri 2:25 PM · try Grok\"). A seat that is\n * merely `tight` (a spent window beside spendable credits, or a spent per-model\n * window beside healthy account-wide ones) stays selectable, as before.\n *\n * V3.9 — EVERY ROW SAYS WHAT CONTEXT IT BUYS. A row used to read \"Claude Max —\n * Opus 5\", and the only window anywhere near the picker was the seat's DEFAULT\n * model's (so \"200k\" for every 1M Claude model). Now each row carries its own\n * model's window and compaction point in the mode that row would run in\n * (\"1M ctx · compacts ≈367k\"), and — when the dialog has sized the chosen\n * folders — whether that code would fit. A model the seat's pinned CLI cannot\n * run (Opus 5.5 on a 2.1.257 seat) is LISTED, disabled, with its reason, so\n * the operator learns why it is missing instead of wondering. The option's\n * tooltip carries the long form: the window's provenance, the pinned CLI\n * version and the seat's own notes. The new-chat dialog repeats those for the\n * chosen seat in visible text, because WebKit's native menus never show an\n * option's title.\n */\nimport { useId } from 'react';\nimport type { VerseModelOption, VerseSeat } from '../../data/api-types.js';\nimport type { VerseContextMode } from '../../../core/verse/types.js';\nimport type { SeatHealthReport } from '../../../core/verse/health-types.js';\nimport { rankSeatAlternatives, seatBlock } from '../../../core/verse/seat-readiness.js';\nimport { seatSubscription } from './seat-subscription.js';\nimport {\n FIT_SHORT,\n modelContextPhrase,\n modelContextSentence,\n modelFit,\n modelUnavailableReason,\n seatCliLine,\n seatContextNotes,\n} from './usage/context-model.js';\nimport { ENGINE_LABEL, groupSeats, seatUnavailableReason } from './verse-model.js';\nimport styles from './Composer.module.css';\n\nexport interface SeatChoice {\n seatId: string;\n model: string;\n}\n\nexport interface SeatSelectorProps {\n seats: readonly VerseSeat[];\n value: SeatChoice | null;\n onChange: (choice: SeatChoice) => void;\n disabled?: boolean;\n label?: string;\n id?: string;\n compact?: boolean;\n /**\n * Estimated tokens of the chosen folders' tracked code (GET /context-fit).\n * When present every row also says whether that code fits the model. Null\n * or absent: nothing is claimed.\n */\n workingSetTokens?: number | null;\n /**\n * The context mode each row would run in, so its compaction point is the\n * one the operator would actually get. Absent → standard for every row.\n */\n modeFor?: (seat: VerseSeat, model: VerseModelOption) => VerseContextMode;\n /**\n * V3.10. Live seat health (GET /api/verse/health). Optional: without it the\n * seat's own `capacity.usability` still decides which seats are blocked.\n */\n healthReports?: readonly SeatHealthReport[] | null;\n}\n\nexport function encodeSeatChoice(choice: SeatChoice): string {\n return JSON.stringify([choice.seatId, choice.model]);\n}\n\nexport function decodeSeatChoice(value: string): SeatChoice | null {\n try {\n const parsed = JSON.parse(value) as unknown;\n if (!Array.isArray(parsed) || parsed.length !== 2) return null;\n const [seatId, model] = parsed as [unknown, unknown];\n if (typeof seatId !== 'string' || typeof model !== 'string') return null;\n return { seatId, model };\n } catch {\n return null;\n }\n}\n\n/**\n * First selectable seat (ready/degraded/unknown) with its first RUNNABLE\n * model. The seat catalog already puts a runnable model first; skipping an\n * unavailable one here as well means a stale or hand-built roster can never\n * make \"Start chat\" land on a model the pinned CLI would reject.\n */\nexport function defaultSeatChoice(\n seats: readonly VerseSeat[],\n healthReports: readonly SeatHealthReport[] | null = null,\n): SeatChoice | null {\n for (const group of groupSeats(seats)) {\n for (const seat of group.seats) {\n if (seat.health.state === 'unavailable') continue;\n // A seat the engine would refuse is never the default (V3.10).\n if (seatBlock(seat, reportFor(healthReports, seat.id)) !== null) continue;\n const model = seat.models.find((m) => modelUnavailableReason(seat, m) === null);\n if (model) return { seatId: seat.id, model: model.id };\n }\n }\n return null;\n}\n\nfunction reportFor(reports: readonly SeatHealthReport[] | null | undefined, seatId: string): SeatHealthReport | null {\n return reports?.find((report) => report.seatId === seatId) ?? null;\n}\n\n/**\n * Why a seat is refused, as an inline note — \"out of usage — resets Fri\n * 2:25 PM · try Grok\" / \"signed out — reconnect it · try Grok\" — or null when\n * the engine would accept it. The seat's label is dropped (the row already\n * leads with it) and the best alternative is named, so the row says where to\n * go instead.\n */\nexport function seatBlockedNote(\n seat: VerseSeat,\n seats: readonly VerseSeat[],\n healthReports: readonly SeatHealthReport[] | null = null,\n now: number = Date.now(),\n): string | null {\n const block = seatBlock(seat, reportFor(healthReports, seat.id), now);\n if (block === null) return null;\n const phrase = block.reason\n .replace(`${seat.label} is `, '')\n .replace(/ to use this seat\\.$/, '')\n .replace(/\\.$/, '');\n const best = rankSeatAlternatives(seat.id, seats, healthReports, now)[0];\n const bestLabel = best === undefined ? null : seats.find((candidate) => candidate.id === best)?.label ?? null;\n return bestLabel === null ? phrase : `${phrase} · try ${bestLabel}`;\n}\n\n/**\n * The option's text, which is also its accessible name:\n * \"Claude Max — Opus 5.5 · 1M ctx · compacts ≈367k · code fits (usable · …)\".\n * Seat and model lead so the CLOSED select still says what was chosen.\n */\nexport function seatOptionText(input: {\n seat: VerseSeat;\n model: VerseModelOption;\n mode: VerseContextMode;\n workingSetTokens?: number | null;\n note: string | null;\n}): string {\n // The seat's own engine: the fit adds THAT CLI's estimated fixed prompt.\n const verdict = modelFit(input.workingSetTokens, input.model, input.mode, input.seat.engine);\n const fit = verdict === null ? '' : ` · ${FIT_SHORT[verdict]}`;\n const note = input.note === null ? '' : ` (${input.note})`;\n return `${input.seat.label} — ${input.model.label} · ${modelContextPhrase(input.model, input.mode)}${fit}${note}`;\n}\n\n/**\n * The option's tooltip: the note first (it is why the row is marked), then the\n * model's full context sentence, then the seat facts no row has room for.\n */\nexport function seatOptionTitle(seat: VerseSeat, model: VerseModelOption, note: string | null): string {\n const lines: string[] = [];\n if (note !== null) lines.push(note.charAt(0).toUpperCase() + note.slice(1));\n lines.push(modelContextSentence(model));\n const cli = seatCliLine(seat);\n if (cli !== null) lines.push(`Runs ${cli}.`);\n lines.push(...seatContextNotes(seat));\n return lines.join('\\n');\n}\n\nexport function SeatSelector({\n seats,\n value,\n onChange,\n disabled = false,\n label = 'Seat and model',\n id,\n compact = false,\n workingSetTokens = null,\n modeFor,\n healthReports = null,\n}: SeatSelectorProps) {\n const generated = useId();\n const selectId = id ?? generated;\n const groups = groupSeats(seats);\n const current = value ? encodeSeatChoice(value) : '';\n const known = value && seats.some((s) => s.id === value.seatId && s.models.some((m) => m.id === value.model));\n return (\n <label className={`${styles.seatField} ${compact ? styles.seatFieldCompact : ''}`} htmlFor={selectId}>\n <span className={compact ? 'visually-hidden' : styles.fieldLabel}>{label}</span>\n <select id={selectId} className={styles.seatSelect} value={known ? current : ''} disabled={disabled || groups.length === 0}\n aria-label={compact ? label : undefined}\n onChange={(event) => {\n const choice = decodeSeatChoice(event.target.value);\n if (choice) onChange(choice);\n }}>\n {!known ? <option value=\"\" disabled>{groups.length === 0 ? 'No seats discovered' : 'Choose a seat…'}</option> : null}\n {groups.map((group) => (\n <optgroup key={group.engine} label={ENGINE_LABEL[group.engine]}>\n {group.seats.flatMap((seat) => {\n // Reachability first, then the engine's own refusal (V3.10).\n const seatReason = seatUnavailableReason(seat) ?? seatBlockedNote(seat, seats, healthReports);\n const capacity = seatSubscription(seat);\n // `unread` is left unsaid: \"no reading\" on every Claude row\n // would be noise, and the absent figure already says it. A local\n // seat is left unsaid too — it has no subscription to report,\n // and its readiness is already carried by the disabled state.\n const capacityNote =\n capacity.cls === 'unread' || capacity.kind === 'local'\n ? null\n : `${capacity.plan === null ? '' : `${capacity.plan} · `}${capacity.word} · ${capacity.summary}`;\n return seat.models.map((model) => {\n // The seat's outage outranks the model's own reason: nothing\n // on an unreachable seat runs, whatever its CLI version.\n const reason = seatReason ?? modelUnavailableReason(seat, model);\n // The label reads inline after the model name, so it stays\n // lowercase; the tooltip stands alone, so it is sentence case.\n const note = reason !== null ? `unavailable: ${reason}` : capacityNote;\n const mode = modeFor?.(seat, model) ?? 'standard';\n const optionValue = encodeSeatChoice({ seatId: seat.id, model: model.id });\n return (\n <option key={optionValue} value={optionValue} disabled={reason !== null}\n title={seatOptionTitle(seat, model, note)}>\n {seatOptionText({ seat, model, mode, workingSetTokens, note })}\n </option>\n );\n });\n })}\n </optgroup>\n ))}\n </select>\n </label>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as e,n as t,s as n}from"./index-oAAq8XJa.js";var r=n(e(),1),i={group:`_group_15ia8_1`,block:`_block_15ia8_11`,option:`_option_15ia8_16`,sm:`_sm_15ia8_45`,glyph:`_glyph_15ia8_72`},a=t();function o({options:e,value:t,onChange:n,size:o=`md`,block:s=!1,className:c,...l}){let u=(0,r.useRef)(null);function d(r){let i=e.filter(e=>!e.disabled);if(i.length===0)return;let a=i[((i.findIndex(e=>e.value===t)+r)%i.length+i.length)%i.length];n(a.value),requestAnimationFrame(()=>{u.current?.querySelector(`[data-value="${a.value}"]`)?.focus()})}return(0,a.jsx)(`div`,{ref:u,role:`radiogroup`,className:`${i.group} ${i[o]} ${s?i.block:``} ${c??``}`,...l,children:e.map(e=>{let r=e.value===t;return(0,a.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":r,"aria-label":e.ariaLabel,"data-value":e.value,tabIndex:r?0:-1,disabled:e.disabled,className:i.option,onClick:()=>n(e.value),onKeyDown:e=>{e.key===`ArrowRight`||e.key===`ArrowDown`?(e.preventDefault(),d(1)):(e.key===`ArrowLeft`||e.key===`ArrowUp`)&&(e.preventDefault(),d(-1))},children:[e.icon?(0,a.jsx)(`span`,{className:i.glyph,children:e.icon}):null,e.label]},e.value)})})}export{o as t};
2
- //# sourceMappingURL=Segmented-BL40udoO.js.map
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";var r=n(e(),1),i={group:`_group_15ia8_1`,block:`_block_15ia8_11`,option:`_option_15ia8_16`,sm:`_sm_15ia8_45`,glyph:`_glyph_15ia8_72`},a=t();function o({options:e,value:t,onChange:n,size:o=`md`,block:s=!1,className:c,...l}){let u=(0,r.useRef)(null);function d(r){let i=e.filter(e=>!e.disabled);if(i.length===0)return;let a=i[((i.findIndex(e=>e.value===t)+r)%i.length+i.length)%i.length];n(a.value),requestAnimationFrame(()=>{u.current?.querySelector(`[data-value="${a.value}"]`)?.focus()})}return(0,a.jsx)(`div`,{ref:u,role:`radiogroup`,className:`${i.group} ${i[o]} ${s?i.block:``} ${c??``}`,...l,children:e.map(e=>{let r=e.value===t;return(0,a.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":r,"aria-label":e.ariaLabel,"data-value":e.value,tabIndex:r?0:-1,disabled:e.disabled,className:i.option,onClick:()=>n(e.value),onKeyDown:e=>{e.key===`ArrowRight`||e.key===`ArrowDown`?(e.preventDefault(),d(1)):(e.key===`ArrowLeft`||e.key===`ArrowUp`)&&(e.preventDefault(),d(-1))},children:[e.icon?(0,a.jsx)(`span`,{className:i.glyph,children:e.icon}):null,e.label]},e.value)})})}export{o as t};
2
+ //# sourceMappingURL=Segmented-BE53BenI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Segmented-BL40udoO.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Segmented.module.css","../../../../../../src/web-ui/components/primitives/Segmented.tsx"],"sourcesContent":[".group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n background: var(--bg-hover);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n}\n\n.block {\n display: flex;\n width: 100%;\n}\n\n.block .option {\n flex: 1;\n justify-content: center;\n}\n\n.option {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-1);\n height: calc(var(--density-row) - 6px);\n padding: 0 var(--space-3);\n /* Transparent rather than absent so the checked state can colour it without\n changing the option's box — everything is border-box, so the hairline\n costs no height and no horizontal drift when it appears. */\n border: 1px solid transparent;\n border-radius: calc(var(--radius-sm) - 1px);\n background: transparent;\n color: var(--text-secondary);\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n cursor: pointer;\n transition:\n background-color var(--duration-fast) var(--ease-standard),\n color var(--duration-fast) var(--ease-standard);\n}\n\n.sm .option {\n height: calc(var(--density-row-sm) - 6px);\n padding: 0 var(--space-2);\n font-size: var(--text-2xs-size);\n}\n\n.option:hover:not(:disabled):not([aria-checked='true']) {\n color: var(--text-primary);\n}\n\n/* No shadow. DESIGN-V2 §1.2 allows drop shadows only on true overlays\n (dialog, menu, toast) and §2 retires every elevation token but those three;\n a segmented control is chrome. It was not carrying its weight either: in\n dark, --shadow-sm is rgba(0,0,0,0.4) on a near-black ground, i.e. invisible,\n so the selected thumb read as fill-only in dark and fill+shadow in light —\n two looks for one state. The hairline does the separating in both. */\n.option[aria-checked='true'] {\n background: var(--bg-surface);\n color: var(--text-primary);\n border-color: var(--border-default);\n}\n\n.option:disabled {\n color: var(--text-disabled);\n cursor: not-allowed;\n}\n\n.glyph {\n display: inline-flex;\n flex: none;\n}\n","/**\n * components/primitives/Segmented.tsx — pick one of 2-4 options where the\n * choice applies instantly (theme, density, a status filter). It replaces\n * both a <select> (too heavy for three options) and a row of toggle buttons\n * (no single-selection semantics for a screen reader).\n *\n * Implemented as a radiogroup with ROVING TABINDEX: one Tab stop for the\n * group, arrows move between options and select as they go — the WAI-ARIA\n * radio-group pattern. Every option is reachable by keyboard and announced\n * as \"N of M\".\n */\nimport { useRef, type ReactNode } from 'react';\nimport styles from './Segmented.module.css';\n\nexport interface SegmentedOption<T extends string> {\n value: T;\n label: ReactNode;\n /** Leading 16px glyph; the text label always stays visible. */\n icon?: ReactNode;\n /** Spoken name when `label` is a glyph or an abbreviation. */\n ariaLabel?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedProps<T extends string> {\n options: ReadonlyArray<SegmentedOption<T>>;\n value: T;\n onChange: (next: T) => void;\n /** Accessible name for the group — required when no visible label precedes it. */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n size?: 'sm' | 'md';\n /** Stretch each option to an equal share of the width. */\n block?: boolean;\n className?: string;\n}\n\nexport function Segmented<T extends string>({\n options,\n value,\n onChange,\n size = 'md',\n block = false,\n className,\n ...aria\n}: SegmentedProps<T>) {\n const groupRef = useRef<HTMLDivElement>(null);\n\n function move(delta: number): void {\n const enabled = options.filter((o) => !o.disabled);\n if (enabled.length === 0) return;\n const current = enabled.findIndex((o) => o.value === value);\n const next = enabled[(((current + delta) % enabled.length) + enabled.length) % enabled.length]!;\n onChange(next.value);\n // Keep DOM focus on the newly selected option (roving tabindex).\n requestAnimationFrame(() => {\n groupRef.current?.querySelector<HTMLButtonElement>(`[data-value=\"${next.value}\"]`)?.focus();\n });\n }\n\n return (\n <div\n ref={groupRef}\n role=\"radiogroup\"\n className={`${styles.group} ${styles[size]} ${block ? styles.block : ''} ${className ?? ''}`}\n {...aria}\n >\n {options.map((option) => {\n const selected = option.value === value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n aria-label={option.ariaLabel}\n data-value={option.value}\n tabIndex={selected ? 0 : -1}\n disabled={option.disabled}\n className={styles.option}\n onClick={() => onChange(option.value)}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n move(1);\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n move(-1);\n }\n }}\n >\n {option.icon ? <span className={styles.glyph}>{option.icon}</span> : null}\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":"kMCqCA,SAAgB,EAA4B,CAC1C,UACA,QACA,WACA,OAAO,KACP,QAAQ,GACR,YACA,GAAG,GACiB,CACpB,IAAM,GAAA,EAAW,EAAA,OAAA,CAAuB,IAAI,EAE5C,SAAS,EAAK,EAAqB,CACjC,IAAM,EAAU,EAAQ,OAAQ,GAAM,CAAC,EAAE,QAAQ,EACjD,GAAI,EAAQ,SAAW,EAAG,OAE1B,IAAM,EAAO,IADG,EAAQ,UAAW,GAAM,EAAE,QAAU,CAC7B,EAAU,GAAS,EAAQ,OAAU,EAAQ,QAAU,EAAQ,QACvF,EAAS,EAAK,KAAK,EAEnB,0BAA4B,CAC1B,EAAS,SAAS,cAAiC,gBAAgB,EAAK,MAAM,GAAG,CAAC,EAAE,MAAM,CAC5F,CAAC,CACH,CAEA,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,EACL,KAAK,aACL,UAAW,GAAG,EAAO,MAAM,GAAG,EAAO,GAAM,GAAG,EAAQ,EAAO,MAAQ,GAAG,GAAG,GAAa,KACxF,GAAI,EAEH,SAAA,EAAQ,IAAK,GAAW,CACvB,IAAM,EAAW,EAAO,QAAU,EAClC,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CAEE,KAAK,SACL,KAAK,QACL,eAAc,EACd,aAAY,EAAO,UACnB,aAAY,EAAO,MACnB,SAAU,EAAW,EAAI,GACzB,SAAU,EAAO,SACjB,UAAW,EAAO,OAClB,YAAe,EAAS,EAAO,KAAK,EACpC,UAAY,GAAM,CACZ,EAAE,MAAQ,cAAgB,EAAE,MAAQ,aACtC,EAAE,eAAe,EACjB,EAAK,CAAC,IACG,EAAE,MAAQ,aAAe,EAAE,MAAQ,aAC5C,EAAE,eAAe,EACjB,EAAK,EAAE,EAEX,EAnBF,SAAA,CAqBG,EAAO,MAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,EAAO,IAAW,CAAA,EAAI,KACpE,EAAO,KACF,CAtBD,EAAA,EAAO,KAsBN,CAEZ,CAAC,CACE,CAAA,CAET"}
1
+ {"version":3,"file":"Segmented-BE53BenI.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Segmented.module.css","../../../../../../src/web-ui/components/primitives/Segmented.tsx"],"sourcesContent":[".group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n background: var(--bg-hover);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n}\n\n.block {\n display: flex;\n width: 100%;\n}\n\n.block .option {\n flex: 1;\n justify-content: center;\n}\n\n.option {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--space-1);\n height: calc(var(--density-row) - 6px);\n padding: 0 var(--space-3);\n /* Transparent rather than absent so the checked state can colour it without\n changing the option's box — everything is border-box, so the hairline\n costs no height and no horizontal drift when it appears. */\n border: 1px solid transparent;\n border-radius: calc(var(--radius-sm) - 1px);\n background: transparent;\n color: var(--text-secondary);\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n cursor: pointer;\n transition:\n background-color var(--duration-fast) var(--ease-standard),\n color var(--duration-fast) var(--ease-standard);\n}\n\n.sm .option {\n height: calc(var(--density-row-sm) - 6px);\n padding: 0 var(--space-2);\n font-size: var(--text-2xs-size);\n}\n\n.option:hover:not(:disabled):not([aria-checked='true']) {\n color: var(--text-primary);\n}\n\n/* No shadow. DESIGN-V2 §1.2 allows drop shadows only on true overlays\n (dialog, menu, toast) and §2 retires every elevation token but those three;\n a segmented control is chrome. It was not carrying its weight either: in\n dark, --shadow-sm is rgba(0,0,0,0.4) on a near-black ground, i.e. invisible,\n so the selected thumb read as fill-only in dark and fill+shadow in light —\n two looks for one state. The hairline does the separating in both. */\n.option[aria-checked='true'] {\n background: var(--bg-surface);\n color: var(--text-primary);\n border-color: var(--border-default);\n}\n\n.option:disabled {\n color: var(--text-disabled);\n cursor: not-allowed;\n}\n\n.glyph {\n display: inline-flex;\n flex: none;\n}\n","/**\n * components/primitives/Segmented.tsx — pick one of 2-4 options where the\n * choice applies instantly (theme, density, a status filter). It replaces\n * both a <select> (too heavy for three options) and a row of toggle buttons\n * (no single-selection semantics for a screen reader).\n *\n * Implemented as a radiogroup with ROVING TABINDEX: one Tab stop for the\n * group, arrows move between options and select as they go — the WAI-ARIA\n * radio-group pattern. Every option is reachable by keyboard and announced\n * as \"N of M\".\n */\nimport { useRef, type ReactNode } from 'react';\nimport styles from './Segmented.module.css';\n\nexport interface SegmentedOption<T extends string> {\n value: T;\n label: ReactNode;\n /** Leading 16px glyph; the text label always stays visible. */\n icon?: ReactNode;\n /** Spoken name when `label` is a glyph or an abbreviation. */\n ariaLabel?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedProps<T extends string> {\n options: ReadonlyArray<SegmentedOption<T>>;\n value: T;\n onChange: (next: T) => void;\n /** Accessible name for the group — required when no visible label precedes it. */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n size?: 'sm' | 'md';\n /** Stretch each option to an equal share of the width. */\n block?: boolean;\n className?: string;\n}\n\nexport function Segmented<T extends string>({\n options,\n value,\n onChange,\n size = 'md',\n block = false,\n className,\n ...aria\n}: SegmentedProps<T>) {\n const groupRef = useRef<HTMLDivElement>(null);\n\n function move(delta: number): void {\n const enabled = options.filter((o) => !o.disabled);\n if (enabled.length === 0) return;\n const current = enabled.findIndex((o) => o.value === value);\n const next = enabled[(((current + delta) % enabled.length) + enabled.length) % enabled.length]!;\n onChange(next.value);\n // Keep DOM focus on the newly selected option (roving tabindex).\n requestAnimationFrame(() => {\n groupRef.current?.querySelector<HTMLButtonElement>(`[data-value=\"${next.value}\"]`)?.focus();\n });\n }\n\n return (\n <div\n ref={groupRef}\n role=\"radiogroup\"\n className={`${styles.group} ${styles[size]} ${block ? styles.block : ''} ${className ?? ''}`}\n {...aria}\n >\n {options.map((option) => {\n const selected = option.value === value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n aria-label={option.ariaLabel}\n data-value={option.value}\n tabIndex={selected ? 0 : -1}\n disabled={option.disabled}\n className={styles.option}\n onClick={() => onChange(option.value)}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n move(1);\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n move(-1);\n }\n }}\n >\n {option.icon ? <span className={styles.glyph}>{option.icon}</span> : null}\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":"kMCqCA,SAAgB,EAA4B,CAC1C,UACA,QACA,WACA,OAAO,KACP,QAAQ,GACR,YACA,GAAG,GACiB,CACpB,IAAM,GAAA,EAAW,EAAA,OAAA,CAAuB,IAAI,EAE5C,SAAS,EAAK,EAAqB,CACjC,IAAM,EAAU,EAAQ,OAAQ,GAAM,CAAC,EAAE,QAAQ,EACjD,GAAI,EAAQ,SAAW,EAAG,OAE1B,IAAM,EAAO,IADG,EAAQ,UAAW,GAAM,EAAE,QAAU,CAC7B,EAAU,GAAS,EAAQ,OAAU,EAAQ,QAAU,EAAQ,QACvF,EAAS,EAAK,KAAK,EAEnB,0BAA4B,CAC1B,EAAS,SAAS,cAAiC,gBAAgB,EAAK,MAAM,GAAG,CAAC,EAAE,MAAM,CAC5F,CAAC,CACH,CAEA,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,EACL,KAAK,aACL,UAAW,GAAG,EAAO,MAAM,GAAG,EAAO,GAAM,GAAG,EAAQ,EAAO,MAAQ,GAAG,GAAG,GAAa,KACxF,GAAI,EAEH,SAAA,EAAQ,IAAK,GAAW,CACvB,IAAM,EAAW,EAAO,QAAU,EAClC,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CAEE,KAAK,SACL,KAAK,QACL,eAAc,EACd,aAAY,EAAO,UACnB,aAAY,EAAO,MACnB,SAAU,EAAW,EAAI,GACzB,SAAU,EAAO,SACjB,UAAW,EAAO,OAClB,YAAe,EAAS,EAAO,KAAK,EACpC,UAAY,GAAM,CACZ,EAAE,MAAQ,cAAgB,EAAE,MAAQ,aACtC,EAAE,eAAe,EACjB,EAAK,CAAC,IACG,EAAE,MAAQ,aAAe,EAAE,MAAQ,aAC5C,EAAE,eAAe,EACjB,EAAK,EAAE,EAEX,EAnBF,SAAA,CAqBG,EAAO,MAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,EAAO,IAAW,CAAA,EAAI,KACpE,EAAO,KACF,CAtBD,EAAA,EAAO,KAsBN,CAEZ,CAAC,CACE,CAAA,CAET"}
@@ -1,2 +1,2 @@
1
- import{a as e,n as t,s as n}from"./index-oAAq8XJa.js";import{a as r}from"./icons-B_yuAgdN.js";var i=n(e(),1),a={field:`_field_1yhua_1`,label:`_label_1yhua_8`,shell:`_shell_1yhua_15`,sm:`_sm_1yhua_28`,select:`_select_1yhua_42`,chevron:`_chevron_1yhua_72`,hint:`_hint_1yhua_79`},o=t();function s({label:e,hint:t,size:n=`md`,className:s,id:c,children:l,...u}){let d=(0,i.useId)(),f=c??d,p=`${f}-hint`;return(0,o.jsxs)(`div`,{className:`${a.field} ${s??``}`,children:[e?(0,o.jsx)(`label`,{className:a.label,htmlFor:f,children:e}):null,(0,o.jsxs)(`div`,{className:`${a.shell} ${a[n]}`,children:[(0,o.jsx)(`select`,{...u,id:f,className:a.select,"aria-describedby":[u[`aria-describedby`],t?p:null].filter(Boolean).join(` `)||void 0,children:l}),(0,o.jsx)(r,{className:a.chevron,size:14})]}),t?(0,o.jsx)(`p`,{id:p,className:a.hint,children:t}):null]})}export{s as t};
2
- //# sourceMappingURL=Select-FWLnAw_j.js.map
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{i as r}from"./icons-DEQa2rTx.js";var i=n(e(),1),a={field:`_field_1yhua_1`,label:`_label_1yhua_8`,shell:`_shell_1yhua_15`,sm:`_sm_1yhua_28`,select:`_select_1yhua_42`,chevron:`_chevron_1yhua_72`,hint:`_hint_1yhua_79`},o=t();function s({label:e,hint:t,size:n=`md`,className:s,id:c,children:l,...u}){let d=(0,i.useId)(),f=c??d,p=`${f}-hint`;return(0,o.jsxs)(`div`,{className:`${a.field} ${s??``}`,children:[e?(0,o.jsx)(`label`,{className:a.label,htmlFor:f,children:e}):null,(0,o.jsxs)(`div`,{className:`${a.shell} ${a[n]}`,children:[(0,o.jsx)(`select`,{...u,id:f,className:a.select,"aria-describedby":[u[`aria-describedby`],t?p:null].filter(Boolean).join(` `)||void 0,children:l}),(0,o.jsx)(r,{className:a.chevron,size:14})]}),t?(0,o.jsx)(`p`,{id:p,className:a.hint,children:t}):null]})}export{s as t};
2
+ //# sourceMappingURL=Select-BwSGkHCS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Select-FWLnAw_j.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Select.module.css","../../../../../../src/web-ui/components/primitives/Select.tsx"],"sourcesContent":[".field {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n}\n\n.label {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n font-weight: var(--font-weight-medium);\n}\n\n.shell {\n position: relative;\n display: flex;\n align-items: center;\n height: var(--density-row);\n background: var(--bg-input);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n transition:\n border-color var(--duration-fast) var(--ease-standard),\n box-shadow var(--duration-fast) var(--ease-standard);\n}\n\n.sm {\n height: var(--density-row-sm);\n}\n\n.shell:hover {\n border-color: var(--border-strong);\n}\n\n/* The system ring, not an --accent-100 wash: that token is pinned at 92%\n lightness in light and 22% in dark (tokens.css), so hue and saturation\n follow the operator's accent but LIGHTNESS never does — every preset and\n every slider position produced the same 1.34:1 / 1.15:1 near-invisible\n ring. --shadow-focus-ring is already the 2px-gap + 2px-accent shape\n DESIGN-V2 §6 asks for, and --border-focus is contrast-tested. */\n.shell:has(.select:focus-visible) {\n border-color: var(--border-focus);\n box-shadow: var(--shadow-focus-ring);\n}\n\n.select {\n appearance: none;\n -webkit-appearance: none;\n width: 100%;\n height: 100%;\n padding: 0 var(--space-6) 0 var(--space-2);\n border: none;\n background: none;\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n cursor: pointer;\n}\n\n.select:focus,\n.select:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.select:disabled {\n color: var(--text-disabled);\n cursor: not-allowed;\n}\n\n.chevron {\n position: absolute;\n right: var(--space-2);\n color: var(--text-tertiary);\n pointer-events: none;\n}\n\n.hint {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n}\n","/**\n * components/primitives/Select.tsx — a native <select> that does not look\n * native: the browser's own control is stripped and the chevron is our own\n * 16px glyph, so the field matches Input at every density.\n *\n * Deliberately NOT a custom listbox. A native select gets the platform's\n * keyboard handling, type-ahead, and mobile picker for free — a hand-rolled\n * popup would be a worse control with more code (DESIGN.md §3).\n */\nimport { useId, type ReactNode, type SelectHTMLAttributes } from 'react';\nimport { IconChevronDown } from './icons.js';\nimport styles from './Select.module.css';\n\nexport interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size' | 'className'> {\n label?: ReactNode;\n hint?: ReactNode;\n size?: 'sm' | 'md';\n className?: string;\n children: ReactNode;\n}\n\nexport function Select({ label, hint, size = 'md', className, id, children, ...rest }: SelectProps) {\n const generatedId = useId();\n const selectId = id ?? generatedId;\n const hintId = `${selectId}-hint`;\n\n return (\n <div className={`${styles.field} ${className ?? ''}`}>\n {label ? (\n <label className={styles.label} htmlFor={selectId}>\n {label}\n </label>\n ) : null}\n <div className={`${styles.shell} ${styles[size]}`}>\n <select\n {...rest}\n id={selectId}\n className={styles.select}\n aria-describedby={[rest['aria-describedby'], hint ? hintId : null].filter(Boolean).join(' ') || undefined}\n >\n {children}\n </select>\n <IconChevronDown className={styles.chevron} size={14} />\n </div>\n {hint ? (\n <p id={hintId} className={styles.hint}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"2RCqBA,SAAgB,EAAO,CAAE,QAAO,OAAM,OAAO,KAAM,YAAW,KAAI,WAAU,GAAG,GAAqB,CAClG,IAAM,GAAA,EAAc,EAAA,MAAA,CAAM,EACpB,EAAW,GAAM,EACjB,EAAS,GAAG,EAAS,OAE3B,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,MAAM,GAAG,GAAa,KAAhD,SAAA,CACG,GACC,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAW,EAAO,MAAO,QAAS,EACtC,SAAA,CACI,CAAA,EACL,MACJ,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,MAAM,GAAG,EAAO,KAA1C,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,GAAI,EACJ,GAAI,EACJ,UAAW,EAAO,OAClB,mBAAkB,CAAC,EAAK,oBAAqB,EAAO,EAAS,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,GAAK,IAAA,GAE/F,UACK,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,UAAW,EAAO,QAAS,KAAM,EAAK,CAAA,CACpD,IACJ,GACC,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,GAAI,EAAQ,UAAW,EAAO,KAC9B,SAAA,CACA,CAAA,EACD,IACD,GAET"}
1
+ {"version":3,"file":"Select-BwSGkHCS.js","names":[],"sources":["../../../../../../src/web-ui/components/primitives/Select.module.css","../../../../../../src/web-ui/components/primitives/Select.tsx"],"sourcesContent":[".field {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n min-width: 0;\n}\n\n.label {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n font-weight: var(--font-weight-medium);\n}\n\n.shell {\n position: relative;\n display: flex;\n align-items: center;\n height: var(--density-row);\n background: var(--bg-input);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n transition:\n border-color var(--duration-fast) var(--ease-standard),\n box-shadow var(--duration-fast) var(--ease-standard);\n}\n\n.sm {\n height: var(--density-row-sm);\n}\n\n.shell:hover {\n border-color: var(--border-strong);\n}\n\n/* The system ring, not an --accent-100 wash: that token is pinned at 92%\n lightness in light and 22% in dark (tokens.css), so hue and saturation\n follow the operator's accent but LIGHTNESS never does — every preset and\n every slider position produced the same 1.34:1 / 1.15:1 near-invisible\n ring. --shadow-focus-ring is already the 2px-gap + 2px-accent shape\n DESIGN-V2 §6 asks for, and --border-focus is contrast-tested. */\n.shell:has(.select:focus-visible) {\n border-color: var(--border-focus);\n box-shadow: var(--shadow-focus-ring);\n}\n\n.select {\n appearance: none;\n -webkit-appearance: none;\n width: 100%;\n height: 100%;\n padding: 0 var(--space-6) 0 var(--space-2);\n border: none;\n background: none;\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-sm-size);\n cursor: pointer;\n}\n\n.select:focus,\n.select:focus-visible {\n outline: none;\n box-shadow: none;\n}\n\n.select:disabled {\n color: var(--text-disabled);\n cursor: not-allowed;\n}\n\n.chevron {\n position: absolute;\n right: var(--space-2);\n color: var(--text-tertiary);\n pointer-events: none;\n}\n\n.hint {\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-tertiary);\n}\n","/**\n * components/primitives/Select.tsx — a native <select> that does not look\n * native: the browser's own control is stripped and the chevron is our own\n * 16px glyph, so the field matches Input at every density.\n *\n * Deliberately NOT a custom listbox. A native select gets the platform's\n * keyboard handling, type-ahead, and mobile picker for free — a hand-rolled\n * popup would be a worse control with more code (DESIGN.md §3).\n */\nimport { useId, type ReactNode, type SelectHTMLAttributes } from 'react';\nimport { IconChevronDown } from './icons.js';\nimport styles from './Select.module.css';\n\nexport interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size' | 'className'> {\n label?: ReactNode;\n hint?: ReactNode;\n size?: 'sm' | 'md';\n className?: string;\n children: ReactNode;\n}\n\nexport function Select({ label, hint, size = 'md', className, id, children, ...rest }: SelectProps) {\n const generatedId = useId();\n const selectId = id ?? generatedId;\n const hintId = `${selectId}-hint`;\n\n return (\n <div className={`${styles.field} ${className ?? ''}`}>\n {label ? (\n <label className={styles.label} htmlFor={selectId}>\n {label}\n </label>\n ) : null}\n <div className={`${styles.shell} ${styles[size]}`}>\n <select\n {...rest}\n id={selectId}\n className={styles.select}\n aria-describedby={[rest['aria-describedby'], hint ? hintId : null].filter(Boolean).join(' ') || undefined}\n >\n {children}\n </select>\n <IconChevronDown className={styles.chevron} size={14} />\n </div>\n {hint ? (\n <p id={hintId} className={styles.hint}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"2RCqBA,SAAgB,EAAO,CAAE,QAAO,OAAM,OAAO,KAAM,YAAW,KAAI,WAAU,GAAG,GAAqB,CAClG,IAAM,GAAA,EAAc,EAAA,MAAA,CAAM,EACpB,EAAW,GAAM,EACjB,EAAS,GAAG,EAAS,OAE3B,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,MAAM,GAAG,GAAa,KAAhD,SAAA,CACG,GACC,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAW,EAAO,MAAO,QAAS,EACtC,SAAA,CACI,CAAA,EACL,MACJ,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,GAAG,EAAO,MAAM,GAAG,EAAO,KAA1C,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,GAAI,EACJ,GAAI,EACJ,UAAW,EAAO,OAClB,mBAAkB,CAAC,EAAK,oBAAqB,EAAO,EAAS,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,GAAK,IAAA,GAE/F,UACK,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAiB,UAAW,EAAO,QAAS,KAAM,EAAK,CAAA,CACpD,IACJ,GACC,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,GAAI,EAAQ,UAAW,EAAO,KAC9B,SAAA,CACA,CAAA,EACD,IACD,GAET"}
@@ -0,0 +1 @@
1
+ ._wrap_14qw9_1{min-height:100%;padding:var(--space-6);background:var(--bg-canvas);justify-content:center;align-items:center;display:flex}._card_14qw9_10{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);width:min(480px,100%);box-shadow:var(--shadow-lg);padding:var(--space-8)}._badge_14qw9_19{margin-bottom:var(--space-4);font-size:28px}._heading_14qw9_24{font-size:var(--text-2xl-size);line-height:var(--text-2xl-line);font-weight:var(--font-weight-semibold);margin-bottom:var(--space-3)}._body_14qw9_31{font-size:var(--text-sm-size);line-height:var(--text-sm-line);color:var(--text-secondary);margin-bottom:var(--space-3)}._code_14qw9_38{font-family:var(--font-mono);font-size:var(--text-sm-size);background:var(--bg-code);border:1px solid var(--border-subtle);border-radius:var(--radius-sm);padding:var(--space-3);margin-bottom:var(--space-3);overflow-x:auto}._example_14qw9_49{font-family:var(--font-mono);background:var(--bg-code);border-radius:var(--radius-xs);padding:1px 4px}._form_14qw9_56{gap:var(--space-2);margin-top:var(--space-5);flex-direction:column;display:flex}._label_14qw9_63{font-size:var(--text-sm-size);font-weight:var(--font-weight-medium)}._input_14qw9_68{padding:var(--space-3);border-radius:var(--radius-md);border:1px solid var(--border-default);background:var(--bg-input);font-family:var(--font-mono);font-size:var(--text-sm-size)}._input_14qw9_68:focus-visible{border-color:var(--border-focus);box-shadow:var(--shadow-focus-ring)}._error_14qw9_82{color:var(--status-danger-fg);font-size:var(--text-sm-size)}._submit_14qw9_87{margin-top:var(--space-2);padding:var(--space-3) var(--space-4);background:var(--accent-500);color:var(--text-on-accent);border-radius:var(--radius-md);font-weight:var(--font-weight-medium);text-align:center;transition:background var(--duration-fast) var(--ease-standard)}._submit_14qw9_87:hover:not(:disabled){background:var(--accent-600)}._submit_14qw9_87:disabled{opacity:.5;cursor:not-allowed}._optional_14qw9_107{font-weight:var(--font-weight-normal,400);color:var(--text-tertiary)}
@@ -0,0 +1,2 @@
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{N as r,S as i,T as a}from"./global-oEl9Qj8u.js";var o=n(e(),1),s={wrap:`_wrap_14qw9_1`,card:`_card_14qw9_10`,badge:`_badge_14qw9_19`,heading:`_heading_14qw9_24`,body:`_body_14qw9_31`,code:`_code_14qw9_38`,example:`_example_14qw9_49`,form:`_form_14qw9_56`,label:`_label_14qw9_63`,input:`_input_14qw9_68`,error:`_error_14qw9_82`,submit:`_submit_14qw9_87`,optional:`_optional_14qw9_107`},c=t(),l=/^[a-f0-9]{64}$/;function u({onAuthenticated:e,heading:t=`Connect to ashlr serve`,command:n=`ashlr serve`,subject:u=`This dashboard`,mutationField:d=!1}){let[f,p]=(0,o.useState)(``),[m,h]=(0,o.useState)(``),[g,_]=(0,o.useState)(null),[v,y]=(0,o.useState)(!1),b=(0,o.useRef)(null),x=(0,o.useId)(),S=(0,o.useId)(),C=(0,o.useId)(),w=(0,o.useRef)(e);w.current=e,(0,o.useEffect)(()=>{let e=!1;return i().then(t=>{t&&!e&&w.current?.()}),()=>{e=!0}},[]);async function T(t){t.preventDefault(),_(null);let n=m.trim();if(d&&n&&!l.test(n)){_(`That does not look like a mutation token — expected 64 hex characters (leave it empty to unlock later).`);return}y(!0);try{await a(f),p(``),d&&n&&r(n),h(``),e?.()}catch(e){_(e instanceof Error?e.message:`Could not establish a session.`),b.current?.select()}finally{y(!1)}}return(0,c.jsx)(`div`,{className:s.wrap,children:(0,c.jsxs)(`div`,{className:s.card,children:[(0,c.jsx)(`div`,{className:s.badge,"aria-hidden":`true`,children:`⛺`}),(0,c.jsx)(`h1`,{className:s.heading,children:t}),(0,c.jsxs)(`p`,{className:s.body,children:[u,` only ever talks to the ashlr server running on this machine (`,(0,c.jsx)(`code`,{children:`127.0.0.1`}),`, never a remote host). To read data, paste the`,` `,(0,c.jsx)(`strong`,{children:`read token`}),` printed in the terminal where you ran:`]}),(0,c.jsx)(`pre`,{className:s.code,children:n}),(0,c.jsxs)(`p`,{className:s.body,children:[`It looks like a 64-character hex string, printed once at startup — something like`,` `,(0,c.jsx)(`code`,{className:s.example,children:`a1b2c3…`}),`. This dialog never stores it: it is exchanged once for a short-lived session cookie, then discarded.`]}),(0,c.jsxs)(`form`,{onSubmit:T,className:s.form,noValidate:!0,children:[(0,c.jsx)(`label`,{htmlFor:x,className:s.label,children:`Read token`}),(0,c.jsx)(`input`,{ref:b,id:x,name:`read-token`,type:`password`,autoComplete:`off`,autoCorrect:`off`,spellCheck:!1,inputMode:`text`,className:s.input,value:f,onChange:e=>p(e.target.value),"aria-invalid":g?!0:void 0,"aria-describedby":g?C:void 0,placeholder:`64 hex characters`,autoFocus:!0}),d?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(`label`,{htmlFor:S,className:s.label,children:[`Mutation token `,(0,c.jsx)(`span`,{className:s.optional,children:`optional — paste it now to enable sending`})]}),(0,c.jsx)(`input`,{id:S,name:`mutation-token`,type:`password`,autoComplete:`off`,autoCorrect:`off`,spellCheck:!1,inputMode:`text`,className:s.input,value:m,onChange:e=>h(e.target.value),placeholder:`64 hex characters, printed under “Dispatch enabled”`})]}):null,g?(0,c.jsx)(`p`,{id:C,className:s.error,role:`alert`,children:g}):null,(0,c.jsx)(`button`,{type:`submit`,className:s.submit,disabled:v||f.trim().length===0,children:v?`Connecting…`:`Connect`})]})]})})}export{u as SessionGate};
2
+ //# sourceMappingURL=SessionGate-e0dFJm9d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionGate-e0dFJm9d.js","names":[],"sources":["../../../../../../src/web-ui/components/auth/SessionGate.module.css","../../../../../../src/web-ui/components/auth/SessionGate.tsx"],"sourcesContent":[".wrap {\n min-height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--space-6);\n background: var(--bg-canvas);\n}\n\n.card {\n width: min(480px, 100%);\n background: var(--bg-surface);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xl);\n box-shadow: var(--shadow-lg);\n padding: var(--space-8);\n}\n\n.badge {\n font-size: 28px;\n margin-bottom: var(--space-4);\n}\n\n.heading {\n font-size: var(--text-2xl-size);\n line-height: var(--text-2xl-line);\n font-weight: var(--font-weight-semibold);\n margin-bottom: var(--space-3);\n}\n\n.body {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n color: var(--text-secondary);\n margin-bottom: var(--space-3);\n}\n\n.code {\n font-family: var(--font-mono);\n font-size: var(--text-sm-size);\n background: var(--bg-code);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n padding: var(--space-3);\n margin-bottom: var(--space-3);\n overflow-x: auto;\n}\n\n.example {\n font-family: var(--font-mono);\n background: var(--bg-code);\n padding: 1px 4px;\n border-radius: var(--radius-xs);\n}\n\n.form {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin-top: var(--space-5);\n}\n\n.label {\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n}\n\n.input {\n padding: var(--space-3);\n border-radius: var(--radius-md);\n border: 1px solid var(--border-default);\n background: var(--bg-input);\n font-family: var(--font-mono);\n font-size: var(--text-sm-size);\n}\n\n.input:focus-visible {\n border-color: var(--border-focus);\n box-shadow: var(--shadow-focus-ring);\n}\n\n.error {\n color: var(--status-danger-fg);\n font-size: var(--text-sm-size);\n}\n\n.submit {\n margin-top: var(--space-2);\n padding: var(--space-3) var(--space-4);\n background: var(--accent-500);\n color: var(--text-on-accent);\n border-radius: var(--radius-md);\n font-weight: var(--font-weight-medium);\n text-align: center;\n transition: background var(--duration-fast) var(--ease-standard);\n}\n\n.submit:hover:not(:disabled) {\n background: var(--accent-600);\n}\n\n.submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.optional { font-weight: var(--font-weight-normal, 400); color: var(--text-tertiary); }\n","/**\n * components/auth/SessionGate.tsx — replaces the old bare \"⚠ HTTP 401 +\n * Retry\" first-run experience (foundation brief item 5). Shown whenever\n * auth-store's phase is 'unauthenticated': on first load before any read\n * token has been entered, AND any time a session expires mid-use (SSE\n * disconnects, the next GET reports 401).\n *\n * By default this screen owns nothing about the MUTATION token — that is a\n * separate, later step (MutationTokenDialog), because read authority and\n * dispatch authority are genuinely different capabilities on this server\n * (see server.ts). Surfaces where sending is the whole point (Verse) can opt\n * into an optional second field with `mutationField`; the authorities stay\n * separate (the mutation token only ever enters the memory-only hold), it\n * just spares the operator a second paste screen on the first Enter.\n */\nimport { useEffect, useId, useRef, useState, type FormEvent } from 'react';\nimport { adoptInjectedTokens, establishReadSession, setMutationToken } from '../../data/auth-store.js';\nimport styles from './SessionGate.module.css';\n\nconst TOKEN_RE = /^[a-f0-9]{64}$/;\n\nexport interface SessionGateProps {\n onAuthenticated?: () => void;\n heading?: string;\n command?: string;\n /** What the copy calls this surface (\"This dashboard\", \"Ashlr Verse\"). */\n subject?: string;\n /**\n * Also offer the mutation token on the same screen. The two authorities\n * stay separate (a pasted mutation token goes straight into the memory-only\n * hold, exactly as MutationTokenDialog would set it); this only collapses\n * two paste screens into one for surfaces where sending is the whole point.\n */\n mutationField?: boolean;\n}\n\nexport function SessionGate({ onAuthenticated, heading = 'Connect to ashlr serve', command = 'ashlr serve', subject = 'This dashboard', mutationField = false }: SessionGateProps) {\n const [token, setToken] = useState('');\n const [mutation, setMutation] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = useId();\n const mutationId = useId();\n const errorId = useId();\n const authenticatedRef = useRef(onAuthenticated);\n authenticatedRef.current = onAuthenticated;\n\n // Desktop wrapper: when the host injected tokens (window.__ASHLR_TOKENS__),\n // establish the session silently instead of asking for a paste.\n useEffect(() => {\n let cancelled = false;\n void adoptInjectedTokens().then((adopted) => {\n if (adopted && !cancelled) authenticatedRef.current?.();\n });\n return () => { cancelled = true; };\n }, []);\n\n async function onSubmit(e: FormEvent) {\n e.preventDefault();\n setError(null);\n const mutationTrimmed = mutation.trim();\n if (mutationField && mutationTrimmed && !TOKEN_RE.test(mutationTrimmed)) {\n setError('That does not look like a mutation token — expected 64 hex characters (leave it empty to unlock later).');\n return;\n }\n setBusy(true);\n try {\n await establishReadSession(token);\n setToken('');\n if (mutationField && mutationTrimmed) setMutationToken(mutationTrimmed);\n setMutation('');\n onAuthenticated?.();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Could not establish a session.');\n inputRef.current?.select();\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <div className={styles.wrap}>\n <div className={styles.card}>\n <div className={styles.badge} aria-hidden=\"true\">\n ⛺\n </div>\n <h1 className={styles.heading}>{heading}</h1>\n <p className={styles.body}>\n {subject} only ever talks to the ashlr server running on this machine\n (<code>127.0.0.1</code>, never a remote host). To read data, paste the{' '}\n <strong>read token</strong> printed in the terminal where you ran:\n </p>\n <pre className={styles.code}>{command}</pre>\n <p className={styles.body}>\n It looks like a 64-character hex string, printed once at startup — something like{' '}\n <code className={styles.example}>a1b2c3…</code>. This dialog never stores it: it is\n exchanged once for a short-lived session cookie, then discarded.\n </p>\n <form onSubmit={onSubmit} className={styles.form} noValidate>\n <label htmlFor={inputId} className={styles.label}>\n Read token\n </label>\n <input\n ref={inputRef}\n id={inputId}\n name=\"read-token\"\n type=\"password\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"text\"\n className={styles.input}\n value={token}\n onChange={(e) => setToken(e.target.value)}\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n placeholder=\"64 hex characters\"\n autoFocus\n />\n {mutationField ? (\n <>\n <label htmlFor={mutationId} className={styles.label}>\n Mutation token <span className={styles.optional}>optional — paste it now to enable sending</span>\n </label>\n <input\n id={mutationId}\n name=\"mutation-token\"\n type=\"password\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"text\"\n className={styles.input}\n value={mutation}\n onChange={(e) => setMutation(e.target.value)}\n placeholder=\"64 hex characters, printed under “Dispatch enabled”\"\n />\n </>\n ) : null}\n {error ? (\n <p id={errorId} className={styles.error} role=\"alert\">\n {error}\n </p>\n ) : null}\n <button type=\"submit\" className={styles.submit} disabled={busy || token.trim().length === 0}>\n {busy ? 'Connecting…' : 'Connect'}\n </button>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{p as r}from"./global-oEl9Qj8u.js";import{l as i}from"./format-BkWdOQDL.js";import{n as a}from"./nav-NVtnuG7A.js";import{d as o}from"./surface-data-DTI7LjvH.js";import{n as s,o as c,t as l}from"./mind.module-gTGAuJt1.js";var u=n(e(),1),d=t();function f({sessionId:e}){let t=r(o,{freshMs:6e4}),[n,f]=(0,u.useState)(!1),p=(0,u.useId)(),m=c(t.data?.value??null,e);if(m.length===0)return null;let h=m[0],g=`${s[h.kind]} · ${h.count}×`;function _(e){e.key===`Escape`&&n&&(e.stopPropagation(),f(!1))}return(0,d.jsxs)(`span`,{className:l.chipWrap,onKeyDown:_,children:[(0,d.jsxs)(`button`,{type:`button`,className:l.chip,"data-severity":h.severity,"aria-expanded":n,"aria-controls":p,"aria-label":`Reasoning insight for this chat: ${h.title}${m.length>1?` and ${m.length-1} more`:``}`,onClick:()=>f(e=>!e),children:[(0,d.jsx)(`span`,{className:l.chipDot,"data-severity":h.severity,"aria-hidden":`true`}),g,m.length>1?(0,d.jsxs)(`span`,{className:l.chipMore,children:[`+`,m.length-1]}):null]}),n?(0,d.jsxs)(`div`,{id:p,className:l.chipPanel,role:`region`,"aria-label":`Insights for this chat`,children:[(0,d.jsx)(`ul`,{className:l.chipList,children:m.map(e=>(0,d.jsxs)(`li`,{children:[(0,d.jsx)(`span`,{className:l.insightTitle,children:e.title}),(0,d.jsxs)(`span`,{className:l.insightMeta,children:[s[e.kind],` · `,e.count,`× · last seen `,i(e.lastAt)]})]},e.id))}),(0,d.jsx)(`button`,{type:`button`,className:l.link,onClick:()=>{f(!1),a(`mind`,`insight-${h.id}`)},children:`See it in Mind`})]}):null]})}export{f as SessionInsightChip};
2
+ //# sourceMappingURL=SessionInsightChip-CxlSyueJ.js.map