@ashlr/hub 3.11.3 → 3.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +44 -18
- package/dist/authority-surface.json +72 -57
- package/dist/build-identity.json +2 -2
- package/dist/cli/authority.d.ts +39 -0
- package/dist/cli/authority.js +222 -55
- package/dist/cli/authority.js.map +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/verse.d.ts +3 -0
- package/dist/cli/verse.js +10 -0
- package/dist/cli/verse.js.map +1 -1
- package/dist/core/authority/types.d.ts +2 -2
- package/dist/core/cloud/cloud-api.js +1 -1
- package/dist/core/cloud/cloud-api.js.map +1 -1
- package/dist/core/cloud/delivery-contract.d.ts +1 -1
- package/dist/core/cloud/delivery-contract.js +25 -15
- package/dist/core/cloud/delivery-contract.js.map +1 -1
- package/dist/core/cloud/store.js +6 -0
- package/dist/core/cloud/store.js.map +1 -1
- package/dist/core/cloud/tracker.d.ts +2 -0
- package/dist/core/cloud/tracker.js +140 -37
- package/dist/core/cloud/tracker.js.map +1 -1
- package/dist/core/cloud/types.d.ts +9 -1
- package/dist/core/cloud/types.js.map +1 -1
- package/dist/core/comms/dispatch.d.ts +5 -0
- package/dist/core/comms/dispatch.js +12 -1
- package/dist/core/comms/dispatch.js.map +1 -1
- package/dist/core/comms/requests.d.ts +27 -1
- package/dist/core/comms/requests.js +50 -1
- package/dist/core/comms/requests.js.map +1 -1
- package/dist/core/daemon/loop.d.ts +14 -0
- package/dist/core/daemon/loop.js +35 -0
- package/dist/core/daemon/loop.js.map +1 -1
- package/dist/core/fabric/claude-usage.js +23 -1
- package/dist/core/fabric/claude-usage.js.map +1 -1
- package/dist/core/fleet/dispatch-router.d.ts +7 -0
- package/dist/core/fleet/dispatch-router.js +4 -1
- package/dist/core/fleet/dispatch-router.js.map +1 -1
- package/dist/core/fleet/tick-hooks-live.d.ts +5 -1
- package/dist/core/fleet/tick-hooks-live.js +10 -1
- package/dist/core/fleet/tick-hooks-live.js.map +1 -1
- package/dist/core/local-runtime/llama/config.d.ts +14 -0
- package/dist/core/local-runtime/llama/config.js +20 -2
- package/dist/core/local-runtime/llama/config.js.map +1 -1
- package/dist/core/local-runtime/llama/process.d.ts +19 -0
- package/dist/core/local-runtime/llama/process.js +67 -17
- package/dist/core/local-runtime/llama/process.js.map +1 -1
- package/dist/core/local-runtime/llama/supervisor.js +14 -3
- package/dist/core/local-runtime/llama/supervisor.js.map +1 -1
- package/dist/core/observability/rollup.d.ts +12 -0
- package/dist/core/observability/rollup.js +37 -2
- package/dist/core/observability/rollup.js.map +1 -1
- package/dist/core/observability/usage-source.js +49 -1
- package/dist/core/observability/usage-source.js.map +1 -1
- package/dist/core/resources/connection-monitor.js +47 -4
- package/dist/core/resources/connection-monitor.js.map +1 -1
- package/dist/core/resources/engineering-mission-store.d.ts +1 -1
- package/dist/core/routing/headroom.js +7 -2
- package/dist/core/routing/headroom.js.map +1 -1
- package/dist/core/routing/router.d.ts +48 -0
- package/dist/core/routing/router.js +129 -13
- package/dist/core/routing/router.js.map +1 -1
- package/dist/core/run/best-of-n.d.ts +7 -0
- package/dist/core/run/best-of-n.js +3 -0
- package/dist/core/run/best-of-n.js.map +1 -1
- package/dist/core/run/harness-dispatch.d.ts +147 -0
- package/dist/core/run/harness-dispatch.js +234 -0
- package/dist/core/run/harness-dispatch.js.map +1 -0
- package/dist/core/run/orchestrator.js +3 -0
- package/dist/core/run/orchestrator.js.map +1 -1
- package/dist/core/run/provider-client.d.ts +8 -0
- package/dist/core/run/provider-client.js +4 -0
- package/dist/core/run/provider-client.js.map +1 -1
- package/dist/core/run/sandboxed-engine.d.ts +8 -0
- package/dist/core/run/sandboxed-engine.js +60 -7
- package/dist/core/run/sandboxed-engine.js.map +1 -1
- package/dist/core/types.d.ts +14 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/universe/builtins/preparation/manifest.json +1 -1
- package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +181 -5
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +180 -4
- package/dist/core/universe/firm-demo.d.ts +1 -1
- package/dist/core/universe/firm-graph.d.ts +2 -2
- package/dist/core/util/scrub.js +16 -3
- package/dist/core/util/scrub.js.map +1 -1
- package/dist/core/verse/accounts.d.ts +9 -1
- package/dist/core/verse/accounts.js +52 -11
- package/dist/core/verse/accounts.js.map +1 -1
- package/dist/core/verse/apps-api.d.ts +12 -0
- package/dist/core/verse/apps-api.js +22 -4
- package/dist/core/verse/apps-api.js.map +1 -1
- package/dist/core/verse/apps.js +22 -12
- package/dist/core/verse/apps.js.map +1 -1
- package/dist/core/verse/local-models.js +3 -7
- package/dist/core/verse/local-models.js.map +1 -1
- package/dist/core/verse/model-display-name.d.ts +34 -0
- package/dist/core/verse/model-display-name.js +125 -0
- package/dist/core/verse/model-display-name.js.map +1 -0
- package/dist/core/verse/seats.d.ts +11 -2
- package/dist/core/verse/seats.js +42 -18
- package/dist/core/verse/seats.js.map +1 -1
- package/dist/core/verse/transient-events.d.ts +21 -0
- package/dist/core/verse/transient-events.js +12 -0
- package/dist/core/verse/transient-events.js.map +1 -0
- package/dist/core/verse/types.d.ts +6 -13
- package/dist/core/verse/types.js +5 -36
- package/dist/core/verse/types.js.map +1 -1
- package/dist/core/web/public/next/assets/ActionMenu-DffwPklw.js +2 -0
- package/dist/core/web/public/next/assets/{ActionMenu-FxXeRbPx.js.map → ActionMenu-DffwPklw.js.map} +1 -1
- package/dist/core/web/public/next/assets/Advanced-CxzE6ekM.js +2 -0
- package/dist/core/web/public/next/assets/Advanced-CxzE6ekM.js.map +1 -0
- package/dist/core/web/public/next/assets/App-DFlp-vdv.js +7 -0
- package/dist/core/web/public/next/assets/App-DFlp-vdv.js.map +1 -0
- package/dist/core/web/public/next/assets/AppsSection-Ct2O605-.js +2 -0
- package/dist/core/web/public/next/assets/AppsSection-Ct2O605-.js.map +1 -0
- package/dist/core/web/public/next/assets/AreaTrend-o-GLl2Is.js +2 -0
- package/dist/core/web/public/next/assets/{AreaTrend-CDxrQU4b.js.map → AreaTrend-o-GLl2Is.js.map} +1 -1
- package/dist/core/web/public/next/assets/AutonomyOffState-CXhXpsim.js +2 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-CXhXpsim.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-DmbE71vI.css +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-BTg7yVa1.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-DuQkHGD_.js.map → AutonomySection-BTg7yVa1.js.map} +1 -1
- package/dist/core/web/public/next/assets/BranchBar-BjPFtGsj.js +2 -0
- package/dist/core/web/public/next/assets/{BranchBar-CLsvOcyK.js.map → BranchBar-BjPFtGsj.js.map} +1 -1
- package/dist/core/web/public/next/assets/BudgetControl-ng6swoZp.js +2 -0
- package/dist/core/web/public/next/assets/{BudgetControl-TL3FeZ1D.js.map → BudgetControl-ng6swoZp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Button-HHXgoXGr.js → Button-OjVJSrFq.js} +2 -2
- package/dist/core/web/public/next/assets/{Button-HHXgoXGr.js.map → Button-OjVJSrFq.js.map} +1 -1
- package/dist/core/web/public/next/assets/CapacityStrip-Bx4c3dxD.js +2 -0
- package/dist/core/web/public/next/assets/{CapacityStrip-qReu0RaF.js.map → CapacityStrip-Bx4c3dxD.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useChartWidth-BW6SwYIK.css → ChartFrame-BVuBe6RP.css} +1 -1
- package/dist/core/web/public/next/assets/ChartFrame-B_w2Siqg.js +2 -0
- package/dist/core/web/public/next/assets/ChartFrame-B_w2Siqg.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-Bisj9R6E.js +3 -0
- package/dist/core/web/public/next/assets/ChatSection-Bisj9R6E.js.map +1 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-5Gf4iAok.js +2 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-5Gf4iAok.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandPalette-iTpk6I8r.js +2 -0
- package/dist/core/web/public/next/assets/CommandPalette-iTpk6I8r.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +1 -0
- package/dist/core/web/public/next/assets/CommandSection-D8ZihzvE.js +2 -0
- package/dist/core/web/public/next/assets/CommandSection-D8ZihzvE.js.map +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-_S9iE-cJ.js +2 -0
- package/dist/core/web/public/next/assets/{ConfirmDialog-DLrLKM0c.js.map → ConfirmDialog-_S9iE-cJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/DeleteChatDialog-KUYUygiA.js +2 -0
- package/dist/core/web/public/next/assets/DeleteChatDialog-KUYUygiA.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-BuIaG6HF.js +2 -0
- package/dist/core/web/public/next/assets/{Dialog-BS9Dxi3G.js.map → Dialog-BuIaG6HF.js.map} +1 -1
- package/dist/core/web/public/next/assets/DiffPane-De4IQt82.js +2 -0
- package/dist/core/web/public/next/assets/{DiffPane-TOmUf3b2.js.map → DiffPane-De4IQt82.js.map} +1 -1
- package/dist/core/web/public/next/assets/DiffViewer-B75t6Ile.js +2 -0
- package/dist/core/web/public/next/assets/{DiffViewer-BpH56302.js.map → DiffViewer-B75t6Ile.js.map} +1 -1
- package/dist/core/web/public/next/assets/DockHost-BPqyhtCP.js +2 -0
- package/dist/core/web/public/next/assets/DockHost-BPqyhtCP.js.map +1 -0
- package/dist/core/web/public/next/assets/{EmptyState-BqR5YAmf.js → EmptyState-DXkT4vhW.js} +2 -2
- package/dist/core/web/public/next/assets/{EmptyState-BqR5YAmf.js.map → EmptyState-DXkT4vhW.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Epistemic-dhvDTwAZ.js → Epistemic-CfqFe_aP.js} +2 -2
- package/dist/core/web/public/next/assets/{Epistemic-dhvDTwAZ.js.map → Epistemic-CfqFe_aP.js.map} +1 -1
- package/dist/core/web/public/next/assets/FleetSection-B7f-XBiX.js +3 -0
- package/dist/core/web/public/next/assets/FleetSection-B7f-XBiX.js.map +1 -0
- package/dist/core/web/public/next/assets/Funnel-pXYySwXQ.js +2 -0
- package/dist/core/web/public/next/assets/{Funnel-D2u7Wlzc.js.map → Funnel-pXYySwXQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/GearTray-gj6lT7ba.js +2 -0
- package/dist/core/web/public/next/assets/{GearTray-Cb2npoxM.js.map → GearTray-gj6lT7ba.js.map} +1 -1
- package/dist/core/web/public/next/assets/GrowthSection-D8e9m9Wy.js +2 -0
- package/dist/core/web/public/next/assets/{GrowthSection-C5aDPs8B.js.map → GrowthSection-D8e9m9Wy.js.map} +1 -1
- package/dist/core/web/public/next/assets/HandoffDialog-VfKxKhxF.js +2 -0
- package/dist/core/web/public/next/assets/{HandoffDialog-BF3AYg-X.js.map → HandoffDialog-VfKxKhxF.js.map} +1 -1
- package/dist/core/web/public/next/assets/Input-u1YR_Ogl.js +2 -0
- package/dist/core/web/public/next/assets/{Input-B5dmGLZx.js.map → Input-u1YR_Ogl.js.map} +1 -1
- package/dist/core/web/public/next/assets/LeaderCard-BDELBrnx.js +2 -0
- package/dist/core/web/public/next/assets/LeaderCard-BDELBrnx.js.map +1 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-NKLF2srR.js +2 -0
- package/dist/core/web/public/next/assets/{MatrixHeatmap-BgEUs2Eu.js.map → MatrixHeatmap-NKLF2srR.js.map} +1 -1
- package/dist/core/web/public/next/assets/McpSection-D1tDvlRa.js +2 -0
- package/dist/core/web/public/next/assets/{McpSection-DZkiOuoq.js.map → McpSection-D1tDvlRa.js.map} +1 -1
- package/dist/core/web/public/next/assets/MessageMarkdown-DlfLEJxu.js +3 -0
- package/dist/core/web/public/next/assets/{MessageMarkdown-BauY8ZTY.js.map → MessageMarkdown-DlfLEJxu.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DLBNLfsn.js → MessageMarkdownRenderer-BYZzI115.js} +4 -4
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DLBNLfsn.js.map → MessageMarkdownRenderer-BYZzI115.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-DNeocJnD.js → Meter-BSVhU43Q.js} +2 -2
- package/dist/core/web/public/next/assets/{Meter-DNeocJnD.js.map → Meter-BSVhU43Q.js.map} +1 -1
- package/dist/core/web/public/next/assets/MindSection-lqV2e_Sq.js +2 -0
- package/dist/core/web/public/next/assets/MindSection-lqV2e_Sq.js.map +1 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-CLGP72g6.js +2 -0
- package/dist/core/web/public/next/assets/{MutationTokenDialog-mxrw0Yvy.js.map → MutationTokenDialog-CLGP72g6.js.map} +1 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-D992XTOn.js +2 -0
- package/dist/core/web/public/next/assets/{NeedsYouDrawer-CO-Balfp.js.map → NeedsYouDrawer-D992XTOn.js.map} +1 -1
- package/dist/core/web/public/next/assets/NeedsYouList-eBOlJr0b.js +2 -0
- package/dist/core/web/public/next/assets/{NeedsYouList-CzDZbzRD.js.map → NeedsYouList-eBOlJr0b.js.map} +1 -1
- package/dist/core/web/public/next/assets/NewChatDialog-DoYTH26M.js +3 -0
- package/dist/core/web/public/next/assets/NewChatDialog-DoYTH26M.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-D3yfITK1.js +2 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-D3yfITK1.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-HUNQGQuU.css +1 -0
- package/dist/core/web/public/next/assets/OnboardingGate-DrDEVBqw.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingGate-DrDEVBqw.js.map +1 -0
- package/dist/core/web/public/next/assets/PreviewPane-ULN673zm.js +2 -0
- package/dist/core/web/public/next/assets/{PreviewPane-BS-CleCd.js.map → PreviewPane-ULN673zm.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ProviderLogo-C5mBg8i0.js → ProviderLogo-8WaUjTlN.js} +2 -2
- package/dist/core/web/public/next/assets/{ProviderLogo-C5mBg8i0.js.map → ProviderLogo-8WaUjTlN.js.map} +1 -1
- package/dist/core/web/public/next/assets/RailStatus-Ckw9nvYU.js +2 -0
- package/dist/core/web/public/next/assets/{RailStatus-cPRyOmrk.js.map → RailStatus-Ckw9nvYU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RefreshIndicator-CMwSCiz5.js → RefreshIndicator-DGubF4vR.js} +2 -2
- package/dist/core/web/public/next/assets/{RefreshIndicator-CMwSCiz5.js.map → RefreshIndicator-DGubF4vR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BFi1opsC.js → ResourcePoolConsoleApp-BahEaY4d.js} +4 -4
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BFi1opsC.js.map → ResourcePoolConsoleApp-BahEaY4d.js.map} +1 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-C2ZrA7la.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-C2ZrA7la.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-BC93fzwQ.js +2 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-BC93fzwQ.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-BvhHNpE_.js +2 -0
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-DYtwc2ja.js.map → RouteErrorBoundary-BvhHNpE_.js.map} +1 -1
- package/dist/core/web/public/next/assets/RunInCloudAction-Dywfnw0C.js +2 -0
- package/dist/core/web/public/next/assets/{RunInCloudAction-BEGEEM8O.js.map → RunInCloudAction-Dywfnw0C.js.map} +1 -1
- package/dist/core/web/public/next/assets/SeatSelector-CH7hTgwy.js +3 -0
- package/dist/core/web/public/next/assets/{SeatSelector-CYHRR7Wp.js.map → SeatSelector-CH7hTgwy.js.map} +1 -1
- package/dist/core/web/public/next/assets/Segmented-Wynbg0F5.js +2 -0
- package/dist/core/web/public/next/assets/{Segmented-BE53BenI.js.map → Segmented-Wynbg0F5.js.map} +1 -1
- package/dist/core/web/public/next/assets/Select-DMyLCkId.js +2 -0
- package/dist/core/web/public/next/assets/{Select-BwSGkHCS.js.map → Select-DMyLCkId.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionGate-8RtQFWeZ.js +2 -0
- package/dist/core/web/public/next/assets/{SessionGate-e0dFJm9d.js.map → SessionGate-8RtQFWeZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionInsightChip-zBJbKv2L.js +2 -0
- package/dist/core/web/public/next/assets/{SessionInsightChip-CxlSyueJ.js.map → SessionInsightChip-zBJbKv2L.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionSearch-DfJIcxxM.js +2 -0
- package/dist/core/web/public/next/assets/{SessionSearch-_yp7S2TP.js.map → SessionSearch-DfJIcxxM.js.map} +1 -1
- package/dist/core/web/public/next/assets/SettingsSection-Da9RYyH5.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-Da9RYyH5.js.map +1 -0
- package/dist/core/web/public/next/assets/Sheet-DhXyIDmq.js +2 -0
- package/dist/core/web/public/next/assets/{Sheet-DVP2Mgy6.js.map → Sheet-DhXyIDmq.js.map} +1 -1
- package/dist/core/web/public/next/assets/ShortcutsOverlay-Bi5f-wUw.js +2 -0
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-BcIcoClX.js.map → ShortcutsOverlay-Bi5f-wUw.js.map} +1 -1
- package/dist/core/web/public/next/assets/Sidebar-BuO3sViG.js +3 -0
- package/dist/core/web/public/next/assets/Sidebar-BuO3sViG.js.map +1 -0
- package/dist/core/web/public/next/assets/Slider-Bd9YFWEV.js +2 -0
- package/dist/core/web/public/next/assets/{Slider-BypUWjpH.js.map → Slider-Bd9YFWEV.js.map} +1 -1
- package/dist/core/web/public/next/assets/StatTile-DScTd3c-.js +2 -0
- package/dist/core/web/public/next/assets/StatTile-DScTd3c-.js.map +1 -0
- package/dist/core/web/public/next/assets/{StatusBadge-HCZp416_.js → StatusBadge-DQ1UtQAJ.js} +2 -2
- package/dist/core/web/public/next/assets/{StatusBadge-HCZp416_.js.map → StatusBadge-DQ1UtQAJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/StepBand-BB3IJxhr.js +2 -0
- package/dist/core/web/public/next/assets/{StepBand-Duz1PUes.js.map → StepBand-BB3IJxhr.js.map} +1 -1
- package/dist/core/web/public/next/assets/Surface-DWMtQe3Q.js +2 -0
- package/dist/core/web/public/next/assets/Surface-DWMtQe3Q.js.map +1 -0
- package/dist/core/web/public/next/assets/Surface-e1z6GdZt.css +1 -0
- package/dist/core/web/public/next/assets/Swimlane-DcENqtdp.js +2 -0
- package/dist/core/web/public/next/assets/{Swimlane-DGcIcnNA.js.map → Swimlane-DcENqtdp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Switch-iveI-8NY.js → Switch-CenChEYf.js} +2 -2
- package/dist/core/web/public/next/assets/{Switch-iveI-8NY.js.map → Switch-CenChEYf.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Tag-DH15CUJp.js → Tag-D4k5E3u0.js} +2 -2
- package/dist/core/web/public/next/assets/{Tag-DH15CUJp.js.map → Tag-D4k5E3u0.js.map} +1 -1
- package/dist/core/web/public/next/assets/TerminalPane-DCQTukcE.js +7 -0
- package/dist/core/web/public/next/assets/TerminalPane-DCQTukcE.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-DsuWT0pi.js +2 -0
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-C8yQ0AaR.js.map → UniverseConsoleApp-DsuWT0pi.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-_nPURPqe.js → UniverseView-DyI5ApsA.js} +3 -3
- package/dist/core/web/public/next/assets/{UniverseView-_nPURPqe.js.map → UniverseView-DyI5ApsA.js.map} +1 -1
- package/dist/core/web/public/next/assets/UsageSection-Imr28nwK.js +3 -0
- package/dist/core/web/public/next/assets/UsageSection-Imr28nwK.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DeuBEvAO.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DeuBEvAO.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-CpxBO98E.js +10 -0
- package/dist/core/web/public/next/assets/Workspace-CpxBO98E.js.map +1 -0
- package/dist/core/web/public/next/assets/actions-BmIf9avl.css +1 -0
- package/dist/core/web/public/next/assets/actions-DE8NoWV_.js +2 -0
- package/dist/core/web/public/next/assets/actions-DE8NoWV_.js.map +1 -0
- package/dist/core/web/public/next/assets/apps-model-CFGCUu9p.js +2 -0
- package/dist/core/web/public/next/assets/apps-model-CFGCUu9p.js.map +1 -0
- package/dist/core/web/public/next/assets/authority-model-CmnfJzmM.js +2 -0
- package/dist/core/web/public/next/assets/authority-model-CmnfJzmM.js.map +1 -0
- package/dist/core/web/public/next/assets/binding-left-DZpq5sLf.js +2 -0
- package/dist/core/web/public/next/assets/binding-left-DZpq5sLf.js.map +1 -0
- package/dist/core/web/public/next/assets/{budget-queries-V3wcJVK_.js → budget-queries-DjrPRFwl.js} +2 -2
- package/dist/core/web/public/next/assets/{budget-queries-V3wcJVK_.js.map → budget-queries-DjrPRFwl.js.map} +1 -1
- package/dist/core/web/public/next/assets/capacity-strip-model-C7cdQnuK.js +2 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-C7cdQnuK.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-DUD_jprE.js +2 -0
- package/dist/core/web/public/next/assets/charts-DUD_jprE.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-DhKTrQLw.css +1 -0
- package/dist/core/web/public/next/assets/clipboard-DkZdqlxf.js +2 -0
- package/dist/core/web/public/next/assets/clipboard-DkZdqlxf.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-D-HXms6q.css +1 -0
- package/dist/core/web/public/next/assets/cloud-model-DoxBMDvx.js +2 -0
- package/dist/core/web/public/next/assets/cloud-model-DoxBMDvx.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-queries-CTGvO-k-.js +2 -0
- package/dist/core/web/public/next/assets/cloud-queries-CTGvO-k-.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud.module-DOP-N4Ch.js +2 -0
- package/dist/core/web/public/next/assets/cloud.module-DOP-N4Ch.js.map +1 -0
- package/dist/core/web/public/next/assets/command-catalog-CmrHNFzh.js +2 -0
- package/dist/core/web/public/next/assets/command-catalog-CmrHNFzh.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-2Owp2jYF.js +3 -0
- package/dist/core/web/public/next/assets/context-model-2Owp2jYF.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-9xywbXxX.js +2 -0
- package/dist/core/web/public/next/assets/context-model-9xywbXxX.js.map +1 -0
- package/dist/core/web/public/next/assets/{context-queries-CrPcHWTz.js → context-queries-wvcRnV-I.js} +2 -2
- package/dist/core/web/public/next/assets/{context-queries-CrPcHWTz.js.map → context-queries-wvcRnV-I.js.map} +1 -1
- package/dist/core/web/public/next/assets/{control-queries-CmgBgKV7.js → control-queries-DB6Kh7UN.js} +2 -2
- package/dist/core/web/public/next/assets/{control-queries-CmgBgKV7.js.map → control-queries-DB6Kh7UN.js.map} +1 -1
- package/dist/core/web/public/next/assets/copy-setup-CJQhFl-4.js +2 -0
- package/dist/core/web/public/next/assets/copy-setup-CJQhFl-4.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-icons-BBUGl4tE.js +2 -0
- package/dist/core/web/public/next/assets/{dock-icons-CUh8dOxJ.js.map → dock-icons-BBUGl4tE.js.map} +1 -1
- package/dist/core/web/public/next/assets/fleet-model-BRfRWkZl.js +2 -0
- package/dist/core/web/public/next/assets/fleet-model-BRfRWkZl.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-queries-tU6UEXN2.js +2 -0
- package/dist/core/web/public/next/assets/fleet-queries-tU6UEXN2.js.map +1 -0
- package/dist/core/web/public/next/assets/{focus-trap-HtcoXeEq.js → focus-trap-BGOceFvj.js} +2 -2
- package/dist/core/web/public/next/assets/{focus-trap-HtcoXeEq.js.map → focus-trap-BGOceFvj.js.map} +1 -1
- package/dist/core/web/public/next/assets/format-DEAaVF6X.js +2 -0
- package/dist/core/web/public/next/assets/format-DEAaVF6X.js.map +1 -0
- package/dist/core/web/public/next/assets/{git-model-bk_RXh3y.js → git-model-53iRLInY.js} +2 -2
- package/dist/core/web/public/next/assets/{git-model-bk_RXh3y.js.map → git-model-53iRLInY.js.map} +1 -1
- package/dist/core/web/public/next/assets/global-CXHHMz9o.js +2 -0
- package/dist/core/web/public/next/assets/{global-oEl9Qj8u.js.map → global-CXHHMz9o.js.map} +1 -1
- package/dist/core/web/public/next/assets/{guarded-runners-LHLXmXIk.js → guarded-runners-B8zFVBVZ.js} +2 -2
- package/dist/core/web/public/next/assets/{guarded-runners-LHLXmXIk.js.map → guarded-runners-B8zFVBVZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/icons-D4s-jlxX.js +2 -0
- package/dist/core/web/public/next/assets/icons-D4s-jlxX.js.map +1 -0
- package/dist/core/web/public/next/assets/{index-BVxOlseC.js → index-BG177cPN.js} +3 -3
- package/dist/core/web/public/next/assets/{index-BVxOlseC.js.map → index-BG177cPN.js.map} +1 -1
- package/dist/core/web/public/next/assets/live-model-CEf01wrW.js +2 -0
- package/dist/core/web/public/next/assets/live-model-CEf01wrW.js.map +1 -0
- package/dist/core/web/public/next/assets/local-model-C9xNi9fN.js +2 -0
- package/dist/core/web/public/next/assets/local-model-C9xNi9fN.js.map +1 -0
- package/dist/core/web/public/next/assets/mind.module-D_xk6HIQ.js +2 -0
- package/dist/core/web/public/next/assets/{mind.module-gTGAuJt1.js.map → mind.module-D_xk6HIQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/mutations-CbTSofVH.js +2 -0
- package/dist/core/web/public/next/assets/{mutations-C5S7okTW.js.map → mutations-CbTSofVH.js.map} +1 -1
- package/dist/core/web/public/next/assets/nav-CmZcbPFJ.js +2 -0
- package/dist/core/web/public/next/assets/{nav-NVtnuG7A.js.map → nav-CmZcbPFJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{overnight-queries-DGm3qL1b.js → overnight-queries-CR0b_j-V.js} +2 -2
- package/dist/core/web/public/next/assets/{overnight-queries-DGm3qL1b.js.map → overnight-queries-CR0b_j-V.js.map} +1 -1
- package/dist/core/web/public/next/assets/primitives-DNI-uJBd.js +1 -0
- package/dist/core/web/public/next/assets/{queries-CYisSAAB.js → queries-rvRsAGW2.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-CYisSAAB.js.map → queries-rvRsAGW2.js.map} +1 -1
- package/dist/core/web/public/next/assets/reasoning-pref-DMPQkujg.js +2 -0
- package/dist/core/web/public/next/assets/{reasoning-pref-BUcFF_5G.js.map → reasoning-pref-DMPQkujg.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reveal-anchor-D-tV8xau.js → reveal-anchor-BKk2wZZZ.js} +2 -2
- package/dist/core/web/public/next/assets/{reveal-anchor-D-tV8xau.js.map → reveal-anchor-BKk2wZZZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/seat-subscription-CLn2ReSZ.js +2 -0
- package/dist/core/web/public/next/assets/{seat-subscription-B-f9ViU2.js.map → seat-subscription-CLn2ReSZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{sidebar-model-DQ-FyBHW.js → sidebar-model-CjQLvdag.js} +2 -2
- package/dist/core/web/public/next/assets/{sidebar-model-DQ-FyBHW.js.map → sidebar-model-CjQLvdag.js.map} +1 -1
- package/dist/core/web/public/next/assets/slots-DRxNosZg.js +3 -0
- package/dist/core/web/public/next/assets/{slots-BhP8b8tf.js.map → slots-DRxNosZg.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-data-DshUC_TU.js +2 -0
- package/dist/core/web/public/next/assets/surface-data-DshUC_TU.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-prefetch-DO8r4ttQ.js +2 -0
- package/dist/core/web/public/next/assets/surface-prefetch-DO8r4ttQ.js.map +1 -0
- package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js → tasks-model-BKPFZAmZ.js} +2 -2
- package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js.map → tasks-model-BKPFZAmZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js → terminal-icons-DoeQkP3y.js} +2 -2
- package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js.map → terminal-icons-DoeQkP3y.js.map} +1 -1
- package/dist/core/web/public/next/assets/transient-events-nTLhMBND.js +2 -0
- package/dist/core/web/public/next/assets/transient-events-nTLhMBND.js.map +1 -0
- package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +1 -1
- package/dist/core/web/public/next/assets/{usage-queries-BZuAANlI.js → usage-queries-MnUeYzwp.js} +2 -2
- package/dist/core/web/public/next/assets/{usage-queries-BZuAANlI.js.map → usage-queries-MnUeYzwp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-guarded-action-Cf4MeNBa.js → use-guarded-action-P12MfNwU.js} +2 -2
- package/dist/core/web/public/next/assets/{use-guarded-action-Cf4MeNBa.js.map → use-guarded-action-P12MfNwU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js → use-ticker-DIvAZ4Ey.js} +2 -2
- package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js.map → use-ticker-DIvAZ4Ey.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-token-gate-DqrSXdX6.js → use-token-gate-DfEja7Wr.js} +2 -2
- package/dist/core/web/public/next/assets/{use-token-gate-DqrSXdX6.js.map → use-token-gate-DfEja7Wr.js.map} +1 -1
- package/dist/core/web/public/next/assets/useOnboarding-CkOHadqC.js +2 -0
- package/dist/core/web/public/next/assets/useOnboarding-CkOHadqC.js.map +1 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-BDlbDlIU.js +2 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-BDlbDlIU.js.map +1 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-BGtA55k2.js +2 -0
- package/dist/core/web/public/next/assets/{useVerseTranscript-CDYrrWOO.js.map → useVerseTranscript-BGtA55k2.js.map} +1 -1
- package/dist/core/web/public/next/assets/verse-icons-wOet9JZy.js +2 -0
- package/dist/core/web/public/next/assets/verse-icons-wOet9JZy.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-model-CSzzdyu2.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-CSzzdyu2.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-store-DNVRuiJL.js +2 -0
- package/dist/core/web/public/next/assets/verse-store-DNVRuiJL.js.map +1 -0
- package/dist/core/web/public/next/assets/warmup-CecO_Nk0.js +3 -0
- package/dist/core/web/public/next/assets/{warmup-HG5vYbsN.js.map → warmup-CecO_Nk0.js.map} +1 -1
- package/dist/core/web/public/next/assets/why-seat-model-D68ZA7G8.js +2 -0
- package/dist/core/web/public/next/assets/why-seat-model-D68ZA7G8.js.map +1 -0
- package/dist/core/web/public/next/assets/{workspace-model-CbhdPhei.js → workspace-model-BdIVybKr.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-CbhdPhei.js.map → workspace-model-BdIVybKr.js.map} +1 -1
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/docs/README.md +2 -1
- package/package.json +1 -1
- package/dist/core/web/public/next/assets/ActionMenu-FxXeRbPx.js +0 -2
- package/dist/core/web/public/next/assets/Advanced-D_eS4472.js +0 -2
- package/dist/core/web/public/next/assets/Advanced-D_eS4472.js.map +0 -1
- package/dist/core/web/public/next/assets/App-Cj4zKbG3.js +0 -7
- package/dist/core/web/public/next/assets/App-Cj4zKbG3.js.map +0 -1
- package/dist/core/web/public/next/assets/AppsSection-Ddu_RCQE.js +0 -2
- package/dist/core/web/public/next/assets/AppsSection-Ddu_RCQE.js.map +0 -1
- package/dist/core/web/public/next/assets/AreaTrend-CDxrQU4b.js +0 -2
- package/dist/core/web/public/next/assets/AutonomySection-DuQkHGD_.js +0 -2
- package/dist/core/web/public/next/assets/BranchBar-CLsvOcyK.js +0 -2
- package/dist/core/web/public/next/assets/BudgetControl-TL3FeZ1D.js +0 -2
- package/dist/core/web/public/next/assets/BurnDown-sFXkUGdB.js +0 -2
- package/dist/core/web/public/next/assets/BurnDown-sFXkUGdB.js.map +0 -1
- package/dist/core/web/public/next/assets/CapacityStrip-qReu0RaF.js +0 -2
- package/dist/core/web/public/next/assets/ChatSection-DZuZfTaC.js +0 -3
- package/dist/core/web/public/next/assets/ChatSection-DZuZfTaC.js.map +0 -1
- package/dist/core/web/public/next/assets/CloudBudgetForm-DJbiT1wi.js +0 -2
- package/dist/core/web/public/next/assets/CloudBudgetForm-DJbiT1wi.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandPalette-zYLFZRnj.js +0 -2
- package/dist/core/web/public/next/assets/CommandPalette-zYLFZRnj.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandSection-rIeMK5Ch.js +0 -2
- package/dist/core/web/public/next/assets/CommandSection-rIeMK5Ch.js.map +0 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-DLrLKM0c.js +0 -2
- package/dist/core/web/public/next/assets/Dialog-BS9Dxi3G.js +0 -2
- package/dist/core/web/public/next/assets/DiffPane-TOmUf3b2.js +0 -2
- package/dist/core/web/public/next/assets/DiffViewer-BpH56302.js +0 -2
- package/dist/core/web/public/next/assets/DockHost-DzkzR-HD.js +0 -2
- package/dist/core/web/public/next/assets/DockHost-DzkzR-HD.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetSection-ViAb549H.js +0 -3
- package/dist/core/web/public/next/assets/FleetSection-ViAb549H.js.map +0 -1
- package/dist/core/web/public/next/assets/Funnel-D2u7Wlzc.js +0 -2
- package/dist/core/web/public/next/assets/GearTray-Cb2npoxM.js +0 -2
- package/dist/core/web/public/next/assets/GrowthSection-C5aDPs8B.js +0 -2
- package/dist/core/web/public/next/assets/HandoffDialog-BF3AYg-X.js +0 -2
- package/dist/core/web/public/next/assets/Input-B5dmGLZx.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-DZrmjDbI.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-DZrmjDbI.js.map +0 -1
- package/dist/core/web/public/next/assets/MatrixHeatmap-BgEUs2Eu.js +0 -2
- package/dist/core/web/public/next/assets/McpSection-DZkiOuoq.js +0 -2
- package/dist/core/web/public/next/assets/MessageMarkdown-BauY8ZTY.js +0 -3
- package/dist/core/web/public/next/assets/MindSection-BvJXFjyX.js +0 -2
- package/dist/core/web/public/next/assets/MindSection-BvJXFjyX.js.map +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-mxrw0Yvy.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouDrawer-CO-Balfp.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouList-CzDZbzRD.js +0 -2
- package/dist/core/web/public/next/assets/NewChatDialog-B8eJjlFf.js +0 -3
- package/dist/core/web/public/next/assets/NewChatDialog-B8eJjlFf.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-Cij6KWat.js +0 -2
- package/dist/core/web/public/next/assets/OnboardingFlow-Cij6KWat.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-DSpPj8UE.css +0 -1
- package/dist/core/web/public/next/assets/PreviewPane-BS-CleCd.js +0 -2
- package/dist/core/web/public/next/assets/RailStatus-cPRyOmrk.js +0 -2
- package/dist/core/web/public/next/assets/ResourcesChrome-BJCauW_t.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesChrome-BJCauW_t.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-BDecg6nO.js +0 -2
- package/dist/core/web/public/next/assets/ResourcesDrawer-BDecg6nO.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-CSKIO_wZ.css +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-DYtwc2ja.js +0 -2
- package/dist/core/web/public/next/assets/RunInCloudAction-BEGEEM8O.js +0 -2
- package/dist/core/web/public/next/assets/SeatSelector-CYHRR7Wp.js +0 -3
- package/dist/core/web/public/next/assets/Segmented-BE53BenI.js +0 -2
- package/dist/core/web/public/next/assets/Select-BwSGkHCS.js +0 -2
- package/dist/core/web/public/next/assets/SessionGate-e0dFJm9d.js +0 -2
- package/dist/core/web/public/next/assets/SessionInsightChip-CxlSyueJ.js +0 -2
- package/dist/core/web/public/next/assets/SessionSearch-_yp7S2TP.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-wGnpWeGW.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-wGnpWeGW.js.map +0 -1
- package/dist/core/web/public/next/assets/Sheet-DVP2Mgy6.js +0 -2
- package/dist/core/web/public/next/assets/ShortcutsOverlay-BcIcoClX.js +0 -2
- package/dist/core/web/public/next/assets/Sidebar-DjQOqPbm.js +0 -3
- package/dist/core/web/public/next/assets/Sidebar-DjQOqPbm.js.map +0 -1
- package/dist/core/web/public/next/assets/Slider-BypUWjpH.js +0 -2
- package/dist/core/web/public/next/assets/StepBand-Duz1PUes.js +0 -2
- package/dist/core/web/public/next/assets/Surface-B75lVfzm.js +0 -2
- package/dist/core/web/public/next/assets/Surface-B75lVfzm.js.map +0 -1
- package/dist/core/web/public/next/assets/Surface-DMca0gAe.css +0 -1
- package/dist/core/web/public/next/assets/Swimlane-DGcIcnNA.js +0 -2
- package/dist/core/web/public/next/assets/TerminalPane-MQT-veKZ.js +0 -7
- package/dist/core/web/public/next/assets/TerminalPane-MQT-veKZ.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-C8yQ0AaR.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-CqxRGJ40.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-CqxRGJ40.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-DTjDpGCd.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-DTjDpGCd.js.map +0 -1
- package/dist/core/web/public/next/assets/Workspace-DfcFGzME.js +0 -10
- package/dist/core/web/public/next/assets/Workspace-DfcFGzME.js.map +0 -1
- package/dist/core/web/public/next/assets/actions-Ddfg2iLl.css +0 -1
- package/dist/core/web/public/next/assets/actions-tWevL9HV.js +0 -2
- package/dist/core/web/public/next/assets/actions-tWevL9HV.js.map +0 -1
- package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js +0 -2
- package/dist/core/web/public/next/assets/apps-model-CDFvmsQV.js.map +0 -1
- package/dist/core/web/public/next/assets/capacity-strip-model-BDbmQ3e3.js +0 -2
- package/dist/core/web/public/next/assets/capacity-strip-model-BDbmQ3e3.js.map +0 -1
- package/dist/core/web/public/next/assets/charts-CfAjuKMv.js +0 -2
- package/dist/core/web/public/next/assets/charts-CfAjuKMv.js.map +0 -1
- package/dist/core/web/public/next/assets/charts-uSX6xVYN.css +0 -1
- package/dist/core/web/public/next/assets/cloud-C1KPNRHC.css +0 -1
- package/dist/core/web/public/next/assets/cloud-queries-Br_r0UAz.js +0 -2
- package/dist/core/web/public/next/assets/cloud-queries-Br_r0UAz.js.map +0 -1
- package/dist/core/web/public/next/assets/cloud.module-ascz58c3.js +0 -2
- package/dist/core/web/public/next/assets/cloud.module-ascz58c3.js.map +0 -1
- package/dist/core/web/public/next/assets/command-bus-xYZoK9nQ.js +0 -2
- package/dist/core/web/public/next/assets/command-bus-xYZoK9nQ.js.map +0 -1
- package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-Bb_PxC5w.js.map +0 -1
- package/dist/core/web/public/next/assets/composer-keys-su0g1h9o.js +0 -2
- package/dist/core/web/public/next/assets/composer-keys-su0g1h9o.js.map +0 -1
- package/dist/core/web/public/next/assets/context-model-BC-HOmPo.js +0 -2
- package/dist/core/web/public/next/assets/context-model-BC-HOmPo.js.map +0 -1
- package/dist/core/web/public/next/assets/context-model-CIBmSugV.js +0 -2
- package/dist/core/web/public/next/assets/context-model-CIBmSugV.js.map +0 -1
- package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js +0 -2
- package/dist/core/web/public/next/assets/dark-since-DOMvtB_G.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-icons-CUh8dOxJ.js +0 -2
- package/dist/core/web/public/next/assets/dock-store-B2vlxqPu.js +0 -2
- package/dist/core/web/public/next/assets/dock-store-B2vlxqPu.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-model-7i-FbzKI.js +0 -2
- package/dist/core/web/public/next/assets/fleet-model-7i-FbzKI.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-queries-DzGoqq8X.js +0 -2
- package/dist/core/web/public/next/assets/fleet-queries-DzGoqq8X.js.map +0 -1
- package/dist/core/web/public/next/assets/format-BkWdOQDL.js +0 -2
- package/dist/core/web/public/next/assets/format-BkWdOQDL.js.map +0 -1
- package/dist/core/web/public/next/assets/global-oEl9Qj8u.js +0 -2
- package/dist/core/web/public/next/assets/guarded-action-OzqcPjmh.js +0 -3
- package/dist/core/web/public/next/assets/guarded-action-OzqcPjmh.js.map +0 -1
- package/dist/core/web/public/next/assets/icon-base-DvM1eI5V.js +0 -2
- package/dist/core/web/public/next/assets/icon-base-DvM1eI5V.js.map +0 -1
- package/dist/core/web/public/next/assets/icons-DEQa2rTx.js +0 -2
- package/dist/core/web/public/next/assets/icons-DEQa2rTx.js.map +0 -1
- package/dist/core/web/public/next/assets/live-model-bmsJgnYD.js +0 -2
- package/dist/core/web/public/next/assets/live-model-bmsJgnYD.js.map +0 -1
- package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js +0 -2
- package/dist/core/web/public/next/assets/local-model-DFyjKX0b.js.map +0 -1
- package/dist/core/web/public/next/assets/mind.module-gTGAuJt1.js +0 -2
- package/dist/core/web/public/next/assets/mutations-C5S7okTW.js +0 -2
- package/dist/core/web/public/next/assets/nav-NVtnuG7A.js +0 -2
- package/dist/core/web/public/next/assets/preloaded-Cwf9rsnZ.js +0 -2
- package/dist/core/web/public/next/assets/preloaded-Cwf9rsnZ.js.map +0 -1
- package/dist/core/web/public/next/assets/primitives-DyCKYSBG.js +0 -1
- package/dist/core/web/public/next/assets/reasoning-pref-BUcFF_5G.js +0 -2
- package/dist/core/web/public/next/assets/seat-subscription-B-f9ViU2.js +0 -2
- package/dist/core/web/public/next/assets/section-visibility-Yctxu-if.js +0 -2
- package/dist/core/web/public/next/assets/section-visibility-Yctxu-if.js.map +0 -1
- package/dist/core/web/public/next/assets/slots-BhP8b8tf.js +0 -3
- package/dist/core/web/public/next/assets/surface-data-DTI7LjvH.js +0 -2
- package/dist/core/web/public/next/assets/surface-data-DTI7LjvH.js.map +0 -1
- package/dist/core/web/public/next/assets/surface-prefetch-CdUEBFrl.js +0 -2
- package/dist/core/web/public/next/assets/surface-prefetch-CdUEBFrl.js.map +0 -1
- package/dist/core/web/public/next/assets/useChartWidth-owwodNVz.js +0 -2
- package/dist/core/web/public/next/assets/useChartWidth-owwodNVz.js.map +0 -1
- package/dist/core/web/public/next/assets/useSeatsRefresh-DgFy-Ph4.js +0 -2
- package/dist/core/web/public/next/assets/useSeatsRefresh-DgFy-Ph4.js.map +0 -1
- package/dist/core/web/public/next/assets/useVerseTranscript-CDYrrWOO.js +0 -2
- package/dist/core/web/public/next/assets/verse-icons-F9VwX07_.js +0 -2
- package/dist/core/web/public/next/assets/verse-icons-F9VwX07_.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-model-DyCwZF-M.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-DyCwZF-M.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js +0 -3
- package/dist/core/web/public/next/assets/verse-store-b_Lek_c5.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-ui-store-62DxpVHS.js +0 -3
- package/dist/core/web/public/next/assets/verse-ui-store-62DxpVHS.js.map +0 -1
- package/dist/core/web/public/next/assets/viewport-nTubFCwf.js +0 -2
- package/dist/core/web/public/next/assets/viewport-nTubFCwf.js.map +0 -1
- package/dist/core/web/public/next/assets/warmup-HG5vYbsN.js +0 -3
- package/dist/core/web/public/next/assets/workbench-types-DzN-5trg.js +0 -2
- package/dist/core/web/public/next/assets/workbench-types-DzN-5trg.js.map +0 -1
- /package/dist/core/web/public/next/assets/{BurnDown-BuLMsJMx.css → StatTile-BuLMsJMx.css} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
._lead_w05r1_8{gap:var(--space-3);flex-direction:column;display:flex}._bar_w05r1_14{align-items:center;gap:var(--space-2) var(--space-3);min-height:var(--control-h);flex-wrap:wrap;display:flex}._barSpacer_w05r1_22{flex:1}._barSecondary_w05r1_26{gap:var(--space-2);flex-wrap:wrap;display:flex}._switchWrap_w05r1_32{align-items:center;gap:var(--space-2);display:inline-flex}._barLabel_w05r1_38,._pillLabel_w05r1_39{font-family:var(--font-display);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-tertiary)}._switchOption_w05r1_48{align-items:center;gap:var(--space-1);display:inline-flex}._touchMark_w05r1_54{color:var(--text-tertiary)}._pill_w05r1_39,._chip_w05r1_59{align-items:center;gap:var(--space-2);min-height:var(--control-h-sm);padding:0 var(--space-3);border:1px solid var(--border-default);border-radius:var(--radius-full);background:var(--bg-surface);color:var(--text-primary);font-family:var(--font-ui);font-size:var(--text-xs-size);line-height:var(--text-xs-line);white-space:nowrap;display:inline-flex}button._pill_w05r1_39,button._chip_w05r1_59{cursor:pointer;transition:background-color var(--duration-fast) var(--ease-standard)}button._pill_w05r1_39:hover,button._chip_w05r1_59:hover{background:var(--bg-hover)}._pill_w05r1_39:focus-visible,._chip_w05r1_59:focus-visible,._linkButton_w05r1_88:focus-visible,._moreLink_w05r1_89:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px}._chip_w05r1_59[data-tone=warning]{border-color:var(--status-warning-solid)}._chip_w05r1_59[data-tone=danger]{border-color:var(--status-danger-solid);color:var(--status-danger-fg)}._dot_w05r1_103{border-radius:var(--radius-full);background:var(--status-neutral-solid);flex:none;width:8px;height:8px}._dot_w05r1_103[data-tone=success]{background:var(--status-success-solid)}._dot_w05r1_103[data-tone=warning]{background:var(--status-warning-solid)}._dot_w05r1_103[data-tone=danger]{background:var(--status-danger-solid)}._dot_w05r1_103[data-tone=unknown]{background:var(--chart-unknown-hatch);border:1px solid var(--status-unknown-solid)}._verdict_w05r1_126{font-size:var(--text-lg-size);line-height:var(--text-lg-line);font-weight:var(--font-weight-medium);color:var(--text-primary);font-variant-numeric:tabular-nums;margin:0}._verdictPart_w05r1_135[data-tone=danger]{color:var(--status-danger-fg)}._verdictPart_w05r1_135[data-tone=warning]{color:var(--status-warning-fg)}._verdictPart_w05r1_135[data-tone=success]{color:var(--status-success-fg)}._verdictPart_w05r1_135[data-tone=unknown]{color:var(--status-unknown-fg);font-style:italic}._verdictSep_w05r1_149{color:var(--text-tertiary)}._since_w05r1_153{align-items:center;gap:var(--space-2);font-size:var(--text-xs-size);line-height:var(--text-xs-line);flex-wrap:wrap;display:flex}._sinceLead_w05r1_162,._sinceEmpty_w05r1_166{color:var(--text-tertiary)}._sinceChip_w05r1_170{padding:1px var(--space-2);border-radius:var(--radius-full);background:var(--status-neutral-bg);color:var(--status-neutral-fg);font-variant-numeric:tabular-nums;align-items:center;display:inline-flex}._sinceChip_w05r1_170[data-tone=success]{background:var(--status-success-bg);color:var(--status-success-fg)}._sinceChip_w05r1_170[data-tone=danger]{background:var(--status-danger-bg);color:var(--status-danger-fg)}._sinceChip_w05r1_170[data-tone=warning]{background:var(--status-warning-bg);color:var(--status-warning-fg)}._sinceChip_w05r1_170[data-tone=info]{background:var(--status-info-bg);color:var(--status-info-fg)}._actionNote_w05r1_196,._actionError_w05r1_197{padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);font-size:var(--text-sm-size);line-height:var(--text-sm-line);margin:0}._actionNote_w05r1_196{background:var(--bg-hover);color:var(--text-secondary)}._actionError_w05r1_197{align-items:baseline;gap:var(--space-3);background:var(--status-danger-bg);color:var(--status-danger-fg);display:flex}._linkButton_w05r1_88,._moreLink_w05r1_89{align-items:center;gap:var(--space-1);color:var(--text-link);font:inherit;font-size:var(--text-xs-size);line-height:var(--text-xs-line);cursor:pointer;white-space:nowrap;background:0 0;border:0;padding:0;text-decoration:none;display:inline-flex}._linkButton_w05r1_88:hover,._moreLink_w05r1_89:hover{text-decoration:underline}._moreLink_w05r1_89{align-self:flex-start}._moreLink_w05r1_89:disabled{color:var(--text-disabled);cursor:default;text-decoration:none}._kbd_w05r1_251{padding:0 var(--space-1);border:1px solid var(--border-subtle);border-radius:var(--radius-xs);color:var(--text-tertiary);font-family:var(--font-mono);font-size:var(--text-2xs-size)}._muted_w05r1_260{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);margin:0}._mono_w05r1_267{font-family:var(--font-mono);font-size:var(--text-xs-size)}._num_w05r1_272{text-align:right;font-variant-numeric:tabular-nums}._confirmBody_w05r1_277{color:var(--text-secondary);font-size:var(--text-sm-size);line-height:var(--text-sm-line-relaxed)}._confirmActions_w05r1_283{justify-content:flex-end;gap:var(--space-2);margin-top:var(--space-5);display:flex}._needsList_w05r1_291{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._needsRow_w05r1_299{align-items:start;gap:var(--space-2) var(--space-3);padding:var(--space-2) 0;border-top:1px solid var(--border-subtle);grid-template-columns:auto minmax(0,1fr) auto;display:grid}._needsRow_w05r1_299:first-child{border-top:0;padding-top:0}._sevDot_w05r1_313{border-radius:var(--radius-full);background:var(--status-info-solid);width:8px;height:8px;margin-top:6px}._sevDot_w05r1_313[data-severity=warn]{background:var(--status-warning-solid)}._sevDot_w05r1_313[data-severity=high]{background:var(--status-danger-solid)}._needsText_w05r1_327{flex-direction:column;gap:2px;min-width:0;display:flex}._needsKind_w05r1_335{font-family:var(--font-display);font-size:var(--text-2xs-size);line-height:var(--text-2xs-line);letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-secondary)}._needsTitle_w05r1_347{-webkit-line-clamp:2;line-clamp:2;color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line);overflow-wrap:break-word;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}._needsDetail_w05r1_359{color:var(--text-secondary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);overflow-wrap:anywhere}._needsMeta_w05r1_367{gap:0 var(--space-1);color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);flex-wrap:wrap;display:flex}._needsRepo_w05r1_376{font-weight:var(--font-weight-medium)}._needsActions_w05r1_380{justify-content:flex-end;align-items:center;gap:var(--space-2);flex-wrap:wrap;display:flex}._allClear_w05r1_388{gap:var(--space-1);padding:var(--space-4) 0;flex-direction:column;display:flex}._allClearTitle_w05r1_395{font-family:var(--font-display);font-size:var(--text-md-size);line-height:var(--text-md-line);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._allClearBody_w05r1_403{color:var(--text-secondary);font-size:var(--text-sm-size)}._memo_w05r1_409{gap:var(--space-2);flex-direction:column;margin:0;display:flex}._memoRow_w05r1_416{gap:var(--space-3);grid-template-columns:96px minmax(0,1fr);align-items:baseline;display:grid}._memoRow_w05r1_416 dd{margin:0}._memoText_w05r1_427{color:var(--text-primary);font-size:var(--text-base-size);line-height:var(--text-base-line)}._delta_w05r1_433{margin-left:var(--space-2);padding:0 var(--space-2);border-radius:var(--radius-full);background:var(--status-info-bg);color:var(--status-info-fg);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);font-variant-numeric:tabular-nums;white-space:nowrap;display:inline-block}._dryRun_w05r1_446{font-family:var(--font-display);padding:0 var(--space-2);border:1px dashed var(--border-strong);border-radius:var(--radius-full);color:var(--text-secondary);font-size:var(--text-2xs-size);line-height:var(--text-xs-line);text-transform:uppercase;letter-spacing:var(--tracking-label)}._actionList_w05r1_458{border-top:1px solid var(--border-subtle);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._actionRow_w05r1_467{gap:var(--space-3);padding:var(--space-2) 0;border-bottom:1px solid var(--border-subtle);grid-template-columns:auto minmax(0,1fr) auto;align-items:center;display:grid}._actionRow_w05r1_467[data-status=vetoed] ._actionSummary_w05r1_476{color:var(--text-tertiary);text-decoration:line-through}._classBadge_w05r1_481{border:1px solid var(--border-default);border-radius:var(--radius-sm);width:20px;height:20px;color:var(--text-secondary);font-family:var(--font-display);font-size:var(--text-2xs-size);font-weight:var(--font-weight-semibold);justify-content:center;align-items:center;display:inline-flex}._classBadge_w05r1_481[data-class=B]{border-color:var(--status-warning-solid);color:var(--status-warning-fg)}._classBadge_w05r1_481[data-class=C]{border-style:dashed}._actionText_w05r1_504{flex-direction:column;min-width:0;display:flex}._actionSummary_w05r1_476{color:var(--text-primary);font-size:var(--text-sm-size);line-height:var(--text-sm-line);overflow-wrap:anywhere}._actionWhy_w05r1_517{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line);overflow-wrap:anywhere}._actionState_w05r1_524{align-items:center;gap:var(--space-2);display:inline-flex}._statusWord_w05r1_530{color:var(--text-tertiary);font-size:var(--text-xs-size);white-space:nowrap}._statusWord_w05r1_530[data-status=escalated]{color:var(--status-warning-fg)}._statusWord_w05r1_530[data-status=failed],._statusWord_w05r1_530[data-status=refused]{color:var(--status-danger-fg)}._vetoChip_w05r1_545{border:1px solid var(--border-default)}._ring_w05r1_549{align-items:center;gap:var(--space-1);color:var(--status-warning-fg);font-size:var(--text-xs-size);font-variant-numeric:tabular-nums;white-space:nowrap;display:inline-flex}._ringTrack_w05r1_559{fill:none;stroke:var(--border-subtle);stroke-width:2.5px}._ringFill_w05r1_565{fill:none;stroke:var(--status-warning-solid);stroke-width:2.5px;stroke-linecap:round}._ringText_w05r1_572{min-width:4ch}._kpis_w05r1_577{gap:var(--surface-gap);grid-template-columns:repeat(5,minmax(0,1fr));align-items:start;display:grid}[data-viewport=medium] ._kpis_w05r1_577{grid-template-columns:repeat(3,minmax(0,1fr))}[data-viewport=compact] ._kpis_w05r1_577{grid-template-columns:repeat(2,minmax(0,1fr))}._burnGrid_w05r1_592{gap:var(--surface-gap);grid-template-columns:repeat(4,minmax(0,1fr));align-items:start;display:grid}[data-viewport=medium] ._burnGrid_w05r1_592{grid-template-columns:repeat(2,minmax(0,1fr))}._burnStrip_w05r1_604{gap:var(--space-3);overscroll-behavior-x:contain;scroll-snap-type:x mandatory;padding-bottom:var(--space-1);grid-auto-columns:86%;grid-auto-flow:column;display:grid;overflow-x:auto}._burnStrip_w05r1_604>._burnItem_w05r1_615{scroll-snap-align:start}._burnItem_w05r1_615{min-width:0}._freeSeat_w05r1_623{gap:var(--space-2);padding:var(--card-pad);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:var(--bg-surface);flex-direction:column;display:flex}._freeHead_w05r1_633{align-items:center;gap:var(--space-2);display:inline-flex}._freeTitle_w05r1_639{font-size:var(--text-sm-size);line-height:var(--text-sm-line);font-weight:var(--font-weight-semibold);color:var(--text-primary)}._freeValue_w05r1_646{font-size:var(--text-2xl-size);line-height:var(--text-2xl-line);font-weight:var(--font-weight-semibold);color:var(--text-secondary)}._freeBody_w05r1_653{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed)}._scope_w05r1_660{gap:var(--space-5);flex-direction:column;display:flex}._scopeBlock_w05r1_666{gap:var(--space-2);flex-direction:column;display:flex}._scopeLead_w05r1_672{color:var(--text-primary);font-size:var(--text-base-size);line-height:var(--text-base-line);margin:0}._scopeMeta_w05r1_679{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);margin:0}._scopeTable_w05r1_686{border-collapse:collapse;width:100%;font-size:var(--text-xs-size)}._scopeTable_w05r1_686 th{padding:var(--space-1) var(--space-2) var(--space-1) 0;border-bottom:1px solid var(--border-subtle);color:var(--text-tertiary);font-weight:var(--font-weight-medium);text-align:left}._scopeTable_w05r1_686 td{padding:var(--space-1) var(--space-2) var(--space-1) 0;border-bottom:1px solid var(--border-subtle);color:var(--text-primary)}._scopeList_w05r1_706{padding-left:var(--space-4);color:var(--text-secondary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);margin:0}._ladder_w05r1_714{gap:var(--space-2);counter-reset:rung;font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);color:var(--text-secondary);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}._ladder_w05r1_714 li{gap:var(--space-2);grid-template-columns:56px minmax(0,1fr);display:grid}._ladderId_w05r1_733{font-family:var(--font-mono);color:var(--text-primary)}._sheetFooter_w05r1_738{gap:var(--space-3);flex-direction:column;display:flex}._sheetFootnote_w05r1_744{color:var(--text-tertiary);font-size:var(--text-xs-size);line-height:var(--text-xs-line-relaxed);margin:0}._sheetButtons_w05r1_751{justify-content:flex-end;gap:var(--space-2);display:flex}@media (prefers-reduced-motion:reduce){button._pill_w05r1_39,button._chip_w05r1_59{transition:none}}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{t as r}from"./Dialog-BS9Dxi3G.js";import{t as i}from"./MutationTokenDialog-mxrw0Yvy.js";import{t as a}from"./Button-HHXgoXGr.js";import{n as o}from"./use-guarded-action-Cf4MeNBa.js";var s=n(e(),1),c={lead:`_lead_w05r1_8`,bar:`_bar_w05r1_14`,barSpacer:`_barSpacer_w05r1_22`,barSecondary:`_barSecondary_w05r1_26`,switchWrap:`_switchWrap_w05r1_32`,barLabel:`_barLabel_w05r1_38`,pillLabel:`_pillLabel_w05r1_39`,switchOption:`_switchOption_w05r1_48`,touchMark:`_touchMark_w05r1_54`,pill:`_pill_w05r1_39`,chip:`_chip_w05r1_59`,linkButton:`_linkButton_w05r1_88`,moreLink:`_moreLink_w05r1_89`,dot:`_dot_w05r1_103`,verdict:`_verdict_w05r1_126`,verdictPart:`_verdictPart_w05r1_135`,verdictSep:`_verdictSep_w05r1_149`,since:`_since_w05r1_153`,sinceLead:`_sinceLead_w05r1_162`,sinceEmpty:`_sinceEmpty_w05r1_166`,sinceChip:`_sinceChip_w05r1_170`,actionNote:`_actionNote_w05r1_196`,actionError:`_actionError_w05r1_197`,kbd:`_kbd_w05r1_251`,muted:`_muted_w05r1_260`,mono:`_mono_w05r1_267`,num:`_num_w05r1_272`,confirmBody:`_confirmBody_w05r1_277`,confirmActions:`_confirmActions_w05r1_283`,needsList:`_needsList_w05r1_291`,needsRow:`_needsRow_w05r1_299`,sevDot:`_sevDot_w05r1_313`,needsText:`_needsText_w05r1_327`,needsKind:`_needsKind_w05r1_335`,needsTitle:`_needsTitle_w05r1_347`,needsDetail:`_needsDetail_w05r1_359`,needsMeta:`_needsMeta_w05r1_367`,needsRepo:`_needsRepo_w05r1_376`,needsActions:`_needsActions_w05r1_380`,allClear:`_allClear_w05r1_388`,allClearTitle:`_allClearTitle_w05r1_395`,allClearBody:`_allClearBody_w05r1_403`,memo:`_memo_w05r1_409`,memoRow:`_memoRow_w05r1_416`,memoText:`_memoText_w05r1_427`,delta:`_delta_w05r1_433`,dryRun:`_dryRun_w05r1_446`,actionList:`_actionList_w05r1_458`,actionRow:`_actionRow_w05r1_467`,actionSummary:`_actionSummary_w05r1_476`,classBadge:`_classBadge_w05r1_481`,actionText:`_actionText_w05r1_504`,actionWhy:`_actionWhy_w05r1_517`,actionState:`_actionState_w05r1_524`,statusWord:`_statusWord_w05r1_530`,vetoChip:`_vetoChip_w05r1_545`,ring:`_ring_w05r1_549`,ringTrack:`_ringTrack_w05r1_559`,ringFill:`_ringFill_w05r1_565`,ringText:`_ringText_w05r1_572`,kpis:`_kpis_w05r1_577`,burnGrid:`_burnGrid_w05r1_592`,burnStrip:`_burnStrip_w05r1_604`,burnItem:`_burnItem_w05r1_615`,freeSeat:`_freeSeat_w05r1_623`,freeHead:`_freeHead_w05r1_633`,freeTitle:`_freeTitle_w05r1_639`,freeValue:`_freeValue_w05r1_646`,freeBody:`_freeBody_w05r1_653`,scope:`_scope_w05r1_660`,scopeBlock:`_scopeBlock_w05r1_666`,scopeLead:`_scopeLead_w05r1_672`,scopeMeta:`_scopeMeta_w05r1_679`,scopeTable:`_scopeTable_w05r1_686`,scopeList:`_scopeList_w05r1_706`,ladder:`_ladder_w05r1_714`,ladderId:`_ladderId_w05r1_733`,sheetFooter:`_sheetFooter_w05r1_738`,sheetFootnote:`_sheetFootnote_w05r1_744`,sheetButtons:`_sheetButtons_w05r1_751`},l=t();function u({spec:e,onConfirm:t,onCancel:n}){let i=(0,s.useId)(),o=(0,s.useRef)(null),u=(0,s.useRef)(null);return(0,l.jsxs)(r,{open:e!==null,onClose:n,titleId:i,title:e?.title??``,initialFocusRef:e?.destructive?o:u,children:[(0,l.jsx)(`div`,{className:c.confirmBody,children:e?.body}),(0,l.jsxs)(`div`,{className:c.confirmActions,children:[(0,l.jsx)(a,{ref:o,variant:`ghost`,onClick:n,children:`Cancel`}),(0,l.jsx)(a,{ref:u,variant:e?.destructive?`danger`:`primary`,onClick:t,children:e?.confirmLabel??`Confirm`})]})]})}function d(){let e=o(),[t,n]=(0,s.useState)(null),{request:r}=e,a=(0,s.useCallback)((e,t,i={})=>{let a=()=>r(e,t,i.onDone);i.confirm?n({spec:i.confirm,run:a}):a()},[r]),c=(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(u,{spec:t?.spec??null,onCancel:()=>n(null),onConfirm:()=>{let e=t;n(null),e?.run()}}),(0,l.jsx)(i,{open:e.tokenOpen,onClose:e.closeToken,reason:e.tokenReason,tokenHelp:`the mutation token ashlr verse printed`})]});return{act:a,busy:e.busy,error:e.error,clearError:e.clearError,readOnly:e.readOnly,dialogs:c}}function f({actions:e}){return e.readOnly?(0,l.jsx)(`p`,{className:c.actionNote,role:`status`,children:`Read-only session: this server was started without dispatch, so switching, stopping and vetoing are unavailable. Everything shown is live.`}):e.error?(0,l.jsxs)(`p`,{className:c.actionError,role:`alert`,children:[e.error,(0,l.jsx)(`button`,{type:`button`,className:c.linkButton,onClick:e.clearError,children:`Dismiss`})]}):null}export{d as n,c as r,f as t};
|
|
2
|
-
//# sourceMappingURL=actions-tWevL9HV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"actions-tWevL9HV.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/command/command.module.css","../../../../../../src/web-ui/routes/verse/command/actions.tsx"],"sourcesContent":["/*\n * routes/verse/command/command.module.css — Command's cards and top bar\n * (unit C7). Tokens only: style-scan-310 bans raw hex colours and px font\n * sizes in this folder, and every colour here follows the theme.\n */\n\n/* ---- lead: top bar, verdict, since ------------------------------------ */\n.lead {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n}\n\n.bar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--space-2) var(--space-3);\n min-height: var(--control-h);\n}\n\n.barSpacer {\n flex: 1;\n}\n\n.barSecondary {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2);\n}\n\n.switchWrap {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.barLabel,\n.pillLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.switchOption {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n}\n\n.touchMark {\n color: var(--text-tertiary);\n}\n\n.pill,\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n background: var(--bg-surface);\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n white-space: nowrap;\n}\n\nbutton.pill,\nbutton.chip {\n cursor: pointer;\n transition: background-color var(--duration-fast) var(--ease-standard);\n}\n\nbutton.pill:hover,\nbutton.chip:hover {\n background: var(--bg-hover);\n}\n\n.pill:focus-visible,\n.chip:focus-visible,\n.linkButton:focus-visible,\n.moreLink:focus-visible {\n outline: 2px solid var(--border-focus);\n outline-offset: 2px;\n}\n\n.chip[data-tone='warning'] {\n border-color: var(--status-warning-solid);\n}\n\n.chip[data-tone='danger'] {\n border-color: var(--status-danger-solid);\n color: var(--status-danger-fg);\n}\n\n.dot {\n width: 8px;\n height: 8px;\n border-radius: var(--radius-full);\n flex: none;\n background: var(--status-neutral-solid);\n}\n\n.dot[data-tone='success'] {\n background: var(--status-success-solid);\n}\n.dot[data-tone='warning'] {\n background: var(--status-warning-solid);\n}\n.dot[data-tone='danger'] {\n background: var(--status-danger-solid);\n}\n.dot[data-tone='unknown'] {\n background: var(--chart-unknown-hatch);\n border: 1px solid var(--status-unknown-solid);\n}\n\n/* Verdict: 17/24, weight 500 (SPEC-310C §6). */\n.verdict {\n margin: 0;\n font-size: var(--text-lg-size);\n line-height: var(--text-lg-line);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n font-variant-numeric: tabular-nums;\n}\n\n.verdictPart[data-tone='danger'] {\n color: var(--status-danger-fg);\n}\n.verdictPart[data-tone='warning'] {\n color: var(--status-warning-fg);\n}\n.verdictPart[data-tone='success'] {\n color: var(--status-success-fg);\n}\n.verdictPart[data-tone='unknown'] {\n color: var(--status-unknown-fg);\n font-style: italic;\n}\n\n.verdictSep {\n color: var(--text-tertiary);\n}\n\n.since {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.sinceLead {\n color: var(--text-tertiary);\n}\n\n.sinceEmpty {\n color: var(--text-tertiary);\n}\n\n.sinceChip {\n display: inline-flex;\n align-items: center;\n padding: 1px var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-neutral-bg);\n color: var(--status-neutral-fg);\n font-variant-numeric: tabular-nums;\n}\n.sinceChip[data-tone='success'] {\n background: var(--status-success-bg);\n color: var(--status-success-fg);\n}\n.sinceChip[data-tone='danger'] {\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n.sinceChip[data-tone='warning'] {\n background: var(--status-warning-bg);\n color: var(--status-warning-fg);\n}\n.sinceChip[data-tone='info'] {\n background: var(--status-info-bg);\n color: var(--status-info-fg);\n}\n\n.actionNote,\n.actionError {\n margin: 0;\n padding: var(--space-2) var(--space-3);\n border-radius: var(--radius-md);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n\n.actionNote {\n background: var(--bg-hover);\n color: var(--text-secondary);\n}\n\n.actionError {\n display: flex;\n align-items: baseline;\n gap: var(--space-3);\n background: var(--status-danger-bg);\n color: var(--status-danger-fg);\n}\n\n/* ---- shared small controls ------------------------------------------- */\n.linkButton,\n.moreLink {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n padding: 0;\n border: 0;\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 text-decoration: none;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.linkButton:hover,\n.moreLink:hover {\n text-decoration: underline;\n}\n\n.moreLink {\n align-self: flex-start;\n}\n\n.moreLink:disabled {\n color: var(--text-disabled);\n cursor: default;\n text-decoration: none;\n}\n\n.kbd {\n padding: 0 var(--space-1);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n color: var(--text-tertiary);\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size);\n}\n\n.muted {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.mono {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n}\n\n.num {\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.confirmBody {\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n}\n\n.confirmActions {\n display: flex;\n justify-content: flex-end;\n gap: var(--space-2);\n margin-top: var(--space-5);\n}\n\n/* ---- Needs you ------------------------------------------------------- */\n.needsList {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.needsRow {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n align-items: start;\n gap: var(--space-2) var(--space-3);\n padding: var(--space-2) 0;\n border-top: 1px solid var(--border-subtle);\n}\n\n.needsRow:first-child {\n border-top: 0;\n padding-top: 0;\n}\n\n.sevDot {\n width: 8px;\n height: 8px;\n margin-top: 6px;\n border-radius: var(--radius-full);\n background: var(--status-info-solid);\n}\n.sevDot[data-severity='warn'] {\n background: var(--status-warning-solid);\n}\n.sevDot[data-severity='high'] {\n background: var(--status-danger-solid);\n}\n\n.needsText {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n/* \"Patch · Claude run\" — the proposal kind and engine the wire title led with. */\n.needsKind {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n line-height: var(--text-2xs-line);\n letter-spacing: var(--tracking-label);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n/* Two lines at most, wrapped at word boundaries. The text already ends on a\n whole word (needs-you-model readableItemTitle); the full server title rides\n in `title`. */\n.needsTitle {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n overflow: hidden;\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n overflow-wrap: break-word;\n}\n\n.needsDetail {\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n overflow-wrap: anywhere;\n}\n\n/* \"binshield · #81 · 38 days ago\". */\n.needsMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0 var(--space-1);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n\n.needsRepo {\n font-weight: var(--font-weight-medium);\n}\n\n.needsActions {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n align-items: center;\n gap: var(--space-2);\n}\n\n.allClear {\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n padding: var(--space-4) 0;\n}\n\n.allClearTitle {\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 color: var(--text-primary);\n}\n\n.allClearBody {\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n}\n\n/* ---- Leader ---------------------------------------------------------- */\n.memo {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n}\n\n.memoRow {\n display: grid;\n grid-template-columns: 96px minmax(0, 1fr);\n gap: var(--space-3);\n align-items: baseline;\n}\n\n.memoRow dd {\n margin: 0;\n}\n\n.memoText {\n color: var(--text-primary);\n font-size: var(--text-base-size);\n line-height: var(--text-base-line);\n}\n\n.delta {\n display: inline-block;\n margin-left: var(--space-2);\n padding: 0 var(--space-2);\n border-radius: var(--radius-full);\n background: var(--status-info-bg);\n color: var(--status-info-fg);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.dryRun {\n font-family: var(--font-display); /* micro-labels follow the Display-font setting */\n padding: 0 var(--space-2);\n border: 1px dashed var(--border-strong);\n border-radius: var(--radius-full);\n color: var(--text-secondary);\n font-size: var(--text-2xs-size);\n line-height: var(--text-xs-line);\n text-transform: uppercase;\n letter-spacing: var(--tracking-label);\n}\n\n.actionList {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n border-top: 1px solid var(--border-subtle);\n}\n\n.actionRow {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n gap: var(--space-3);\n align-items: center;\n padding: var(--space-2) 0;\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.actionRow[data-status='vetoed'] .actionSummary {\n text-decoration: line-through;\n color: var(--text-tertiary);\n}\n\n.classBadge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n color: var(--text-secondary);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size);\n font-weight: var(--font-weight-semibold);\n}\n\n.classBadge[data-class='B'] {\n border-color: var(--status-warning-solid);\n color: var(--status-warning-fg);\n}\n\n.classBadge[data-class='C'] {\n border-style: dashed;\n}\n\n.actionText {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.actionSummary {\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n overflow-wrap: anywhere;\n}\n\n.actionWhy {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n overflow-wrap: anywhere;\n}\n\n.actionState {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.statusWord {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n white-space: nowrap;\n}\n\n.statusWord[data-status='escalated'] {\n color: var(--status-warning-fg);\n}\n\n.statusWord[data-status='failed'],\n.statusWord[data-status='refused'] {\n color: var(--status-danger-fg);\n}\n\n.vetoChip {\n border: 1px solid var(--border-default);\n}\n\n.ring {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n color: var(--status-warning-fg);\n font-size: var(--text-xs-size);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.ringTrack {\n fill: none;\n stroke: var(--border-subtle);\n stroke-width: 2.5;\n}\n\n.ringFill {\n fill: none;\n stroke: var(--status-warning-solid);\n stroke-width: 2.5;\n stroke-linecap: round;\n}\n\n.ringText {\n min-width: 4ch;\n}\n\n/* ---- KPIs and burn-downs --------------------------------------------- */\n.kpis {\n display: grid;\n grid-template-columns: repeat(5, minmax(0, 1fr));\n gap: var(--surface-gap);\n align-items: start;\n}\n\n[data-viewport='medium'] .kpis {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n\n[data-viewport='compact'] .kpis {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.burnGrid {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--surface-gap);\n align-items: start;\n}\n\n[data-viewport='medium'] .burnGrid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n/* 375: one card at a time, snapping — the next card peeks in at the edge. */\n.burnStrip {\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: 86%;\n gap: var(--space-3);\n overflow-x: auto;\n overscroll-behavior-x: contain;\n scroll-snap-type: x mandatory;\n padding-bottom: var(--space-1);\n}\n\n.burnStrip > .burnItem {\n scroll-snap-align: start;\n}\n\n.burnItem {\n min-width: 0;\n}\n\n.freeSeat {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n padding: var(--card-pad);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-lg);\n background: var(--bg-surface);\n}\n\n.freeHead {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n}\n\n.freeTitle {\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-primary);\n}\n\n.freeValue {\n font-size: var(--text-2xl-size);\n line-height: var(--text-2xl-line);\n font-weight: var(--font-weight-semibold);\n color: var(--text-secondary);\n}\n\n.freeBody {\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n/* ---- Touch ID sheet -------------------------------------------------- */\n.scope {\n display: flex;\n flex-direction: column;\n gap: var(--space-5);\n}\n\n.scopeBlock {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n}\n\n.scopeLead {\n margin: 0;\n color: var(--text-primary);\n font-size: var(--text-base-size);\n line-height: var(--text-base-line);\n}\n\n.scopeMeta {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.scopeTable {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--text-xs-size);\n}\n\n.scopeTable th {\n padding: var(--space-1) var(--space-2) var(--space-1) 0;\n border-bottom: 1px solid var(--border-subtle);\n color: var(--text-tertiary);\n font-weight: var(--font-weight-medium);\n text-align: left;\n}\n\n.scopeTable td {\n padding: var(--space-1) var(--space-2) var(--space-1) 0;\n border-bottom: 1px solid var(--border-subtle);\n color: var(--text-primary);\n}\n\n.scopeList {\n margin: 0;\n padding-left: var(--space-4);\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.ladder {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n counter-reset: rung;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-secondary);\n}\n\n.ladder li {\n display: grid;\n grid-template-columns: 56px minmax(0, 1fr);\n gap: var(--space-2);\n}\n\n.ladderId {\n font-family: var(--font-mono);\n color: var(--text-primary);\n}\n\n.sheetFooter {\n display: flex;\n flex-direction: column;\n gap: var(--space-3);\n}\n\n.sheetFootnote {\n margin: 0;\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.sheetButtons {\n display: flex;\n justify-content: flex-end;\n gap: var(--space-2);\n}\n\n@media (prefers-reduced-motion: reduce) {\n button.pill,\n button.chip {\n transition: none;\n }\n}\n","/**\n * routes/verse/command/actions.tsx — how every write on the four surfaces\n * reaches the server (unit C7).\n *\n * Order is fixed and the same for a click, a key and the palette\n * (SPEC-310C §1 \"Guarded actions ask for confirmation, then the mutation\n * token\"):\n *\n * 1. a confirmation dialog, when the action asks for one (Stop, Veto,\n * Resume, every Needs-you approve / reject / veto);\n * 2. the mutation token, when none is held (useGuardedAction);\n * 3. the request, one at a time, with the server's own refusal sentence\n * shown on failure and read-only sessions explained, never errored.\n *\n * LOWERING needs no confirmation (SPEC-310B I1: \"lowering authority is\n * instant\") — callers simply omit `confirm` for the switch-down path.\n */\nimport { useCallback, useId, useRef, useState, type ReactNode } from 'react';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { Dialog } from '../../../components/primitives/Dialog.js';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { useGuardedAction } from '../autonomy/use-guarded-action.js';\nimport styles from './command.module.css';\n\nexport interface ConfirmSpec {\n title: string;\n body: ReactNode;\n confirmLabel: string;\n destructive?: boolean;\n}\n\nexport function ConfirmDialog({ spec, onConfirm, onCancel }: { spec: ConfirmSpec | null; onConfirm: () => void; onCancel: () => void }) {\n const titleId = useId();\n const cancelRef = useRef<HTMLButtonElement>(null);\n const confirmRef = useRef<HTMLButtonElement>(null);\n return (\n <Dialog\n open={spec !== null}\n onClose={onCancel}\n titleId={titleId}\n title={spec?.title ?? ''}\n // A destructive confirm starts on Cancel, so a stray Enter never stops the fleet.\n initialFocusRef={spec?.destructive ? cancelRef : confirmRef}\n >\n <div className={styles.confirmBody}>{spec?.body}</div>\n <div className={styles.confirmActions}>\n <Button ref={cancelRef} variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n <Button ref={confirmRef} variant={spec?.destructive ? 'danger' : 'primary'} onClick={onConfirm}>\n {spec?.confirmLabel ?? 'Confirm'}\n </Button>\n </div>\n </Dialog>\n );\n}\n\nexport interface SurfaceActions {\n /** Confirm (when asked), then token (when needed), then run `fn`. */\n act: <T>(fn: () => Promise<T>, reason: string, options?: { confirm?: ConfirmSpec; onDone?: (result: T) => void }) => void;\n busy: boolean;\n error: string | null;\n clearError: () => void;\n readOnly: boolean;\n /** Render once per surface. */\n dialogs: ReactNode;\n}\n\nexport function useSurfaceActions(): SurfaceActions {\n const guard = useGuardedAction();\n const [pending, setPending] = useState<{ spec: ConfirmSpec; run: () => void } | null>(null);\n const { request } = guard;\n\n const act = useCallback(\n <T,>(fn: () => Promise<T>, reason: string, options: { confirm?: ConfirmSpec; onDone?: (result: T) => void } = {}) => {\n const run = () => request(fn, reason, options.onDone);\n if (options.confirm) setPending({ spec: options.confirm, run });\n else run();\n },\n [request],\n );\n\n const dialogs = (\n <>\n <ConfirmDialog\n spec={pending?.spec ?? null}\n onCancel={() => setPending(null)}\n onConfirm={() => {\n const next = pending;\n setPending(null);\n next?.run();\n }}\n />\n <MutationTokenDialog open={guard.tokenOpen} onClose={guard.closeToken} reason={guard.tokenReason} tokenHelp=\"the mutation token ashlr verse printed\" />\n </>\n );\n\n return { act, busy: guard.busy, error: guard.error, clearError: guard.clearError, readOnly: guard.readOnly, dialogs };\n}\n\n/** The error / read-only line a surface shows under its top bar. */\nexport function ActionStatus({ actions }: { actions: Pick<SurfaceActions, 'error' | 'clearError' | 'readOnly'> }) {\n if (actions.readOnly) {\n return (\n <p className={styles.actionNote} role=\"status\">\n Read-only session: this server was started without dispatch, so switching, stopping and vetoing are unavailable. Everything shown is live.\n </p>\n );\n }\n if (!actions.error) return null;\n return (\n <p className={styles.actionError} role=\"alert\">\n {actions.error}\n <button type=\"button\" className={styles.linkButton} onClick={actions.clearError}>\n Dismiss\n </button>\n </p>\n );\n}\n"],"mappings":"kvFC+BA,SAAgB,EAAc,CAAE,OAAM,YAAW,YAAuF,CACtI,IAAM,GAAA,EAAU,EAAA,MAAA,CAAM,EAChB,GAAA,EAAY,EAAA,OAAA,CAA0B,IAAI,EAC1C,GAAA,EAAa,EAAA,OAAA,CAA0B,IAAI,EACjD,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CACE,KAAM,IAAS,KACf,QAAS,EACA,UACT,MAAO,GAAM,OAAS,GAEtB,gBAAiB,GAAM,YAAc,EAAY,EANnD,SAAA,EAQE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,YAAc,SAAA,GAAM,IAAU,CAAA,GACrD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAO,eAAvB,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,IAAK,EAAW,QAAQ,QAAQ,QAAS,EAAU,SAAA,QAEnD,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,IAAK,EAAY,QAAS,GAAM,YAAc,SAAW,UAAW,QAAS,EAClF,SAAA,GAAM,cAAgB,SACjB,CAAA,CACL,CACC,CAAA,CAAA,GAEZ,CAaA,SAAgB,GAAoC,CAClD,IAAM,EAAQ,EAAiB,EACzB,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAwD,IAAI,EACpF,CAAE,WAAY,EAEd,GAAA,EAAM,EAAA,YAAA,EACL,EAAsB,EAAgB,EAAmE,CAAC,IAAM,CACnH,IAAM,MAAY,EAAQ,EAAI,EAAQ,EAAQ,MAAM,EAChD,EAAQ,QAAS,EAAW,CAAE,KAAM,EAAQ,QAAS,KAAI,CAAC,EACzD,EAAI,CACX,EACA,CAAC,CAAO,CACV,EAEM,GACJ,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,GAAS,MAAQ,KACvB,aAAgB,EAAW,IAAI,EAC/B,cAAiB,CACf,IAAM,EAAO,EACb,EAAW,IAAI,EACf,GAAM,IAAI,CACZ,CACD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAqB,KAAM,EAAM,UAAW,QAAS,EAAM,WAAY,OAAQ,EAAM,YAAa,UAAU,wCAA0C,CAAA,CACtJ,CAAA,CAAA,EAGJ,MAAO,CAAE,MAAK,KAAM,EAAM,KAAM,MAAO,EAAM,MAAO,WAAY,EAAM,WAAY,SAAU,EAAM,SAAU,SAAQ,CACtH,CAGA,SAAgB,EAAa,CAAE,WAAmF,CAShH,OARI,EAAQ,UAER,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAO,WAAY,KAAK,SAAS,SAAA,4IAE5C,CAAA,EAGF,EAAQ,OAEX,EAAA,EAAA,KAAA,CAAC,IAAD,CAAG,UAAW,EAAO,YAAa,KAAK,QAAvC,SAAA,CACG,EAAQ,OACT,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,KAAK,SAAS,UAAW,EAAO,WAAY,QAAS,EAAQ,WAAY,SAAA,SAEzE,CAAA,CACP,IAPsB,IAS7B"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./workbench-types-DzN-5trg.js";var t={name:`name`,command:`command`,args:`args`,env:`env`,sourceRef:`sourceRef`},n={seatId:`seatId`,label:`label`,engine:`engine`,accountId:`accountId`,servers:`servers`,reason:`reason`,configFile:`configFile`,configFormat:`configFormat`,notes:`notes`},r={servers:`servers`,configured:`configured`,note:`note`},i={sampledAt:`sampledAt`,seats:`seats`,machine:`machine`,scope:`scope`,notes:`notes`},a={accountId:`accountId`,label:`label`,provider:`provider`,authentication:`authentication`,state:`state`,planType:`planType`,reason:`reason`,version:`version`,pinnedVersion:`pinnedVersion`,versionState:`versionState`,usageBlockedByPin:`usageBlockedByPin`,notes:`notes`},o={sampledAt:`sampledAt`,accounts:`accounts`,driftDetected:`driftDetected`,notes:`notes`},s={available:`available`,pinned:`pinned`,aliasRef:`aliasRef`,tenantRef:`tenantRef`,principalRef:`principalRef`,reason:`reason`};function c(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:null}function l(e){return typeof e==`string`?e:null}function u(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function d(e){return e===!0}function f(e){let n=c(e);if(n===null)return null;let r=l(n[t.name]),i=l(n[t.command]);if(r===null||i===null)return null;let a=null,o=c(n[t.env]);if(o!==null){let e=Object.keys(o);if(e.length>0){a={};for(let t of e)a[t]=`<set>`}}return{name:r,command:i,args:u(n[t.args]),env:a,sourceRef:l(n[t.sourceRef])??`(unknown source)`}}function p(e){let t=c(e);if(t===null)return null;let r=l(t[n.seatId]);if(r===null)return null;let i=Array.isArray(t[n.servers])?t[n.servers].map(f).filter(e=>e!==null):[];return{seatId:r,label:l(t[n.label])??r,engine:l(t[n.engine])??`unknown`,accountId:l(t[n.accountId])??r,servers:i,reason:l(t[n.reason])??`unknown`,configFile:l(t[n.configFile]),configFormat:l(t[n.configFormat]),notes:u(t[n.notes])}}function m(e){let t=c(e);return t===null?null:{available:d(t[s.available]),pinned:d(t[s.pinned]),aliasRef:l(t[s.aliasRef]),tenantRef:l(t[s.tenantRef]),principalRef:l(t[s.principalRef]),reason:l(t[s.reason])??`unknown`}}function h(e){let t=c(e);if(t===null||!Array.isArray(t[i.seats]))return null;let n=c(t[i.machine]),a=n!==null&&Array.isArray(n[r.servers])?n[r.servers].map(f).filter(e=>e!==null):[];return{sampledAt:l(t[i.sampledAt]),seats:t[i.seats].map(p).filter(e=>e!==null),machine:{servers:a,configured:n===null?a.length>0:d(n[r.configured]),note:(n===null?null:l(n[r.note]))??``},scope:m(t[i.scope]),notes:u(t[i.notes])}}function g(e){let t=c(e);if(t===null)return null;let n=l(t[a.accountId]);return n===null?null:{accountId:n,label:l(t[a.label])??n,provider:l(t[a.provider])??`unknown`,authentication:l(t[a.authentication])??`unknown`,state:l(t[a.state])??`unknown`,planType:l(t[a.planType]),reason:l(t[a.reason])??`unknown`,version:l(t[a.version]),pinnedVersion:l(t[a.pinnedVersion]),versionState:l(t[a.versionState])??`unverified`,usageBlockedByPin:d(t[a.usageBlockedByPin]),notes:u(t[a.notes])}}function _(e){let t=c(e);if(t===null||!Array.isArray(t[o.accounts]))return null;let n=t[o.accounts].map(g).filter(e=>e!==null);return{sampledAt:l(t[o.sampledAt]),accounts:n,driftDetected:d(t[o.driftDetected])||n.some(e=>e.versionState===`drift`),notes:u(t[o.notes])}}var v={"mcp-seat-isolated-by-adapter":`Verse launches every turn on this seat with an empty MCP configuration, so it loads no MCP servers at all — whatever is configured elsewhere on this machine.`,"mcp-account-config-absent":`This account has no MCP configuration file of its own, so it starts with none.`,"mcp-account-config-not-json":`This account keeps its MCP servers in a TOML config that the provider CLI reads directly. Hub does not parse or rewrite it, so it cannot list what is in there.`,"mcp-account-config-read":`Read from this account's own private configuration.`,"mcp-account-config-unreadable":`This account's configuration could not be read, so nothing here is a reading.`,"mcp-account-profile-unresolved":`This account's private profile could not be located, so Hub cannot say what it would load.`},y={"mcp-scope-locus-unavailable":`Locus is not reachable on this machine, so writes are not attributable to a tenant.`,"mcp-scope-unpinned":`Locus is running but nothing is pinned, so there is no tenant to scope a write to.`,"mcp-scope-seal-unverified":`Locus reports a pin whose seal did not verify. Fix the pin before writing anything.`,"mcp-scope-expired":`The Locus pin has expired.`,"mcp-scope-pinned":`Writes are attributed to the pinned Locus tenant shown here.`};function b(e,t,n){return e[t]??n}var x={ok:`success`,warn:`warning`,error:`danger`,off:`off`,unknown:`neutral`};function S(e){return x[e]}var C=[`claude`,`codex`,`grok`,`local`];function w(e){return C.includes(e)?e:null}function T(e){let t=e.replace(/\/+$/,``),n=t.lastIndexOf(`/`);return n===-1?t:t.slice(n+1)||t}function E(e){if(!e)return[];let t=[],n=new Set,r=(e,r)=>{typeof e!=`string`||e.length===0||n.has(e)||(n.add(e),t.push({path:e,name:r??T(e)}))},i=[...e.sessions].sort((e,t)=>Date.parse(t.updatedAt)-Date.parse(e.updatedAt));for(let e of i)r(e.projectPath);for(let t of e.projects)r(t.path,t.name);return t}function D(e){let t=[];for(let n of e){if(n.engine!==`local`)continue;let e=n.models[0]?.id??(n.id.startsWith(`local:`)?n.id.slice(6):null);e&&!t.includes(e)&&t.push(e)}return t}function O(e,t){return t.via===`ollama`?e.ollamaLaunch?t.model?[...e.ollamaLaunch,`--model`,t.model]:[...e.ollamaLaunch]:null:e.actions.find(e=>e.kind===`launch`)?.command??null}var k=new Set([`spent`,`not-checked`,`unavailable`]);function A(e,t){if(e.kind===`local`)return[];let n=[],r=e.connection,i=e.signedOut||r!==null&&(r.connection===`signed-out`||r.connection===`expiring`||r.fixKind===`reauth`);i&&n.push({kind:`reconnect`,label:`Reconnect`,command:null,primary:!0});let a=!i&&t!=null&&k.has(t.kind);return a&&n.push({kind:`check-again`,label:`Check again`,command:null,primary:!0}),r!==null&&r.fixKind!==`reauth`&&r.fixKind!==`none`&&r.fixCommand!==null&&n.push({kind:`fix`,label:`Fix`,command:r.fixCommand,primary:!i&&!a}),n.push({kind:`edit-budget`,label:`Edit budget`,command:null,primary:!1}),n}function j(t){return t.seats.map(t=>{let n=w(t.engine),r=t.reason===`mcp-seat-isolated-by-adapter`,i=t.servers.length;return{seatId:t.seatId,label:t.label,engine:n,monogram:n?e[n]:t.label.slice(0,1).toUpperCase(),servers:t.servers,loads:i>0?`loads ${i} server${i===1?``:`s`}`:r?`loads none — isolated by Verse`:`loads none`,isolated:r,sentence:b(v,t.reason,`Hub cannot say what this seat would load.`),reason:t.reason,notes:t.notes}})}function M(e){let t=[{id:`hub`,label:`Hub gateway registry`,disabledReason:null}];for(let n of e?.seats??[]){if(n.seatId===`local`)continue;let e=n.configFormat===`toml`||n.reason===`mcp-account-config-not-json`;t.push({id:`account:${n.accountId}`,label:`${n.label} (${n.engine})`,disabledReason:e?`Keeps its MCP servers in TOML, which Hub does not rewrite.`:null})}return t}function N(e){let t=[],n=``,r=null,i=!1;for(let a of e){if(r){a===r?r=null:n+=a;continue}if(a===`"`||a===`'`){r=a,i=!0;continue}if(/\s/.test(a)){(i||n.length>0)&&t.push(n),n=``,i=!1;continue}n+=a}return(i||n.length>0)&&t.push(n),t}function P(e){let t={};for(let n of e.split(/\r?\n/)){let e=n.trim();if(e.length===0||e.startsWith(`#`))continue;let r=e.indexOf(`=`),i=r===-1?``:e.slice(0,r).trim();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i))return{ok:!1,error:`“${e.slice(0,40)}” is not KEY=value.`};t[i]=e.slice(r+1)}return{ok:!0,env:t}}export{D as a,P as c,f as d,_ as f,E as i,N as l,b as m,S as n,j as o,h as p,O as r,M as s,A as t,y as u};
|
|
2
|
-
//# sourceMappingURL=apps-model-CDFvmsQV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"apps-model-CDFvmsQV.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/mcp/mcp-contract.ts","../../../../../../src/web-ui/routes/verse/apps/apps-model.ts"],"sourcesContent":["/**\n * routes/verse/mcp/mcp-contract.ts — the wire seam for MCP management.\n *\n * Same posture as routes/verse/usage/usage-contract.ts, for the same two\n * reasons:\n *\n * 1. EVERY import from src/core here MUST be type-only. `core/verse/\n * mcp-seat-view.ts` pulls `node:fs` and `node:os`; a VALUE import of even\n * one constant drags that graph into the browser bundle and `vite build`\n * fails. Type-only imports are erased, so the seam guards below cost\n * nothing at runtime.\n * 2. Nothing is CAST. Every read goes through a structural narrower, so a\n * field rename in src/core degrades this panel to an honest \"unknown\"\n * instead of throwing at render time — and the `WIRE_*_KEYS` blocks make\n * that rename fail `npm run typecheck:web` here, at the seam, first.\n *\n * SECURITY: the server already redacts every env value to '<set>' via\n * `redactEnv` and publishes config files as home-relative refs. This module\n * is the client-side backstop on top of that: {@link narrowServer} FORCES\n * every env value to '<set>' whatever arrived, so a server that ever\n * regressed could not print a secret through this panel.\n *\n * Pure: no React, no I/O.\n */\nimport type {\n VerseMcpMachineRegistry,\n VerseMcpSeatView,\n VerseMcpServerView,\n VerseMcpSnapshot,\n} from '../../../../core/verse/mcp-seat-view.js';\nimport type { VerseMcpScope } from '../../../../core/verse/mcp-scope.js';\nimport type {\n VerseAccountCliHealth,\n VerseCliHealthSnapshot,\n} from '../../../../core/verse/mcp-cli-health.js';\n\n// ---------------------------------------------------------------------------\n// Seam contract — compile-time only, zero runtime cost.\n// ---------------------------------------------------------------------------\n\nconst WIRE_SERVER_KEYS = {\n name: 'name',\n command: 'command',\n args: 'args',\n env: 'env',\n sourceRef: 'sourceRef',\n} as const satisfies Record<string, keyof VerseMcpServerView>;\n\nconst WIRE_SEAT_KEYS = {\n seatId: 'seatId',\n label: 'label',\n engine: 'engine',\n accountId: 'accountId',\n servers: 'servers',\n reason: 'reason',\n configFile: 'configFile',\n configFormat: 'configFormat',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseMcpSeatView>;\n\nconst WIRE_MACHINE_KEYS = {\n servers: 'servers',\n configured: 'configured',\n note: 'note',\n} as const satisfies Record<string, keyof VerseMcpMachineRegistry>;\n\nconst WIRE_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n seats: 'seats',\n machine: 'machine',\n scope: 'scope',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseMcpSnapshot>;\n\nconst WIRE_HEALTH_KEYS = {\n accountId: 'accountId',\n label: 'label',\n provider: 'provider',\n authentication: 'authentication',\n state: 'state',\n planType: 'planType',\n reason: 'reason',\n version: 'version',\n pinnedVersion: 'pinnedVersion',\n versionState: 'versionState',\n usageBlockedByPin: 'usageBlockedByPin',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountCliHealth>;\n\nconst WIRE_HEALTH_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n accounts: 'accounts',\n driftDetected: 'driftDetected',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseCliHealthSnapshot>;\n\nconst WIRE_SCOPE_KEYS = {\n available: 'available',\n pinned: 'pinned',\n aliasRef: 'aliasRef',\n tenantRef: 'tenantRef',\n principalRef: 'principalRef',\n reason: 'reason',\n} as const satisfies Record<string, keyof VerseMcpScope>;\n\n// ---------------------------------------------------------------------------\n// Display shapes\n// ---------------------------------------------------------------------------\n\nexport interface McpServer {\n name: string;\n command: string;\n args: string[];\n /** Keys only. Every value is '<set>' — forced here, not merely trusted. */\n env: Record<string, string> | null;\n sourceRef: string;\n}\n\nexport interface McpSeat {\n seatId: string;\n label: string;\n engine: string;\n accountId: string;\n servers: McpServer[];\n reason: string;\n configFile: string | null;\n configFormat: string | null;\n notes: string[];\n}\n\nexport interface McpScope {\n available: boolean;\n pinned: boolean;\n aliasRef: string | null;\n tenantRef: string | null;\n principalRef: string | null;\n reason: string;\n}\n\nexport interface McpSnapshot {\n sampledAt: string | null;\n seats: McpSeat[];\n machine: { servers: McpServer[]; configured: boolean; note: string };\n scope: McpScope | null;\n notes: string[];\n}\n\nexport interface CliHealthRow {\n accountId: string;\n label: string;\n provider: string;\n authentication: string;\n state: string;\n planType: string | null;\n reason: string;\n version: string | null;\n pinnedVersion: string | null;\n versionState: string;\n usageBlockedByPin: boolean;\n notes: string[];\n}\n\nexport interface CliHealthSnapshot {\n sampledAt: string | null;\n accounts: CliHealthRow[];\n driftDetected: boolean;\n notes: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Narrowers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction text(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nfunction strings(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [];\n}\n\nfunction flag(value: unknown): boolean {\n return value === true;\n}\n\n/**\n * Narrow one server, forcing every env value to '<set>'.\n *\n * The redaction is re-applied rather than trusted. The server already did it;\n * doing it again here means no future server bug can turn this panel into a\n * secret printer, and it costs one map over at most a handful of keys.\n */\nexport function narrowServer(raw: unknown): McpServer | null {\n const row = record(raw);\n if (row === null) return null;\n const name = text(row[WIRE_SERVER_KEYS.name]);\n const command = text(row[WIRE_SERVER_KEYS.command]);\n if (name === null || command === null) return null;\n\n let env: Record<string, string> | null = null;\n const rawEnv = record(row[WIRE_SERVER_KEYS.env]);\n if (rawEnv !== null) {\n const keys = Object.keys(rawEnv);\n if (keys.length > 0) {\n env = {};\n for (const key of keys) env[key] = '<set>';\n }\n }\n\n return {\n name,\n command,\n args: strings(row[WIRE_SERVER_KEYS.args]),\n env,\n sourceRef: text(row[WIRE_SERVER_KEYS.sourceRef]) ?? '(unknown source)',\n };\n}\n\nfunction narrowSeat(raw: unknown): McpSeat | null {\n const row = record(raw);\n if (row === null) return null;\n const seatId = text(row[WIRE_SEAT_KEYS.seatId]);\n if (seatId === null) return null;\n const servers = Array.isArray(row[WIRE_SEAT_KEYS.servers])\n ? (row[WIRE_SEAT_KEYS.servers] as unknown[]).map(narrowServer).filter((s): s is McpServer => s !== null)\n : [];\n return {\n seatId,\n label: text(row[WIRE_SEAT_KEYS.label]) ?? seatId,\n engine: text(row[WIRE_SEAT_KEYS.engine]) ?? 'unknown',\n accountId: text(row[WIRE_SEAT_KEYS.accountId]) ?? seatId,\n servers,\n reason: text(row[WIRE_SEAT_KEYS.reason]) ?? 'unknown',\n configFile: text(row[WIRE_SEAT_KEYS.configFile]),\n configFormat: text(row[WIRE_SEAT_KEYS.configFormat]),\n notes: strings(row[WIRE_SEAT_KEYS.notes]),\n };\n}\n\nfunction narrowScope(raw: unknown): McpScope | null {\n const row = record(raw);\n if (row === null) return null;\n return {\n available: flag(row[WIRE_SCOPE_KEYS.available]),\n pinned: flag(row[WIRE_SCOPE_KEYS.pinned]),\n aliasRef: text(row[WIRE_SCOPE_KEYS.aliasRef]),\n tenantRef: text(row[WIRE_SCOPE_KEYS.tenantRef]),\n principalRef: text(row[WIRE_SCOPE_KEYS.principalRef]),\n reason: text(row[WIRE_SCOPE_KEYS.reason]) ?? 'unknown',\n };\n}\n\n/** Narrow GET /api/verse/mcp. Null when the body is not this shape at all. */\nexport function projectMcpSnapshot(raw: unknown): McpSnapshot | null {\n const row = record(raw);\n if (row === null) return null;\n if (!Array.isArray(row[WIRE_SNAPSHOT_KEYS.seats])) return null;\n\n const machine = record(row[WIRE_SNAPSHOT_KEYS.machine]);\n const machineServers = machine !== null && Array.isArray(machine[WIRE_MACHINE_KEYS.servers])\n ? (machine[WIRE_MACHINE_KEYS.servers] as unknown[]).map(narrowServer).filter((s): s is McpServer => s !== null)\n : [];\n\n return {\n sampledAt: text(row[WIRE_SNAPSHOT_KEYS.sampledAt]),\n seats: (row[WIRE_SNAPSHOT_KEYS.seats] as unknown[])\n .map(narrowSeat)\n .filter((s): s is McpSeat => s !== null),\n machine: {\n servers: machineServers,\n configured: machine !== null ? flag(machine[WIRE_MACHINE_KEYS.configured]) : machineServers.length > 0,\n note: (machine !== null ? text(machine[WIRE_MACHINE_KEYS.note]) : null) ?? '',\n },\n scope: narrowScope(row[WIRE_SNAPSHOT_KEYS.scope]),\n notes: strings(row[WIRE_SNAPSHOT_KEYS.notes]),\n };\n}\n\nfunction narrowHealthRow(raw: unknown): CliHealthRow | null {\n const row = record(raw);\n if (row === null) return null;\n const accountId = text(row[WIRE_HEALTH_KEYS.accountId]);\n if (accountId === null) return null;\n return {\n accountId,\n label: text(row[WIRE_HEALTH_KEYS.label]) ?? accountId,\n provider: text(row[WIRE_HEALTH_KEYS.provider]) ?? 'unknown',\n authentication: text(row[WIRE_HEALTH_KEYS.authentication]) ?? 'unknown',\n state: text(row[WIRE_HEALTH_KEYS.state]) ?? 'unknown',\n planType: text(row[WIRE_HEALTH_KEYS.planType]),\n reason: text(row[WIRE_HEALTH_KEYS.reason]) ?? 'unknown',\n // A missing version stays NULL. It is never coerced to a string, because\n // \"no reading\" and \"some version\" are different facts.\n version: text(row[WIRE_HEALTH_KEYS.version]),\n pinnedVersion: text(row[WIRE_HEALTH_KEYS.pinnedVersion]),\n versionState: text(row[WIRE_HEALTH_KEYS.versionState]) ?? 'unverified',\n usageBlockedByPin: flag(row[WIRE_HEALTH_KEYS.usageBlockedByPin]),\n notes: strings(row[WIRE_HEALTH_KEYS.notes]),\n };\n}\n\n/** Narrow GET /api/verse/mcp/cli-health. */\nexport function projectCliHealth(raw: unknown): CliHealthSnapshot | null {\n const row = record(raw);\n if (row === null) return null;\n if (!Array.isArray(row[WIRE_HEALTH_SNAPSHOT_KEYS.accounts])) return null;\n const accounts = (row[WIRE_HEALTH_SNAPSHOT_KEYS.accounts] as unknown[])\n .map(narrowHealthRow)\n .filter((a): a is CliHealthRow => a !== null);\n return {\n sampledAt: text(row[WIRE_HEALTH_SNAPSHOT_KEYS.sampledAt]),\n accounts,\n // Derived locally as well as read, so a server that forgot the flag still\n // renders the banner rather than silently hiding a drift.\n driftDetected:\n flag(row[WIRE_HEALTH_SNAPSHOT_KEYS.driftDetected]) ||\n accounts.some((account) => account.versionState === 'drift'),\n notes: strings(row[WIRE_HEALTH_SNAPSHOT_KEYS.notes]),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Copy for the machine-readable reasons this surface renders\n// ---------------------------------------------------------------------------\n\n/**\n * Plain language for each seat reason. The CODE is still shown next to the\n * sentence — it is the thing to search for — but it is never the sentence.\n * Same split `usage/accounts-model.ts` uses for probe reasons.\n */\nexport const SEAT_REASON_COPY: Record<string, string> = {\n 'mcp-seat-isolated-by-adapter':\n 'Verse launches every turn on this seat with an empty MCP configuration, so it loads no MCP '\n + 'servers at all — whatever is configured elsewhere on this machine.',\n 'mcp-account-config-absent':\n 'This account has no MCP configuration file of its own, so it starts with none.',\n 'mcp-account-config-not-json':\n 'This account keeps its MCP servers in a TOML config that the provider CLI reads directly. '\n + 'Hub does not parse or rewrite it, so it cannot list what is in there.',\n 'mcp-account-config-read':\n 'Read from this account\\'s own private configuration.',\n 'mcp-account-config-unreadable':\n 'This account\\'s configuration could not be read, so nothing here is a reading.',\n 'mcp-account-profile-unresolved':\n 'This account\\'s private profile could not be located, so Hub cannot say what it would load.',\n};\n\nexport const SCOPE_REASON_COPY: Record<string, string> = {\n 'mcp-scope-locus-unavailable':\n 'Locus is not reachable on this machine, so writes are not attributable to a tenant.',\n 'mcp-scope-unpinned':\n 'Locus is running but nothing is pinned, so there is no tenant to scope a write to.',\n 'mcp-scope-seal-unverified':\n 'Locus reports a pin whose seal did not verify. Fix the pin before writing anything.',\n 'mcp-scope-expired': 'The Locus pin has expired.',\n 'mcp-scope-pinned': 'Writes are attributed to the pinned Locus tenant shown here.',\n};\n\n/** Prose for a code, or the caller's own sentence. NEVER the raw code alone. */\nexport function reasonSentence(\n copy: Record<string, string>,\n reason: string,\n fallback: string,\n): string {\n return copy[reason] ?? fallback;\n}\n","/**\n * routes/verse/apps/apps-model.ts — pure view-model for Apps & Accounts.\n *\n * The page has five groups (SPEC-310C §4), from three kinds of source:\n * ACCOUNTS the shared capacity rows (usage/capacity-strip-model.ts)\n * plus the actions each seat needs (Reconnect / Check again / Fix / Edit budget);\n * DESKTOP, TERMINAL AGENTS, LOCAL MODELS GET /api/verse/apps, as served;\n * MCP SERVERS GET /api/verse/mcp (what each seat would ACTUALLY load).\n * Everything that decides a word, a tone or whether a control is enabled\n * lives here, so it is unit-tested without a DOM.\n *\n * Pure: no React, no I/O.\n */\nimport type { VerseAppHealthState, VerseAppRow } from '../../../../core/verse/workbench-types.js';\nimport { ENGINE_MONOGRAM } from '../../../../core/verse/workbench-types.js';\nimport type { VerseBootstrap, VerseEngine, VerseSeat } from '../../../data/api-types.js';\nimport type { HealthTone } from '../health/health-model.js';\nimport type { McpSeat, McpServer, McpSnapshot } from '../mcp/mcp-contract.js';\nimport { reasonSentence, SEAT_REASON_COPY } from '../mcp/mcp-contract.js';\nimport type { AccountStatus, CapacityRow } from '../usage/capacity-strip-model.js';\n\n/** SPEC-310C §4 order. */\nexport const APPS_GROUP_ORDER = ['accounts', 'desktop', 'terminal-agents', 'local-models', 'mcp-servers'] as const;\nexport type AppsGroupId = (typeof APPS_GROUP_ORDER)[number];\n\nexport const APPS_GROUP_TITLE: Readonly<Record<AppsGroupId, string>> = {\n accounts: 'Accounts',\n desktop: 'Desktop',\n 'terminal-agents': 'Terminal agents',\n 'local-models': 'Local models',\n 'mcp-servers': 'MCP servers',\n};\n\nconst HEALTH_TONE: Readonly<Record<VerseAppHealthState, HealthTone | 'off'>> = {\n ok: 'success',\n warn: 'warning',\n error: 'danger',\n off: 'off',\n unknown: 'neutral',\n};\n\n/** A row's dot tone. `off` is its own quiet state (not installed, switched off) — never a fault. */\nexport function appHealthTone(state: VerseAppHealthState): HealthTone | 'off' {\n return HEALTH_TONE[state];\n}\n\nconst VERSE_ENGINES: readonly VerseEngine[] = ['claude', 'codex', 'grok', 'local'];\n\nexport function asEngine(value: string): VerseEngine | null {\n return (VERSE_ENGINES as readonly string[]).includes(value) ? (value as VerseEngine) : null;\n}\n\n// ---------------------------------------------------------------------------\n// Launch targets\n// ---------------------------------------------------------------------------\n\nexport interface LaunchProject {\n path: string;\n name: string;\n}\n\nfunction baseName(path: string): string {\n const trimmed = path.replace(/\\/+$/, '');\n const i = trimmed.lastIndexOf('/');\n return i === -1 ? trimmed : trimmed.slice(i + 1) || trimmed;\n}\n\n/**\n * Where a Launch may start, most relevant first: the folders of the most\n * recently used chats (the \"current project\"), then every discovered project.\n * The server re-checks each against the same two sources, so this list is a\n * convenience, never the gate.\n */\nexport function launchProjects(bootstrap: Pick<VerseBootstrap, 'sessions' | 'projects'> | undefined): LaunchProject[] {\n if (!bootstrap) return [];\n const out: LaunchProject[] = [];\n const seen = new Set<string>();\n const add = (path: string, name?: string) => {\n if (typeof path !== 'string' || path.length === 0 || seen.has(path)) return;\n seen.add(path);\n out.push({ path, name: name ?? baseName(path) });\n };\n const recent = [...bootstrap.sessions].sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt));\n for (const s of recent) add(s.projectPath);\n for (const p of bootstrap.projects) add(p.path, p.name);\n return out;\n}\n\n/** Ollama tags the local seats run — the model choices for `ollama launch <id> --model`. */\nexport function localModelTags(seats: readonly VerseSeat[]): string[] {\n const out: string[] = [];\n for (const seat of seats) {\n if (seat.engine !== 'local') continue;\n const tag = seat.models[0]?.id ?? (seat.id.startsWith('local:') ? seat.id.slice('local:'.length) : null);\n if (tag && !out.includes(tag)) out.push(tag);\n }\n return out;\n}\n\nexport type LaunchVia = 'native' | 'ollama';\n\nexport interface LaunchChoice {\n via: LaunchVia;\n model: string | null;\n}\n\n/** The argv a launch choice runs, as the operator would type it. */\nexport function launchCommand(row: VerseAppRow, choice: LaunchChoice): string[] | null {\n if (choice.via === 'ollama') {\n if (!row.ollamaLaunch) return null;\n return choice.model ? [...row.ollamaLaunch, '--model', choice.model] : [...row.ollamaLaunch];\n }\n return row.actions.find((a) => a.kind === 'launch')?.command ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Accounts\n// ---------------------------------------------------------------------------\n\nexport type AccountActionKind = 'reconnect' | 'check-again' | 'fix' | 'edit-budget';\n\nexport interface AccountAction {\n kind: AccountActionKind;\n label: string;\n /** Fix only: the command the dialog shows. */\n command: string[] | null;\n /** Primary = the one thing this seat needs now. */\n primary: boolean;\n}\n\n/** Statuses a fresh health sweep can change on its own: offer \"Check again\" for them. */\nconst RECHECKABLE: ReadonlySet<AccountStatus['kind']> = new Set(['spent', 'not-checked', 'unavailable']);\n\n/**\n * What a seat row offers, the one it needs most first:\n * Reconnect signed out or sign-in expiring (the provider's own login, in Terminal);\n * Check again spent, not checked, or unavailable — a zero-cost health sweep\n * is what moves those (pass the row's SETTLED status, so the\n * button stays put while its own check runs);\n * Fix A2 has a command for what is wrong (a re-pin);\n * Edit budget every paid seat.\n * Local rows need none of these.\n */\nexport function accountActions(row: CapacityRow, status?: AccountStatus | null): AccountAction[] {\n if (row.kind === 'local') return [];\n const out: AccountAction[] = [];\n const c = row.connection;\n const needsLogin = row.signedOut\n || (c !== null && (c.connection === 'signed-out' || c.connection === 'expiring' || c.fixKind === 'reauth'));\n if (needsLogin) out.push({ kind: 'reconnect', label: 'Reconnect', command: null, primary: true });\n const recheck = !needsLogin && status != null && RECHECKABLE.has(status.kind);\n if (recheck) out.push({ kind: 'check-again', label: 'Check again', command: null, primary: true });\n if (c !== null && c.fixKind !== 'reauth' && c.fixKind !== 'none' && c.fixCommand !== null) {\n out.push({ kind: 'fix', label: 'Fix', command: c.fixCommand, primary: !needsLogin && !recheck });\n }\n out.push({ kind: 'edit-budget', label: 'Edit budget', command: null, primary: false });\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// MCP\n// ---------------------------------------------------------------------------\n\nexport interface McpSeatRow {\n seatId: string;\n label: string;\n engine: VerseEngine | null;\n monogram: string;\n servers: McpServer[];\n /** \"loads 2 servers\", \"loads none — isolated by Verse\". */\n loads: string;\n isolated: boolean;\n /** Plain language for the seat's reason; the code rides beside it. */\n sentence: string;\n reason: string;\n notes: string[];\n}\n\nexport function mcpSeatRows(snapshot: McpSnapshot): McpSeatRow[] {\n return snapshot.seats.map((seat: McpSeat) => {\n const engine = asEngine(seat.engine);\n const isolated = seat.reason === 'mcp-seat-isolated-by-adapter';\n const n = seat.servers.length;\n return {\n seatId: seat.seatId,\n label: seat.label,\n engine,\n monogram: engine ? ENGINE_MONOGRAM[engine] : seat.label.slice(0, 1).toUpperCase(),\n servers: seat.servers,\n loads: n > 0 ? `loads ${n} server${n === 1 ? '' : 's'}` : isolated ? 'loads none — isolated by Verse' : 'loads none',\n isolated,\n sentence: reasonSentence(SEAT_REASON_COPY, seat.reason, 'Hub cannot say what this seat would load.'),\n reason: seat.reason,\n notes: seat.notes,\n };\n });\n}\n\n/** Where an Add can write: the hub registry, and each account whose config is JSON. */\nexport interface McpTargetOption {\n id: string;\n label: string;\n /** Why this target cannot take a write, or null. */\n disabledReason: string | null;\n}\n\nexport function mcpTargets(snapshot: McpSnapshot | null): McpTargetOption[] {\n const out: McpTargetOption[] = [{ id: 'hub', label: 'Hub gateway registry', disabledReason: null }];\n for (const seat of snapshot?.seats ?? []) {\n if (seat.seatId === 'local') continue;\n // An isolated (Claude) account CAN be written — Claude Code in a terminal\n // reads it — and the form says a Verse chat on it still loads nothing.\n const toml = seat.configFormat === 'toml' || seat.reason === 'mcp-account-config-not-json';\n out.push({\n id: `account:${seat.accountId}`,\n label: `${seat.label} (${seat.engine})`,\n disabledReason: toml ? 'Keeps its MCP servers in TOML, which Hub does not rewrite.' : null,\n });\n }\n return out;\n}\n\n/** Split `a \"b c\" d` into argv the way a shell would, for the Add form's arguments field. */\nexport function splitArgs(text: string): string[] {\n const out: string[] = [];\n let current = '';\n let quote: '\"' | \"'\" | null = null;\n let has = false;\n for (const ch of text) {\n if (quote) {\n if (ch === quote) quote = null;\n else current += ch;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n has = true;\n continue;\n }\n if (/\\s/.test(ch)) {\n if (has || current.length > 0) out.push(current);\n current = '';\n has = false;\n continue;\n }\n current += ch;\n }\n if (has || current.length > 0) out.push(current);\n return out;\n}\n\n/** `KEY=value` lines → an env object; the first bad line is reported, never guessed. */\nexport function parseEnvLines(text: string): { ok: true; env: Record<string, string> } | { ok: false; error: string } {\n const env: Record<string, string> = {};\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (line.length === 0 || line.startsWith('#')) continue;\n const eq = line.indexOf('=');\n const key = eq === -1 ? '' : line.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) return { ok: false, error: `“${line.slice(0, 40)}” is not KEY=value.` };\n env[key] = line.slice(eq + 1);\n }\n return { ok: true, env };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./workbench-types-DzN-5trg.js";import{r as t}from"./verse-model-DyCwZF-M.js";import{g as n,v as r,y as i}from"./format-BkWdOQDL.js";import{n as a,t as o}from"./seat-subscription-B-f9ViU2.js";import{v as s}from"./context-model-BC-HOmPo.js";Object.freeze({"all-in":Object.freeze({claude:Object.freeze({enabled:!0,reservePercent:0}),codex:Object.freeze({enabled:!1,reservePercent:0}),grok:Object.freeze({enabled:!0,reservePercent:0}),local:Object.freeze({enabled:!0,reservePercent:0})}),balanced:Object.freeze({claude:Object.freeze({enabled:!0,reservePercent:40,maxSessionWindowPercent:70}),codex:Object.freeze({enabled:!1,reservePercent:40,maxSessionWindowPercent:70}),grok:Object.freeze({enabled:!0,reservePercent:0}),local:Object.freeze({enabled:!0,reservePercent:0})}),reserve:Object.freeze({claude:Object.freeze({enabled:!0,reservePercent:85,maxSessionWindowPercent:50}),codex:Object.freeze({enabled:!1,reservePercent:85,maxSessionWindowPercent:50}),grok:Object.freeze({enabled:!0,reservePercent:85}),local:Object.freeze({enabled:!0,reservePercent:0})})});var c=Object.freeze({"all-in":`Autonomy may use all available usage on every enabled seat.`,balanced:`Autonomy stops at each seat’s reserve, so you keep headroom for your own sessions.`,reserve:`Autonomy runs on free local models, plus only a small slice of paid seats.`}),l={eligible:`Eligible`,held:`Held back`,off:`Off`,unknown:`No reading`},u=[{value:`reserve`,label:`Reserve`,description:c.reserve},{value:`balanced`,label:`Balanced`,description:c.balanced},{value:`all-in`,label:`All-in`,description:c[`all-in`]}];function d(e,t){if(!t)return!1;let n=e=>u.findIndex(t=>t.value===e);return n(e)>n(t)}function f(e){return Math.round(e)}function p(e,t,n){return t.enabled?n?.eligibleForAutonomy?`eligible`:!e&&(n===null||n.sessionUsedPercent===null&&n.weeklyUsedPercent===null)?`unknown`:`held`:`off`}function m(e,t,r,i){if(t||i===null)return[];let a=[],o=100-r.reservePercent,s=i.weeklyUsedPercent!==null||e===`claude`||e===`grok`;if(s){let t=i.weeklyUsedPercent;a.push({kind:`weekly`,label:e===`grok`?`Billing period`:`Weekly`,usedPercent:t,ceilingPercent:o,binding:i.bindingWindow===`weekly`,description:t===null?`Weekly window: no reading.`:`Weekly window ${n(t)} used; autonomy stops at ${f(o)}%, ${f(r.reservePercent)}% kept for you.`})}if(i.sessionUsedPercent!==null||e===`claude`){let e=i.sessionUsedPercent,t=r.maxSessionWindowPercent??100,c=s?t:Math.min(t,o);a.push({kind:`session`,label:`5-hour`,usedPercent:e,ceilingPercent:c,binding:i.bindingWindow===`session`,description:e===null?`5-hour window: no reading.`:`5-hour window ${n(e)} used; ${c>=100?`no autonomy ceiling`:`autonomy stops at ${f(c)}%`}.`})}return a}function ee(e,t=Date.now()){let n=new Map(e.headroom.map(e=>[e.seatId,e]));return e.seatInfo.map(i=>{let a=e.effective[i.seatId]??{seatId:i.seatId,enabled:!1,reservePercent:100},o=n.get(i.seatId)??null,s=(o?.reasons??[]).map(e=>r(e,t).trim()).filter(e=>e.length>0);return{seatId:i.seatId,label:i.label,engine:i.engine,free:i.free,policy:a,headroom:o,status:p(i.free,a,o),why:s[0]??(i.free?`Local model — free.`:`No reading yet.`),more:s.slice(1),bars:m(i.engine,i.free,a,o),hasSessionCeiling:!i.free&&(i.engine===`claude`||i.engine===`codex`)}})}function te(e){let t=e.filter(e=>e.status===`eligible`).length,n=e.length;if(n===0)return{eligible:t,total:n,sentence:`No seats are known yet.`};let r=e.filter(e=>e.status===`eligible`&&!e.free).length,i=t-r,a=[];return r>0&&a.push(`${r} paid`),i>0&&a.push(`${i} local`),{eligible:t,total:n,sentence:t===0?`No seat can take autonomous work right now.`:`${t} of ${n} seats can take autonomous work (${a.join(`, `)}).`}}function h(e,t){let n=Date.parse(e);if(!Number.isFinite(n))return`unknown`;let r=Math.max(0,Math.round((t-n)/6e4));return r<1?`just now`:r<120?`${r} min ago`:`${Math.round(r/60)} h ago`}function g(e,t=0,n=100){return Number.isFinite(e)?Math.max(t,Math.min(n,Math.round(e))):t}var _={available:`ready`,credits:`ready`,tight:`tight`,exhausted:`blocked`,"signed-out":`blocked`,"probe-unsupported":`blocked`,unknown:`unread`};function v(e,t,n){return e===1?t:n}function y(e){let{ready:t,tight:n,blocked:r,unread:i,total:a,local:o}=e;if(a===0)return`No seats are reported at all. This is an empty roster, not a set of seats at zero.`;let s=o===null?``:o.reachable&&o.residentCount>0?` ${o.residentCount} local ${v(o.residentCount,`model is`,`models are`)} resident and answer with no load delay.`:o.reachable&&o.agenticCount>0?` No local model is resident, but ${o.agenticCount} installed ${v(o.agenticCount,`one can`,`ones can`)} drive a session after a load.`:o.reachable?` No local model is resident.`:` The local runtime did not answer, so local capacity is unknown.`,c=i===0?``:` ${i} ${v(i,`seat has`,`seats have`)} no reading at all — unread, not exhausted.`;return t>0?`${t} of ${a} ${v(a,`seat is`,`seats are`)} usable right now.${c}${s}`:n>0?`No seat is clear: ${n} ${v(n,`is`,`are`)} running tight and ${r} ${v(r,`is`,`are`)} blocked.${c}${s}`:r>0?`No cloud seat reports headroom — ${r} blocked.${c}${s}`:`No seat reported a usable window.${c}${s}`}function b(e){let t=e.binding;return{id:e.id,label:e.label,kind:`account`,color:e.color,cls:_[e.verdict.state],headline:e.verdict.headline,usedPct:t&&t.measured&&!t.limitReached?t.usedPct:null,measured:t!==null&&t.measured&&!t.limitReached}}function x(e){return{id:`local`,label:`Local`,kind:`local`,color:e.color,cls:_[e.verdict.state],headline:e.verdict.headline,usedPct:e.usedPct,measured:e.usedPct!==null}}function S(e,t){let n=[],r=[],i=new Set;for(let a of e)for(let e of a.windows){if(e.resetsAt!==null){let r=Date.parse(e.resetsAt);if(!Number.isNaN(r)){let i=r-t;n.push({seatLabel:a.label,windowLabel:e.label,atMs:r,inMs:i,overdue:i<=0});continue}}if(e.resetText!==null){let t=`${a.label}|${e.label}|${e.resetText}`;if(i.has(t))continue;i.add(t),r.push({seatLabel:a.label,windowLabel:e.label,text:e.resetText})}}return{instants:n,prose:r}}function C(e){let t=e.filter(e=>!e.overdue);return t.length>0?t.reduce((e,t)=>t.inMs<e.inMs?t:e):e.length===0?null:e.reduce((e,t)=>t.atMs>e.atMs?t:e)}function w(e,t){let n=e.filter(e=>e.atMs>t);return n.length>0?n.reduce((e,t)=>t.atMs<e.atMs?t:e):e.length===0?null:e.reduce((e,t)=>t.atMs>e.atMs?t:e)}function T(e,t){if(e===null&&t===null)return null;let n=e?.residentBytes??t?.residentBytes??null,r=e?.memoryBudgetBytes??t?.memoryBudgetBytes??null;return{reachable:t?.reachable??e?.verdict.state!==`unknown`,residentCount:e?.residentCount??t?.rows.filter(e=>e.resident).length??0,installedCount:e?.installedCount??t?.rows.length??0,agenticCount:t?.agenticCount??0,unknownToolCount:t?.unknownToolCount??0,residentBytes:n,memoryBudgetBytes:r,headroomBytes:n!==null&&r!==null?Math.max(0,r-n):null,freeMemoryBytes:t?.freeMemoryBytes??null,usedPct:e?.usedPct??t?.memoryUsedPct??null}}function E(e){let t=e.nowMs??Date.now(),n=e.cards.map(b);e.localCard&&n.push(x(e.localCard));let r=e=>n.filter(t=>t.cls===e).length,i=r(`ready`),a=r(`tight`),o=r(`blocked`),s=r(`unread`),{instants:c,prose:l}=S(e.cards.map(e=>({label:e.label,windows:e.allWindows})),t),u=T(e.localCard,e.localView);return{seats:n,ready:i,tight:a,blocked:o,unread:s,total:n.length,resets:c,nextReset:C(c),proseResets:l,local:u,headline:y({ready:i,tight:a,blocked:o,unread:s,total:n.length,local:u}),noCapacity:n.length>0&&i===0&&a===0&&s<n.length}}function D(e){if(!Number.isFinite(e))return`—`;if(e<=0)return`overdue`;let t=Math.floor(e/1e3),n=Math.floor(t/86400),r=Math.floor(t%86400/3600),i=Math.floor(t%3600/60);return n>0?`${n}d ${r}h`:r>0?`${r}h ${i}m`:i>0?`${i}m`:`${t}s`}var O={connected:`connected`,expiring:`sign-in expiring`,"signed-out":`signed out`,exhausted:`out of usage`,"binary-skew":`older CLI pinned`,unknown:`not checked`},k={connected:`success`,expiring:`warning`,"signed-out":`danger`,exhausted:`danger`,"binary-skew":`warning`,unknown:`neutral`},A={"signed-out":0,exhausted:1,expiring:2,"binary-skew":3,unknown:4,connected:5};function j(e,t=Date.now()){if(typeof e!=`string`)return null;let n=Date.parse(e);return!Number.isFinite(n)||n<=t?null:`usable again in ${D(n-t)}`}function M(e){return e.connection===`connected`?!1:e.connection!==`unknown`||e.reasons.length>0&&!e.reasons[0].includes(`has not reached this seat`)}function N(e,t=[],n=Date.now()){let s=new Map(t.map(e=>[e.id,e]));return e.filter(M).map(e=>{let t=s.get(e.seatId),c=e.connection===`exhausted`&&t!==void 0?o(a(t,n),e.resetAt):e.resetAt,l=i(c,n);return{report:e,label:t?.label??e.seatId,word:O[e.connection],tone:k[e.connection],detail:e.reasons[0]?r(e.reasons[0],n):null,reset:l===null?null:`resets ${l}`,usableAgain:e.connection===`exhausted`?j(c,n):null}}).sort((e,t)=>A[e.report.connection]-A[t.report.connection])}function P(e){return e.map(e=>/^[A-Za-z0-9_@%+=:,./-]+$/.test(e)||e.startsWith(`~/`)&&/^[A-Za-z0-9_@%+=:,./~-]+$/.test(e)?e:e.startsWith(`~/`)?`~/'${e.slice(2).replaceAll(`'`,`'\\''`)}'`:`'${e.replaceAll(`'`,`'\\''`)}'`).join(` `)}function F(e){if(e.length===0)return`All seats are connected.`;let t=e.filter(e=>e.tone===`danger`).length;return t>0?t===1?`${e.find(e=>e.tone===`danger`).label} can't run turns right now.`:`${t} seats can't run turns right now.`:e.length===1?`${e[0].label} needs attention.`:`${e.length} seats need attention.`}var I={ready:`success`,tight:`warning`,blocked:`danger`,unread:`neutral`};function L(e){return I[e]}function R(e,t){return{id:e.id,label:e.label,usedPercent:e.usedPercent,limitReached:e.limitReached,resetText:e.resetText,resetsAt:e.resetsAt,binding:t}}function z(e){return typeof e==`string`&&Number.isFinite(Date.parse(e))}function B(e){return e.limitReached||e.usedPercent!==null&&e.usedPercent>=100}function V(e,t){return e?{connection:e.connection,word:O[e.connection],tone:k[e.connection],reasons:H(e.reasons,t),fixKind:e.fix.kind,fixCommand:e.fix.command&&e.fix.command.length>0?[...e.fix.command]:null}:null}function H(e,t){return e.map(e=>r(e,t).trim()).filter(e=>e.length>0)}function U(e){if(!e||e.free)return null;let{policy:t}=e,n=Math.max(0,Math.min(100,Math.round(t.reservePercent))),r=t.enabled?n===0?`No reserve — autonomy may use all of it`:`Reserved for you ${n}%`:`Autonomy off — all yours`;return{percent:t.enabled?n:null,label:r,autonomy:e.status,autonomyWord:l[e.status],why:e.why}}function W(n,r,i,s){let c=a(n,s),l=[];c.binding&&l.push(R(c.binding,!0));for(let e of c.others){if(l.length>=3)break;l.push(R(e,!1))}let u=r.get(n.id),d=V(u,s),f=d!==null&&(d.connection===`signed-out`||d.connection===`exhausted`);return{seatId:n.id,label:n.label,engine:n.engine,monogram:e[n.engine],kind:c.kind,plan:c.plan,cls:f?`blocked`:c.cls,word:f?t.blocked:c.word,summary:f?d.reasons[0]??d.word:c.summary,connection:d,windows:l,credits:c.credits,reserve:U(i.get(n.id)),notes:[...c.notes],localCount:1,checkedAt:z(u?.checkedAt)?u.checkedAt:z(c.observedAt)?c.observedAt:null,resetAt:o(c,u?.resetAt),signedOut:d?.connection===`signed-out`||n.capacity?.usability===`signed-out`}}function ne(t,n,r){let i=t.map(e=>a(e,r)),o=i.filter(e=>e.cls===`ready`).length,s=i.filter(e=>e.cls===`blocked`).length,c=o>0?`ready`:s===i.length?`blocked`:`unread`,l=t.map(e=>n.get(e.id)).find(e=>e!==void 0),u=t.length;return{seatId:`local`,label:`Local models`,engine:`local`,monogram:e.local,kind:`local`,plan:null,cls:c,word:i.find(e=>e.cls===c)?.word??`no reading`,summary:c===`ready`?`${u} ${u===1?`model`:`models`} on this machine · free`:c===`blocked`?i[0]?.summary??`local runtime unavailable`:`readiness not reported`,connection:V(l,r),windows:[],credits:null,reserve:null,notes:[],localCount:u,checkedAt:z(l?.checkedAt)?l.checkedAt:i.map(e=>e.observedAt).filter(z).sort((e,t)=>Date.parse(t)-Date.parse(e))[0]??null,resetAt:null,signedOut:!1}}function G(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var K=e=>typeof e==`number`&&Number.isFinite(e)?e:null;function q(e){if(!G(e)||typeof e.seatId!=`string`)return null;let t=e.bindingWindow;return{seatId:e.seatId,sessionUsedPercent:K(e.sessionUsedPercent),weeklyUsedPercent:K(e.weeklyUsedPercent),bindingWindow:t===`session`||t===`weekly`?t:null,autonomyHeadroomPercent:K(e.autonomyHeadroomPercent),resetAt:typeof e.resetAt==`string`?e.resetAt:null,eligibleForAutonomy:e.eligibleForAutonomy===!0,reasons:Array.isArray(e.reasons)?e.reasons.filter(e=>typeof e==`string`):[]}}function J(e,t){if(!G(t)||typeof t.enabled!=`boolean`)return null;let n=t.reservePercent;if(typeof n!=`number`||!Number.isFinite(n))return null;let r={seatId:e,enabled:t.enabled,reservePercent:n},i=t.maxSessionWindowPercent;return typeof i==`number`&&Number.isFinite(i)&&(r.maxSessionWindowPercent=i),r}function Y(e){if(!G(e)||!Array.isArray(e.seatInfo))return new Map;let t=G(e.effective)?e.effective:{},n={},r=[];for(let i of e.seatInfo){if(!G(i)||typeof i.seatId!=`string`)continue;let e=i.seatId,a=i.engine;if(a===`claude`||a===`codex`||a===`grok`||a===`local`){if(Object.prototype.hasOwnProperty.call(t,e)){let r=J(e,t[e]);if(r===null)continue;n[e]=r}r.push({seatId:e,label:typeof i.label==`string`?i.label:e,engine:a,free:i.free===!0})}}let i=Array.isArray(e.headroom)?e.headroom.map(q).filter(e=>e!==null):[],a={...e,seatInfo:r,effective:n,headroom:i};try{return new Map(ee(a).map(e=>[e.seatId,e]))}catch{return new Map}}function X(e){let t=new Map;if(!Array.isArray(e))return t;for(let n of e){if(!G(n)||typeof n.seatId!=`string`)continue;let e=n.connection;if(typeof e!=`string`||!Object.prototype.hasOwnProperty.call(O,e))continue;let r=G(n.fix)?n.fix:{},i=r.kind,a=Array.isArray(r.command)&&r.command.every(e=>typeof e==`string`)?r.command:void 0;t.set(n.seatId,{...n,reasons:Array.isArray(n.reasons)?n.reasons.filter(e=>typeof e==`string`):[],fix:{kind:i===`reauth`||i===`repin`||i===`wait`?i:`none`,...a?{command:a}:{}}})}return t}function Z(e,t={}){let n=X(t.health),r=Y(t.budget),i=Array.isArray(e)?e.filter(e=>G(e)&&typeof e.id==`string`):[],a=t.local??`collapse`,o=t.now??Date.now(),s=i;if(t.seatIds){let e=new Map(i.map(e=>[e.id,e]));s=t.seatIds.map(t=>e.get(t)).filter(e=>e!==void 0)}let c=[],l=[],u=-1;for(let e of s){if(e.engine===`local`){if(a===`hide`)continue;if(a===`collapse`){u===-1&&(u=c.length),l.push(e);continue}}c.push(W(e,n,r,o))}if(l.length>0){let e=l.length===1?W(l[0],n,r,o):ne(l,n,o);c.splice(u,0,e)}return c}function re(e){let t=e.filter(e=>e.kind===`subscription`),n=e.filter(e=>e.kind===`local`),r=t.filter(e=>e.cls===`ready`||e.cls===`tight`).length,i=t.filter(e=>e.cls===`unread`).length,a=[];return t.length===0?a.push(`No accounts connected`):a.push(`${r} of ${t.length} ${t.length===1?`account`:`accounts`} usable`),i>0&&a.push(`${i} not read yet`),n.some(e=>e.cls===`ready`)?a.push(`local models ready`):n.length>0&&a.push(`local models not ready`),a.join(` · `)}function ie(e){let t=null;for(let n of e){if(n.kind!==`subscription`)continue;let e=n.windows.find(e=>e.binding)??null,r;if(n.cls===`blocked`||e?.limitReached)r=300;else if(e?.usedPercent!=null)r=(n.cls===`tight`?100:0)+e.usedPercent;else continue;(t===null||r>t.score)&&(t={row:n,score:r})}return t?.row??null}function ae(e,t,n={}){return Z(e,{...n,seatIds:[t],local:`each`})[0]??null}function oe(e,t,r){let i=`${e.label} ${t.label}`,a=t.resetText===null?``:`, ${t.resetText}`;if(t.limitReached)return`${i}: limit reached${a}`;if(t.usedPercent===null)return`${i}: no reading${a}`;let o=r!==null&&r>0?`; ${r}% kept for you`:``;return`${i}: ${n(t.usedPercent)} used${o}${a}`}var se={usable:`success`,low:`warning`,spent:`danger`,"signed-out":`danger`,unavailable:`danger`,"not-checked":`neutral`,checking:`neutral`},Q={usable:0,low:1,checking:2,"not-checked":3,spent:4,unavailable:5,"signed-out":6};function ce(e,t){let n=s(e.checkedAt,t);if(n===null||e.checkedAt===null)return{checked:null,checkedTitle:null};let r=new Date(e.checkedAt);return{checked:`checked ${n}`,checkedTitle:`Last checked ${r.toLocaleString([],{weekday:`short`,month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`})}`}}function $(e,t){let n=t.now??Date.now(),{checked:r,checkedTitle:a}=ce(e,n),o=(e,t,n,i={})=>({kind:e,label:t,detail:n,tone:se[e],usableAgain:null,checked:r,checkedTitle:a,coversConnection:!1,...i});if(t.checking)return o(`checking`,`Checking…`,null);if(e.kind===`local`)return e.cls===`ready`?o(`usable`,`Ready`,e.localCount>1?`${e.localCount} models on this machine · free`:`runs on this machine · free`):e.cls===`blocked`?o(`unavailable`,`Not running`,e.summary):t.healthRead?o(`not-checked`,`Not checked`,`readiness not reported yet`):o(`checking`,`Checking…`,null);let s=e.connection?.connection??null;if(e.signedOut)return o(`signed-out`,`Signed out`,`reconnect to use it`,{coversConnection:!0});let c=e.windows.find(e=>e.binding)??null;if(s===`exhausted`||e.cls===`blocked`&&c!==null&&B(c)){let t=i(e.resetAt,n),r=e.resetAt!==null&&Date.parse(e.resetAt)>n,a=(e.windows.find(e=>B(e)&&!z(e.resetsAt)&&e.resetText!==null)??null)?.resetText??(c!==null&&!z(c.resetsAt)?c.resetText:null);return o(`spent`,`Spent`,t===null?a??`reset time not reported`:r?`resets ${t}`:`was due to reset ${t}`,{usableAgain:j(e.resetAt,n),coversConnection:s===`exhausted`})}if(e.cls===`blocked`)return o(`unavailable`,`Unavailable`,e.summary);if(e.cls===`unread`)return t.healthRead?s===null||s===`unknown`?o(`not-checked`,`Not checked`,`no reading yet`):o(`usable`,`Connected`,`no usage reading yet`):o(`checking`,`Checking…`,null);let l=s===null||s===`unknown`?`Usable`:`Connected`;if(e.cls===`tight`){let t=c!==null&&B(c)&&e.credits!==null;return l===`Usable`?o(`low`,`Usable`,t?`on credits`:`running low`):o(`low`,l,t?`usable on credits`:`running low`)}return l===`Usable`?o(`usable`,`Usable now`,null):o(`usable`,`Connected`,`usable now`)}function le(e,t){let n=e.map((e,n)=>({row:e,index:n,rank:Q[$(e,{...t,checking:!1}).kind],local:+(e.kind===`local`)}));return n.sort((e,t)=>e.rank-t.rank||e.local-t.local||e.index-t.index),n.map(e=>e.row)}export{l as _,L as a,d as b,ie as c,N as d,P as f,u as g,w as h,ae as i,oe as l,D as m,Z as n,le as o,E as p,re as r,Y as s,$ as t,F as u,te as v,h as x,g as y};
|
|
2
|
-
//# sourceMappingURL=capacity-strip-model-BDbmQ3e3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capacity-strip-model-BDbmQ3e3.js","names":[],"sources":["../../../../../../src/core/routing/policy.ts","../../../../../../src/web-ui/routes/verse/budget/budget-model.ts","../../../../../../src/web-ui/routes/verse/usage/capacity-model.ts","../../../../../../src/web-ui/routes/verse/health/health-model.ts","../../../../../../src/web-ui/routes/verse/usage/capacity-strip-model.ts"],"sourcesContent":["/**\n * Budget policy — mode defaults, effective per-seat policy, and strict update\n * parsing (V3.10 unit A9).\n *\n * THE MODEL (what a stored policy means)\n *\n * `policy.mode` picks a column of MODE_DEFAULTS below. `policy.seats` holds\n * the per-seat policies IN FORCE for that mode, but only for seats the\n * operator has touched; every other seat gets the mode's default for its\n * engine. So what the Budget panel shows is exactly what the router uses —\n * there is no hidden transform layered on top of a slider.\n *\n * Switching mode (`applyModeSwitch`) re-bases every stored seat on the new\n * mode's defaults and keeps only the two choices that are not \"how much\" but\n * \"whether at all\": `enabled` and a hard `dailyUsdCap`. A reserve tuned for\n * `balanced` would be meaningless in `all-in` (which by definition keeps\n * nothing back), so it is not carried across.\n *\n * DEFAULTS (Mason's decisions, recorded 2026-09-24 — binding):\n * balanced (default) — Claude keeps 40% of its weekly window for Mason and\n * is never touched while its 5-hour window is above 70%\n * (protects his live session). Grok 0% reserve. Local\n * unlimited. Codex OFF (no usage) until switched on.\n * all-in — autonomy may use all available usage (no reserve, no\n * session ceiling). Codex stays OFF by default.\n * reserve — free local models plus only a small paid cap: every\n * paid seat keeps 85% of its binding window back and a\n * 5-hour ceiling of 50%, and the router ranks local\n * first (router.ts).\n *\n * BROWSER-SAFE and PURE: no node: imports, no I/O. The Budget UI imports the\n * defaults from here so the \"reset to default\" hint can never drift from the\n * server.\n */\nimport {\n BUDGET_MODES,\n type BudgetMode,\n type BudgetPolicy,\n type BudgetResponse,\n type BudgetUpdateRequest,\n type SeatBudgetPolicy,\n} from './types.js';\n\n/** The engines a seat can belong to (mirrors `VerseEngine`, kept local so this file has no verse import). */\nexport type BudgetEngine = 'claude' | 'codex' | 'grok' | 'local';\n\nexport const BUDGET_ENGINES: readonly BudgetEngine[] = ['claude', 'codex', 'grok', 'local'];\n\n/** Same spelling rule the seat catalog and preferences use for seat ids. */\nexport const BUDGET_SEAT_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:@/+-]{0,199}$/;\n\n/** Registry bound — a blast radius for a runaway client, not a UI limit. */\nexport const BUDGET_MAX_SEATS = 64;\n\n/** Upper bound on a daily USD cap; anything larger is a typo, not a budget. */\nexport const BUDGET_MAX_DAILY_USD = 10_000;\n\nexport const DEFAULT_BUDGET_MODE: BudgetMode = 'balanced';\n\n/** Who a seat is, for the Budget panel (headroom rows carry only the id). */\nexport interface BudgetSeatInfo {\n seatId: string;\n label: string;\n engine: BudgetEngine;\n /** True for local seats: $0, no provider window. */\n free: boolean;\n}\n\n/**\n * The body `GET/POST /api/verse/budget` actually serves: the frozen\n * `BudgetResponse` plus two ADDITIVE fields the panel needs to render a seat\n * it has never stored a policy for. `seats` stays the stored policy (only the\n * seats the operator touched); `effective` is what the router applies to\n * every seat it currently knows.\n */\nexport interface BudgetView extends BudgetResponse {\n seatInfo: BudgetSeatInfo[];\n effective: Record<string, SeatBudgetPolicy>;\n /** How old a reading may be before autonomy stops spending against it. */\n readingMaxAgeMs: number;\n /** When the seat readings behind `headroom` were sampled. */\n sampledAt: string;\n}\n\n/** Per-engine default in one mode; `seatId` is filled in by `defaultSeatPolicy`. */\ntype EngineDefault = Omit<SeatBudgetPolicy, 'seatId'>;\n\n/**\n * Mode × engine defaults. Frozen so a caller can never mutate the table the\n * whole process reads.\n *\n * Codex is `enabled: false` in every mode on purpose: on 2026-09-24 both Codex\n * accounts were at 100% with resets days away, and Mason turned Codex OFF for\n * autonomy \"until usage returns\". That is a standing choice, not a function of\n * the mode, so a mode switch must not silently turn it back on.\n */\nexport const MODE_DEFAULTS: Readonly<Record<BudgetMode, Readonly<Record<BudgetEngine, Readonly<EngineDefault>>>>> =\n Object.freeze({\n 'all-in': Object.freeze({\n claude: Object.freeze({ enabled: true, reservePercent: 0 }),\n codex: Object.freeze({ enabled: false, reservePercent: 0 }),\n grok: Object.freeze({ enabled: true, reservePercent: 0 }),\n local: Object.freeze({ enabled: true, reservePercent: 0 }),\n }),\n balanced: Object.freeze({\n claude: Object.freeze({ enabled: true, reservePercent: 40, maxSessionWindowPercent: 70 }),\n codex: Object.freeze({ enabled: false, reservePercent: 40, maxSessionWindowPercent: 70 }),\n grok: Object.freeze({ enabled: true, reservePercent: 0 }),\n local: Object.freeze({ enabled: true, reservePercent: 0 }),\n }),\n reserve: Object.freeze({\n claude: Object.freeze({ enabled: true, reservePercent: 85, maxSessionWindowPercent: 50 }),\n codex: Object.freeze({ enabled: false, reservePercent: 85, maxSessionWindowPercent: 50 }),\n grok: Object.freeze({ enabled: true, reservePercent: 85 }),\n local: Object.freeze({ enabled: true, reservePercent: 0 }),\n }),\n });\n\n/** Plain-language one-liners for the mode control (UI + API `why` text share them). */\nexport const MODE_DESCRIPTIONS: Readonly<Record<BudgetMode, string>> = Object.freeze({\n 'all-in': 'Autonomy may use all available usage on every enabled seat.',\n balanced: 'Autonomy stops at each seat’s reserve, so you keep headroom for your own sessions.',\n reserve: 'Autonomy runs on free local models, plus only a small slice of paid seats.',\n});\n\nexport function isBudgetMode(value: unknown): value is BudgetMode {\n return typeof value === 'string' && (BUDGET_MODES as readonly string[]).includes(value);\n}\n\n/**\n * Which engine a seat id belongs to, when the caller has no seat record.\n *\n * Seat ids are account ids from connections.json (`claude`, `codex-personal`,\n * `grok`) or `local:<tag>` for Ollama. An id that names no known engine is\n * treated as `claude`-class — the most protected default — rather than as\n * free local capacity: guessing \"free\" for an unknown seat would be the\n * fail-open this module exists to close.\n */\nexport function engineOfSeatId(seatId: string): BudgetEngine {\n const id = seatId.toLowerCase();\n if (id === 'local' || id.startsWith('local:')) return 'local';\n if (id.startsWith('codex')) return 'codex';\n if (id.startsWith('grok')) return 'grok';\n return 'claude';\n}\n\nexport function defaultSeatPolicy(mode: BudgetMode, seatId: string, engine: BudgetEngine = engineOfSeatId(seatId)): SeatBudgetPolicy {\n const base = MODE_DEFAULTS[mode][engine];\n const out: SeatBudgetPolicy = { seatId, enabled: base.enabled, reservePercent: base.reservePercent };\n if (base.maxSessionWindowPercent !== undefined) out.maxSessionWindowPercent = base.maxSessionWindowPercent;\n if (base.dailyUsdCap !== undefined) out.dailyUsdCap = base.dailyUsdCap;\n return out;\n}\n\n/** The policy the router applies to one seat: the stored one, or the mode default. */\nexport function effectiveSeatPolicy(policy: BudgetPolicy, seatId: string, engine?: BudgetEngine): SeatBudgetPolicy {\n const stored = policy.seats[seatId];\n if (stored) return { ...stored, seatId };\n return defaultSeatPolicy(policy.mode, seatId, engine ?? engineOfSeatId(seatId));\n}\n\n/** The policy a fresh install starts with: balanced, no per-seat deviations. */\nexport function defaultBudgetPolicy(): BudgetPolicy {\n // Epoch, not \"now\": nothing was ever decided here, and a timestamp that\n // moves on every read would claim a change that never happened.\n return { mode: DEFAULT_BUDGET_MODE, seats: {}, updatedAt: new Date(0).toISOString() };\n}\n\n// ---------------------------------------------------------------------------\n// Validation (shared by the store's lenient load and the API's strict update)\n// ---------------------------------------------------------------------------\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isPercent(value: unknown, low = 0): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= low && value <= 100;\n}\n\nfunction isUsd(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= BUDGET_MAX_DAILY_USD;\n}\n\n/** Whole percents only: a 40.000001% reserve is noise, and integers diff cleanly. */\nfunction wholePercent(value: number): number {\n return Math.round(value);\n}\n\n/** Cents are the finest a USD cap means anything at. */\nfunction cents(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/**\n * Salvage one stored seat entry, or null when it is unusable. Lenient on\n * purpose (the file is ours but may be hand-edited): an invalid optional field\n * is dropped, an invalid required field drops the entry — which then falls\n * back to the mode default, the conservative outcome.\n */\nexport function sanitizeSeatPolicy(seatId: string, raw: unknown): SeatBudgetPolicy | null {\n if (!BUDGET_SEAT_ID_RE.test(seatId) || !isObject(raw)) return null;\n if (typeof raw['enabled'] !== 'boolean' || !isPercent(raw['reservePercent'])) return null;\n const out: SeatBudgetPolicy = {\n seatId,\n enabled: raw['enabled'],\n reservePercent: wholePercent(raw['reservePercent']),\n };\n if (isPercent(raw['maxSessionWindowPercent'], 1)) {\n out.maxSessionWindowPercent = wholePercent(raw['maxSessionWindowPercent']);\n }\n if (isUsd(raw['dailyUsdCap'])) out.dailyUsdCap = cents(raw['dailyUsdCap']);\n return out;\n}\n\n/** Field-by-field salvage of a whole stored policy. Never throws. */\nexport function sanitizeBudgetPolicy(raw: unknown): BudgetPolicy {\n const out = defaultBudgetPolicy();\n if (!isObject(raw)) return out;\n if (isBudgetMode(raw['mode'])) out.mode = raw['mode'];\n const updatedAt = raw['updatedAt'];\n if (typeof updatedAt === 'string' && Number.isFinite(Date.parse(updatedAt))) {\n out.updatedAt = new Date(Date.parse(updatedAt)).toISOString();\n }\n const seats = raw['seats'];\n if (isObject(seats)) {\n let kept = 0;\n for (const seatId of Object.keys(seats).sort()) {\n if (kept >= BUDGET_MAX_SEATS) break;\n const entry = sanitizeSeatPolicy(seatId, seats[seatId]);\n if (!entry) continue;\n out.seats[seatId] = entry;\n kept += 1;\n }\n }\n return out;\n}\n\n/** The error the budget module throws for a bad request (duck-typed by `code`, like VerseServiceError). */\nexport class BudgetPolicyError extends Error {\n readonly code: 'VERSE_INVALID' | 'VERSE_TOO_LARGE';\n readonly status: 400 | 413;\n\n constructor(code: 'VERSE_INVALID' | 'VERSE_TOO_LARGE', message: string) {\n super(message);\n this.name = 'BudgetPolicyError';\n this.code = code;\n this.status = code === 'VERSE_TOO_LARGE' ? 413 : 400;\n }\n}\n\n/**\n * A validated per-seat patch. `null` on an optional field means \"clear it\"\n * (JSON has no `undefined`): `maxSessionWindowPercent: null` removes the\n * session ceiling, `dailyUsdCap: null` removes the cap.\n */\nexport interface SeatPolicyPatch {\n enabled?: boolean;\n reservePercent?: number;\n maxSessionWindowPercent?: number | null;\n dailyUsdCap?: number | null;\n}\n\nexport type ParsedBudgetUpdate =\n | { kind: 'mode'; mode: BudgetMode }\n | { kind: 'seat'; seatId: string; patch: SeatPolicyPatch };\n\nconst SEAT_PATCH_KEYS: ReadonlySet<string> = new Set([\n 'enabled',\n 'reservePercent',\n 'maxSessionWindowPercent',\n 'dailyUsdCap',\n]);\n\nfunction sameKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {\n const own = Object.keys(value);\n return own.length === keys.length && keys.every((key) => Object.prototype.hasOwnProperty.call(value, key));\n}\n\n/**\n * Validate a POST body against EXACTLY one `BudgetUpdateRequest` form, so a\n * body can never change more than the operator clicked. Unknown keys are\n * refused (a misspelt `reservepercent` silently dropped would \"succeed\" and\n * change nothing).\n */\nexport function parseBudgetUpdate(value: unknown): ParsedBudgetUpdate {\n if (!isObject(value)) throw new BudgetPolicyError('VERSE_INVALID', 'budget update must be a JSON object');\n\n if (sameKeys(value, ['mode'])) {\n if (!isBudgetMode(value['mode'])) {\n throw new BudgetPolicyError('VERSE_INVALID', `mode must be one of: ${BUDGET_MODES.join(', ')}`);\n }\n return { kind: 'mode', mode: value['mode'] };\n }\n\n if (sameKeys(value, ['seatId', 'policy'])) {\n const seatId = value['seatId'];\n if (typeof seatId !== 'string' || !BUDGET_SEAT_ID_RE.test(seatId)) {\n throw new BudgetPolicyError('VERSE_INVALID', 'seatId must be a seat id');\n }\n const policy = value['policy'];\n if (!isObject(policy)) throw new BudgetPolicyError('VERSE_INVALID', 'policy must be an object');\n const keys = Object.keys(policy);\n if (keys.length === 0) throw new BudgetPolicyError('VERSE_INVALID', 'policy must change at least one field');\n for (const key of keys) {\n if (!SEAT_PATCH_KEYS.has(key)) throw new BudgetPolicyError('VERSE_INVALID', `unknown policy key: ${key}`);\n }\n const patch: SeatPolicyPatch = {};\n if ('enabled' in policy) {\n if (typeof policy['enabled'] !== 'boolean') throw new BudgetPolicyError('VERSE_INVALID', 'enabled must be a boolean');\n patch.enabled = policy['enabled'];\n }\n if ('reservePercent' in policy) {\n if (!isPercent(policy['reservePercent'])) {\n throw new BudgetPolicyError('VERSE_INVALID', 'reservePercent must be a number from 0 to 100');\n }\n patch.reservePercent = wholePercent(policy['reservePercent']);\n }\n if ('maxSessionWindowPercent' in policy) {\n const v = policy['maxSessionWindowPercent'];\n if (v !== null && !isPercent(v, 1)) {\n throw new BudgetPolicyError('VERSE_INVALID', 'maxSessionWindowPercent must be a number from 1 to 100, or null');\n }\n patch.maxSessionWindowPercent = v === null ? null : wholePercent(v);\n }\n if ('dailyUsdCap' in policy) {\n const v = policy['dailyUsdCap'];\n if (v !== null && !isUsd(v)) {\n throw new BudgetPolicyError('VERSE_INVALID', `dailyUsdCap must be a number from 0 to ${BUDGET_MAX_DAILY_USD}, or null`);\n }\n patch.dailyUsdCap = v === null ? null : cents(v);\n }\n return { kind: 'seat', seatId, patch };\n }\n\n throw new BudgetPolicyError('VERSE_INVALID', 'budget update must be exactly one of {mode} or {seatId, policy}');\n}\n\n/**\n * Re-base every stored seat on `mode`'s defaults, keeping `enabled` and a hard\n * `dailyUsdCap` (see the file header for why reserves are not carried).\n */\nexport function applyModeSwitch(\n policy: BudgetPolicy,\n mode: BudgetMode,\n nowIso: string,\n engineOf?: (seatId: string) => BudgetEngine | undefined,\n): BudgetPolicy {\n const seats: Record<string, SeatBudgetPolicy> = {};\n for (const seatId of Object.keys(policy.seats).sort()) {\n const stored = policy.seats[seatId]!;\n const next = defaultSeatPolicy(mode, seatId, engineOf?.(seatId) ?? engineOfSeatId(seatId));\n next.enabled = stored.enabled;\n if (stored.dailyUsdCap !== undefined) next.dailyUsdCap = stored.dailyUsdCap;\n seats[seatId] = next;\n }\n return { mode, seats, updatedAt: nowIso };\n}\n\n/** Apply one validated per-seat patch on top of the seat's effective policy. */\nexport function applySeatPatch(\n policy: BudgetPolicy,\n seatId: string,\n patch: SeatPolicyPatch,\n nowIso: string,\n engine?: BudgetEngine,\n): BudgetPolicy {\n if (!(seatId in policy.seats) && Object.keys(policy.seats).length >= BUDGET_MAX_SEATS) {\n throw new BudgetPolicyError('VERSE_TOO_LARGE', `at most ${BUDGET_MAX_SEATS} seats can carry a budget policy`);\n }\n const next = effectiveSeatPolicy(policy, seatId, engine);\n if (patch.enabled !== undefined) next.enabled = patch.enabled;\n if (patch.reservePercent !== undefined) next.reservePercent = patch.reservePercent;\n if (patch.maxSessionWindowPercent !== undefined) {\n if (patch.maxSessionWindowPercent === null) delete next.maxSessionWindowPercent;\n else next.maxSessionWindowPercent = patch.maxSessionWindowPercent;\n }\n if (patch.dailyUsdCap !== undefined) {\n if (patch.dailyUsdCap === null) delete next.dailyUsdCap;\n else next.dailyUsdCap = patch.dailyUsdCap;\n }\n const seats: Record<string, SeatBudgetPolicy> = { ...policy.seats, [seatId]: next };\n const sorted: Record<string, SeatBudgetPolicy> = {};\n for (const id of Object.keys(seats).sort()) sorted[id] = seats[id]!;\n return { mode: policy.mode, seats: sorted, updatedAt: nowIso };\n}\n\n/** Apply exactly one update form. Pure — the caller persists. */\nexport function applyBudgetUpdate(\n policy: BudgetPolicy,\n update: BudgetUpdateRequest | ParsedBudgetUpdate,\n nowIso: string,\n engineOf?: (seatId: string) => BudgetEngine | undefined,\n): BudgetPolicy {\n const parsed: ParsedBudgetUpdate = 'kind' in update ? update : parseBudgetUpdate(update);\n if (parsed.kind === 'mode') return applyModeSwitch(policy, parsed.mode, nowIso, engineOf);\n return applySeatPatch(policy, parsed.seatId, parsed.patch, nowIso, engineOf?.(parsed.seatId));\n}\n","/**\n * routes/verse/budget/budget-model.ts — pure view-model for the Budget panel.\n *\n * Turns a `BudgetView` (GET /api/verse/budget) into one row per seat: who it\n * is, the policy in force, a one-line verdict, and the geometry of its\n * headroom bars. No React, no fetch — so every honesty rule is unit-tested\n * here rather than asserted through the DOM.\n *\n * HONESTY RULES (docs/VERSE-TELEMETRY-V2.md):\n * - Unknown is not zero. A window with no reading renders as `unknown`\n * (dashed track + words), never an empty bar (\"plenty left\") or a full one\n * (\"exhausted\").\n * - The verdict is always a WORD (Eligible / Held back / Off / No reading);\n * colour only reinforces it.\n * - The \"why\" line is the server's own sentence, verbatim — except that an\n * ISO instant inside it (\"resets 2026-09-26T03:46:56.000Z\") is shown in\n * local time, and \".;\" joins read as \";\" (autonomy/format `tidyProse`).\n */\nimport {\n MODE_DESCRIPTIONS,\n type BudgetEngine,\n type BudgetView,\n} from '../../../../core/routing/policy.js';\nimport type { BudgetMode, SeatBudgetPolicy, SeatHeadroom } from '../../../../core/routing/types.js';\nimport { percentText, tidyProse } from '../autonomy/format.js';\n\nexport type BudgetSeatStatus = 'eligible' | 'held' | 'off' | 'unknown';\n\nexport const STATUS_WORDS: Readonly<Record<BudgetSeatStatus, string>> = {\n eligible: 'Eligible',\n held: 'Held back',\n off: 'Off',\n unknown: 'No reading',\n};\n\n/** One horizontal headroom bar (a usage window against its autonomy ceiling). */\nexport interface BudgetBar {\n kind: 'weekly' | 'session';\n label: string;\n /** 0–100, or null when this window has no reading. */\n usedPercent: number | null;\n /** Where autonomy stops (0–100). 100 = no ceiling. */\n ceilingPercent: number;\n /** Plain-language summary for screen readers and the table view. */\n description: string;\n /** True when this bar is the one binding autonomy right now. */\n binding: boolean;\n}\n\nexport interface BudgetSeatRow {\n seatId: string;\n label: string;\n engine: BudgetEngine;\n free: boolean;\n policy: SeatBudgetPolicy;\n headroom: SeatHeadroom | null;\n status: BudgetSeatStatus;\n /** First server reason, verbatim (instants in local time). */\n why: string;\n /** Remaining server reasons, verbatim (instants in local time). */\n more: string[];\n bars: BudgetBar[];\n /** Whether the 5-hour ceiling control applies (subscription seats with a short window). */\n hasSessionCeiling: boolean;\n}\n\nexport const BUDGET_MODE_OPTIONS: ReadonlyArray<{ value: BudgetMode; label: string; description: string }> = [\n { value: 'reserve', label: 'Reserve', description: MODE_DESCRIPTIONS.reserve },\n { value: 'balanced', label: 'Balanced', description: MODE_DESCRIPTIONS.balanced },\n { value: 'all-in', label: 'All-in', description: MODE_DESCRIPTIONS['all-in'] },\n];\n\n/**\n * Whether `mode` is above a grant's ceiling. Rank is the order of\n * BUDGET_MODE_OPTIONS (reserve < balanced < all-in) — the same order as\n * core/authority BUDGET_MODE_RANK, restated here so the budget panel does not\n * import the authority module into the web bundle. No ceiling (null) = no\n * mode is above it.\n */\nexport function modeAboveCeiling(mode: BudgetMode, ceiling: BudgetMode | null | undefined): boolean {\n if (!ceiling) return false;\n const rank = (m: BudgetMode) => BUDGET_MODE_OPTIONS.findIndex((o) => o.value === m);\n return rank(mode) > rank(ceiling);\n}\n\nfunction round(n: number): number {\n return Math.round(n);\n}\n\nfunction statusOf(free: boolean, policy: SeatBudgetPolicy, headroom: SeatHeadroom | null): BudgetSeatStatus {\n if (!policy.enabled) return 'off';\n if (headroom?.eligibleForAutonomy) return 'eligible';\n if (!free && (headroom === null || (headroom.sessionUsedPercent === null && headroom.weeklyUsedPercent === null))) {\n return 'unknown';\n }\n return 'held';\n}\n\nfunction barsFor(engine: BudgetEngine, free: boolean, policy: SeatBudgetPolicy, h: SeatHeadroom | null): BudgetBar[] {\n if (free || h === null) return [];\n const bars: BudgetBar[] = [];\n const reserveCeiling = 100 - policy.reservePercent;\n const hasWeekly = h.weeklyUsedPercent !== null || engine === 'claude' || engine === 'grok';\n if (hasWeekly) {\n const used = h.weeklyUsedPercent;\n bars.push({\n kind: 'weekly',\n label: engine === 'grok' ? 'Billing period' : 'Weekly',\n usedPercent: used,\n ceilingPercent: reserveCeiling,\n binding: h.bindingWindow === 'weekly',\n description: used === null\n ? 'Weekly window: no reading.'\n : `Weekly window ${percentText(used)} used; autonomy stops at ${round(reserveCeiling)}%, ${round(policy.reservePercent)}% kept for you.`,\n });\n }\n if (h.sessionUsedPercent !== null || engine === 'claude') {\n const used = h.sessionUsedPercent;\n const sessionCeiling = policy.maxSessionWindowPercent ?? 100;\n const ceiling = hasWeekly ? sessionCeiling : Math.min(sessionCeiling, reserveCeiling);\n bars.push({\n kind: 'session',\n label: '5-hour',\n usedPercent: used,\n ceilingPercent: ceiling,\n binding: h.bindingWindow === 'session',\n description: used === null\n ? '5-hour window: no reading.'\n : `5-hour window ${percentText(used)} used; ${ceiling >= 100 ? 'no autonomy ceiling' : `autonomy stops at ${round(ceiling)}%`}.`,\n });\n }\n return bars;\n}\n\n/** Rows in the server's seat order (which lists the operator's preferred local tags first). */\nexport function buildBudgetRows(view: BudgetView, nowMs: number = Date.now()): BudgetSeatRow[] {\n const headroomById = new Map(view.headroom.map((h) => [h.seatId, h]));\n return view.seatInfo.map((info) => {\n const policy = view.effective[info.seatId] ?? { seatId: info.seatId, enabled: false, reservePercent: 100 };\n const headroom = headroomById.get(info.seatId) ?? null;\n const reasons = (headroom?.reasons ?? []).map((r) => tidyProse(r, nowMs).trim()).filter((r) => r.length > 0);\n return {\n seatId: info.seatId,\n label: info.label,\n engine: info.engine,\n free: info.free,\n policy,\n headroom,\n status: statusOf(info.free, policy, headroom),\n why: reasons[0] ?? (info.free ? 'Local model — free.' : 'No reading yet.'),\n more: reasons.slice(1),\n bars: barsFor(info.engine, info.free, policy, headroom),\n hasSessionCeiling: !info.free && (info.engine === 'claude' || info.engine === 'codex'),\n };\n });\n}\n\n/** Headline counts for the panel summary (\"3 of 7 seats can take autonomous work\"). */\nexport function budgetSummary(rows: readonly BudgetSeatRow[]): { eligible: number; total: number; sentence: string } {\n const eligible = rows.filter((r) => r.status === 'eligible').length;\n const total = rows.length;\n if (total === 0) return { eligible, total, sentence: 'No seats are known yet.' };\n const paid = rows.filter((r) => r.status === 'eligible' && !r.free).length;\n const free = eligible - paid;\n const parts: string[] = [];\n if (paid > 0) parts.push(`${paid} paid`);\n if (free > 0) parts.push(`${free} local`);\n return {\n eligible,\n total,\n sentence: eligible === 0\n ? 'No seat can take autonomous work right now.'\n : `${eligible} of ${total} seats can take autonomous work (${parts.join(', ')}).`,\n };\n}\n\n/** Human age of the readings, e.g. \"just now\", \"4 min ago\". */\nexport function readingAge(sampledAt: string, nowMs: number): string {\n const t = Date.parse(sampledAt);\n if (!Number.isFinite(t)) return 'unknown';\n const minutes = Math.max(0, Math.round((nowMs - t) / 60_000));\n if (minutes < 1) return 'just now';\n if (minutes < 120) return `${minutes} min ago`;\n return `${Math.round(minutes / 60)} h ago`;\n}\n\n/** Clamp a slider value to the range the API accepts. */\nexport function clampPercent(value: number, low = 0, high = 100): number {\n if (!Number.isFinite(value)) return low;\n return Math.max(low, Math.min(high, Math.round(value)));\n}\n","/**\n * routes/verse/usage/capacity-model.ts — \"what can I run right now\", in one\n * pure projection.\n *\n * The Usage section already answers this per seat, one card at a time. This\n * module answers it for the WHOLE ROSTER in one line, because the operator's\n * first question on opening the view is not \"how is Codex A doing\" — it is\n * \"do I have anything to run, and if not, when does that change\".\n *\n * Four rules, each one a place where the obvious summary would lie:\n *\n * 1. A COUNT IS NOT A CAPACITY. \"3 of 5 seats usable\" is only true if the\n * other two were actually read. Seats with no reading are counted in their\n * own bucket and named in the sentence, never folded into \"blocked\" — an\n * unread seat might be perfectly usable.\n * 2. ONLY A MACHINE-READABLE INSTANT MAY BECOME A COUNTDOWN. Claude's reset\n * is provider prose and `resetsAt` is structurally null\n * (docs/VERSE-TELEMETRY-V2.md), so prose resets travel in their own\n * channel and are rendered verbatim. Nothing here parses a sentence into\n * a time.\n * 3. A RESET IN THE PAST IS NOT A RESET. A `resetsAt` that has already\n * elapsed means the reading predates the rollover; it is reported as\n * overdue rather than as a negative countdown or as \"now\".\n * 4. LOCAL HEADROOM IS NOT \"BUDGET MINUS RESIDENT\" UNLESS BOTH ARE KNOWN.\n * One unknown makes the headroom unknown, and the strip says so.\n *\n * Pure: no React, no I/O, no formatting of currency/percent.\n */\nimport type { AccountCardModel, AccountVerdictState, LocalCardModel, WindowView } from './accounts-model.js';\nimport type { LocalModelsView } from './local-model.js';\n\n/**\n * The four buckets the strip counts in. Deliberately coarser than\n * `AccountVerdictState`: at a glance there are only four useful answers, and\n * the card below carries the nuance.\n */\nexport type CapacityClass = 'ready' | 'tight' | 'blocked' | 'unread';\n\n/**\n * `signed-out` and `probe-unsupported` are BLOCKED-by-action, not unread: in\n * both cases we know exactly why there is no capacity and what to do about\n * it. `unknown` is the only genuinely unread state — nobody told us anything,\n * so counting it as blocked would assert an outage we did not observe.\n */\nexport const CAPACITY_CLASS: Record<AccountVerdictState, CapacityClass> = {\n available: 'ready',\n credits: 'ready',\n tight: 'tight',\n exhausted: 'blocked',\n 'signed-out': 'blocked',\n 'probe-unsupported': 'blocked',\n unknown: 'unread',\n};\n\nexport interface SeatCapacity {\n id: string;\n label: string;\n kind: 'account' | 'local';\n /** Engine hue — used only for the 2px marker, never for text. */\n color: string;\n cls: CapacityClass;\n /** The card's own verdict headline, so the strip and the card agree. */\n headline: string;\n /**\n * The binding window's percent, when it is a real measurement. Null for an\n * unread seat AND for a flagged limit, whose sentinel 100 is not a reading.\n */\n usedPct: number | null;\n /** False when `usedPct` is null because the figure would be a sentinel. */\n measured: boolean;\n}\n\n/** A reset the provider gave as a real instant, so a countdown is honest. */\nexport interface ResetInstant {\n seatLabel: string;\n windowLabel: string;\n /**\n * Epoch ms — the ONLY durable fact here. `inMs`/`overdue` below are a\n * snapshot taken when the model was built; a view that renders a countdown\n * must derive it from `atMs` against a live clock instead, or it will print\n * whatever the elapsed time happened to be when the memo last ran.\n */\n atMs: number;\n /** Signed ms until the reset AT BUILD TIME. Selection only — never rendered. */\n inMs: number;\n /** True when `inMs <= 0` AT BUILD TIME. Selection only — never rendered. */\n overdue: boolean;\n}\n\n/** A reset whose ONLY signal is provider prose. Rendered verbatim, never parsed. */\nexport interface ResetProse {\n seatLabel: string;\n windowLabel: string;\n text: string;\n}\n\nexport interface LocalCapacity {\n reachable: boolean;\n residentCount: number;\n installedCount: number;\n /** Models that can actually drive an agentic session. */\n agenticCount: number;\n /** Models whose runtime did not report a capability list. Never \"cannot\". */\n unknownToolCount: number;\n residentBytes: number | null;\n memoryBudgetBytes: number | null;\n /** Budget minus resident. Null when either side is unknown. */\n headroomBytes: number | null;\n /** The machine's own reported free memory, which is not the same figure. */\n freeMemoryBytes: number | null;\n usedPct: number | null;\n}\n\nexport interface CapacityOverview {\n seats: SeatCapacity[];\n ready: number;\n tight: number;\n blocked: number;\n unread: number;\n total: number;\n /**\n * Every dated reset, so a view can re-select the soonest one against a live\n * clock rather than against the instant this model was built.\n */\n resets: ResetInstant[];\n /** The soonest real reset across every seat, or null when none is dated. */\n nextReset: ResetInstant | null;\n /** Every window whose reset is prose only, deduplicated by sentence. */\n proseResets: ResetProse[];\n local: LocalCapacity | null;\n /** The one-line answer. Never claims anything about an unread seat. */\n headline: string;\n /**\n * True when the roster WAS read and nothing in it is usable.\n *\n * An entirely unread roster is deliberately excluded. `noCapacity` is what\n * tints the headline as a warning, and \"you have no capacity\" over seats\n * nobody managed to probe is an assertion about an unobserved state — the\n * same lie `capacityHeadline` is written case-by-case to avoid, and the same\n * one the `unread` chip word exists to prevent. A PARTLY unread roster still\n * counts: a seat known to be blocked is a measured constraint.\n */\n noCapacity: boolean;\n}\n\nfunction plural(n: number, one: string, many: string): string {\n return n === 1 ? one : many;\n}\n\n/**\n * The strip's sentence. Written by cases rather than by template because each\n * case has a different honest claim to make, and a single interpolated string\n * ended up asserting \"0 usable\" over a roster nobody had read.\n */\nexport function capacityHeadline(input: {\n ready: number;\n tight: number;\n blocked: number;\n unread: number;\n total: number;\n local: LocalCapacity | null;\n}): string {\n const { ready, tight, blocked, unread, total, local } = input;\n if (total === 0) {\n return 'No seats are reported at all. This is an empty roster, not a set of seats at zero.';\n }\n\n const localClause =\n local === null\n ? ''\n : local.reachable && local.residentCount > 0\n ? ` ${local.residentCount} local ${plural(local.residentCount, 'model is', 'models are')} resident and answer with no load delay.`\n : local.reachable && local.agenticCount > 0\n ? ` No local model is resident, but ${local.agenticCount} installed ${plural(local.agenticCount, 'one can', 'ones can')} drive a session after a load.`\n : local.reachable\n ? ' No local model is resident.'\n : ' The local runtime did not answer, so local capacity is unknown.';\n\n const unreadClause =\n unread === 0\n ? ''\n : ` ${unread} ${plural(unread, 'seat has', 'seats have')} no reading at all — unread, not exhausted.`;\n\n if (ready > 0) {\n return `${ready} of ${total} ${plural(total, 'seat is', 'seats are')} usable right now.${unreadClause}${localClause}`;\n }\n if (tight > 0) {\n return `No seat is clear: ${tight} ${plural(tight, 'is', 'are')} running tight and ${blocked} ${plural(blocked, 'is', 'are')} blocked.${unreadClause}${localClause}`;\n }\n if (blocked > 0) {\n return `No cloud seat reports headroom — ${blocked} blocked.${unreadClause}${localClause}`;\n }\n return `No seat reported a usable window.${unreadClause}${localClause}`;\n}\n\nfunction seatFromCard(card: AccountCardModel): SeatCapacity {\n const binding = card.binding;\n return {\n id: card.id,\n label: card.label,\n kind: 'account',\n color: card.color,\n cls: CAPACITY_CLASS[card.verdict.state],\n headline: card.verdict.headline,\n usedPct: binding && binding.measured && !binding.limitReached ? binding.usedPct : null,\n measured: binding !== null && binding.measured && !binding.limitReached,\n };\n}\n\nfunction seatFromLocal(card: LocalCardModel): SeatCapacity {\n return {\n id: 'local',\n label: 'Local',\n kind: 'local',\n color: card.color,\n cls: CAPACITY_CLASS[card.verdict.state],\n headline: card.verdict.headline,\n usedPct: card.usedPct,\n measured: card.usedPct !== null,\n };\n}\n\n/**\n * Collect reset signals, keeping the two channels apart.\n *\n * A window contributes to `instants` ONLY through `resetsAt`, an ISO string\n * the provider actually gave. `resetText` alone — Claude's entire reset\n * signal — contributes to `prose` and is never parsed.\n */\nexport function collectResets(\n seats: readonly { label: string; windows: readonly WindowView[] }[],\n nowMs: number,\n): { instants: ResetInstant[]; prose: ResetProse[] } {\n const instants: ResetInstant[] = [];\n const prose: ResetProse[] = [];\n const seenProse = new Set<string>();\n\n for (const seat of seats) {\n for (const w of seat.windows) {\n if (w.resetsAt !== null) {\n const atMs = Date.parse(w.resetsAt);\n if (!Number.isNaN(atMs)) {\n const inMs = atMs - nowMs;\n instants.push({\n seatLabel: seat.label,\n windowLabel: w.label,\n atMs,\n inMs,\n overdue: inMs <= 0,\n });\n continue;\n }\n }\n if (w.resetText !== null) {\n const key = `${seat.label}|${w.label}|${w.resetText}`;\n if (seenProse.has(key)) continue;\n seenProse.add(key);\n prose.push({ seatLabel: seat.label, windowLabel: w.label, text: w.resetText });\n }\n }\n }\n return { instants, prose };\n}\n\n/**\n * The soonest reset still ahead of us. An overdue instant is never chosen as\n * \"next\" — it is in the past — but if EVERY instant is overdue the most recent\n * one is returned so the strip can say the readings predate a rollover rather\n * than silently showing nothing.\n */\nexport function nextReset(instants: readonly ResetInstant[]): ResetInstant | null {\n const ahead = instants.filter((r) => !r.overdue);\n if (ahead.length > 0) {\n return ahead.reduce((soonest, r) => (r.inMs < soonest.inMs ? r : soonest));\n }\n if (instants.length === 0) return null;\n return instants.reduce((latest, r) => (r.atMs > latest.atMs ? r : latest));\n}\n\n/**\n * The same choice as {@link nextReset}, but judged against a clock the caller\n * supplies rather than against the `overdue` flag frozen into each instant.\n * This is what a rendering countdown must use: a reset that was 40s away when\n * the model was built is in the PAST a minute later, and picking it as \"next\"\n * would keep a positive number on screen for a window that already rolled.\n */\nexport function nextResetAt(instants: readonly ResetInstant[], nowMs: number): ResetInstant | null {\n const ahead = instants.filter((r) => r.atMs > nowMs);\n if (ahead.length > 0) {\n return ahead.reduce((soonest, r) => (r.atMs < soonest.atMs ? r : soonest));\n }\n if (instants.length === 0) return null;\n return instants.reduce((latest, r) => (r.atMs > latest.atMs ? r : latest));\n}\n\nfunction buildLocalCapacity(\n card: LocalCardModel | null,\n view: LocalModelsView | null,\n): LocalCapacity | null {\n if (card === null && view === null) return null;\n const residentBytes = card?.residentBytes ?? view?.residentBytes ?? null;\n const budget = card?.memoryBudgetBytes ?? view?.memoryBudgetBytes ?? null;\n return {\n reachable: view?.reachable ?? card?.verdict.state !== 'unknown',\n residentCount: card?.residentCount ?? view?.rows.filter((r) => r.resident).length ?? 0,\n installedCount: card?.installedCount ?? view?.rows.length ?? 0,\n agenticCount: view?.agenticCount ?? 0,\n unknownToolCount: view?.unknownToolCount ?? 0,\n residentBytes,\n memoryBudgetBytes: budget,\n // One unknown side makes the difference unknown. Treating a missing\n // resident figure as 0 would report the whole machine as free.\n headroomBytes:\n residentBytes !== null && budget !== null ? Math.max(0, budget - residentBytes) : null,\n freeMemoryBytes: view?.freeMemoryBytes ?? null,\n usedPct: card?.usedPct ?? view?.memoryUsedPct ?? null,\n };\n}\n\nexport function buildCapacityOverview(input: {\n cards: readonly AccountCardModel[];\n localCard: LocalCardModel | null;\n localView: LocalModelsView | null;\n nowMs?: number;\n}): CapacityOverview {\n const nowMs = input.nowMs ?? Date.now();\n const seats: SeatCapacity[] = input.cards.map(seatFromCard);\n if (input.localCard) seats.push(seatFromLocal(input.localCard));\n\n const count = (cls: CapacityClass): number => seats.filter((s) => s.cls === cls).length;\n const ready = count('ready');\n const tight = count('tight');\n const blocked = count('blocked');\n const unread = count('unread');\n\n const { instants, prose } = collectResets(\n input.cards.map((c) => ({ label: c.label, windows: c.allWindows })),\n nowMs,\n );\n\n const local = buildLocalCapacity(input.localCard, input.localView);\n\n return {\n seats,\n ready,\n tight,\n blocked,\n unread,\n total: seats.length,\n resets: instants,\n nextReset: nextReset(instants),\n proseResets: prose,\n local,\n headline: capacityHeadline({ ready, tight, blocked, unread, total: seats.length, local }),\n // `unread < seats.length` is the whole guard: a roster where every seat\n // came back unread is unobserved, not exhausted.\n noCapacity: seats.length > 0 && ready === 0 && tight === 0 && unread < seats.length,\n };\n}\n\n/**\n * \"in 2h 14m\" material for a dated reset. Kept beside the model rather than in\n * `chartFormat` because it is a duration, not a chart number, and because the\n * overdue case must not read as a negative time.\n */\nexport function formatUntil(inMs: number): string {\n if (!Number.isFinite(inMs)) return '—';\n if (inMs <= 0) return 'overdue';\n const total = Math.floor(inMs / 1000);\n const d = Math.floor(total / 86_400);\n const h = Math.floor((total % 86_400) / 3600);\n const m = Math.floor((total % 3600) / 60);\n if (d > 0) return `${d}d ${h}h`;\n if (h > 0) return `${h}h ${m}m`;\n if (m > 0) return `${m}m`;\n return `${total}s`;\n}\n","/**\n * routes/verse/health/health-model.ts — how a seat health report reads on\n * screen (V3.10, unit A2). Pure: no React, no I/O.\n *\n * Every surface that shows seat health (the banner, the Composer block, the\n * seat picker) takes its words from here so one seat is never described two\n * ways. State is never carried by colour alone: every tone comes with a word.\n */\nimport type { SeatConnection, SeatHealthReport } from '../../../../core/verse/health-types.js';\nimport { describeResetAt } from '../../../../core/verse/seat-readiness.js';\nimport type { VerseSeat } from '../../../data/api-types.js';\nimport { tidyProse } from '../autonomy/format.js';\nimport { seatReopensAt, seatSubscription } from '../seat-subscription.js';\nimport { formatUntil } from '../usage/capacity-model.js';\n\nexport type HealthTone = 'danger' | 'warning' | 'neutral' | 'success';\n\nexport const CONNECTION_WORD: Record<SeatConnection, string> = {\n connected: 'connected',\n expiring: 'sign-in expiring',\n 'signed-out': 'signed out',\n exhausted: 'out of usage',\n 'binary-skew': 'older CLI pinned',\n unknown: 'not checked',\n};\n\nexport const CONNECTION_TONE: Record<SeatConnection, HealthTone> = {\n connected: 'success',\n expiring: 'warning',\n 'signed-out': 'danger',\n exhausted: 'danger',\n 'binary-skew': 'warning',\n unknown: 'neutral',\n};\n\n/** Most urgent first: what blocks work, then what will, then what could be better. */\nconst SEVERITY: Record<SeatConnection, number> = {\n 'signed-out': 0,\n exhausted: 1,\n expiring: 2,\n 'binary-skew': 3,\n unknown: 4,\n connected: 5,\n};\n\nexport interface SeatHealthIssue {\n report: SeatHealthReport;\n /** The seat's human label (falls back to the id when the seat is not in the roster). */\n label: string;\n word: string;\n tone: HealthTone;\n /** The first, most specific reason, or null. */\n detail: string | null;\n /** \"resets Fri 2:25 PM\" when the provider gave an instant. */\n reset: string | null;\n /** \"usable again in 7h 12m\" for a spent seat whose reset is still ahead; null otherwise. */\n usableAgain: string | null;\n}\n\n/**\n * \"usable again in 7h 12m\" for an instant still ahead of `now`; null when the\n * instant is missing, unparseable or already past (a past reset is a stale\n * reading, not a negative countdown).\n */\nexport function usableAgainPhrase(resetAt: string | null | undefined, now: number = Date.now()): string | null {\n if (typeof resetAt !== 'string') return null;\n const at = Date.parse(resetAt);\n if (!Number.isFinite(at) || at <= now) return null;\n return `usable again in ${formatUntil(at - now)}`;\n}\n\n/**\n * Is this report worth interrupting the operator for? Every non-connected\n * state is, EXCEPT an `unknown` with nothing to say (a sweep that has not run\n * yet is not a fault, and saying \"not checked\" about every seat at boot would\n * teach the operator to ignore the banner).\n */\nexport function needsAttention(report: SeatHealthReport): boolean {\n if (report.connection === 'connected') return false;\n if (report.connection === 'unknown') {\n return report.reasons.length > 0 && !report.reasons[0]!.includes('has not reached this seat');\n }\n return true;\n}\n\nexport function seatHealthIssues(\n reports: readonly SeatHealthReport[],\n seats: readonly VerseSeat[] = [],\n now: number = Date.now(),\n): SeatHealthIssue[] {\n const byId = new Map(seats.map((seat) => [seat.id, seat]));\n return reports\n .filter(needsAttention)\n .map((report) => {\n // A spent seat is usable again when its LAST spent window resets, not\n // when the sweep's binding window does (seatReopensAt) — the same instant\n // Accounts and Fleet name. Without the seat's windows, the sweep's own.\n const seat = byId.get(report.seatId);\n const resetAt = report.connection === 'exhausted' && seat !== undefined\n ? seatReopensAt(seatSubscription(seat, now), report.resetAt)\n : report.resetAt;\n const when = describeResetAt(resetAt, now);\n return {\n report,\n label: seat?.label ?? report.seatId,\n word: CONNECTION_WORD[report.connection],\n tone: CONNECTION_TONE[report.connection],\n // Server sentences may carry a raw ISO instant or a \".;\" join; tidyProse fixes exactly those.\n detail: report.reasons[0] ? tidyProse(report.reasons[0], now) : null,\n reset: when === null ? null : `resets ${when}`,\n usableAgain: report.connection === 'exhausted' ? usableAgainPhrase(resetAt, now) : null,\n };\n })\n .sort((a, b) => SEVERITY[a.report.connection] - SEVERITY[b.report.connection]);\n}\n\n/**\n * An argv rendered for copy-paste into a POSIX shell. Plain words stay bare;\n * anything else is single-quoted. A leading `~/` stays OUTSIDE the quotes so\n * the shell still expands it.\n */\nexport function shellCommandText(argv: readonly string[]): string {\n return argv.map((arg) => {\n if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)) return arg;\n if (arg.startsWith('~/') && /^[A-Za-z0-9_@%+=:,./~-]+$/.test(arg)) return arg;\n if (arg.startsWith('~/')) return `~/'${arg.slice(2).replaceAll(\"'\", \"'\\\\''\")}'`;\n return `'${arg.replaceAll(\"'\", \"'\\\\''\")}'`;\n }).join(' ');\n}\n\n/** One line summarising the whole roster for a collapsed banner. */\nexport function issuesHeadline(issues: readonly SeatHealthIssue[]): string {\n if (issues.length === 0) return 'All seats are connected.';\n const blocked = issues.filter((issue) => issue.tone === 'danger').length;\n if (blocked > 0) {\n return blocked === 1 ? `${issues.find((i) => i.tone === 'danger')!.label} can't run turns right now.`\n : `${blocked} seats can't run turns right now.`;\n }\n return issues.length === 1 ? `${issues[0]!.label} needs attention.` : `${issues.length} seats need attention.`;\n}\n","/**\n * routes/verse/usage/capacity-strip-model.ts — ONE projection of \"how much of\n * each seat is left, what is it tied to, and how much is kept for me\", for\n * every surface that shows seat capacity (SPEC-310C §4: Apps & Accounts,\n * Usage, Resources, NewChatDialog, onboarding; the rail foot's capacity ring\n * and the composer's seat chip read `scarcestSeat` / `capacityRowFor`).\n *\n * Three sources, each already cached app-wide, each read HERE and nowhere\n * else so a seat is never described two ways:\n * - the seat itself (`VerseSeat`, from bootstrap / the /seats poll) — plan,\n * windows, resets, credits, through `seat-subscription.ts`, which owns the\n * honesty rules (binding window leads, no reading ≠ zero, the sentinel 100\n * is a flag, prose resets stay prose);\n * - A2's health report — connected / expiring / signed out / older CLI, and\n * the command that fixes it;\n * - A9's budget view — the reserve kept for Mason and whether autonomy may\n * use the seat right now, through `budget-model.ts`'s own rows.\n * Any of the last two may be missing; the row then says less, never more.\n *\n * Pure: no React, no I/O.\n */\nimport type { BudgetView } from '../../../../core/routing/policy.js';\nimport type { SeatBudgetPolicy, SeatHeadroom } from '../../../../core/routing/types.js';\nimport type { SeatConnection, SeatFixKind, SeatHealthReport } from '../../../../core/verse/health-types.js';\nimport { describeResetAt } from '../../../../core/verse/seat-readiness.js';\nimport { ENGINE_MONOGRAM } from '../../../../core/verse/workbench-types.js';\nimport type { VerseEngine, VerseSeat } from '../../../data/api-types.js';\nimport { buildBudgetRows, STATUS_WORDS, type BudgetSeatStatus } from '../budget/budget-model.js';\nimport { relativePhrase } from '../context/context-model.js';\nimport { percentText, tidyProse } from '../autonomy/format.js';\nimport { CONNECTION_TONE, CONNECTION_WORD, usableAgainPhrase, type HealthTone } from '../health/health-model.js';\nimport { seatReopensAt, seatSubscription, type SeatCapacityClass, type SeatWindowView } from '../seat-subscription.js';\nimport { SEAT_CAPACITY_WORD } from '../verse-model.js';\n\nexport type { SeatCapacityClass };\n\ntype BudgetRow = ReturnType<typeof buildBudgetRows>[number];\n\n/** Rows show at most this many windows: the binding one and the next two. */\nexport const CAPACITY_MAX_WINDOWS = 3;\n\nexport interface CapacityWindowRow {\n id: string;\n /** \"5-hour window\", \"weekly window\", \"weekly fable window\". */\n label: string;\n /** 0–100, or null = no reading (never a substituted zero). */\n usedPercent: number | null;\n /** The provider flagged the limit; no percentage exists. */\n limitReached: boolean;\n /** Provider prose verbatim, or a formatted local instant; null when neither. */\n resetText: string | null;\n /** The machine-readable reset instant (ISO), when the provider gave one. */\n resetsAt: string | null;\n /** True for the window that constrains work right now. */\n binding: boolean;\n}\n\nexport interface CapacityConnection {\n connection: SeatConnection;\n word: string;\n tone: HealthTone;\n /** Plain, already-scrubbed reasons; empty when connected. */\n reasons: string[];\n fixKind: SeatFixKind;\n /** argv; null when nothing fixes it from a terminal. */\n fixCommand: string[] | null;\n}\n\nexport interface CapacityReserve {\n /** Share of the binding window kept for Mason; null when autonomy is off for this seat. */\n percent: number | null;\n /** \"Reserved for you 40%\", \"Autonomy off — all yours\", \"No reserve\". */\n label: string;\n autonomy: BudgetSeatStatus;\n /** \"Eligible\", \"Held back\", \"Off\", \"No reading\". */\n autonomyWord: string;\n /** The router's own first reason, verbatim. */\n why: string;\n}\n\nexport interface CapacityRow {\n /** A seat id, or `local` for the collapsed local row. */\n seatId: string;\n label: string;\n engine: VerseEngine;\n monogram: string;\n kind: 'subscription' | 'local';\n plan: string | null;\n cls: SeatCapacityClass;\n /** usable / tight / blocked / no reading. */\n word: string;\n /** One phrase: \"62% of 5-hour window used\", \"signed out — reconnect this account\". */\n summary: string;\n connection: CapacityConnection | null;\n windows: CapacityWindowRow[];\n credits: string | null;\n reserve: CapacityReserve | null;\n notes: string[];\n /** For the collapsed local row: how many local seats it stands for. */\n localCount: number;\n /** When this seat was last checked (health sweep, else the usage reading), ISO; null when never. */\n checkedAt: string | null;\n /** The instant a spent seat becomes usable again (ISO), when one is known. */\n resetAt: string | null;\n /** The account is signed out — by the health sweep or by its own capacity record. */\n signedOut: boolean;\n}\n\nexport interface CapacityInputs {\n health?: readonly SeatHealthReport[] | null;\n budget?: BudgetView | null;\n /**\n * Local seats: `collapse` (default) folds every Ollama tag into one row —\n * they share one machine and one readiness, and twelve identical rows are\n * noise; `each` lists them; `hide` drops them.\n */\n local?: 'collapse' | 'each' | 'hide';\n /** Only these seats, in this order (the new-chat dialog passes the chosen one). */\n seatIds?: readonly string[];\n /**\n * The clock every reset and reason in the rows is worded against (\"today\n * 11:46 PM\" vs \"Sat 11:46 PM\"); defaults to now. Passed explicitly so the\n * words are a function of the inputs — a row built against the real clock\n * inside a test is a time bomb.\n */\n now?: number;\n}\n\nconst TONE_OF_CLASS: Record<SeatCapacityClass, HealthTone> = {\n ready: 'success',\n tight: 'warning',\n blocked: 'danger',\n unread: 'neutral',\n};\n\n/** How a capacity class reads as a tone (a word always rides with it). */\nexport function capacityTone(cls: SeatCapacityClass): HealthTone {\n return TONE_OF_CLASS[cls];\n}\n\n/**\n * `resetText` comes from seat-subscription as-is: it already words a machine\n * instant the way every other reset in the app does (`describeResetAt`:\n * \"resets Fri 11:46 PM\") and leaves provider prose verbatim — one wording,\n * owned in one place.\n */\nfunction windowRow(w: SeatWindowView, binding: boolean): CapacityWindowRow {\n return {\n id: w.id,\n label: w.label,\n usedPercent: w.usedPercent,\n limitReached: w.limitReached,\n resetText: w.resetText,\n resetsAt: w.resetsAt,\n binding,\n };\n}\n\nfunction parseable(iso: string | null | undefined): iso is string {\n return typeof iso === 'string' && Number.isFinite(Date.parse(iso));\n}\n\nfunction isSpentWindow(w: Pick<SeatWindowView, 'limitReached' | 'usedPercent'>): boolean {\n return w.limitReached || (w.usedPercent !== null && w.usedPercent >= 100);\n}\n\nfunction connectionOf(report: SeatHealthReport | undefined, now: number): CapacityConnection | null {\n if (!report) return null;\n return {\n connection: report.connection,\n word: CONNECTION_WORD[report.connection],\n tone: CONNECTION_TONE[report.connection],\n reasons: readableReasons(report.reasons, now),\n fixKind: report.fix.kind,\n fixCommand: report.fix.command && report.fix.command.length > 0 ? [...report.fix.command] : null,\n };\n}\n\n/** Reasons as printed: server sentences with any ISO instant shown in local time. */\nfunction readableReasons(reasons: readonly string[], now: number): string[] {\n return reasons.map((r) => tidyProse(r, now).trim()).filter((r) => r.length > 0);\n}\n\nfunction reserveOf(budgetRow: BudgetRow | undefined): CapacityReserve | null {\n if (!budgetRow || budgetRow.free) return null;\n const { policy } = budgetRow;\n const pct = Math.max(0, Math.min(100, Math.round(policy.reservePercent)));\n const label = !policy.enabled\n ? 'Autonomy off — all yours'\n : pct === 0\n ? 'No reserve — autonomy may use all of it'\n : `Reserved for you ${pct}%`;\n return {\n percent: policy.enabled ? pct : null,\n label,\n autonomy: budgetRow.status,\n autonomyWord: STATUS_WORDS[budgetRow.status],\n why: budgetRow.why,\n };\n}\n\nfunction seatRow(\n seat: VerseSeat,\n health: ReadonlyMap<string, SeatHealthReport>,\n budget: ReadonlyMap<string, BudgetRow>,\n now: number,\n): CapacityRow {\n const view = seatSubscription(seat, now);\n const windows: CapacityWindowRow[] = [];\n if (view.binding) windows.push(windowRow(view.binding, true));\n for (const w of view.others) {\n if (windows.length >= CAPACITY_MAX_WINDOWS) break;\n windows.push(windowRow(w, false));\n }\n const report = health.get(seat.id);\n const connection = connectionOf(report, now);\n // A seat A2 found signed out or out of usage cannot run a turn, whatever\n // its last window reading says (the engine's readiness gate refuses it —\n // seat-readiness.ts SEAT_BLOCKING_CONNECTIONS). Counting it \"usable\"\n // would promise a chat the engine will refuse.\n const blockedByHealth = connection !== null && (connection.connection === 'signed-out' || connection.connection === 'exhausted');\n return {\n seatId: seat.id,\n label: seat.label,\n engine: seat.engine,\n monogram: ENGINE_MONOGRAM[seat.engine],\n kind: view.kind,\n plan: view.plan,\n cls: blockedByHealth ? 'blocked' : view.cls,\n word: blockedByHealth ? SEAT_CAPACITY_WORD.blocked : view.word,\n summary: blockedByHealth ? (connection.reasons[0] ?? connection.word) : view.summary,\n connection,\n windows,\n credits: view.credits,\n reserve: reserveOf(budget.get(seat.id)),\n notes: [...view.notes],\n localCount: 1,\n checkedAt: parseable(report?.checkedAt) ? report!.checkedAt : parseable(view.observedAt) ? view.observedAt : null,\n // The LATEST reset among ALL the spent windows (not only the ones this row\n // has room to draw) — seat-subscription `seatReopensAt`, which Fleet's\n // \"eligible again\" and the health banner agree with.\n resetAt: seatReopensAt(view, report?.resetAt),\n signedOut: connection?.connection === 'signed-out' || seat.capacity?.usability === 'signed-out',\n };\n}\n\nfunction collapsedLocal(seats: readonly VerseSeat[], health: ReadonlyMap<string, SeatHealthReport>, now: number): CapacityRow {\n const rows = seats.map((s) => seatSubscription(s, now));\n const ready = rows.filter((r) => r.cls === 'ready').length;\n const blocked = rows.filter((r) => r.cls === 'blocked').length;\n const cls: SeatCapacityClass = ready > 0 ? 'ready' : blocked === rows.length ? 'blocked' : 'unread';\n // One runtime behind every tag: the first report that says anything speaks for it.\n const report = seats.map((s) => health.get(s.id)).find((r) => r !== undefined);\n const count = seats.length;\n return {\n seatId: 'local',\n label: 'Local models',\n engine: 'local',\n monogram: ENGINE_MONOGRAM.local,\n kind: 'local',\n plan: null,\n cls,\n word: rows.find((r) => r.cls === cls)?.word ?? 'no reading',\n summary: cls === 'ready'\n ? `${count} ${count === 1 ? 'model' : 'models'} on this machine · free`\n : cls === 'blocked'\n ? (rows[0]?.summary ?? 'local runtime unavailable')\n : 'readiness not reported',\n connection: connectionOf(report, now),\n windows: [],\n credits: null,\n reserve: null,\n notes: [],\n localCount: count,\n checkedAt: parseable(report?.checkedAt)\n ? report!.checkedAt\n : rows.map((r) => r.observedAt).filter(parseable).sort((a, b) => Date.parse(b) - Date.parse(a))[0] ?? null,\n resetAt: null,\n signedOut: false,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tolerant readers\n// ---------------------------------------------------------------------------\n//\n// WHY THESE EXIST. The strip is mounted on five surfaces (Apps, Usage,\n// onboarding, NewChatDialog, the rail ring via scarcestSeat) and renders\n// synchronously from three cached server reads. The types say what a healthy\n// server sends, but the cache holds whatever arrived: a `{}` from a budget\n// route that has not landed on an older sidecar, a half-written health file,\n// a future field shape. One `undefined.map` inside `useMemo` takes the whole\n// surface down with it (INT6 found exactly that with `/api/verse/budget` →\n// `{}`). So each optional source is checked HERE, at the one boundary every\n// view shares, and the rule is the module's own: a source that cannot be\n// read makes the row say LESS, never crash and never invent. A bad entry is\n// dropped on its own; the rest of the source still speaks.\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nconst nullablePercent = (v: unknown): number | null => (typeof v === 'number' && Number.isFinite(v) ? v : null);\n\nfunction readHeadroom(value: unknown): SeatHeadroom | null {\n if (!isRecord(value) || typeof value['seatId'] !== 'string') return null;\n const binding = value['bindingWindow'];\n return {\n seatId: value['seatId'],\n sessionUsedPercent: nullablePercent(value['sessionUsedPercent']),\n weeklyUsedPercent: nullablePercent(value['weeklyUsedPercent']),\n bindingWindow: binding === 'session' || binding === 'weekly' ? binding : null,\n autonomyHeadroomPercent: nullablePercent(value['autonomyHeadroomPercent']),\n resetAt: typeof value['resetAt'] === 'string' ? value['resetAt'] : null,\n // Only an explicit `true` makes a seat eligible — a garbled flag is \"not known to be eligible\".\n eligibleForAutonomy: value['eligibleForAutonomy'] === true,\n reasons: Array.isArray(value['reasons']) ? value['reasons'].filter((r): r is string => typeof r === 'string') : [],\n };\n}\n\nfunction readPolicy(seatId: string, value: unknown): SeatBudgetPolicy | null {\n if (!isRecord(value) || typeof value['enabled'] !== 'boolean') return null;\n const reserve = value['reservePercent'];\n if (typeof reserve !== 'number' || !Number.isFinite(reserve)) return null;\n const out: SeatBudgetPolicy = { seatId, enabled: value['enabled'], reservePercent: reserve };\n const session = value['maxSessionWindowPercent'];\n if (typeof session === 'number' && Number.isFinite(session)) out.maxSessionWindowPercent = session;\n return out;\n}\n\n/**\n * The budget view → rows keyed by seat, or an empty map when the view cannot\n * be read. A seat whose policy entry is present but malformed is DROPPED\n * rather than handed to budget-model's \"no policy → off\" default: that default\n * is right for a seat the server genuinely has no policy for, but for a\n * garbled entry it would print \"Autonomy off — all yours\", a claim nobody\n * made.\n */\nexport function readBudgetRows(view: unknown): Map<string, BudgetRow> {\n if (!isRecord(view) || !Array.isArray(view['seatInfo'])) return new Map();\n const effectiveIn = isRecord(view['effective']) ? view['effective'] : {};\n const effective: Record<string, SeatBudgetPolicy> = {};\n const seatInfo: BudgetView['seatInfo'] = [];\n for (const info of view['seatInfo']) {\n if (!isRecord(info) || typeof info['seatId'] !== 'string') continue;\n const seatId = info['seatId'];\n const engine = info['engine'];\n if (engine !== 'claude' && engine !== 'codex' && engine !== 'grok' && engine !== 'local') continue;\n if (Object.prototype.hasOwnProperty.call(effectiveIn, seatId)) {\n const policy = readPolicy(seatId, effectiveIn[seatId]);\n if (policy === null) continue;\n effective[seatId] = policy;\n }\n seatInfo.push({\n seatId,\n label: typeof info['label'] === 'string' ? info['label'] : seatId,\n engine,\n free: info['free'] === true,\n });\n }\n const headroom = Array.isArray(view['headroom'])\n ? view['headroom'].map(readHeadroom).filter((h): h is SeatHeadroom => h !== null)\n : [];\n const safe = { ...(view as unknown as BudgetView), seatInfo, effective, headroom };\n try {\n return new Map(buildBudgetRows(safe).map((r) => [r.seatId, r]));\n } catch {\n // Belt and braces: budget-model is pure and the input is now well-typed,\n // but a reserve line is never worth a blank strip.\n return new Map();\n }\n}\n\n/** Health reports keyed by seat, keeping only reports that can be described honestly. */\nexport function readHealthReports(reports: unknown): Map<string, SeatHealthReport> {\n const out = new Map<string, SeatHealthReport>();\n if (!Array.isArray(reports)) return out;\n for (const r of reports) {\n if (!isRecord(r) || typeof r['seatId'] !== 'string') continue;\n const connection = r['connection'];\n // An unknown connection word has no tone or wording — describing it\n // would mean guessing; the row falls back to its window reading.\n if (typeof connection !== 'string' || !Object.prototype.hasOwnProperty.call(CONNECTION_WORD, connection)) continue;\n const fix = isRecord(r['fix']) ? r['fix'] : {};\n const kind = fix['kind'];\n const command = Array.isArray(fix['command']) && fix['command'].every((a) => typeof a === 'string')\n ? (fix['command'] as string[])\n : undefined;\n out.set(r['seatId'], {\n ...(r as unknown as SeatHealthReport),\n reasons: Array.isArray(r['reasons']) ? r['reasons'].filter((x): x is string => typeof x === 'string') : [],\n fix: {\n kind: kind === 'reauth' || kind === 'repin' || kind === 'wait' ? kind : 'none',\n ...(command ? { command } : {}),\n },\n });\n }\n return out;\n}\n\n/** Seats → rows, in the roster's own order (the server lists the operator's preferred seats first). */\nexport function buildCapacityRows(seats: readonly VerseSeat[], inputs: CapacityInputs = {}): CapacityRow[] {\n const health = readHealthReports(inputs.health);\n const budget = readBudgetRows(inputs.budget);\n // The roster comes from bootstrap; a malformed one reads as \"no seats yet\",\n // the strip's honest empty state, rather than a crash.\n const roster = Array.isArray(seats)\n ? seats.filter((s): s is VerseSeat => isRecord(s) && typeof (s as { id?: unknown }).id === 'string')\n : [];\n const localMode = inputs.local ?? 'collapse';\n const now = inputs.now ?? Date.now();\n let chosen: readonly VerseSeat[] = roster;\n if (inputs.seatIds) {\n const byId = new Map(roster.map((s) => [s.id, s]));\n chosen = inputs.seatIds.map((id) => byId.get(id)).filter((s): s is VerseSeat => s !== undefined);\n }\n const out: CapacityRow[] = [];\n const locals: VerseSeat[] = [];\n let localIndex = -1;\n for (const seat of chosen) {\n if (seat.engine === 'local') {\n if (localMode === 'hide') continue;\n if (localMode === 'collapse') {\n if (localIndex === -1) localIndex = out.length;\n locals.push(seat);\n continue;\n }\n }\n out.push(seatRow(seat, health, budget, now));\n }\n if (locals.length > 0) {\n // A single local seat keeps its own name; several fold into one row.\n const row = locals.length === 1 ? seatRow(locals[0]!, health, budget, now) : collapsedLocal(locals, health, now);\n out.splice(localIndex, 0, row);\n }\n return out;\n}\n\n/**\n * The strip's one sentence: how many paid seats are usable, and what local\n * adds. Counts only what was READ — an unread seat is named as unread, never\n * folded into \"blocked\".\n */\nexport function capacityHeadline(rows: readonly CapacityRow[]): string {\n const paid = rows.filter((r) => r.kind === 'subscription');\n const local = rows.filter((r) => r.kind === 'local');\n const usable = paid.filter((r) => r.cls === 'ready' || r.cls === 'tight').length;\n const unread = paid.filter((r) => r.cls === 'unread').length;\n const parts: string[] = [];\n if (paid.length === 0) parts.push('No accounts connected');\n else parts.push(`${usable} of ${paid.length} ${paid.length === 1 ? 'account' : 'accounts'} usable`);\n if (unread > 0) parts.push(`${unread} not read yet`);\n if (local.some((r) => r.cls === 'ready')) parts.push('local models ready');\n else if (local.length > 0) parts.push('local models not ready');\n return parts.join(' · ');\n}\n\n/**\n * The seat closest to running out — the rail foot's capacity ring (C1).\n * Blocked beats tight beats a measured percent; unread seats never win,\n * because an empty ring would claim headroom nobody measured.\n */\nexport function scarcestSeat(rows: readonly CapacityRow[]): CapacityRow | null {\n let best: { row: CapacityRow; score: number } | null = null;\n for (const row of rows) {\n if (row.kind !== 'subscription') continue;\n const binding = row.windows.find((w) => w.binding) ?? null;\n let score: number;\n if (row.cls === 'blocked' || binding?.limitReached) score = 300;\n else if (binding?.usedPercent != null) score = (row.cls === 'tight' ? 100 : 0) + binding.usedPercent;\n else continue;\n if (best === null || score > best.score) best = { row, score };\n }\n return best?.row ?? null;\n}\n\n/** One seat's row (the composer's seat chip, C3), or null when the seat is not in the roster. */\nexport function capacityRowFor(seats: readonly VerseSeat[], seatId: string, inputs: Omit<CapacityInputs, 'seatIds' | 'local'> = {}): CapacityRow | null {\n return buildCapacityRows(seats, { ...inputs, seatIds: [seatId], local: 'each' })[0] ?? null;\n}\n\n/**\n * The one percent rule lives with the app's other number formats\n * (autonomy/format); re-exported so every capacity view keeps importing it\n * from the capacity model.\n */\nexport { percentText };\n\n/** The accessible sentence for one window bar. */\nexport function windowSentence(row: Pick<CapacityRow, 'label'>, w: CapacityWindowRow, reservePercent: number | null): string {\n const head = `${row.label} ${w.label}`;\n const reset = w.resetText === null ? '' : `, ${w.resetText}`;\n if (w.limitReached) return `${head}: limit reached${reset}`;\n if (w.usedPercent === null) return `${head}: no reading${reset}`;\n const kept = reservePercent !== null && reservePercent > 0 ? `; ${reservePercent}% kept for you` : '';\n return `${head}: ${percentText(w.usedPercent)} used${kept}${reset}`;\n}\n\n// ---------------------------------------------------------------------------\n// Account status (Apps & Accounts)\n// ---------------------------------------------------------------------------\n\n/**\n * - `usable` — connected (or read as usable) with room left;\n * - `low` — usable, but tight: past the warning line, or spent and running on credits;\n * - `spent` — the binding window is used up; comes back at `resetAt`;\n * - `signed-out` — needs the provider's own sign-in (Reconnect);\n * - `unavailable` — blocked for another reason (runtime down, CLI missing);\n * - `not-checked` — the health sweep has answered but said nothing usable about this seat;\n * - `checking` — nothing has answered yet, or a check is running right now.\n */\nexport type AccountStatusKind = 'usable' | 'low' | 'spent' | 'signed-out' | 'unavailable' | 'not-checked' | 'checking';\n\nexport interface AccountStatus {\n kind: AccountStatusKind;\n /** Sentence case, leads the row: \"Connected\", \"Spent\", \"Signed out\", \"Checking…\". */\n label: string;\n /** Rides after a middle dot: \"usable now\", \"resets Fri 11:46 PM\", \"reconnect to use it\". */\n detail: string | null;\n tone: HealthTone;\n /** \"usable again in 7h 12m\" — only for a spent seat whose reset is still ahead. */\n usableAgain: string | null;\n /** \"checked 2m ago\"; null when the seat was never checked. */\n checked: string | null;\n /** The last check as a local date and time, for a tooltip. */\n checkedTitle: string | null;\n /** True when `label` already says what the connection word would (signed out, out of usage). */\n coversConnection: boolean;\n}\n\nexport interface AccountStatusOptions {\n /** False until the health sweep has answered once: an unanswered seat is \"Checking…\", not \"Not checked\". */\n healthRead: boolean;\n /** A check of this seat is running right now. */\n checking?: boolean;\n now?: number;\n}\n\nconst STATUS_TONE: Record<AccountStatusKind, HealthTone> = {\n usable: 'success',\n low: 'warning',\n spent: 'danger',\n 'signed-out': 'danger',\n unavailable: 'danger',\n 'not-checked': 'neutral',\n checking: 'neutral',\n};\n\n/** Usable first, then what will come back by itself, then what needs you. Used by `orderAccountRows`. */\nconst STATUS_RANK: Record<AccountStatusKind, number> = {\n usable: 0,\n low: 1,\n checking: 2,\n 'not-checked': 3,\n spent: 4,\n unavailable: 5,\n 'signed-out': 6,\n};\n\nfunction checkedParts(row: Pick<CapacityRow, 'checkedAt'>, now: number): { checked: string | null; checkedTitle: string | null } {\n const phrase = relativePhrase(row.checkedAt, now);\n if (phrase === null || row.checkedAt === null) return { checked: null, checkedTitle: null };\n const at = new Date(row.checkedAt);\n return {\n checked: `checked ${phrase}`,\n checkedTitle: `Last checked ${at.toLocaleString([], { weekday: 'short', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })}`,\n };\n}\n\n/**\n * The one status an account row leads with, in the operator's words:\n *\n * Connected · usable now Spent · resets Fri 11:46 PM\n * Connected · running low Signed out · reconnect to use it\n * Connected · usable on credits Checking…\n *\n * Built from the row alone (no second reading of the seat), against a clock\n * the caller passes, because \"usable again in 7h\" must keep counting down\n * while the rows themselves are memoized on the data.\n */\nexport function accountStatus(row: CapacityRow, opts: AccountStatusOptions): AccountStatus {\n const now = opts.now ?? Date.now();\n const { checked, checkedTitle } = checkedParts(row, now);\n const make = (kind: AccountStatusKind, label: string, detail: string | null, extra: Partial<AccountStatus> = {}): AccountStatus => ({\n kind,\n label,\n detail,\n tone: STATUS_TONE[kind],\n usableAgain: null,\n checked,\n checkedTitle,\n coversConnection: false,\n ...extra,\n });\n\n if (opts.checking) return make('checking', 'Checking…', null);\n\n if (row.kind === 'local') {\n if (row.cls === 'ready') {\n return make('usable', 'Ready', row.localCount > 1 ? `${row.localCount} models on this machine · free` : 'runs on this machine · free');\n }\n if (row.cls === 'blocked') return make('unavailable', 'Not running', row.summary);\n return opts.healthRead ? make('not-checked', 'Not checked', 'readiness not reported yet') : make('checking', 'Checking…', null);\n }\n\n const c = row.connection?.connection ?? null;\n if (row.signedOut) return make('signed-out', 'Signed out', 'reconnect to use it', { coversConnection: true });\n\n const binding = row.windows.find((w) => w.binding) ?? null;\n const spent = c === 'exhausted' || (row.cls === 'blocked' && binding !== null && isSpentWindow(binding));\n if (spent) {\n const when = describeResetAt(row.resetAt, now);\n const ahead = row.resetAt !== null && Date.parse(row.resetAt) > now;\n // No instant: the provider's own reset prose, verbatim, is the next best\n // thing — the prose of the spent window with no instant (the one that\n // holds the seat), never another window's earlier instant, which would\n // promise the seat back before it is.\n const heldBy = row.windows.find((w) => isSpentWindow(w) && !parseable(w.resetsAt) && w.resetText !== null) ?? null;\n const prose = heldBy?.resetText ?? (binding !== null && !parseable(binding.resetsAt) ? binding.resetText : null);\n const detail = when !== null\n ? (ahead ? `resets ${when}` : `was due to reset ${when}`)\n : (prose ?? 'reset time not reported');\n return make('spent', 'Spent', detail, {\n usableAgain: usableAgainPhrase(row.resetAt, now),\n coversConnection: c === 'exhausted',\n });\n }\n\n if (row.cls === 'blocked') return make('unavailable', 'Unavailable', row.summary);\n\n // A seat nobody has read is not \"fine\" and not \"broken\": it is waiting on a check.\n if (row.cls === 'unread') {\n if (!opts.healthRead) return make('checking', 'Checking…', null);\n if (c === null || c === 'unknown') return make('not-checked', 'Not checked', 'no reading yet');\n return make('usable', 'Connected', 'no usage reading yet');\n }\n\n const lead = c === null || c === 'unknown' ? 'Usable' : 'Connected';\n if (row.cls === 'tight') {\n const onCredits = binding !== null && isSpentWindow(binding) && row.credits !== null;\n if (lead === 'Usable') return make('low', 'Usable', onCredits ? 'on credits' : 'running low');\n return make('low', lead, onCredits ? 'usable on credits' : 'running low');\n }\n return lead === 'Usable' ? make('usable', 'Usable now', null) : make('usable', 'Connected', 'usable now');\n}\n\n/**\n * Usable accounts first, then the ones that come back on their own, then the\n * ones that need you — stable within each group (the roster's own order), and\n * paid seats ahead of local ones of the same standing. Ordered on the settled\n * status (never on a running check), so a row does not jump while \"Checking…\".\n */\nexport function orderAccountRows(rows: readonly CapacityRow[], opts: Omit<AccountStatusOptions, 'checking'>): CapacityRow[] {\n const ranked = rows.map((row, index) => ({\n row,\n index,\n rank: STATUS_RANK[accountStatus(row, { ...opts, checking: false }).kind],\n local: row.kind === 'local' ? 1 : 0,\n }));\n ranked.sort((a, b) => a.rank - b.rank || a.local - b.local || a.index - b.index);\n return ranked.map((r) => r.row);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as e,n as t,s as n}from"./index-BVxOlseC.js";import{C as r,R as i,T as a,_ as o,d as s,f as c,g as l,m as u,u as d,w as f}from"./useChartWidth-owwodNVz.js";import{_ as p,a as m,c as h,t as g}from"./colors-BZ3a9wFf.js";import{l as _}from"./format-DKrNjdwD.js";import"./Swimlane-DGcIcnNA.js";import"./BurnDown-sFXkUGdB.js";import"./AreaTrend-CDxrQU4b.js";import"./Funnel-D2u7Wlzc.js";import"./StepBand-Duz1PUes.js";import"./MatrixHeatmap-BgEUs2Eu.js";var v={figure:`_figure_1si9v_1`,caption:`_caption_1si9v_12`,title:`_title_1si9v_20`,description:`_description_1si9v_26`,plot:`_plot_1si9v_31`,tableDisclosure:`_tableDisclosure_1si9v_36`,tableBody:`_tableBody_1si9v_61`,caveat:`_caveat_1si9v_65`,empty:`_empty_1si9v_75`},y=t();function b({title:e,description:t,caveat:n,children:r,table:i,empty:a,emptyMessage:o=`No data for this window.`}){return(0,y.jsxs)(`figure`,{className:v.figure,children:[(0,y.jsxs)(`figcaption`,{className:v.caption,children:[(0,y.jsx)(`span`,{className:v.title,children:e}),t?(0,y.jsx)(`span`,{className:v.description,children:t}):null]}),n?(0,y.jsx)(`p`,{className:v.caveat,role:`note`,children:n}):null,a?(0,y.jsx)(`p`,{className:v.empty,children:o}):(0,y.jsx)(`div`,{className:v.plot,children:r}),i?(0,y.jsxs)(`details`,{className:v.tableDisclosure,children:[(0,y.jsx)(`summary`,{children:`View as table`}),(0,y.jsx)(`div`,{className:v.tableBody,children:i})]}):null]})}var x={legend:`_legend_4pgvn_1`,item:`_item_4pgvn_10`,swatch:`_swatch_4pgvn_18`,swatchLine:`_swatchLine_4pgvn_25`};function S({items:e}){return e.length<2?null:(0,y.jsx)(`ul`,{className:x.legend,children:e.map(e=>(0,y.jsxs)(`li`,{className:x.item,children:[(0,y.jsx)(`span`,{className:e.kind===`line`?x.swatchLine:x.swatch,style:{background:e.color},"aria-hidden":`true`}),e.label]},e.label))})}var C=n(e(),1),w={svg:`_svg_djmd1_1`,gridline:`_gridline_djmd1_7`,axis:`_axis_djmd1_12`,axisLabel:`_axisLabel_djmd1_17`,line:`_line_djmd1_23`,area:`_area_djmd1_30`,marker:`_marker_djmd1_35`,endLabel:`_endLabel_djmd1_40`,crosshairLine:`_crosshairLine_djmd1_46`,overlay:`_overlay_djmd1_52`,wrap:`_wrap_djmd1_57`,tooltip:`_tooltip_djmd1_61`,tooltipDate:`_tooltipDate_djmd1_77`,tooltipRow:`_tooltipRow_djmd1_82`,tooltipKey:`_tooltipKey_djmd1_88`,tooltipValue:`_tooltipValue_djmd1_94`,tooltipGap:`_tooltipGap_djmd1_99`},T=640,ee=44,te=12,E=12,D=24,ne=4,re=6.4,O=4,ie=150,ae=14;function oe(e){let t=[],n=[];for(let r of e){if(r.y===null){n.length&&t.push(n),n=[];continue}n.push({x:r.x,y:r.y})}return n.length&&t.push(n),t}function k({series:e,height:t=200,area:n=!1,formatX:h,formatY:v,ariaLabel:b}){let x=(0,C.useRef)(null),k=d(),A=f(k),[j,M]=(0,C.useState)(null),[N,se]=(0,C.useState)(null),P=h??(e=>String(e)),ce=v??(e=>String(e)),le=i(e.flatMap(e=>e.points.map(e=>e.x))),F=e.map(e=>({...e,points:e.points.filter(e=>le(e.x))})),I=F.flatMap(e=>e.points.map(e=>e.x)),L=F.flatMap(e=>e.points.map(e=>e.y)).filter(e=>e!==null&&Number.isFinite(e));if(I.length===0)return(0,y.jsx)(`p`,{children:`No data.`});let R=Math.min(...I),z=Math.max(...I),ue=r(I),[B,de]=ue&&z>R?o(R,z,s):[R,z],V=de-B||1,H=u(Math.min(0,...L),Math.max(0,...L),{count:ne,integer:L.length>0&&c(L),format:v}),U=H.ticks,W=U[0],fe=U[U.length-1]-W||1,G=t-E-D,K=e=>E+G-(e-W)/fe*G,q=Math.max(ee,Math.ceil(Math.max(0,...H.labels.map(e=>e.length))*A)+8),J=F.length>=1&&F.length<=4,pe=J?Math.max(...F.map(e=>e.label.length))*re*k:0,me=F.flatMap(e=>{for(let t=e.points.length-1;t>=0;t--){let n=e.points[t].y;if(n!==null&&Number.isFinite(n))return[{key:e.id,y:K(n)}]}return[]}),he=J&&pe<=ie?l(me,ae*k,E,E+G):null,ge=he!==null&&me.length>0,Y=te+(ge?O+pe:0),X=F.length>=2,Z=T-q-Y,Q=e=>q+(e-B)/V*Z,$=Array.from(new Set(I)).sort((e,t)=>e-t),_e=$.length>1?[$[0],$[$.length-1]]:[],ve=ue?_(R,z,h,_e):[P],ye=a(_e.map((e,t)=>{let n=Q(e),r=t===0?n<=q+.5:n>=T-Y-.5;return{key:t===0?`start`:`end`,x:n,anchor:r?t===0?`start`:`end`:`middle`,priority:t===0?2:3,variants:ve.map(t=>t(e))}}),{min:q,max:T-Y,charPx:A});function be(e){let t=x.current;if(!t)return null;let n=t.getBoundingClientRect(),r=(e-n.left)/n.width*T,i=B+(r-q)/Z*V,a=$[0],o=1/0;for(let e of $){let t=Math.abs(e-i);t<o&&(o=t,a=e)}return a}function xe(e){let t=be(e.clientX);if(t===null)return;M(t);let n=x.current;if(n){let e=n.getBoundingClientRect(),r=Q(t)/T*e.width;se({left:r,top:0})}}let Se=j===null?null:F.map(e=>({series:e,point:e.points.find(e=>e.x===j)??null}));return(0,y.jsxs)(`div`,{className:w.wrap,children:[(0,y.jsxs)(`svg`,{ref:x,className:w.svg,viewBox:`0 0 ${T} ${t}`,role:`img`,"aria-label":b,onPointerMove:xe,onPointerLeave:()=>M(null),children:[U.map((e,t)=>(0,y.jsxs)(`g`,{children:[(0,y.jsx)(`line`,{x1:q,x2:T-Y,y1:K(e),y2:K(e),className:w.gridline,stroke:m}),(0,y.jsx)(`text`,{x:q-6,y:K(e),dy:`0.32em`,textAnchor:`end`,className:w.axisLabel,children:H.labels[t]})]},t)),(0,y.jsx)(`line`,{x1:q,x2:T-Y,y1:t-D,y2:t-D,className:w.axis,stroke:g}),ye.map(e=>(0,y.jsx)(`text`,{"data-axis-label":e.key,x:e.x,y:t-6,textAnchor:e.anchor,className:w.axisLabel,children:e.text},e.key)),F.map((e,t)=>{let r=p(t),i=oe(e.points);return(0,y.jsxs)(`g`,{children:[n&&F.length===1?i.map((e,t)=>{let n=e.map((e,t)=>`${t===0?`M`:`L`}${Q(e.x)},${K(e.y)}`).join(` `)+` L${Q(e[e.length-1].x)},${K(W)} L${Q(e[0].x)},${K(W)} Z`;return(0,y.jsx)(`path`,{d:n,fill:r,className:w.area},t)}):null,i.map((e,t)=>(0,y.jsx)(`path`,{d:e.map((e,t)=>`${t===0?`M`:`L`}${Q(e.x)},${K(e.y)}`).join(` `),stroke:r,className:w.line},t)),ge&&i.length?(()=>{let t=i[i.length-1],n=t[t.length-1];return(0,y.jsx)(`text`,{"data-end-label":e.id,x:Q(n.x)+O,y:he?.get(e.id)??K(n.y),dy:`0.32em`,className:w.endLabel,fill:r,children:e.label})})():null]},e.id)}),j===null?null:(0,y.jsx)(`line`,{x1:Q(j),x2:Q(j),y1:E,y2:t-D,className:w.crosshairLine}),j===null?null:F.map((e,t)=>{let n=e.points.find(e=>e.x===j);return!n||n.y===null?null:(0,y.jsx)(`circle`,{cx:Q(n.x),cy:K(n.y),r:4,fill:p(t),className:w.marker},e.id)}),(0,y.jsx)(`rect`,{x:q,y:E,width:Z,height:G,className:w.overlay,onFocus:()=>M($[$.length-1]??null)})]}),Se&&N?(0,y.jsxs)(`div`,{className:w.tooltip,style:{left:N.left,top:N.top},children:[(0,y.jsx)(`div`,{className:w.tooltipDate,children:P(j)}),Se.map(({series:e,point:t},n)=>(0,y.jsxs)(`div`,{className:w.tooltipRow,children:[(0,y.jsx)(`span`,{className:w.tooltipKey,style:{background:p(n)},"aria-hidden":`true`}),t&&t.y!==null?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`span`,{className:w.tooltipValue,children:ce(t.y)}),X?(0,y.jsx)(`span`,{children:e.label}):null]}):(0,y.jsxs)(`span`,{className:w.tooltipGap,children:[`no data`,X?` — ${e.label}`:``]})]},e.id))]}):null,X?(0,y.jsx)(S,{items:F.map((e,t)=>({label:e.label,color:p(t),kind:`line`}))}):null]})}var A={svg:`_svg_o4jfa_1`,bar:`_bar_o4jfa_6`,baseline:`_baseline_o4jfa_15`,gridline:`_gridline_o4jfa_20`,axisLabel:`_axisLabel_o4jfa_25`,valueLabel:`_valueLabel_o4jfa_31`,categoryLabel:`_categoryLabel_o4jfa_38`,hitArea:`_hitArea_o4jfa_44`,tooltip:`_tooltip_o4jfa_49`,tooltipValue:`_tooltipValue_o4jfa_63`,tooltipLabel:`_tooltipLabel_o4jfa_68`,wrap:`_wrap_o4jfa_73`},j=24,M=10;function N({data:e,height:t=160,orientation:n=`vertical`,color:r=h,formatValue:i=e=>String(e),ariaLabel:a}){let o=(0,C.useId)(),[s,c]=(0,C.useState)(null),l=e.map(e=>e.value).filter(e=>e!==null),u=Math.max(0,...l,1e-4),d=Math.min(0,...l),f=u-d||1;if(n===`horizontal`){let n=Math.min(j,Math.max(14,Math.floor((t-M)/e.length)-M)),o=e.length*(n+M)+M;return(0,y.jsxs)(`div`,{className:A.wrap,children:[(0,y.jsxs)(`svg`,{className:A.svg,width:588,height:o,viewBox:`0 0 588 ${o}`,role:`img`,"aria-label":a,children:[(0,y.jsx)(`line`,{x1:120,y1:0,x2:120,y2:o,className:A.baseline,stroke:g}),e.map((e,t)=>{let a=M+t*(n+M),o=e.value===null?0:(e.value-d)/f*420;return(0,y.jsxs)(`g`,{children:[(0,y.jsx)(`text`,{x:112,y:a+n/2,dy:`0.32em`,textAnchor:`end`,className:A.categoryLabel,children:e.label.length>22?`${e.label.slice(0,21)}…`:e.label}),e.value===null?(0,y.jsx)(`line`,{x1:124,y1:a+n/2,x2:134,y2:a+n/2,stroke:m,strokeWidth:2,strokeDasharray:`2 2`}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`rect`,{x:120,y:a,width:Math.max(2,o),height:n,rx:4,fill:r,className:A.bar}),(0,y.jsx)(`text`,{x:120+Math.max(2,o)+6,y:a+n/2,dy:`0.32em`,className:A.valueLabel,children:i(e.value)})]}),(0,y.jsx)(`rect`,{className:A.hitArea,x:0,y:a-M/2,width:588,height:n+M,tabIndex:0,role:`img`,"aria-label":`${e.label}: ${e.value===null?`no data`:i(e.value)}`,onPointerEnter:()=>c(t),onPointerLeave:()=>c(e=>e===t?null:e),onFocus:()=>c(t),onBlur:()=>c(e=>e===t?null:e)})]},e.label+t)})]}),s===null?null:(0,y.jsxs)(`div`,{className:A.tooltip,style:{left:128,top:M+s*(n+M)-4},children:[(0,y.jsx)(`span`,{className:A.tooltipValue,children:e[s].value===null?`no data`:i(e[s].value)}),(0,y.jsx)(`span`,{className:A.tooltipLabel,children:e[s].label})]})]})}let p=e.length?Math.max(j,0):j,_=Math.min(j,p),v=t,b=v+20+30,x=e.length*(_+M)+M,S=20+v-(0-d)/f*v;return(0,y.jsxs)(`div`,{className:A.wrap,children:[(0,y.jsxs)(`svg`,{className:A.svg,width:x,height:b,viewBox:`0 0 ${x} ${b}`,role:`img`,"aria-label":a,children:[(0,y.jsx)(`line`,{x1:0,y1:S,x2:x,y2:S,className:A.baseline,stroke:g}),e.map((e,t)=>{let n=M+t*(_+M),a=e.value===null?0:Math.abs(e.value-d)/f*v,o=e.value!==null&&e.value>=0?S-a:S;return(0,y.jsxs)(`g`,{children:[e.value===null?(0,y.jsx)(`line`,{x1:n+_/2-5,y1:S,x2:n+_/2+5,y2:S,stroke:m,strokeWidth:2,strokeDasharray:`2 2`}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`rect`,{x:n,y:o,width:_,height:Math.max(2,a),rx:4,fill:r,className:A.bar}),(0,y.jsx)(`text`,{x:n+_/2,y:o-4,textAnchor:`middle`,className:A.valueLabel,children:i(e.value)})]}),(0,y.jsx)(`text`,{x:n+_/2,y:b-8,textAnchor:`middle`,className:A.axisLabel,children:e.label.length>10?`${e.label.slice(0,9)}…`:e.label}),(0,y.jsx)(`rect`,{className:A.hitArea,x:n-M/2,y:0,width:_+M,height:b,tabIndex:0,role:`img`,"aria-label":`${e.label}: ${e.value===null?`no data`:i(e.value)}`,onPointerEnter:()=>c(t),onPointerLeave:()=>c(e=>e===t?null:e),onFocus:()=>c(t),onBlur:()=>c(e=>e===t?null:e)})]},e.label+t)})]}),s===null?null:(0,y.jsxs)(`div`,{className:A.tooltip,style:{left:M+s*(_+M),top:0},id:`${o}-tooltip`,children:[(0,y.jsx)(`span`,{className:A.tooltipValue,children:e[s].value===null?`no data`:i(e[s].value)}),(0,y.jsx)(`span`,{className:A.tooltipLabel,children:e[s].label})]})]})}export{b as i,k as n,S as r,N as t};
|
|
2
|
-
//# sourceMappingURL=charts-CfAjuKMv.js.map
|