@ashlr/hub 3.11.3 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -0
- package/README.md +44 -18
- package/dist/authority-surface.json +74 -59
- 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/trust-roots.js +7 -1
- package/dist/core/authority/trust-roots.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 +188 -6
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +187 -5
- 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-B4-39f2S.js +2 -0
- package/dist/core/web/public/next/assets/{ActionMenu-FxXeRbPx.js.map → ActionMenu-B4-39f2S.js.map} +1 -1
- package/dist/core/web/public/next/assets/Advanced-B-LqYXvd.js +2 -0
- package/dist/core/web/public/next/assets/Advanced-B-LqYXvd.js.map +1 -0
- package/dist/core/web/public/next/assets/App-E2zCDRxm.js +7 -0
- package/dist/core/web/public/next/assets/App-E2zCDRxm.js.map +1 -0
- package/dist/core/web/public/next/assets/AppsSection-8wXPPhZb.js +2 -0
- package/dist/core/web/public/next/assets/AppsSection-8wXPPhZb.js.map +1 -0
- package/dist/core/web/public/next/assets/AreaTrend-BFimExYn.js +2 -0
- package/dist/core/web/public/next/assets/{AreaTrend-CDxrQU4b.js.map → AreaTrend-BFimExYn.js.map} +1 -1
- package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js +2 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-DmbE71vI.css +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-B46igJKR.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-DuQkHGD_.js.map → AutonomySection-B46igJKR.js.map} +1 -1
- package/dist/core/web/public/next/assets/BranchBar-BRkrEQGs.js +2 -0
- package/dist/core/web/public/next/assets/{BranchBar-CLsvOcyK.js.map → BranchBar-BRkrEQGs.js.map} +1 -1
- package/dist/core/web/public/next/assets/BudgetControl-T_RjPrw9.js +2 -0
- package/dist/core/web/public/next/assets/{BudgetControl-TL3FeZ1D.js.map → BudgetControl-T_RjPrw9.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Button-HHXgoXGr.js → Button-BhO-WKPp.js} +2 -2
- package/dist/core/web/public/next/assets/{Button-HHXgoXGr.js.map → Button-BhO-WKPp.js.map} +1 -1
- package/dist/core/web/public/next/assets/CapacityStrip-CkFz5vq2.js +2 -0
- package/dist/core/web/public/next/assets/{CapacityStrip-qReu0RaF.js.map → CapacityStrip-CkFz5vq2.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-SygZ7B3x.js +2 -0
- package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js +3 -0
- package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js.map +1 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-Bd91iStN.js +2 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-Bd91iStN.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js +2 -0
- package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +1 -0
- package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js +2 -0
- package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js.map +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-Bv4hdK2T.js +2 -0
- package/dist/core/web/public/next/assets/{ConfirmDialog-DLrLKM0c.js.map → ConfirmDialog-Bv4hdK2T.js.map} +1 -1
- package/dist/core/web/public/next/assets/DeleteChatDialog-CH1Ix8Eh.js +2 -0
- package/dist/core/web/public/next/assets/DeleteChatDialog-CH1Ix8Eh.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-BSsIFNqD.js +2 -0
- package/dist/core/web/public/next/assets/{Dialog-BS9Dxi3G.js.map → Dialog-BSsIFNqD.js.map} +1 -1
- package/dist/core/web/public/next/assets/DiffPane-BpNuJmth.js +2 -0
- package/dist/core/web/public/next/assets/{DiffPane-TOmUf3b2.js.map → DiffPane-BpNuJmth.js.map} +1 -1
- package/dist/core/web/public/next/assets/DiffViewer-CJarUvs0.js +2 -0
- package/dist/core/web/public/next/assets/{DiffViewer-BpH56302.js.map → DiffViewer-CJarUvs0.js.map} +1 -1
- package/dist/core/web/public/next/assets/DockHost-DW9q0NdR.js +2 -0
- package/dist/core/web/public/next/assets/DockHost-DW9q0NdR.js.map +1 -0
- package/dist/core/web/public/next/assets/{EmptyState-BqR5YAmf.js → EmptyState-DPrd2aak.js} +2 -2
- package/dist/core/web/public/next/assets/{EmptyState-BqR5YAmf.js.map → EmptyState-DPrd2aak.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Epistemic-dhvDTwAZ.js → Epistemic-D7MxSmED.js} +2 -2
- package/dist/core/web/public/next/assets/{Epistemic-dhvDTwAZ.js.map → Epistemic-D7MxSmED.js.map} +1 -1
- package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js +3 -0
- package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js.map +1 -0
- package/dist/core/web/public/next/assets/Funnel-BeNQZWv2.js +2 -0
- package/dist/core/web/public/next/assets/{Funnel-D2u7Wlzc.js.map → Funnel-BeNQZWv2.js.map} +1 -1
- package/dist/core/web/public/next/assets/GearTray-CIPtzeIx.js +2 -0
- package/dist/core/web/public/next/assets/{GearTray-Cb2npoxM.js.map → GearTray-CIPtzeIx.js.map} +1 -1
- package/dist/core/web/public/next/assets/GrowthSection-iiQg6wvK.js +2 -0
- package/dist/core/web/public/next/assets/{GrowthSection-C5aDPs8B.js.map → GrowthSection-iiQg6wvK.js.map} +1 -1
- package/dist/core/web/public/next/assets/HandoffDialog-DrQ6ofuy.js +2 -0
- package/dist/core/web/public/next/assets/{HandoffDialog-BF3AYg-X.js.map → HandoffDialog-DrQ6ofuy.js.map} +1 -1
- package/dist/core/web/public/next/assets/Input-C0MQxEM6.js +2 -0
- package/dist/core/web/public/next/assets/{Input-B5dmGLZx.js.map → Input-C0MQxEM6.js.map} +1 -1
- package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js +2 -0
- package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js.map +1 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-DZvZeWXL.js +2 -0
- package/dist/core/web/public/next/assets/{MatrixHeatmap-BgEUs2Eu.js.map → MatrixHeatmap-DZvZeWXL.js.map} +1 -1
- package/dist/core/web/public/next/assets/McpSection-BRuCcTjT.js +2 -0
- package/dist/core/web/public/next/assets/{McpSection-DZkiOuoq.js.map → McpSection-BRuCcTjT.js.map} +1 -1
- package/dist/core/web/public/next/assets/MessageMarkdown-bRvD5nSc.js +3 -0
- package/dist/core/web/public/next/assets/{MessageMarkdown-BauY8ZTY.js.map → MessageMarkdown-bRvD5nSc.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DLBNLfsn.js → MessageMarkdownRenderer-FjjkPKA2.js} +4 -4
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DLBNLfsn.js.map → MessageMarkdownRenderer-FjjkPKA2.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-DNeocJnD.js → Meter-CFNLpwA-.js} +2 -2
- package/dist/core/web/public/next/assets/{Meter-DNeocJnD.js.map → Meter-CFNLpwA-.js.map} +1 -1
- package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js +2 -0
- package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js.map +1 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-T7gv3a9r.js +2 -0
- package/dist/core/web/public/next/assets/{MutationTokenDialog-mxrw0Yvy.js.map → MutationTokenDialog-T7gv3a9r.js.map} +1 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-lYN4G_aM.js +2 -0
- package/dist/core/web/public/next/assets/{NeedsYouDrawer-CO-Balfp.js.map → NeedsYouDrawer-lYN4G_aM.js.map} +1 -1
- package/dist/core/web/public/next/assets/NeedsYouList-BgH8ezqf.js +2 -0
- package/dist/core/web/public/next/assets/{NeedsYouList-CzDZbzRD.js.map → NeedsYouList-BgH8ezqf.js.map} +1 -1
- package/dist/core/web/public/next/assets/NewChatDialog-Db5Xjrk8.js +3 -0
- package/dist/core/web/public/next/assets/NewChatDialog-Db5Xjrk8.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-HUNQGQuU.css +1 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js +2 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js.map +1 -0
- package/dist/core/web/public/next/assets/PreviewPane-BPBbcROb.js +2 -0
- package/dist/core/web/public/next/assets/{PreviewPane-BS-CleCd.js.map → PreviewPane-BPBbcROb.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ProviderLogo-C5mBg8i0.js → ProviderLogo-CT2cSfkg.js} +2 -2
- package/dist/core/web/public/next/assets/{ProviderLogo-C5mBg8i0.js.map → ProviderLogo-CT2cSfkg.js.map} +1 -1
- package/dist/core/web/public/next/assets/RailStatus-Vgl0GYtd.js +2 -0
- package/dist/core/web/public/next/assets/{RailStatus-cPRyOmrk.js.map → RailStatus-Vgl0GYtd.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RefreshIndicator-CMwSCiz5.js → RefreshIndicator-CSyqpY_q.js} +2 -2
- package/dist/core/web/public/next/assets/{RefreshIndicator-CMwSCiz5.js.map → RefreshIndicator-CSyqpY_q.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BFi1opsC.js → ResourcePoolConsoleApp-BX2nkdmZ.js} +4 -4
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BFi1opsC.js.map → ResourcePoolConsoleApp-BX2nkdmZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js +2 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-BaC7YVzR.js +2 -0
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-DYtwc2ja.js.map → RouteErrorBoundary-BaC7YVzR.js.map} +1 -1
- package/dist/core/web/public/next/assets/RunInCloudAction-D5PDHJPE.js +2 -0
- package/dist/core/web/public/next/assets/{RunInCloudAction-BEGEEM8O.js.map → RunInCloudAction-D5PDHJPE.js.map} +1 -1
- package/dist/core/web/public/next/assets/SeatSelector-Cg75LInq.js +3 -0
- package/dist/core/web/public/next/assets/{SeatSelector-CYHRR7Wp.js.map → SeatSelector-Cg75LInq.js.map} +1 -1
- package/dist/core/web/public/next/assets/Segmented-CametjLt.js +2 -0
- package/dist/core/web/public/next/assets/{Segmented-BE53BenI.js.map → Segmented-CametjLt.js.map} +1 -1
- package/dist/core/web/public/next/assets/Select-De52fghU.js +2 -0
- package/dist/core/web/public/next/assets/{Select-BwSGkHCS.js.map → Select-De52fghU.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionGate-CzlcNq3O.js +2 -0
- package/dist/core/web/public/next/assets/{SessionGate-e0dFJm9d.js.map → SessionGate-CzlcNq3O.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionInsightChip-Bk_Owa7u.js +2 -0
- package/dist/core/web/public/next/assets/{SessionInsightChip-CxlSyueJ.js.map → SessionInsightChip-Bk_Owa7u.js.map} +1 -1
- package/dist/core/web/public/next/assets/SessionSearch-C6C8DHN8.js +2 -0
- package/dist/core/web/public/next/assets/{SessionSearch-_yp7S2TP.js.map → SessionSearch-C6C8DHN8.js.map} +1 -1
- package/dist/core/web/public/next/assets/SettingsSection-mI9wQYZg.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-mI9wQYZg.js.map +1 -0
- package/dist/core/web/public/next/assets/Sheet-CJhK9Dqv.js +2 -0
- package/dist/core/web/public/next/assets/{Sheet-DVP2Mgy6.js.map → Sheet-CJhK9Dqv.js.map} +1 -1
- package/dist/core/web/public/next/assets/ShortcutsOverlay-DDW-i9Fc.js +2 -0
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-BcIcoClX.js.map → ShortcutsOverlay-DDW-i9Fc.js.map} +1 -1
- package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js +3 -0
- package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js.map +1 -0
- package/dist/core/web/public/next/assets/Slider-Bwd9HfXl.js +2 -0
- package/dist/core/web/public/next/assets/{Slider-BypUWjpH.js.map → Slider-Bwd9HfXl.js.map} +1 -1
- package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js +2 -0
- package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js.map +1 -0
- package/dist/core/web/public/next/assets/{StatusBadge-HCZp416_.js → StatusBadge-DHKRtttH.js} +2 -2
- package/dist/core/web/public/next/assets/{StatusBadge-HCZp416_.js.map → StatusBadge-DHKRtttH.js.map} +1 -1
- package/dist/core/web/public/next/assets/StepBand-DQykLkk_.js +2 -0
- package/dist/core/web/public/next/assets/{StepBand-Duz1PUes.js.map → StepBand-DQykLkk_.js.map} +1 -1
- package/dist/core/web/public/next/assets/Surface-D--LXgQm.js +2 -0
- package/dist/core/web/public/next/assets/Surface-D--LXgQm.js.map +1 -0
- package/dist/core/web/public/next/assets/Surface-e1z6GdZt.css +1 -0
- package/dist/core/web/public/next/assets/Swimlane-BzH6OCee.js +2 -0
- package/dist/core/web/public/next/assets/{Swimlane-DGcIcnNA.js.map → Swimlane-BzH6OCee.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Switch-iveI-8NY.js → Switch-PMixU6b0.js} +2 -2
- package/dist/core/web/public/next/assets/{Switch-iveI-8NY.js.map → Switch-PMixU6b0.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Tag-DH15CUJp.js → Tag-fordBsrJ.js} +2 -2
- package/dist/core/web/public/next/assets/{Tag-DH15CUJp.js.map → Tag-fordBsrJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/TerminalPane-BSnGdUuF.js +7 -0
- package/dist/core/web/public/next/assets/TerminalPane-BSnGdUuF.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-DtXFhAhw.js +2 -0
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-C8yQ0AaR.js.map → UniverseConsoleApp-DtXFhAhw.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-_nPURPqe.js → UniverseView-sWm3pnTW.js} +3 -3
- package/dist/core/web/public/next/assets/{UniverseView-_nPURPqe.js.map → UniverseView-sWm3pnTW.js.map} +1 -1
- package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js +3 -0
- package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-BQSZFSeO.js +10 -0
- package/dist/core/web/public/next/assets/Workspace-BQSZFSeO.js.map +1 -0
- package/dist/core/web/public/next/assets/actions-BmIf9avl.css +1 -0
- package/dist/core/web/public/next/assets/actions-Ci6I4C0l.js +2 -0
- package/dist/core/web/public/next/assets/actions-Ci6I4C0l.js.map +1 -0
- package/dist/core/web/public/next/assets/apps-model-DlwnfqwJ.js +2 -0
- package/dist/core/web/public/next/assets/apps-model-DlwnfqwJ.js.map +1 -0
- package/dist/core/web/public/next/assets/authority-model-BFuPezSo.js +2 -0
- package/dist/core/web/public/next/assets/authority-model-BFuPezSo.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-DsAjH8ac.js} +2 -2
- package/dist/core/web/public/next/assets/{budget-queries-V3wcJVK_.js.map → budget-queries-DsAjH8ac.js.map} +1 -1
- package/dist/core/web/public/next/assets/capacity-strip-model-Dn1cNOhz.js +2 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-Dn1cNOhz.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-C_xJbJiw.js +2 -0
- package/dist/core/web/public/next/assets/charts-C_xJbJiw.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-CX407gPY.js +2 -0
- package/dist/core/web/public/next/assets/cloud-model-CX407gPY.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-queries-QAhpExlz.js +2 -0
- package/dist/core/web/public/next/assets/cloud-queries-QAhpExlz.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-CF0cQQac.js +2 -0
- package/dist/core/web/public/next/assets/command-catalog-CF0cQQac.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-Co4wh3SM.js +2 -0
- package/dist/core/web/public/next/assets/context-model-Co4wh3SM.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-DV1zCfAm.js +3 -0
- package/dist/core/web/public/next/assets/context-model-DV1zCfAm.js.map +1 -0
- package/dist/core/web/public/next/assets/{context-queries-CrPcHWTz.js → context-queries-CktFQqSS.js} +2 -2
- package/dist/core/web/public/next/assets/{context-queries-CrPcHWTz.js.map → context-queries-CktFQqSS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{control-queries-CmgBgKV7.js → control-queries-DAvlh_YM.js} +2 -2
- package/dist/core/web/public/next/assets/{control-queries-CmgBgKV7.js.map → control-queries-DAvlh_YM.js.map} +1 -1
- package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js +2 -0
- package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-icons-BFuBbqJl.js +2 -0
- package/dist/core/web/public/next/assets/{dock-icons-CUh8dOxJ.js.map → dock-icons-BFuBbqJl.js.map} +1 -1
- package/dist/core/web/public/next/assets/fleet-model-Dfd5JyLR.js +2 -0
- package/dist/core/web/public/next/assets/fleet-model-Dfd5JyLR.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-queries-RtMTd5rR.js +2 -0
- package/dist/core/web/public/next/assets/fleet-queries-RtMTd5rR.js.map +1 -0
- package/dist/core/web/public/next/assets/{focus-trap-HtcoXeEq.js → focus-trap-BdrbWfC4.js} +2 -2
- package/dist/core/web/public/next/assets/{focus-trap-HtcoXeEq.js.map → focus-trap-BdrbWfC4.js.map} +1 -1
- package/dist/core/web/public/next/assets/format-Dk4Fmxax.js +2 -0
- package/dist/core/web/public/next/assets/format-Dk4Fmxax.js.map +1 -0
- package/dist/core/web/public/next/assets/{git-model-bk_RXh3y.js → git-model-_BnI_Ogh.js} +2 -2
- package/dist/core/web/public/next/assets/{git-model-bk_RXh3y.js.map → git-model-_BnI_Ogh.js.map} +1 -1
- package/dist/core/web/public/next/assets/global-CNNGMril.js +2 -0
- package/dist/core/web/public/next/assets/{global-oEl9Qj8u.js.map → global-CNNGMril.js.map} +1 -1
- package/dist/core/web/public/next/assets/{guarded-runners-LHLXmXIk.js → guarded-runners-DPh2d32e.js} +2 -2
- package/dist/core/web/public/next/assets/{guarded-runners-LHLXmXIk.js.map → guarded-runners-DPh2d32e.js.map} +1 -1
- package/dist/core/web/public/next/assets/icons-0haWy6nh.js +2 -0
- package/dist/core/web/public/next/assets/icons-0haWy6nh.js.map +1 -0
- package/dist/core/web/public/next/assets/{index-BVxOlseC.js → index-QesfXBsb.js} +3 -3
- package/dist/core/web/public/next/assets/{index-BVxOlseC.js.map → index-QesfXBsb.js.map} +1 -1
- package/dist/core/web/public/next/assets/live-model-De-q0ZFK.js +2 -0
- package/dist/core/web/public/next/assets/live-model-De-q0ZFK.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-BrK2nFOL.js +2 -0
- package/dist/core/web/public/next/assets/{mind.module-gTGAuJt1.js.map → mind.module-BrK2nFOL.js.map} +1 -1
- package/dist/core/web/public/next/assets/mutations-DTCtKCn_.js +2 -0
- package/dist/core/web/public/next/assets/{mutations-C5S7okTW.js.map → mutations-DTCtKCn_.js.map} +1 -1
- package/dist/core/web/public/next/assets/nav-KmGX0CVz.js +2 -0
- package/dist/core/web/public/next/assets/{nav-NVtnuG7A.js.map → nav-KmGX0CVz.js.map} +1 -1
- package/dist/core/web/public/next/assets/{overnight-queries-DGm3qL1b.js → overnight-queries-mlO0xzsr.js} +2 -2
- package/dist/core/web/public/next/assets/{overnight-queries-DGm3qL1b.js.map → overnight-queries-mlO0xzsr.js.map} +1 -1
- package/dist/core/web/public/next/assets/primitives-D0Fb3TtS.js +1 -0
- package/dist/core/web/public/next/assets/{queries-CYisSAAB.js → queries-CyBE8nsW.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-CYisSAAB.js.map → queries-CyBE8nsW.js.map} +1 -1
- package/dist/core/web/public/next/assets/reasoning-pref-CaoA4_Vl.js +2 -0
- package/dist/core/web/public/next/assets/{reasoning-pref-BUcFF_5G.js.map → reasoning-pref-CaoA4_Vl.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reveal-anchor-D-tV8xau.js → reveal-anchor-BP1VqnPU.js} +2 -2
- package/dist/core/web/public/next/assets/{reveal-anchor-D-tV8xau.js.map → reveal-anchor-BP1VqnPU.js.map} +1 -1
- package/dist/core/web/public/next/assets/seat-subscription-C5Tvr0WQ.js +2 -0
- package/dist/core/web/public/next/assets/{seat-subscription-B-f9ViU2.js.map → seat-subscription-C5Tvr0WQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{sidebar-model-DQ-FyBHW.js → sidebar-model-B5Qk95k_.js} +2 -2
- package/dist/core/web/public/next/assets/{sidebar-model-DQ-FyBHW.js.map → sidebar-model-B5Qk95k_.js.map} +1 -1
- package/dist/core/web/public/next/assets/slots-DHKQDoE6.js +3 -0
- package/dist/core/web/public/next/assets/{slots-BhP8b8tf.js.map → slots-DHKQDoE6.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-data-CchClvHo.js +2 -0
- package/dist/core/web/public/next/assets/surface-data-CchClvHo.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js +2 -0
- package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js.map +1 -0
- package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js → tasks-model-D6WFVULI.js} +2 -2
- package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js.map → tasks-model-D6WFVULI.js.map} +1 -1
- package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js → terminal-icons-BvCvuXk2.js} +2 -2
- package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js.map → terminal-icons-BvCvuXk2.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-D1SU1t7r.js} +2 -2
- package/dist/core/web/public/next/assets/{usage-queries-BZuAANlI.js.map → usage-queries-D1SU1t7r.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-guarded-action-Cf4MeNBa.js → use-guarded-action-BZmBv7CJ.js} +2 -2
- package/dist/core/web/public/next/assets/{use-guarded-action-Cf4MeNBa.js.map → use-guarded-action-BZmBv7CJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js → use-ticker-CkJ4-0wU.js} +2 -2
- package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js.map → use-ticker-CkJ4-0wU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-token-gate-DqrSXdX6.js → use-token-gate-CYcfk_GS.js} +2 -2
- package/dist/core/web/public/next/assets/{use-token-gate-DqrSXdX6.js.map → use-token-gate-CYcfk_GS.js.map} +1 -1
- package/dist/core/web/public/next/assets/useOnboarding-CujRS6PK.js +2 -0
- package/dist/core/web/public/next/assets/useOnboarding-CujRS6PK.js.map +1 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-BEaQdkZs.js +2 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-BEaQdkZs.js.map +1 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-BQ0J6Xhx.js +2 -0
- package/dist/core/web/public/next/assets/{useVerseTranscript-CDYrrWOO.js.map → useVerseTranscript-BQ0J6Xhx.js.map} +1 -1
- package/dist/core/web/public/next/assets/verse-icons-DndgEgKS.js +2 -0
- package/dist/core/web/public/next/assets/verse-icons-DndgEgKS.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-model-MMySehjj.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-MMySehjj.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-CNEH_-be.js +3 -0
- package/dist/core/web/public/next/assets/{warmup-HG5vYbsN.js.map → warmup-CNEH_-be.js.map} +1 -1
- package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js +2 -0
- package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js.map +1 -0
- package/dist/core/web/public/next/assets/{workspace-model-CbhdPhei.js → workspace-model-Dukb2wwv.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-CbhdPhei.js.map → workspace-model-Dukb2wwv.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
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{B as e}from"./global-CNNGMril.js";import{p as t}from"./queries-CyBE8nsW.js";import{E as n,S as r,T as i}from"./VerseConsoleApp-BCY5uSok.js";import{n as a,t as o}from"./budget-queries-DsAjH8ac.js";import{r as s}from"./cloud-queries-QAhpExlz.js";import{r as c}from"./overnight-queries-mlO0xzsr.js";import{a as l,d as u,i as d,n as f,o as p,r as m}from"./surface-data-CchClvHo.js";var h={command:[f,d,l,p,m,a,s],fleet:[d,f,c,a,o],growth:[m,p,t(`30d`),f,d],mind:[l,u,r,n,f,d],chat:[r,i,n]},g=6e4;async function _(t,n={}){let r=n.ensure??e;for(let e of h[t]??[])try{if(n.beforeEach&&!await n.beforeEach())return;await r(e.key,()=>e.fetch(),g)}catch{}}export{g as PREFETCH_FRESH_MS,h as SURFACE_PREFETCH,_ as prefetchSurfaceData};
|
|
2
|
+
//# sourceMappingURL=surface-prefetch-BWr0LBQn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-prefetch-BWr0LBQn.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/surface-prefetch.ts"],"sourcesContent":["/**\n * routes/verse/shell/surface-prefetch.ts — the reads each rail surface opens\n * with, so the shell can warm them while the operator is still reading chat\n * (shell/warmup.ts, once the operator is idle after first paint). A first\n * visit to Command, Fleet, Growth or Mind then paints from the cache instead\n * of a skeleton; the surface's own useQuery still refreshes whatever is older\n * than it accepts.\n *\n * LAZY ONLY. shell/warmup.ts loads this module with import(): these query\n * defs pull in the surfaces' data modules, none of which may cost chat\n * first-paint bytes (VerseApp.first-paint.test.ts pins it). The QueryDefs\n * themselves are the surfaces' own — same keys, same fetchers — so a warmed\n * entry IS the entry the surface reads.\n *\n * Keep each list in step with its surface's useQuery calls:\n * surface-prefetch.test.ts renders Command, Growth and Mind and fails when\n * they read something this table does not warm.\n */\nimport { ensureQuery } from '../../../data/cache.js';\nimport { modelsQuery, type QueryDef } from '../../../data/queries.js';\nimport { overnightQuery } from '../autonomy/overnight-queries.js';\nimport { budgetPreviewQuery, budgetQuery } from '../budget/budget-queries.js';\nimport { cloudQuery } from '../cloud/cloud-queries.js';\nimport {\n authorityQuery,\n fleetHistoryQuery,\n fleetLiveQuery,\n leaderQuery,\n learningQuery,\n reasoningDigestQuery,\n} from '../command/surface-data.js';\nimport { verseBootstrapQuery, verseSessionsQuery, verseWorkspacesQuery } from '../verse-queries.js';\nimport type { VerseSectionId } from '../verse-ui-store.js';\n\ntype AnyQuery = QueryDef<unknown>;\n\n/** What each rail surface reads the moment it mounts. */\nexport const SURFACE_PREFETCH: Readonly<Partial<Record<VerseSectionId, readonly AnyQuery[]>>> = {\n // No seat history: the burn-downs that drew it moved to Usage (audit 14);\n // Command's seat strip reads the budget and the rail's warm seat caches.\n // cloudQuery (3.11): the Cloud card's overview — without it a first visit\n // paints \"Reading the cloud lane…\" under the seat strip.\n command: [authorityQuery, fleetLiveQuery, leaderQuery, learningQuery, fleetHistoryQuery, budgetQuery, cloudQuery],\n // authorityQuery + fleetLiveQuery on Fleet, Growth and Mind: the shared\n // \"Autonomy is off\" state (autonomy/AutonomyOffState) reads both.\n fleet: [fleetLiveQuery, authorityQuery, overnightQuery, budgetQuery, budgetPreviewQuery],\n growth: [fleetHistoryQuery, learningQuery, modelsQuery('30d'), authorityQuery, fleetLiveQuery],\n mind: [leaderQuery, reasoningDigestQuery, verseBootstrapQuery, verseWorkspacesQuery, authorityQuery, fleetLiveQuery],\n chat: [verseBootstrapQuery, verseSessionsQuery, verseWorkspacesQuery],\n};\n\n/**\n * A cached answer younger than this is left alone. The surfaces accept 10–60 s\n * old data on mount, so anything fresher than a minute is already as good as\n * a warm-up can make it.\n */\nexport const PREFETCH_FRESH_MS = 60_000;\n\ntype Ensure = (key: string, fetcher: () => Promise<unknown>, maxAgeMs: number) => Promise<void>;\n\nexport interface PrefetchOptions {\n /** The cache's mount path (a seam for tests). */\n ensure?: Ensure;\n /**\n * Awaited before EACH read (the warm-up's idle gate). Resolving false stops\n * the warm-up there — the gate was cancelled.\n */\n beforeEach?: () => Promise<boolean> | boolean;\n}\n\n/**\n * Warm one surface's reads through the shared cache (joins an in-flight read,\n * skips a fresh one, and goes through the cache's concurrency gate).\n *\n * ONE AT A TIME: each read is awaited before the next is even considered, so\n * the warm-up never holds more than one of the gate's slots, and the operator\n * (who gets the other three, and whose reads the next `beforeEach` waits out)\n * is never queued behind a burst of it.\n *\n * Never rejects: a read that fails leaves the surface to load it as it always did.\n */\nexport async function prefetchSurfaceData(id: VerseSectionId, options: PrefetchOptions = {}): Promise<void> {\n const ensure = options.ensure ?? ensureQuery;\n for (const def of SURFACE_PREFETCH[id] ?? []) {\n try {\n if (options.beforeEach && !(await options.beforeEach())) return;\n await ensure(def.key, () => def.fetch(), PREFETCH_FRESH_MS);\n } catch {\n // A warm-up read that fails (or cannot even start) is not worth surfacing.\n }\n }\n}\n"],"mappings":"iYAqCA,IAAa,EAAmF,CAK9F,QAAS,CAAC,EAAgB,EAAgB,EAAa,EAAe,EAAmB,EAAa,CAAU,EAGhH,MAAO,CAAC,EAAgB,EAAgB,EAAgB,EAAa,CAAkB,EACvF,OAAQ,CAAC,EAAmB,EAAe,EAAY,KAAK,EAAG,EAAgB,CAAc,EAC7F,KAAM,CAAC,EAAa,EAAsB,EAAqB,EAAsB,EAAgB,CAAc,EACnH,KAAM,CAAC,EAAqB,EAAoB,CAAoB,CACtE,EAOa,EAAoB,IAyBjC,eAAsB,EAAoB,EAAoB,EAA2B,CAAC,EAAkB,CAC1G,IAAM,EAAS,EAAQ,QAAU,EACjC,IAAK,IAAM,KAAO,EAAiB,IAAO,CAAC,EACzC,GAAI,CACF,GAAI,EAAQ,YAAc,CAAE,MAAM,EAAQ,WAAW,EAAI,OACzD,MAAM,EAAO,EAAI,QAAW,EAAI,MAAM,EAAG,CAAiB,CAC5D,MAAQ,CAER,CAEJ"}
|
package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js → tasks-model-D6WFVULI.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
//# sourceMappingURL=tasks-model-
|
|
1
|
+
import{w as e}from"./verse-model-MMySehjj.js";import{n as t}from"./tool-semantics-GX8ScuSH.js";import{i as n}from"./sidebar-model-B5Qk95k_.js";function r(n){let r=0;for(let e=n.length-1;e>=0;--e)if(n[e].kind===`user`){r=e;break}let i=[],a=[];for(let o=r;o<n.length;o+=1){let r=n[o];if(r.kind!==`tool`)continue;let s={toolUseId:r.toolUseId,kind:t(r.name)===`task`?`subagent`:`tool`,name:r.name,detail:e(r.input)||r.name,startedAt:r.at,status:r.result===null?`running`:r.result.isError?`failed`:`done`,durationMs:r.durationMs};(s.status===`running`?i:a).push(s)}return[...i,...a.reverse()]}function i(e,t,r){let i=new Map;for(let e of t?.running??[])e.sessionId!==r&&i.set(e.sessionId,{sessionId:e.sessionId,title:e.title,engine:e.engine,startedAt:e.startedAt,live:n(e.live)});for(let t of e)t.id===r||t.status!==`running`||i.has(t.id)||i.set(t.id,{sessionId:t.id,title:t.title,engine:t.engine,startedAt:null,live:null});return[...i.values()]}function a(e,t){let n=e.filter(e=>e.status===`running`);return{turn:n.length,subagents:n.filter(e=>e.kind===`subagent`).length,chats:t.length,total:n.length+t.length}}function o(e){let t=`${e.total} running task${e.total===1?``:`s`}`,n=[];return e.turn>0&&n.push(`${e.turn} in this chat`),e.chats>0&&n.push(`${e.chats} other chat${e.chats===1?``:`s`}`),n.length>0?`${t}: ${n.join(`, `)}`:t}export{a as countTasks,r as currentTurnTasks,o as describeTaskCounts,i as otherRunningChats};
|
|
2
|
+
//# sourceMappingURL=tasks-model-D6WFVULI.js.map
|
package/dist/core/web/public/next/assets/{tasks-model-BKDNqmmt.js.map → tasks-model-D6WFVULI.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-model-
|
|
1
|
+
{"version":3,"file":"tasks-model-D6WFVULI.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/chat/tasks-model.ts"],"sourcesContent":["/**\n * routes/verse/chat/tasks-model.ts — what is running right now, for the\n * \"◌ 3 running tasks\" chip and the dock's Tasks pane (SPEC-310C §2–§3, C2).\n *\n * Two kinds of task, because the operator is waiting on both:\n * - THIS TURN: the open chat's tool calls and subagents since its last ask\n * (a running `Task` is a subagent; everything else is a tool);\n * - OTHER CHATS: every other chat with a turn in flight, from activity\n * (C1) when it answers, else from the session list's `status`.\n *\n * Pure over transcript items and the session / activity lists.\n */\nimport type { VerseEngine, VerseSession } from '../../../data/api-types.js';\nimport type { VerseActivityResponse } from '../../../../core/verse/workbench-types.js';\nimport type { TranscriptItem } from '../verse-store.js';\nimport { summarizeToolInput } from '../verse-model.js';\nimport { liveLine } from './sidebar-model.js';\nimport { actionForName } from './tool-semantics.js';\n\nexport type TurnTaskStatus = 'running' | 'done' | 'failed';\n\nexport interface TurnTask {\n toolUseId: string;\n kind: 'subagent' | 'tool';\n /** Tool name as the CLI spelled it. */\n name: string;\n /** What it is doing: the command, the path, the subagent's description. */\n detail: string;\n /** ISO time the call started. */\n startedAt: string;\n status: TurnTaskStatus;\n durationMs: number | null;\n}\n\nexport interface ChatTask {\n sessionId: string;\n title: string;\n engine: VerseEngine;\n /** ISO start of the running turn when activity knows it; null = unknown. */\n startedAt: string | null;\n /** The muted \"what it is doing\" line; null when unknown. */\n live: string | null;\n}\n\n/** The last turn's tool calls, running first (in start order), then finished (newest first). */\nexport function currentTurnTasks(items: readonly TranscriptItem[]): TurnTask[] {\n let start = 0;\n for (let i = items.length - 1; i >= 0; i -= 1) {\n if (items[i]!.kind === 'user') {\n start = i;\n break;\n }\n }\n const running: TurnTask[] = [];\n const finished: TurnTask[] = [];\n for (let i = start; i < items.length; i += 1) {\n const item = items[i]!;\n if (item.kind !== 'tool') continue;\n const task: TurnTask = {\n toolUseId: item.toolUseId,\n kind: actionForName(item.name) === 'task' ? 'subagent' : 'tool',\n name: item.name,\n detail: summarizeToolInput(item.input) || item.name,\n startedAt: item.at,\n status: item.result === null ? 'running' : item.result.isError ? 'failed' : 'done',\n durationMs: item.durationMs,\n };\n (task.status === 'running' ? running : finished).push(task);\n }\n return [...running, ...finished.reverse()];\n}\n\nexport function otherRunningChats(\n sessions: readonly VerseSession[],\n activity: VerseActivityResponse | null,\n currentId: string | null,\n): ChatTask[] {\n const out = new Map<string, ChatTask>();\n for (const row of activity?.running ?? []) {\n if (row.sessionId === currentId) continue;\n out.set(row.sessionId, {\n sessionId: row.sessionId,\n title: row.title,\n engine: row.engine,\n startedAt: row.startedAt,\n live: liveLine(row.live),\n });\n }\n // The session list can know about a run activity has not reported (a\n // server without C1's route, or the few seconds between polls).\n for (const session of sessions) {\n if (session.id === currentId || session.status !== 'running' || out.has(session.id)) continue;\n out.set(session.id, { sessionId: session.id, title: session.title, engine: session.engine, startedAt: null, live: null });\n }\n return [...out.values()];\n}\n\nexport interface TaskCounts {\n /** Running calls in this turn. */\n turn: number;\n /** Of which subagents. */\n subagents: number;\n /** Other chats running. */\n chats: number;\n total: number;\n}\n\nexport function countTasks(turn: readonly TurnTask[], chats: readonly ChatTask[]): TaskCounts {\n const running = turn.filter((t) => t.status === 'running');\n return {\n turn: running.length,\n subagents: running.filter((t) => t.kind === 'subagent').length,\n chats: chats.length,\n total: running.length + chats.length,\n };\n}\n\n/** \"3 running tasks\" — and what they are, for the chip's accessible name. */\nexport function describeTaskCounts(counts: TaskCounts): string {\n const head = `${counts.total} running task${counts.total === 1 ? '' : 's'}`;\n const parts: string[] = [];\n if (counts.turn > 0) parts.push(`${counts.turn} in this chat`);\n if (counts.chats > 0) parts.push(`${counts.chats} other chat${counts.chats === 1 ? '' : 's'}`);\n return parts.length > 0 ? `${head}: ${parts.join(', ')}` : head;\n}\n"],"mappings":"+IA6CA,SAAgB,EAAiB,EAA8C,CAC7E,IAAI,EAAQ,EACZ,IAAK,IAAI,EAAI,EAAM,OAAS,EAAG,GAAK,EAAG,IACrC,GAAI,EAAM,EAAE,CAAE,OAAS,OAAQ,CAC7B,EAAQ,EACR,KACF,CAEF,IAAM,EAAsB,CAAC,EACvB,EAAuB,CAAC,EAC9B,IAAK,IAAI,EAAI,EAAO,EAAI,EAAM,OAAQ,GAAK,EAAG,CAC5C,IAAM,EAAO,EAAM,GACnB,GAAI,EAAK,OAAS,OAAQ,SAC1B,IAAM,EAAiB,CACrB,UAAW,EAAK,UAChB,KAAM,EAAc,EAAK,IAAI,IAAM,OAAS,WAAa,OACzD,KAAM,EAAK,KACX,OAAQ,EAAmB,EAAK,KAAK,GAAK,EAAK,KAC/C,UAAW,EAAK,GAChB,OAAQ,EAAK,SAAW,KAAO,UAAY,EAAK,OAAO,QAAU,SAAW,OAC5E,WAAY,EAAK,UACnB,GACC,EAAK,SAAW,UAAY,EAAU,EAAA,CAAU,KAAK,CAAI,CAC5D,CACA,MAAO,CAAC,GAAG,EAAS,GAAG,EAAS,QAAQ,CAAC,CAC3C,CAEA,SAAgB,EACd,EACA,EACA,EACY,CACZ,IAAM,EAAM,IAAI,IAChB,IAAK,IAAM,KAAO,GAAU,SAAW,CAAC,EAClC,EAAI,YAAc,GACtB,EAAI,IAAI,EAAI,UAAW,CACrB,UAAW,EAAI,UACf,MAAO,EAAI,MACX,OAAQ,EAAI,OACZ,UAAW,EAAI,UACf,KAAM,EAAS,EAAI,IAAI,CACzB,CAAC,EAIH,IAAK,IAAM,KAAW,EAChB,EAAQ,KAAO,GAAa,EAAQ,SAAW,WAAa,EAAI,IAAI,EAAQ,EAAE,GAClF,EAAI,IAAI,EAAQ,GAAI,CAAE,UAAW,EAAQ,GAAI,MAAO,EAAQ,MAAO,OAAQ,EAAQ,OAAQ,UAAW,KAAM,KAAM,IAAK,CAAC,EAE1H,MAAO,CAAC,GAAG,EAAI,OAAO,CAAC,CACzB,CAYA,SAAgB,EAAW,EAA2B,EAAwC,CAC5F,IAAM,EAAU,EAAK,OAAQ,GAAM,EAAE,SAAW,SAAS,EACzD,MAAO,CACL,KAAM,EAAQ,OACd,UAAW,EAAQ,OAAQ,GAAM,EAAE,OAAS,UAAU,CAAC,CAAC,OACxD,MAAO,EAAM,OACb,MAAO,EAAQ,OAAS,EAAM,MAChC,CACF,CAGA,SAAgB,EAAmB,EAA4B,CAC7D,IAAM,EAAO,GAAG,EAAO,MAAM,eAAe,EAAO,QAAU,EAAI,GAAK,MAChE,EAAkB,CAAC,EAGzB,OAFI,EAAO,KAAO,GAAG,EAAM,KAAK,GAAG,EAAO,KAAK,cAAc,EACzD,EAAO,MAAQ,GAAG,EAAM,KAAK,GAAG,EAAO,MAAM,aAAa,EAAO,QAAU,EAAI,GAAK,KAAK,EACtF,EAAM,OAAS,EAAI,GAAG,EAAK,IAAI,EAAM,KAAK,IAAI,IAAM,CAC7D"}
|
package/dist/core/web/public/next/assets/{terminal-icons-D2xe-aM1.js → terminal-icons-BvCvuXk2.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e}from"./index-
|
|
2
|
-
//# sourceMappingURL=terminal-icons-
|
|
1
|
+
import{n as e}from"./index-QesfXBsb.js";var t=e();function n({size:e=16,children:n,...r}){return(0,t.jsx)(`svg`,{width:e,height:e,viewBox:`0 0 16 16`,fill:`none`,stroke:`currentColor`,strokeWidth:1.5,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,focusable:`false`,...r,children:n})}function r(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`1.75`,y:`2.75`,width:`12.5`,height:`10.5`,rx:`1.5`}),(0,t.jsx)(`path`,{d:`m4.5 6.25 2 1.75-2 1.75M8.25 10h3`})]})}function i(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`1.75`,y:`2.75`,width:`12.5`,height:`10.5`,rx:`1.5`}),(0,t.jsx)(`path`,{d:`M1.75 5.75h12.5M4 4.25h.01M5.75 4.25h.01`})]})}function a(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`m4.5 6.5 3.5 3.5 3.5-3.5`})})}function o(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M2.5 6v4h2.5l3.5 3V3L5 6H2.5Z`}),(0,t.jsx)(`path`,{d:`M11 5.5a3.5 3.5 0 0 1 0 5M12.75 3.75a6 6 0 0 1 0 8.5`})]})}function s(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M13 8H3.5M7.5 4 3.5 8l4 4`})})}function c(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M3 8h9.5M8.5 4l4 4-4 4`})})}function l(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M13 8a5 5 0 1 1-1.46-3.54`}),(0,t.jsx)(`path`,{d:`M13 2.75v2.5h-2.5`})]})}function u(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`1.75`,y:`2.75`,width:`12.5`,height:`8.5`,rx:`1.25`}),(0,t.jsx)(`path`,{d:`M6 13.75h4M8 11.25v2.5`})]})}function d(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`4.75`,y:`1.75`,width:`6.5`,height:`12.5`,rx:`1.5`}),(0,t.jsx)(`path`,{d:`M7.25 12h1.5`})]})}function f(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M5 3.5v9l7-4.5-7-4.5Z`})})}function p(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M9 1.75H4.25a1 1 0 0 0-1 1v10.5a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1V5.5L9 1.75Z`}),(0,t.jsx)(`path`,{d:`M9 1.75V5.5h3.75`})]})}function m(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`2.25`,y:`2.25`,width:`11.5`,height:`4.5`,rx:`1`}),(0,t.jsx)(`rect`,{x:`2.25`,y:`9.25`,width:`11.5`,height:`4.5`,rx:`1`}),(0,t.jsx)(`path`,{d:`M4.75 4.5h.01M4.75 11.5h.01`})]})}export{p as a,i as c,m as d,r as f,u as i,l,c as n,d as o,a as r,f as s,s as t,o as u};
|
|
2
|
+
//# sourceMappingURL=terminal-icons-BvCvuXk2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-icons-
|
|
1
|
+
{"version":3,"file":"terminal-icons-BvCvuXk2.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/dock/terminal/terminal-icons.tsx"],"sourcesContent":["/**\n * dock/terminal/terminal-icons.tsx — the Terminal / Preview panes' own 16px\n * glyphs (unit C4). Same grammar as components/primitives/icons.tsx (16-unit\n * box, 1.5 stroke, round caps, currentColor, decorative) so they sit beside\n * the shared set; kept here because the shared set is not this unit's file.\n */\nimport type { ReactNode, SVGProps } from 'react';\n\nexport interface GlyphProps extends Omit<SVGProps<SVGSVGElement>, 'children' | 'viewBox'> {\n size?: number;\n}\n\nfunction Glyph({ size = 16, children, ...rest }: GlyphProps & { children: ReactNode }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5}\n strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\" focusable=\"false\" {...rest}>\n {children}\n </svg>\n );\n}\n\nexport function TerminalGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"1.75\" y=\"2.75\" width=\"12.5\" height=\"10.5\" rx=\"1.5\" /><path d=\"m4.5 6.25 2 1.75-2 1.75M8.25 10h3\" /></Glyph>;\n}\n\nexport function PreviewGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"1.75\" y=\"2.75\" width=\"12.5\" height=\"10.5\" rx=\"1.5\" /><path d=\"M1.75 5.75h12.5M4 4.25h.01M5.75 4.25h.01\" /></Glyph>;\n}\n\nexport function ChevronDownGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"m4.5 6.5 3.5 3.5 3.5-3.5\" /></Glyph>;\n}\n\n/** Screen-reader mode: a speaker with sound lines. */\nexport function ScreenReaderGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M2.5 6v4h2.5l3.5 3V3L5 6H2.5Z\" /><path d=\"M11 5.5a3.5 3.5 0 0 1 0 5M12.75 3.75a6 6 0 0 1 0 8.5\" /></Glyph>;\n}\n\nexport function ArrowLeftGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M13 8H3.5M7.5 4 3.5 8l4 4\" /></Glyph>;\n}\n\nexport function ArrowRightGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M3 8h9.5M8.5 4l4 4-4 4\" /></Glyph>;\n}\n\nexport function ReloadGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M13 8a5 5 0 1 1-1.46-3.54\" /><path d=\"M13 2.75v2.5h-2.5\" /></Glyph>;\n}\n\nexport function DesktopGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"1.75\" y=\"2.75\" width=\"12.5\" height=\"8.5\" rx=\"1.25\" /><path d=\"M6 13.75h4M8 11.25v2.5\" /></Glyph>;\n}\n\nexport function PhoneGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"4.75\" y=\"1.75\" width=\"6.5\" height=\"12.5\" rx=\"1.5\" /><path d=\"M7.25 12h1.5\" /></Glyph>;\n}\n\nexport function PlayGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M5 3.5v9l7-4.5-7-4.5Z\" /></Glyph>;\n}\n\nexport function FileGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M9 1.75H4.25a1 1 0 0 0-1 1v10.5a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1V5.5L9 1.75Z\" /><path d=\"M9 1.75V5.5h3.75\" /></Glyph>;\n}\n\nexport function ServerGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"2.25\" y=\"2.25\" width=\"11.5\" height=\"4.5\" rx=\"1\" /><rect x=\"2.25\" y=\"9.25\" width=\"11.5\" height=\"4.5\" rx=\"1\" /><path d=\"M4.75 4.5h.01M4.75 11.5h.01\" /></Glyph>;\n}\n"],"mappings":"kDAYA,SAAS,EAAM,CAAE,OAAO,GAAI,WAAU,GAAG,GAA8C,CACrF,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,EAAM,OAAQ,EAAM,QAAQ,YAAY,KAAK,OAAO,OAAO,eAAe,YAAa,IACjG,cAAc,QAAQ,eAAe,QAAQ,cAAY,OAAO,UAAU,QAAQ,GAAI,EACrF,UACE,CAAA,CAET,CAEA,SAAgB,EAAc,EAAe,CAC3C,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,OAAO,EAAE,OAAO,MAAM,OAAO,OAAO,OAAO,GAAG,KAAO,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,mCAAqC,CAAA,CAAQ,GAC1I,CAEA,SAAgB,EAAa,EAAe,CAC1C,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,OAAO,EAAE,OAAO,MAAM,OAAO,OAAO,OAAO,GAAG,KAAO,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,0CAA4C,CAAA,CAAQ,GACjJ,CAEA,SAAgB,EAAiB,EAAe,CAC9C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,GAAI,EAAG,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,0BAA4B,CAAA,CAAQ,CAAA,CACnE,CAGA,SAAgB,EAAkB,EAAe,CAC/C,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,+BAAiC,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,sDAAwD,CAAA,CAAQ,GACzI,CAEA,SAAgB,EAAe,EAAe,CAC5C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,GAAI,EAAG,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,2BAA6B,CAAA,CAAQ,CAAA,CACpE,CAEA,SAAgB,EAAgB,EAAe,CAC7C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,GAAI,EAAG,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,wBAA0B,CAAA,CAAQ,CAAA,CACjE,CAEA,SAAgB,EAAY,EAAe,CACzC,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,2BAA6B,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,mBAAqB,CAAA,CAAQ,GAClG,CAEA,SAAgB,EAAa,EAAe,CAC1C,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,OAAO,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,GAAG,MAAQ,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,wBAA0B,CAAA,CAAQ,GAC/H,CAEA,SAAgB,EAAW,EAAe,CACxC,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,OAAO,EAAE,OAAO,MAAM,MAAM,OAAO,OAAO,GAAG,KAAO,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,cAAgB,CAAA,CAAQ,GACpH,CAEA,SAAgB,EAAU,EAAe,CACvC,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,GAAI,EAAG,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,uBAAyB,CAAA,CAAQ,CAAA,CAChE,CAEA,SAAgB,EAAU,EAAe,CACvC,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,6EAA+E,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,kBAAoB,CAAA,CAAQ,GACnJ,CAEA,SAAgB,EAAY,EAAe,CACzC,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,GAAI,EAAX,SAAA,EAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,OAAO,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,GAAG,GAAK,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,OAAO,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,GAAG,GAAK,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,6BAA+B,CAAA,CAAQ,GAC5L"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transient-events-nTLhMBND.js","names":[],"sources":["../../../../../../src/core/verse/transient-events.ts"],"sourcesContent":["/**\n * core/verse/transient-events.ts — V3.10 event types that are NEVER\n * persisted, emitted to live SSE listeners only. Wire rules (A5 server, A6\n * client):\n * - a transient event carries `seq` = the session's LAST PERSISTED seq (the\n * counter does not advance), so the stored log stays gap-free and a server\n * restart can never reissue a seq a client already saw;\n * - its SSE frame has NO `id:` line, so the browser's Last-Event-ID resume\n * cursor only ever points at persisted events;\n * - clients must not dedupe, store or resume by a transient event's seq.\n *\n * Browser-safe (plain Set) and dependency-free at runtime: the web chat's\n * first-paint store imports the guard from HERE, not from ./types.ts (which\n * re-exports both), so the rest of types.ts's runtime values stay out of the\n * chat first-paint JS.\n */\nimport type { VerseEvent, VerseEventType, VerseTransientEvent } from './types.js';\n\nexport const TRANSIENT_EVENT_TYPE_LIST = [\n 'thinking-delta',\n 'thinking-progress',\n 'progress',\n 'status',\n] as const satisfies readonly VerseEventType[];\n\nexport const VERSE_TRANSIENT_EVENT_TYPES: ReadonlySet<VerseEventType> = new Set<VerseEventType>(TRANSIENT_EVENT_TYPE_LIST);\n\n/** V3.10. Type guard over VERSE_TRANSIENT_EVENT_TYPES. */\nexport function isTransientVerseEvent(event: VerseEvent): event is VerseTransientEvent {\n return VERSE_TRANSIENT_EVENT_TYPES.has(event.type);\n}\n"],"mappings":"AAyBA,IAAa,EAA2D,IAAI,IAAoB,CAN9F,iBACA,oBACA,WACA,QAG8F,CAAyB,EAGzH,SAAgB,EAAsB,EAAiD,CACrF,OAAO,EAA4B,IAAI,EAAM,IAAI,CACnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-D5XOdyw8.js","names":[],"sources":["../../../../../../src/core/cloud/types.ts"],"sourcesContent":["/**\n * Cloud lane (3.11) — FROZEN CONTRACTS.\n *\n * Ashlr Verse launches Claude Code cloud sessions (claude.ai/code) that run on\n * the operator's Claude account — including its cloud / usage credits once\n * the subscription window is spent — and tracks what they deliver.\n *\n * How a launch works (verified 2026-09-24 against Claude Code 2.1.280):\n * - A NEW cloud session can only be created by the interactive CLI:\n * `claude --cloud \"<task>\"` (with `-p` it is refused). Run under a\n * pseudo-terminal it prints, then exits 0:\n * Created cloud session: <title>\n * View: https://claude.ai/code/session_<id>?from=cli&m=0\n * Resume with: claude --teleport session_<id>\n * - It must run as the `claude-a` seat's native-profile launcher, which is\n * signed in with a claude.ai account; API-key auth is refused (\"cloud\n * sessions require authentication with a Claude.ai account\").\n * - The session clones the cwd's `origin` GitHub repo at the cwd's CURRENT\n * branch, which must be pushed. The Claude GitHub app already has access\n * to ashlrai/*.\n * - Attaching to / reading an existing session from the CLI is NOT enabled\n * for this account, so Verse never reads a session back. Every task is\n * told to DELIVER to GitHub instead (see delivery-contract.ts): push\n * branch `ashlr-cloud/<taskId>` and open a DRAFT PR whose body carries a\n * fenced `ashlr-cloud-report` JSON block. Verse tracks tasks with `gh`.\n * - The credit balance is not readable (neither `/usage` nor the CLI show\n * it), so spend is an ESTIMATE the operator can calibrate; the UI always\n * says so and links to https://claude.ai/settings/usage.\n *\n * Nothing here merges. A cloud PR is judged and merged by the existing merge\n * gates (custody) or by Mason — never by the cloud lane.\n */\n\nexport const CLOUD_TASK_SCHEMA_VERSION = 1 as const;\nexport const CLOUD_BUDGET_SCHEMA_VERSION = 1 as const;\n\n/** Branch every cloud task delivers to: `ashlr-cloud/<taskId>`. */\nexport const CLOUD_BRANCH_PREFIX = 'ashlr-cloud/' as const;\n/** Fenced block language tag carrying the task report in the PR body. */\nexport const CLOUD_REPORT_FENCE = 'ashlr-cloud-report' as const;\n/** Draft PR title prefix, so tasks are recognisable in GitHub lists. */\nexport const CLOUD_PR_TITLE_PREFIX = '[ashlr-cloud]' as const;\n/** Where the real credit balance lives (not readable programmatically). */\nexport const CLOUD_BALANCE_URL = 'https://claude.ai/settings/usage' as const;\n/** The seat whose claude.ai login launches cloud sessions. */\nexport const CLOUD_SEAT_ID = 'claude-a' as const;\n/** A task with no PR after this long is marked `expired` (still linkable). */\nexport const CLOUD_TASK_EXPIRY_MS = 6 * 60 * 60 * 1000;\n/** Max prompt length accepted from any entry point (chars). */\nexport const CLOUD_PROMPT_MAX_CHARS = 20_000;\n/** Launch timeout for the PTY-wrapped CLI (creation took < 10 s in testing). */\nexport const CLOUD_LAUNCH_TIMEOUT_MS = 90_000;\n\n/** Task ids look like `ct_20260924T2331_k3f9q2` (sortable, branch-safe). */\nexport const CLOUD_TASK_ID_PATTERN = /^ct_\\d{8}T\\d{4}_[a-z0-9]{6}$/;\n\nexport type CloudTaskOrigin = 'chat' | 'operator' | 'leader' | 'self-improve' | 'cli';\n\n/**\n * queued accepted, waiting for its repo's launch slot (launches are\n * serialised per checkout folder — two concurrent `--cloud` runs\n * in one folder conflict).\n * launching PTY launch in flight.\n * running session created; no PR yet.\n * pr-open draft/ready PR exists on `ashlr-cloud/<id>`.\n * merged PR merged (by gates or Mason).\n * closed PR closed without merge (or dismissed by the operator).\n * failed launch failed (see stateReason / failure code).\n * expired no PR after CLOUD_TASK_EXPIRY_MS — the session link still works.\n */\nexport type CloudTaskState = 'queued' | 'launching' | 'running' | 'pr-open' | 'merged' | 'closed' | 'failed' | 'expired';\n\nexport const CLOUD_TERMINAL_STATES: readonly CloudTaskState[] = ['merged', 'closed', 'failed', 'expired'];\n\nexport type CloudLaunchFailureCode =\n | 'seat-unavailable' // claude-a launcher missing / not a native profile\n | 'auth' // not signed in with a claude.ai account\n | 'not-enabled' // cloud sessions not enabled for the account\n | 'rate-limited' // provider refused (no credits left / limit)\n | 'no-remote' // checkout has no GitHub origin / branch not pushed\n | 'checkout-failed' // could not prepare the isolated checkout\n | 'budget' // refused by the cloud budget before launching\n | 'timeout' // CLI produced no session within CLOUD_LAUNCH_TIMEOUT_MS\n | 'unparsed' // CLI exited but printed no recognisable session\n | 'unknown';\n\nexport interface CloudTaskReport {\n status: 'done' | 'partial' | 'blocked' | 'no-change';\n summary: string;\n testsRun: string[];\n risks: string[];\n filesChanged?: number;\n}\n\nexport interface CloudTaskPr {\n number: number;\n url: string;\n state: 'open' | 'closed' | 'merged';\n draft: boolean;\n title: string;\n}\n\nexport interface CloudTaskV1 {\n v: typeof CLOUD_TASK_SCHEMA_VERSION;\n id: string;\n /** GitHub `owner/name`. */\n repo: string;\n /** Branch the session starts from (must exist on origin). */\n baseBranch: string;\n /** Always `${CLOUD_BRANCH_PREFIX}${id}`. */\n branch: string;\n /** Short human title (≤ 80 chars). */\n title: string;\n /** The operator's / Leader's task text — WITHOUT the delivery contract. */\n prompt: string;\n origin: CloudTaskOrigin;\n requestedBy: 'mason' | 'leader' | 'self-improve';\n seat: string;\n sessionId: string | null;\n sessionUrl: string | null;\n state: CloudTaskState;\n /** Plain-language reason for the current state (never raw ISO / paths). */\n stateReason: string | null;\n failure: CloudLaunchFailureCode | null;\n createdAt: string;\n launchedAt: string | null;\n updatedAt: string;\n pr: CloudTaskPr | null;\n report: CloudTaskReport | null;\n /** Budget accounting — an ESTIMATE fixed at launch. */\n estimatedCostUsd: number;\n /** Backlog item this task came from (self-improvement), if any. */\n backlogItemId: string | null;\n /** Needs-you item created for approval (Leader-suggested tasks), if any. */\n needsYouId: string | null;\n}\n\nexport interface CloudBudgetV1 {\n v: typeof CLOUD_BUDGET_SCHEMA_VERSION;\n /** Credits the operator says the account has (default 250). */\n creditsTotalUsd: number;\n /**\n * Operator calibration: credits already spent BEFORE the tasks Verse\n * tracks (or a correction after checking claude.ai). Added to the estimate.\n */\n creditsSpentAdjustmentUsd: number;\n /** Flat per-session estimate used for accounting (default 3). */\n estimatedCostPerSessionUsd: number;\n /** Max sessions in `launching|running` at once (all origins). */\n maxConcurrent: number;\n /** Max sessions per local day from ANY origin. */\n maxSessionsPerDay: number;\n selfImprove: {\n /** Verse may launch its own self-improvement tasks without a click. */\n enabled: boolean;\n /** Repo self-improvement targets (default ashlrai/ashlr-hub). */\n repo: string;\n /** Max self-improvement launches per local day. */\n maxPerDay: number;\n /** Stop self-improvement when estimated remaining credits fall below this. */\n reserveUsd: number;\n };\n updatedAt: string;\n}\n\nexport const DEFAULT_CLOUD_BUDGET: Omit<CloudBudgetV1, 'updatedAt'> = Object.freeze({\n v: CLOUD_BUDGET_SCHEMA_VERSION,\n creditsTotalUsd: 250,\n creditsSpentAdjustmentUsd: 0,\n estimatedCostPerSessionUsd: 3,\n maxConcurrent: 4,\n maxSessionsPerDay: 20,\n selfImprove: Object.freeze({ enabled: true, repo: 'ashlrai/ashlr-hub', maxPerDay: 4, reserveUsd: 40 }),\n}) as Omit<CloudBudgetV1, 'updatedAt'>;\n\nexport interface CloudGate {\n ok: boolean;\n /** Plain sentence when !ok (\"4 of 4 self-improvement launches used today.\"). */\n reason: string | null;\n}\n\nexport interface CloudBudgetView {\n creditsTotalUsd: number;\n estimatedSpentUsd: number;\n estimatedRemainingUsd: number;\n sessionsToday: number;\n selfImproveToday: number;\n running: number;\n canLaunch: CloudGate;\n canSelfImprove: CloudGate;\n /** Always shown next to spend: why this is an estimate. */\n estimateNote: string;\n balanceUrl: typeof CLOUD_BALANCE_URL;\n budget: CloudBudgetV1;\n}\n\nexport interface CloudSeatStatus {\n id: string;\n ready: boolean;\n /** Plain sentence when not ready. */\n reason: string | null;\n}\n\n/** One self-improvement item: built in (improvement-backlog.ts) or added by the operator/Leader (<cloudHome>/backlog.json). */\nexport interface CloudBacklogItem {\n id: string;\n title: string;\n /** Full task prompt handed to the cloud session. */\n prompt: string;\n area: string;\n priority: 1 | 2 | 3;\n /** Repo the item targets (default: budget.selfImprove.repo). */\n repo?: string;\n}\n\nexport interface CloudBacklogView {\n items: Array<CloudBacklogItem & { claimedBy: string | null; lastState: CloudTaskState | null }>;\n nextUp: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP contract — mounted as the 'cloud' module (verse-api.ts)\n// ---------------------------------------------------------------------------\n\nexport const VERSE_CLOUD_PATH = '/api/verse/cloud' as const;\nexport const VERSE_CLOUD_LAUNCH_PATH = '/api/verse/cloud/launch' as const;\nexport const VERSE_CLOUD_BUDGET_PATH = '/api/verse/cloud/budget' as const;\nexport const VERSE_CLOUD_REFRESH_PATH = '/api/verse/cloud/refresh' as const;\nexport const VERSE_CLOUD_IMPROVE_PATH = '/api/verse/cloud/improve' as const;\n/** POST `${VERSE_CLOUD_TASKS_PATH}/<id>/dismiss` */\nexport const VERSE_CLOUD_TASKS_PATH = '/api/verse/cloud/tasks' as const;\n\n/** GET /api/verse/cloud */\nexport interface CloudOverviewResponse {\n generatedAt: string;\n seat: CloudSeatStatus;\n budget: CloudBudgetView;\n /** Newest first, at most 100. */\n tasks: CloudTaskV1[];\n backlog: CloudBacklogView;\n}\n\n/** POST /api/verse/cloud/launch (write token + read session) */\nexport interface CloudLaunchRequest {\n repo: string;\n baseBranch?: string;\n title?: string;\n prompt: string;\n origin: Extract<CloudTaskOrigin, 'chat' | 'operator' | 'cli'>;\n}\n\nexport interface CloudLaunchResponse {\n ok: boolean;\n task: CloudTaskV1 | null;\n /** Plain sentence on refusal/failure. */\n error: string | null;\n failure: CloudLaunchFailureCode | null;\n}\n\n/** POST /api/verse/cloud/budget — any subset; validated and clamped. */\nexport type CloudBudgetUpdate = Partial<Pick<CloudBudgetV1,\n 'creditsTotalUsd' | 'creditsSpentAdjustmentUsd' | 'estimatedCostPerSessionUsd' | 'maxConcurrent' | 'maxSessionsPerDay'>> & {\n selfImprove?: Partial<CloudBudgetV1['selfImprove']>;\n};\n\n/** POST /api/verse/cloud/improve — launch up to `count` backlog items now. */\nexport interface CloudImproveRequest {\n count?: number;\n}\n\nexport interface CloudImproveResponse {\n launched: CloudTaskV1[];\n skipped: Array<{ itemId: string; reason: string }>;\n}\n"],"mappings":"AA2CA,IAAa,EAAoB,mCAMpB,EAAyB,IAKzB,EAAwB,+BAkBxB,EAAmD,CAAC,SAAU,SAAU,SAAU,SAAS,EA6F3F,EAAyD,OAAO,OAAO,CAClF,EAAA,EACA,gBAAiB,IACjB,0BAA2B,EAC3B,2BAA4B,EAC5B,cAAe,EACf,kBAAmB,GACnB,YAAa,OAAO,OAAO,CAAE,QAAS,GAAM,KAAM,oBAAqB,UAAW,EAAG,WAAY,EAAG,CAAC,CACvG,CAAC,EAmDY,EAAmB,mBACnB,EAA0B,0BAC1B,EAA0B,0BAC1B,EAA2B,2BAC3B,EAA2B,2BAE3B,EAAyB"}
|
|
1
|
+
{"version":3,"file":"types-D5XOdyw8.js","names":[],"sources":["../../../../../../src/core/cloud/types.ts"],"sourcesContent":["/**\n * Cloud lane (3.11) — FROZEN CONTRACTS.\n *\n * Ashlr Verse launches Claude Code cloud sessions (claude.ai/code) that run on\n * the operator's Claude account — including its cloud / usage credits once\n * the subscription window is spent — and tracks what they deliver.\n *\n * How a launch works (verified 2026-09-24 against Claude Code 2.1.280):\n * - A NEW cloud session can only be created by the interactive CLI:\n * `claude --cloud \"<task>\"` (with `-p` it is refused). Run under a\n * pseudo-terminal it prints, then exits 0:\n * Created cloud session: <title>\n * View: https://claude.ai/code/session_<id>?from=cli&m=0\n * Resume with: claude --teleport session_<id>\n * - It must run as the `claude-a` seat's native-profile launcher, which is\n * signed in with a claude.ai account; API-key auth is refused (\"cloud\n * sessions require authentication with a Claude.ai account\").\n * - The session clones the cwd's `origin` GitHub repo at the cwd's CURRENT\n * branch, which must be pushed. The Claude GitHub app already has access\n * to ashlrai/*.\n * - Attaching to / reading an existing session from the CLI is NOT enabled\n * for this account, so Verse never reads a session back. Every task is\n * told to DELIVER to GitHub instead (see delivery-contract.ts): push\n * branch `ashlr-cloud/<taskId>` and open a DRAFT PR whose body carries a\n * fenced `ashlr-cloud-report` JSON block. Verse tracks tasks with `gh`.\n * - The credit balance is not readable (neither `/usage` nor the CLI show\n * it), so spend is an ESTIMATE the operator can calibrate; the UI always\n * says so and links to https://claude.ai/settings/usage.\n *\n * Nothing here merges. A cloud PR is judged and merged by the existing merge\n * gates (custody) or by Mason — never by the cloud lane.\n */\n\nexport const CLOUD_TASK_SCHEMA_VERSION = 1 as const;\nexport const CLOUD_BUDGET_SCHEMA_VERSION = 1 as const;\n\n/** Branch every cloud task delivers to: `ashlr-cloud/<taskId>`. */\nexport const CLOUD_BRANCH_PREFIX = 'ashlr-cloud/' as const;\n/** Fenced block language tag carrying the task report in the PR body. */\nexport const CLOUD_REPORT_FENCE = 'ashlr-cloud-report' as const;\n/** Draft PR title prefix, so tasks are recognisable in GitHub lists. */\nexport const CLOUD_PR_TITLE_PREFIX = '[ashlr-cloud]' as const;\n/** Where the real credit balance lives (not readable programmatically). */\nexport const CLOUD_BALANCE_URL = 'https://claude.ai/settings/usage' as const;\n/** The seat whose claude.ai login launches cloud sessions. */\nexport const CLOUD_SEAT_ID = 'claude-a' as const;\n/** A task with no PR after this long is marked `expired` (still linkable). */\nexport const CLOUD_TASK_EXPIRY_MS = 6 * 60 * 60 * 1000;\n/** Max prompt length accepted from any entry point (chars). */\nexport const CLOUD_PROMPT_MAX_CHARS = 20_000;\n/** Launch timeout for the PTY-wrapped CLI (creation took < 10 s in testing). */\nexport const CLOUD_LAUNCH_TIMEOUT_MS = 90_000;\n\n/** Task ids look like `ct_20260924T2331_k3f9q2` (sortable, branch-safe). */\nexport const CLOUD_TASK_ID_PATTERN = /^ct_\\d{8}T\\d{4}_[a-z0-9]{6}$/;\n\nexport type CloudTaskOrigin = 'chat' | 'operator' | 'leader' | 'self-improve' | 'cli';\n\n/**\n * queued accepted, waiting for its repo's launch slot (launches are\n * serialised per checkout folder — two concurrent `--cloud` runs\n * in one folder conflict).\n * launching PTY launch in flight.\n * running session created; no PR yet.\n * pr-open a draft/ready PR was observed on `ashlr-cloud/<id>`; `pr` is null\n * while later verification is unavailable or its identity changed.\n * merged PR merged (by gates or Mason).\n * closed PR closed without merge (or dismissed by the operator).\n * failed launch failed (see stateReason / failure code).\n * expired no PR after CLOUD_TASK_EXPIRY_MS — the session link still works.\n */\nexport type CloudTaskState = 'queued' | 'launching' | 'running' | 'pr-open' | 'merged' | 'closed' | 'failed' | 'expired';\n\nexport const CLOUD_TERMINAL_STATES: readonly CloudTaskState[] = ['merged', 'closed', 'failed', 'expired'];\n\nexport type CloudLaunchFailureCode =\n | 'seat-unavailable' // claude-a launcher missing / not a native profile\n | 'auth' // not signed in with a claude.ai account\n | 'not-enabled' // cloud sessions not enabled for the account\n | 'rate-limited' // provider refused (no credits left / limit)\n | 'no-remote' // checkout has no GitHub origin / branch not pushed\n | 'checkout-failed' // could not prepare the isolated checkout\n | 'budget' // refused by the cloud budget before launching\n | 'timeout' // CLI produced no session within CLOUD_LAUNCH_TIMEOUT_MS\n | 'unparsed' // CLI exited but printed no recognisable session\n | 'unknown';\n\nexport interface CloudTaskReport {\n status: 'done' | 'partial' | 'blocked' | 'no-change';\n summary: string;\n testsRun: string[];\n risks: string[];\n filesChanged?: number;\n}\n\nexport interface CloudTaskPr {\n number: number;\n url: string;\n state: 'open' | 'closed' | 'merged';\n draft: boolean;\n title: string;\n}\n\n/** Immutable identity of the first PR verified for this task. Remains after a lookup outage. */\nexport interface CloudDeliveryPin {\n number: number;\n url: string;\n}\n\nexport interface CloudTaskV1 {\n v: typeof CLOUD_TASK_SCHEMA_VERSION;\n id: string;\n /** GitHub `owner/name`. */\n repo: string;\n /** Branch the session starts from (must exist on origin). */\n baseBranch: string;\n /** Always `${CLOUD_BRANCH_PREFIX}${id}`. */\n branch: string;\n /** Short human title (≤ 80 chars). */\n title: string;\n /** The operator's / Leader's task text — WITHOUT the delivery contract. */\n prompt: string;\n origin: CloudTaskOrigin;\n requestedBy: 'mason' | 'leader' | 'self-improve';\n seat: string;\n sessionId: string | null;\n sessionUrl: string | null;\n state: CloudTaskState;\n /** Plain-language reason for the current state (never raw ISO / paths). */\n stateReason: string | null;\n failure: CloudLaunchFailureCode | null;\n createdAt: string;\n launchedAt: string | null;\n updatedAt: string;\n pr: CloudTaskPr | null;\n report: CloudTaskReport | null;\n /** Optional for 3.11 task files written before PR identity was pinned. */\n deliveryPin?: CloudDeliveryPin;\n /** Budget accounting — an ESTIMATE fixed at launch. */\n estimatedCostUsd: number;\n /** Backlog item this task came from (self-improvement), if any. */\n backlogItemId: string | null;\n /** Needs-you item created for approval (Leader-suggested tasks), if any. */\n needsYouId: string | null;\n}\n\nexport interface CloudBudgetV1 {\n v: typeof CLOUD_BUDGET_SCHEMA_VERSION;\n /** Credits the operator says the account has (default 250). */\n creditsTotalUsd: number;\n /**\n * Operator calibration: credits already spent BEFORE the tasks Verse\n * tracks (or a correction after checking claude.ai). Added to the estimate.\n */\n creditsSpentAdjustmentUsd: number;\n /** Flat per-session estimate used for accounting (default 3). */\n estimatedCostPerSessionUsd: number;\n /** Max sessions in `launching|running` at once (all origins). */\n maxConcurrent: number;\n /** Max sessions per local day from ANY origin. */\n maxSessionsPerDay: number;\n selfImprove: {\n /** Verse may launch its own self-improvement tasks without a click. */\n enabled: boolean;\n /** Repo self-improvement targets (default ashlrai/ashlr-hub). */\n repo: string;\n /** Max self-improvement launches per local day. */\n maxPerDay: number;\n /** Stop self-improvement when estimated remaining credits fall below this. */\n reserveUsd: number;\n };\n updatedAt: string;\n}\n\nexport const DEFAULT_CLOUD_BUDGET: Omit<CloudBudgetV1, 'updatedAt'> = Object.freeze({\n v: CLOUD_BUDGET_SCHEMA_VERSION,\n creditsTotalUsd: 250,\n creditsSpentAdjustmentUsd: 0,\n estimatedCostPerSessionUsd: 3,\n maxConcurrent: 4,\n maxSessionsPerDay: 20,\n selfImprove: Object.freeze({ enabled: true, repo: 'ashlrai/ashlr-hub', maxPerDay: 4, reserveUsd: 40 }),\n}) as Omit<CloudBudgetV1, 'updatedAt'>;\n\nexport interface CloudGate {\n ok: boolean;\n /** Plain sentence when !ok (\"4 of 4 self-improvement launches used today.\"). */\n reason: string | null;\n}\n\nexport interface CloudBudgetView {\n creditsTotalUsd: number;\n estimatedSpentUsd: number;\n estimatedRemainingUsd: number;\n sessionsToday: number;\n selfImproveToday: number;\n running: number;\n canLaunch: CloudGate;\n canSelfImprove: CloudGate;\n /** Always shown next to spend: why this is an estimate. */\n estimateNote: string;\n balanceUrl: typeof CLOUD_BALANCE_URL;\n budget: CloudBudgetV1;\n}\n\nexport interface CloudSeatStatus {\n id: string;\n ready: boolean;\n /** Plain sentence when not ready. */\n reason: string | null;\n}\n\n/** One self-improvement item: built in (improvement-backlog.ts) or added by the operator/Leader (<cloudHome>/backlog.json). */\nexport interface CloudBacklogItem {\n id: string;\n title: string;\n /** Full task prompt handed to the cloud session. */\n prompt: string;\n area: string;\n priority: 1 | 2 | 3;\n /** Repo the item targets (default: budget.selfImprove.repo). */\n repo?: string;\n}\n\nexport interface CloudBacklogView {\n items: Array<CloudBacklogItem & { claimedBy: string | null; lastState: CloudTaskState | null }>;\n nextUp: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP contract — mounted as the 'cloud' module (verse-api.ts)\n// ---------------------------------------------------------------------------\n\nexport const VERSE_CLOUD_PATH = '/api/verse/cloud' as const;\nexport const VERSE_CLOUD_LAUNCH_PATH = '/api/verse/cloud/launch' as const;\nexport const VERSE_CLOUD_BUDGET_PATH = '/api/verse/cloud/budget' as const;\nexport const VERSE_CLOUD_REFRESH_PATH = '/api/verse/cloud/refresh' as const;\nexport const VERSE_CLOUD_IMPROVE_PATH = '/api/verse/cloud/improve' as const;\n/** POST `${VERSE_CLOUD_TASKS_PATH}/<id>/dismiss` */\nexport const VERSE_CLOUD_TASKS_PATH = '/api/verse/cloud/tasks' as const;\n\n/** GET /api/verse/cloud */\nexport interface CloudOverviewResponse {\n generatedAt: string;\n seat: CloudSeatStatus;\n budget: CloudBudgetView;\n /** Newest first, at most 100. */\n tasks: CloudTaskV1[];\n backlog: CloudBacklogView;\n}\n\n/** POST /api/verse/cloud/launch (write token + read session) */\nexport interface CloudLaunchRequest {\n repo: string;\n baseBranch?: string;\n title?: string;\n prompt: string;\n origin: Extract<CloudTaskOrigin, 'chat' | 'operator' | 'cli'>;\n}\n\nexport interface CloudLaunchResponse {\n ok: boolean;\n task: CloudTaskV1 | null;\n /** Plain sentence on refusal/failure. */\n error: string | null;\n failure: CloudLaunchFailureCode | null;\n}\n\n/** POST /api/verse/cloud/budget — any subset; validated and clamped. */\nexport type CloudBudgetUpdate = Partial<Pick<CloudBudgetV1,\n 'creditsTotalUsd' | 'creditsSpentAdjustmentUsd' | 'estimatedCostPerSessionUsd' | 'maxConcurrent' | 'maxSessionsPerDay'>> & {\n selfImprove?: Partial<CloudBudgetV1['selfImprove']>;\n};\n\n/** POST /api/verse/cloud/improve — launch up to `count` backlog items now. */\nexport interface CloudImproveRequest {\n count?: number;\n}\n\nexport interface CloudImproveResponse {\n launched: CloudTaskV1[];\n skipped: Array<{ itemId: string; reason: string }>;\n}\n"],"mappings":"AA2CA,IAAa,EAAoB,mCAMpB,EAAyB,IAKzB,EAAwB,+BAmBxB,EAAmD,CAAC,SAAU,SAAU,SAAU,SAAS,EAqG3F,EAAyD,OAAO,OAAO,CAClF,EAAA,EACA,gBAAiB,IACjB,0BAA2B,EAC3B,2BAA4B,EAC5B,cAAe,EACf,kBAAmB,GACnB,YAAa,OAAO,OAAO,CAAE,QAAS,GAAM,KAAM,oBAAqB,UAAW,EAAG,WAAY,EAAG,CAAC,CACvG,CAAC,EAmDY,EAAmB,mBACnB,EAA0B,0BAC1B,EAA0B,0BAC1B,EAA2B,2BAC3B,EAA2B,2BAE3B,EAAyB"}
|
package/dist/core/web/public/next/assets/{usage-queries-BZuAANlI.js → usage-queries-D1SU1t7r.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c as e,o as t}from"./global-
|
|
2
|
-
//# sourceMappingURL=usage-queries-
|
|
1
|
+
import{c as e,o as t}from"./global-CNNGMril.js";var n=`2.1.280`;function r(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:null}function i(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:null}function a(e,t){let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:null}function o(e,t,n=!1){let r=e[t];return typeof r==`boolean`?r:n}function s(e){return Array.isArray(e)?e:[]}var c=/(launcher\.mjs|native-profiles|account-connections|console-startup|\/\.ashlr\b|Bearer\s|--token\b)/i;function l(e){if(typeof e!=`string`)return null;let t=e.trim();return t.length===0||t.length>200||c.test(t)||/[\r\n]/.test(t)?null:t}function u(e){return e===null?null:Math.max(0,Math.min(100,e))}function d(e){let t=r(e);if(!t)return null;let n=i(t,`id`)??i(t,`label`);if(n===null)return null;let s=r(t.nativeReport),c=o(t,`limitReached`)||o(t,`rateLimitReached`),l=t.measured;return{id:n,label:i(t,`label`),usedPercent:u(a(t,`usedPercent`)??a(t,`used_percent`)),resetsAt:i(t,`resetsAt`)??i(t,`resets_at`),resetDescription:(s?i(s,`resetDescription`):null)??i(t,`resetDescription`),limitReached:c,measured:typeof l==`boolean`?l:!c}}function f(e){let t=r(e);if(!t)return null;let n=i(t,`balance`),s=n===null?a(t,`balance`):Number.parseFloat(n);return{hasCredits:o(t,`hasCredits`)||o(t,`has_credits`),unlimited:o(t,`unlimited`),balance:n,balanceValue:typeof s==`number`&&Number.isFinite(s)?s:null}}var p=[`claude`,`codex`,`grok`];function m(e){let t=r(e);if(!t)return null;let n=i(t,`id`),a=i(t,`provider`);if(n===null||a===null||!p.includes(a))return null;let o=s(t.windows).map(d).filter(e=>e!==null),c=i(t,`state`),u=i(t,`authentication`),m=r(t.unsupported);return{id:n,label:i(t,`label`)??n,provider:a,state:c===`checking`||c===`observed`||c===`signed-out`||c===`unavailable`?c:`unavailable`,authentication:u===`signed-in`||u===`signed-out`?u:`unknown`,health:i(t,`health`),planType:i(t,`planType`)??i(t,`plan_type`),observedAt:i(t,`observedAt`),windows:o,binding:d(t.binding),credits:f(t.credits),reason:i(t,`reason`),unsupported:h(t,m),reconnectCommand:l(t.reconnectCommand),notes:s(t.notes).filter(e=>typeof e==`string`)}}function h(e,t){if(t)return{code:i(t,`code`)??`usage-version-unsupported`,pinnedVersion:i(t,`pinnedVersion`)??i(t,`version`)};let r=i(e,`reason`);return r===`usage-version-unsupported`?{code:r,pinnedVersion:n}:null}function g(e){let t=i(e,`collectorNote`);if(t)return t;let n=r(e.collector);return!n||i(n,`owner`)!==`another-collector`?null:i(n,`note`)??`Another collector process owns the quota-refresh lease, so these readings are read-only and may be staler than this server’s poll interval.`}function _(e){let t=r(e);if(!t)return null;let n=Array.isArray(t.accounts)?t.accounts:Array.isArray(e)?e:null;return n===null?null:{sampledAt:i(t,`sampledAt`),refreshing:o(t,`refreshing`),accounts:n.map(m).filter(e=>e!==null),collectorNote:g(t)}}function v(e){let t=r(e);if(!t)return null;let n=i(t,`day`);return n===null||!/^\d{4}-\d{2}-\d{2}$/.test(n)?null:{day:n,tokensIn:a(t,`tokensIn`)??0,tokensOut:a(t,`tokensOut`)??0,estCostUsd:a(t,`estCostUsd`)??0,sessions:a(t,`sessions`)??0,cacheRead:a(t,`cacheRead`),cacheWrite:a(t,`cacheWrite`),cacheHitRate:a(t,`cacheHitRate`)}}function y(e,t){let n=r(e),a=n?Array.isArray(n.byDay)?n.byDay:Array.isArray(n.days)?n.days:null:Array.isArray(e)?e:null;if(a===null)return null;let c=n?i(n,`window`):null;return{window:c===`7d`||c===`30d`?c:t,days:a.map(v).filter(e=>e!==null).sort((e,t)=>e.day.localeCompare(t.day)),generatedAt:n?i(n,`generatedAt`):null,estimated:!n||o(n,`estimated`,!0),caveats:n?s(n.caveats).filter(e=>typeof e==`string`):[]}}function b(e,t){let n=r(e);if(!n)return null;let s=i(n,`label`)??i(n,`id`)??i(n,`name`)??i(n,`model`);if(s===null)return null;let c=n.capabilities,l=i(n,`state`),d=n.supportsTools,f=a(n,`nativeContextLength`)??a(n,`nativeContext`),p=a(n,`contextLength`)??a(n,`configuredContext`),m=i(n,`placement`);return{name:s,runtime:t,loaded:l===null?o(n,`loaded`)||o(n,`resident`):l===`loaded`,sizeBytes:a(n,`sizeBytes`)??a(n,`size`),sizeVramBytes:a(n,`sizeVramBytes`)??a(n,`size_vram`),placement:m===`gpu`||m===`cpu`||m===`split`?m:`unknown`,gpuPercent:u(a(n,`gpuPercent`)),memoryPercent:u(a(n,`memoryPercent`)),family:i(n,`family`),arch:i(n,`arch`),expiresAt:i(n,`expiresAt`)??i(n,`expires_at`),parameterSize:i(n,`parameterSize`)??i(n,`parameter_size`),quantization:i(n,`quantization`)??i(n,`quantization_level`),nativeContext:f,configuredContext:p!==null&&f!==null&&p===f?null:p,capabilities:Array.isArray(c)?c.filter(e=>typeof e==`string`):null,supportsTools:typeof d==`boolean`?d:null}}function x(e,t){let n=r(e);if(!n)return null;let s=Array.isArray(n.models)?n.models:null;if(s===null)return null;let c=s.map(e=>b(e,t)).filter(e=>e!==null),l=o(n,`stale`);return{models:c,status:{runtime:t,reachable:o(n,`reachable`),reason:i(n,`reason`),stale:l,staleForMs:l?a(n,`staleForMs`):null,modelCount:c.length}}}function S(e){let t=r(e);if(!t)return null;let n=x(t.ollama,`ollama`),c=x(t.lmStudio??t.lmstudio,`lmstudio`);if(n!==null||c!==null){let e=[n,c].filter(e=>e!==null),o=e.some(e=>e.status.reachable),l=r(t.machine);return{reachable:o,models:e.flatMap(e=>e.models),memoryBudgetBytes:(l?a(l,`totalMemoryBytes`):null)??a(t,`memoryBudgetBytes`)??a(t,`memoryBudget`),freeMemoryBytes:l?a(l,`freeMemoryBytes`):null,reason:o?null:e.map(e=>e.status.reason).find(e=>e!==null)??null,runtimes:e.map(e=>e.status),notes:s(t.notes).filter(e=>typeof e==`string`),sampledAt:i(t,`sampledAt`)}}let l=Array.isArray(t.models)?t.models:null;return l===null?null:{reachable:o(t,`reachable`,!0),models:l.map(e=>b(e,null)).filter(e=>e!==null),memoryBudgetBytes:a(t,`memoryBudgetBytes`)??a(t,`memoryBudget`),freeMemoryBytes:a(t,`freeMemoryBytes`),reason:i(t,`reason`),runtimes:[],notes:s(t.notes).filter(e=>typeof e==`string`),sampledAt:i(t,`sampledAt`)}}var C=`verse-usage-frontier`,w=`verse-usage-control`,T={key:C,fetch:t=>e(`/api/usage`,t)};function E(e){return e instanceof t?e.status===404?`This server does not expose /api/verse/control, so configured caps and today’s spend are unavailable here.`:`Configured caps unavailable (HTTP ${e.status}).`:`Configured caps unavailable: the request failed.`}var D={key:w,fetch:async n=>{try{return{raw:await e(`/api/verse/control`,n),available:!0,reason:null}}catch(e){if(e instanceof t&&e.status===401||e instanceof DOMException&&e.name===`AbortError`)throw e;return{raw:null,available:!1,reason:E(e)}}}},O=`verse-usage-accounts`,k=`verse-usage-local-models`,A=`verse-usage-series`;function j(e,n){return n instanceof t?n.status===404?`This server does not expose ${e} yet, so this panel has no source.`:`${e} answered HTTP ${n.status}.`:`${e} could not be reached.`}function M(n){return async r=>{try{return{raw:await e(n,r),available:!0,reason:null}}catch(e){if(e instanceof t&&e.status===401||e instanceof DOMException&&e.name===`AbortError`)throw e;return{raw:null,available:!1,reason:j(n,e)}}}}var N={key:O,fetch:M(`/api/verse/accounts`)},P=[350,1200],F=M(`/api/verse/local-models`);function I(e){if(!e.available)return!1;let t=S(e.raw);return t!==null&&!t.reachable}function L(e,t){return new Promise((n,r)=>{if(t?.aborted){r(new DOMException(`Aborted`,`AbortError`));return}let i=()=>{clearTimeout(a),r(new DOMException(`Aborted`,`AbortError`))},a=setTimeout(()=>{t?.removeEventListener(`abort`,i),n()},e);t?.addEventListener(`abort`,i,{once:!0})})}var R={key:k,fetch:async e=>{let t=await F(e);for(let n of P){if(!I(t))return t;await L(n,e),t=await F(e)}return t}},z={"7d":{key:`${A}:7d`,fetch:M(`/api/verse/usage-series?window=7d`)},"30d":{key:`${A}:30d`,fetch:M(`/api/verse/usage-series?window=30d`)}};function B(e){return z[e]}export{R as a,y as c,D as i,B as n,_ as o,N as r,S as s,T as t};
|
|
2
|
+
//# sourceMappingURL=usage-queries-D1SU1t7r.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-queries-BZuAANlI.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/usage/usage-contract.ts","../../../../../../src/web-ui/routes/verse/usage/usage-queries.ts"],"sourcesContent":["/**\n * routes/verse/usage/usage-contract.ts\n *\n * ┌───────────────────────────────────────────────────────────────────────┐\n * │ INTEGRATION — RECONCILED AGAINST OWNER T'S REAL ROUTES (V2.1) │\n * │ │\n * │ GET /api/verse/accounts → VerseAccountsSnapshot │\n * │ GET /api/verse/usage-series → {window, byDay, estimated, caveats} │\n * │ GET /api/verse/local-models → VerseLocalModelsSnapshot │\n * │ │\n * │ T's types now exist and are imported below as the WIRE shapes. The │\n * │ interfaces in this file are no longer stand-ins for them: they are │\n * │ the DISPLAY shapes this section renders, and they differ from the │\n * │ wire on purpose in three places the seam actually required — │\n * │ │\n * │ 1. local-models arrives as TWO runtime reports (ollama, lmStudio) │\n * │ plus a `machine` budget. This section shows one list of models │\n * │ against one budget, so `projectLocalModels` flattens them. │\n * │ 2. usage-series arrives as `{byDay}`, not `{days}` (T's documented │\n * │ deviation 1). The projector reads `byDay` and still accepts │\n * │ `days`/a bare array so an older server degrades rather than dies. │\n * │ 3. `unsupported` is not a wire field. T reports the version-pin │\n * │ failure in `reason` as the verbatim probe code, so it is DERIVED │\n * │ here from that code plus T's exported pin constant rather than │\n * │ being added to T's contract late in the run. │\n * │ │\n * │ The `WIRE_*_KEYS` blocks below are the executable seam contract: │\n * │ every canonical field name this module reads is pinned to `keyof` the │\n * │ corresponding core type, so a rename in src/core/verse breaks THIS │\n * │ build instead of silently degrading the panel to \"unknown\" at run │\n * │ time — which is exactly how this seam was broken when integration │\n * │ started. │\n * └───────────────────────────────────────────────────────────────────────┘\n *\n * Why every read goes through a structural narrower instead of a cast:\n *\n * - This section must render correctly against a server that does NOT have\n * T's routes (404) and against one that has an earlier spelling of them.\n * A cast would turn a field-name drift into `undefined.something` at\n * render time; a narrower turns it into an honest \"unknown\" with a reason.\n * - Nothing here is ever coerced. A missing percentage stays `null`, never\n * 0 — `usedPercent: 0` and \"no reading\" are different facts and the UI\n * draws them differently (docs/VERSE-TELEMETRY-V2.md, closing rules).\n *\n * SECURITY (docs/VERSE-CONTRACT-V2.md ground rules): a native-profile\n * launcher command must never reach a surface. `sanitizeCommand` below is a\n * client-side backstop on top of the server's own stripping — if a payload\n * ever carries a launcher path, this module drops it rather than printing it.\n *\n * Pure: no React, no I/O.\n */\n// EVERY import from src/core here MUST be type-only.\n//\n// `core/verse/accounts.ts` is the server's collector: it pulls node:fs,\n// node:child_process, the quota lease and the connection monitor. A VALUE\n// import of even a one-word constant from it drags that entire graph into the\n// browser bundle — `vite build` externalizes the node built-ins and the build\n// fails. Type-only imports are erased, so the seam guards below cost nothing\n// at runtime. The two constants this module needs are therefore re-declared\n// locally and PINNED TO CORE'S LITERAL TYPES (see below), which gives the same\n// drift protection with no emitted import.\nimport type {\n VerseAccountRecord,\n VerseAccountWindow,\n VerseAccountsCollectorStatus,\n VerseAccountsSnapshot,\n VerseCodexCredits,\n} from '../../../../core/verse/accounts.js';\nimport type {\n VerseLocalModel,\n VerseLocalModelsSnapshot,\n VerseLocalRuntimeReport,\n} from '../../../../core/verse/local-models.js';\nimport type { DailyUsage as CoreDailyUsage } from '../../../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Seam contract — compile-time only, zero runtime cost.\n//\n// Each entry pins a field name this module reads off the wire to `keyof` the\n// core type that produces it. Renaming a field in src/core/verse now fails\n// `npm run typecheck:web` here, at the seam, rather than turning a live panel\n// into a silent \"unknown\".\n// ---------------------------------------------------------------------------\n\nconst WIRE_ACCOUNT_KEYS = {\n id: 'id',\n label: 'label',\n provider: 'provider',\n state: 'state',\n authentication: 'authentication',\n health: 'health',\n planType: 'planType',\n observedAt: 'observedAt',\n windows: 'windows',\n binding: 'binding',\n credits: 'credits',\n reason: 'reason',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountRecord>;\n\nconst WIRE_WINDOW_KEYS = {\n id: 'id',\n usedPercent: 'usedPercent',\n resetsAt: 'resetsAt',\n nativeReport: 'nativeReport',\n limitReached: 'limitReached',\n measured: 'measured',\n} as const satisfies Record<string, keyof VerseAccountWindow>;\n\nconst WIRE_CREDITS_KEYS = {\n hasCredits: 'hasCredits',\n unlimited: 'unlimited',\n balance: 'balance',\n} as const satisfies Record<string, keyof VerseCodexCredits>;\n\nconst WIRE_ACCOUNTS_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n refreshing: 'refreshing',\n accounts: 'accounts',\n collector: 'collector',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountsSnapshot>;\n\nconst WIRE_COLLECTOR_KEYS = {\n owner: 'owner',\n note: 'note',\n} as const satisfies Record<string, keyof VerseAccountsCollectorStatus>;\n\nconst WIRE_LOCAL_SNAPSHOT_KEYS = {\n machine: 'machine',\n ollama: 'ollama',\n lmStudio: 'lmStudio',\n} as const satisfies Record<string, keyof VerseLocalModelsSnapshot>;\n\nconst WIRE_LOCAL_RUNTIME_KEYS = {\n reachable: 'reachable',\n models: 'models',\n reason: 'reason',\n // V2.1: a RETAINED known-good reading rather than a fresh probe. Both must\n // be projected — a stale reading presented as fresh is the exact failure\n // this seam exists to prevent.\n stale: 'stale',\n staleForMs: 'staleForMs',\n} as const satisfies Record<string, keyof VerseLocalRuntimeReport>;\n\nconst WIRE_LOCAL_MODEL_KEYS = {\n id: 'id',\n label: 'label',\n state: 'state',\n sizeBytes: 'sizeBytes',\n sizeVramBytes: 'sizeVramBytes',\n placement: 'placement',\n gpuPercent: 'gpuPercent',\n memoryPercent: 'memoryPercent',\n family: 'family',\n arch: 'arch',\n expiresAt: 'expiresAt',\n contextLength: 'contextLength',\n nativeContextLength: 'nativeContextLength',\n parameterSize: 'parameterSize',\n quantization: 'quantization',\n capabilities: 'capabilities',\n supportsTools: 'supportsTools',\n} as const satisfies Record<string, keyof VerseLocalModel>;\n\n/**\n * Claude's version-pin constants, re-declared rather than imported.\n *\n * The annotations are the drift guard: `typeof import(...)` is a TYPE position,\n * so it is erased at build time, but it resolves to core's literal type\n * (`'2.1.257'`, `'usage-version-unsupported'`). Change either constant in\n * `core/verse/accounts.ts` and this file stops compiling — the same protection\n * a value import would give, without pulling node:fs into the browser.\n */\ntype CoreAccountsModule = typeof import('../../../../core/verse/accounts.js');\n\nexport const CLAUDE_VERSION_REASON: CoreAccountsModule['VERSE_CLAUDE_VERSION_REASON'] =\n 'usage-version-unsupported';\n\nexport const CLAUDE_USAGE_PINNED_VERSION: CoreAccountsModule['VERSE_CLAUDE_USAGE_PINNED_VERSION'] =\n '2.1.280';\n\n/** `byDay` is the wire key (T's deviation 1); `DailyUsage` below mirrors core. */\nconst WIRE_DAILY_USAGE_KEYS = {\n day: 'day',\n tokensIn: 'tokensIn',\n tokensOut: 'tokensOut',\n estCostUsd: 'estCostUsd',\n sessions: 'sessions',\n cacheRead: 'cacheRead',\n cacheWrite: 'cacheWrite',\n cacheHitRate: 'cacheHitRate',\n} as const satisfies Record<string, keyof CoreDailyUsage>;\n\n// Referenced so the guards are not dead code under `noUnusedLocals`.\nexport const WIRE_CONTRACT_KEYS = {\n account: WIRE_ACCOUNT_KEYS,\n window: WIRE_WINDOW_KEYS,\n credits: WIRE_CREDITS_KEYS,\n accountsSnapshot: WIRE_ACCOUNTS_SNAPSHOT_KEYS,\n collector: WIRE_COLLECTOR_KEYS,\n localSnapshot: WIRE_LOCAL_SNAPSHOT_KEYS,\n localRuntime: WIRE_LOCAL_RUNTIME_KEYS,\n localModel: WIRE_LOCAL_MODEL_KEYS,\n dailyUsage: WIRE_DAILY_USAGE_KEYS,\n} as const;\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/accounts\n// ---------------------------------------------------------------------------\n\n/** Provider ids this surface knows how to describe. */\nexport type AccountProvider = 'claude' | 'codex' | 'grok';\n\n/**\n * One quota window on an account.\n *\n * `resetsAt` is an ISO string when the provider gave a real timestamp (Codex\n * publishes an epoch the server normalizes). Claude's is STRUCTURALLY always\n * null and the human sentence lives in `nativeReport.resetDescription`, which\n * is rendered verbatim and never turned into a countdown.\n */\nexport interface AccountWindow {\n id: string;\n /** Human label when the server supplies one; otherwise `id` is shown. */\n label: string | null;\n /** 0–100. `null` is \"no reading\", never 0. */\n usedPercent: number | null;\n /** ISO 8601, or null. */\n resetsAt: string | null;\n /** Verbatim provider prose, e.g. \"resets Sep 25 at 7pm (America/New_York)\". */\n resetDescription: string | null;\n /**\n * True when the provider signalled `rateLimitReachedType` — the upstream\n * writes the SENTINEL 100, which is a flag, not a measurement. Rendered as\n * \"limit reached\", never as \"100% used\".\n */\n limitReached: boolean;\n /**\n * False when `usedPercent` is a FLAGGED SENTINEL rather than a reading.\n *\n * Codex writes `rateLimitReachedType` upstream as the value 100, so a bare\n * 100 is indistinguishable from a genuinely measured 100 by the time it\n * arrives. The server distinguishes them; this surface must not collapse\n * them back together. Absent on the wire → assumed measured UNLESS the\n * limit flag is set, which is the only case where the sentinel is written.\n */\n measured: boolean;\n}\n\n/**\n * Codex credits. Independent of the window: a 100%-used week with a spendable\n * balance is NOT blocked, and this surface must not say it is.\n */\nexport interface AccountCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Raw decimal string from the provider, kept verbatim for the title text. */\n balance: string | null;\n /** `balance` parsed, or null when it was absent/unparseable. */\n balanceValue: number | null;\n}\n\nexport interface Account {\n id: string;\n label: string;\n provider: AccountProvider;\n state: 'checking' | 'observed' | 'signed-out' | 'unavailable';\n authentication: 'signed-in' | 'signed-out' | 'unknown';\n /**\n * The connection monitor's own health verdict. Claude's is ALWAYS `unknown`\n * by construction (docs/VERSE-TELEMETRY-V2.md) — that is not a fault and is\n * never rendered as one.\n */\n health: string | null;\n planType: string | null;\n observedAt: string | null;\n windows: AccountWindow[];\n /**\n * The server's computed binding window (highest used percent). Kept as its\n * own field rather than recomputed blindly, but `accounts-model.ts` verifies\n * it against `windows` and falls back to computing it when absent.\n */\n binding: AccountWindow | null;\n credits: AccountCredits | null;\n /** Plain-language reason for a non-observed state. */\n reason: string | null;\n /**\n * Present when a probe failed CLOSED on a version pin (Claude's probe is\n * pinned to a specific Claude Code build). The fix is a one-line constant\n * bump, so the UI names it instead of showing a silent \"unknown\".\n */\n unsupported: { code: string; pinnedVersion: string | null } | null;\n /** Already sanitized — see `sanitizeCommand`. Null when nothing safe to show. */\n reconnectCommand: string | null;\n /**\n * The server's plain-language facts for this account (`VerseAccountRecord.\n * notes`). Grok's \"reconnect through `ashlr resources`, profile path withheld\n * on purpose\" lives here, which is why this surface shows notes rather than\n * only the machine-readable `reason`.\n */\n notes: string[];\n}\n\nexport interface AccountsSnapshot {\n sampledAt: string | null;\n refreshing: boolean;\n accounts: Account[];\n /**\n * Set when another collector process owns the quota-refresh lease, so these\n * readings are read-only and may be staler than this server's poll interval.\n */\n collectorNote: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/usage-series?window=7d|30d\n// ---------------------------------------------------------------------------\n\nexport type SeriesWindow = '7d' | '30d';\n\n/** `buildRollup(window, cfg).byDay` — see docs/VERSE-TELEMETRY-V2.md. */\nexport interface DailyUsage {\n /** YYYY-MM-DD. */\n day: string;\n tokensIn: number;\n tokensOut: number;\n /** ESTIMATED from a static price table. Never a billed figure. */\n estCostUsd: number;\n sessions: number;\n /** Optional: absent means the rollup carried no cache columns for that day. */\n cacheRead: number | null;\n cacheWrite: number | null;\n /** 0–1 fraction, or null. */\n cacheHitRate: number | null;\n}\n\nexport interface UsageSeries {\n window: SeriesWindow;\n days: DailyUsage[];\n generatedAt: string | null;\n /**\n * The server states outright that every cost column here is estimated.\n * Carried through rather than re-asserted locally so the disclosure the UI\n * prints is the one the producer actually made.\n */\n estimated: boolean;\n /** The server's own caveats, rendered verbatim beside the charts. */\n caveats: string[];\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models\n// ---------------------------------------------------------------------------\n\nexport interface LocalModel {\n name: string;\n /** Which runtime reported it, so a flattened list stays attributable. */\n runtime: 'ollama' | 'lmstudio' | null;\n /** Resident in memory right now (Ollama /api/ps), vs merely installed. */\n loaded: boolean;\n /** Total resident bytes, or null when not reported. */\n sizeBytes: number | null;\n /** Of `sizeBytes`, how much sits in VRAM. null = not reported. */\n sizeVramBytes: number | null;\n /**\n * Where the weights actually sit. `split` is the one that matters: a model\n * that only half-fits the GPU runs at a fraction of the speed of one that\n * fits, and that is the difference between usable and not.\n */\n placement: 'gpu' | 'cpu' | 'split' | 'unknown';\n /** The runtime's own GPU share, 0–100. Preferred over recomputing it. */\n gpuPercent: number | null;\n /** Resident size against total machine memory, 0–100, else null. */\n memoryPercent: number | null;\n family: string | null;\n arch: string | null;\n /** Keep-alive expiry (ISO). Only meaningful while `loaded`. */\n expiresAt: string | null;\n /** e.g. \"79.7B\". Provider string, never parsed into a number for display. */\n parameterSize: string | null;\n /** e.g. \"Q4_K_M\". */\n quantization: string | null;\n /** Native context from model_info[\"<arch>.context_length\"]. */\n nativeContext: number | null;\n /** Context Ashlr actually configures for this seat, when it differs. */\n configuredContext: number | null;\n /**\n * `capabilities` from /api/show. `null` means the capability list was not\n * reported — which is NOT the same as \"does not support tools\".\n */\n capabilities: string[] | null;\n /**\n * The runtime's own answer to \"can this drive an agentic session\", which is\n * AUTHORITATIVE over `capabilities` and must be preferred when non-null.\n *\n * This matters: owner T sends `capabilities: []` when a runtime reported no\n * capability list, and reading that array alone would render \"no tools\" —\n * a hard, wrong gate — where T's `supportsTools: null` correctly means\n * \"unknown\". Deriving tool support from the array alone was a real defect\n * at this seam, not a cosmetic one.\n */\n supportsTools: boolean | null;\n}\n\n/**\n * One runtime's own reachability, kept per-runtime rather than folded into the\n * flattened list, because STALENESS is per-runtime and must be stated.\n *\n * `stale` means the server served a RETAINED known-good reading after a probe\n * TIMED OUT (core `VERSE_LOCAL_LAST_GOOD_TTL_MS`). That is the honest choice\n * server-side — a timeout is \"no answer yet\", not \"the runtime is gone\" — but\n * it obliges this surface to say plainly that the numbers are N seconds old\n * rather than presenting them as fresh.\n */\nexport interface LocalRuntimeStatus {\n runtime: 'ollama' | 'lmstudio';\n reachable: boolean;\n /** Machine-readable degradation code; never rendered as a sentence. */\n reason: string | null;\n /** True when this report is a retained reading rather than a fresh probe. */\n stale: boolean;\n /** Age of that retained reading in ms. Null when `stale` is false. */\n staleForMs: number | null;\n modelCount: number;\n}\n\nexport interface LocalModelsSnapshot {\n reachable: boolean;\n models: LocalModel[];\n /** Machine memory budget in bytes, or null when the server did not say. */\n memoryBudgetBytes: number | null;\n /** Machine memory reported free right now, or null. */\n freeMemoryBytes: number | null;\n reason: string | null;\n /** Per-runtime reachability and staleness. Empty on a flat legacy body. */\n runtimes: LocalRuntimeStatus[];\n /** The server's own plain-language caveats for this snapshot. */\n notes: string[];\n sampledAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Narrowing helpers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction str(source: Record<string, unknown>, key: string): string | null {\n const v = source[key];\n return typeof v === 'string' && v.length > 0 ? v : null;\n}\n\nfunction num(source: Record<string, unknown>, key: string): number | null {\n const v = source[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n}\n\nfunction bool(source: Record<string, unknown>, key: string, fallback = false): boolean {\n const v = source[key];\n return typeof v === 'boolean' ? v : fallback;\n}\n\nfunction list(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\n/**\n * Drop anything that looks like a native-profile launcher invocation or an\n * absolute path into the private account store. The server is supposed to\n * strip these; this is the client-side backstop, because the cost of printing\n * one is unacceptable and the cost of showing \"no command\" is a sentence.\n */\nconst FORBIDDEN_COMMAND = /(launcher\\.mjs|native-profiles|account-connections|console-startup|\\/\\.ashlr\\b|Bearer\\s|--token\\b)/i;\n\nexport function sanitizeCommand(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 200) return null;\n if (FORBIDDEN_COMMAND.test(trimmed)) return null;\n // A newline would let a payload smuggle a second command onto the surface.\n if (/[\\r\\n]/.test(trimmed)) return null;\n return trimmed;\n}\n\nfunction clampPercent(value: number | null): number | null {\n if (value === null) return null;\n return Math.max(0, Math.min(100, value));\n}\n\nfunction projectWindow(raw: unknown): AccountWindow | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id') ?? str(r, 'label');\n if (id === null) return null;\n const native = record(r['nativeReport']);\n const limitReached = bool(r, 'limitReached') || bool(r, 'rateLimitReached');\n const measuredRaw = r['measured'];\n return {\n id,\n label: str(r, 'label'),\n usedPercent: clampPercent(num(r, 'usedPercent') ?? num(r, 'used_percent')),\n resetsAt: str(r, 'resetsAt') ?? str(r, 'resets_at'),\n resetDescription:\n (native ? str(native, 'resetDescription') : null) ?? str(r, 'resetDescription'),\n limitReached,\n // Absent → measured, EXCEPT under a limit flag, which is the one case the\n // upstream writes the sentinel 100. Defaulting a flagged window to\n // `measured: true` would let a denial print as \"100% used\".\n measured: typeof measuredRaw === 'boolean' ? measuredRaw : !limitReached,\n };\n}\n\nfunction projectCredits(raw: unknown): AccountCredits | null {\n const r = record(raw);\n if (!r) return null;\n const balance = str(r, 'balance');\n const parsed = balance === null ? num(r, 'balance') : Number.parseFloat(balance);\n return {\n hasCredits: bool(r, 'hasCredits') || bool(r, 'has_credits'),\n unlimited: bool(r, 'unlimited'),\n balance,\n balanceValue: typeof parsed === 'number' && Number.isFinite(parsed) ? parsed : null,\n };\n}\n\nconst PROVIDERS: readonly string[] = ['claude', 'codex', 'grok'];\n\nfunction projectAccount(raw: unknown): Account | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id');\n const provider = str(r, 'provider');\n if (id === null || provider === null || !PROVIDERS.includes(provider)) return null;\n\n const windows = list(r['windows'])\n .map(projectWindow)\n .filter((w): w is AccountWindow => w !== null);\n\n const state = str(r, 'state');\n const auth = str(r, 'authentication');\n const unsupportedRaw = record(r['unsupported']);\n\n return {\n id,\n label: str(r, 'label') ?? id,\n provider: provider as AccountProvider,\n state:\n state === 'checking' || state === 'observed' || state === 'signed-out' || state === 'unavailable'\n ? state\n : 'unavailable',\n authentication: auth === 'signed-in' || auth === 'signed-out' ? auth : 'unknown',\n health: str(r, 'health'),\n planType: str(r, 'planType') ?? str(r, 'plan_type'),\n observedAt: str(r, 'observedAt'),\n windows,\n binding: projectWindow(r['binding']),\n credits: projectCredits(r['credits']),\n reason: str(r, 'reason'),\n unsupported: projectUnsupported(r, unsupportedRaw),\n reconnectCommand: sanitizeCommand(r['reconnectCommand']),\n notes: list(r['notes']).filter((n): n is string => typeof n === 'string'),\n };\n}\n\n/**\n * A version-pinned probe that failed CLOSED, named rather than swallowed.\n *\n * `unsupported` is not a field on the wire. Owner T reports the failure as the\n * verbatim probe code in `reason` (`usage-version-unsupported`) and states the\n * pin in `notes`, so this derives the structured form from those rather than\n * requiring a late contract change. An explicit `unsupported` object is still\n * honoured first, so a server that grows one later wins without a client edit.\n */\nfunction projectUnsupported(\n r: Record<string, unknown>,\n explicit: Record<string, unknown> | null,\n): Account['unsupported'] {\n if (explicit) {\n return {\n code: str(explicit, 'code') ?? CLAUDE_VERSION_REASON,\n pinnedVersion: str(explicit, 'pinnedVersion') ?? str(explicit, 'version'),\n };\n }\n const reason = str(r, 'reason');\n if (reason !== CLAUDE_VERSION_REASON) return null;\n return { code: reason, pinnedVersion: CLAUDE_USAGE_PINNED_VERSION };\n}\n\n/**\n * The read-only banner. Owner T reports lease ownership as a structured\n * `collector` status, not a flat `collectorNote`, so the note is derived from\n * it — and ONLY when another process owns the lease, because that is the one\n * case where these readings may be staler than this server's poll interval.\n * A stray `collectorNote` string is still accepted for forward compatibility.\n */\nfunction projectCollectorNote(root: Record<string, unknown>): string | null {\n const flat = str(root, 'collectorNote');\n if (flat) return flat;\n const collector = record(root['collector']);\n if (!collector) return null;\n if (str(collector, 'owner') !== 'another-collector') return null;\n return (\n str(collector, 'note') ??\n 'Another collector process owns the quota-refresh lease, so these readings are read-only and may be staler than this server’s poll interval.'\n );\n}\n\nexport function projectAccountsSnapshot(raw: unknown): AccountsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n const rawAccounts = Array.isArray(root['accounts']) ? root['accounts'] : Array.isArray(raw) ? raw : null;\n if (rawAccounts === null) return null;\n return {\n sampledAt: str(root, 'sampledAt'),\n refreshing: bool(root, 'refreshing'),\n accounts: rawAccounts.map(projectAccount).filter((a): a is Account => a !== null),\n collectorNote: projectCollectorNote(root),\n };\n}\n\nfunction projectDay(raw: unknown): DailyUsage | null {\n const r = record(raw);\n if (!r) return null;\n const day = str(r, 'day');\n if (day === null || !/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return null;\n return {\n day,\n tokensIn: num(r, 'tokensIn') ?? 0,\n tokensOut: num(r, 'tokensOut') ?? 0,\n estCostUsd: num(r, 'estCostUsd') ?? 0,\n sessions: num(r, 'sessions') ?? 0,\n cacheRead: num(r, 'cacheRead'),\n cacheWrite: num(r, 'cacheWrite'),\n cacheHitRate: num(r, 'cacheHitRate'),\n };\n}\n\n/**\n * `byDay` is the wire key. Owner T wraps the series as\n * `{window, byDay, estimated, caveats}` rather than returning a bare array\n * (documented deviation 1), so `byDay` is read FIRST. `days` and a bare array\n * remain accepted so an older or differently-shaped server degrades to a\n * rendered series instead of a dead panel.\n */\nexport function projectUsageSeries(raw: unknown, requested: SeriesWindow): UsageSeries | null {\n const root = record(raw);\n const rawDays = root\n ? Array.isArray(root['byDay'])\n ? root['byDay']\n : Array.isArray(root['days'])\n ? root['days']\n : null\n : Array.isArray(raw)\n ? raw\n : null;\n if (rawDays === null) return null;\n const windowValue = root ? str(root, 'window') : null;\n return {\n window: windowValue === '7d' || windowValue === '30d' ? windowValue : requested,\n days: rawDays\n .map(projectDay)\n .filter((d): d is DailyUsage => d !== null)\n .sort((a, b) => a.day.localeCompare(b.day)),\n generatedAt: root ? str(root, 'generatedAt') : null,\n // The producer asserts estimation explicitly. Absent → still true: every\n // cost column on this route is price-table derived, and defaulting the\n // disclosure OFF would drop it exactly when the server is older.\n estimated: root ? bool(root, 'estimated', true) : true,\n caveats: root ? list(root['caveats']).filter((c): c is string => typeof c === 'string') : [],\n };\n}\n\nfunction projectLocalModel(raw: unknown, runtime: LocalModel['runtime']): LocalModel | null {\n const r = record(raw);\n if (!r) return null;\n // `label`/`id` are owner T's spellings; `name`/`model` are the Ollama-native\n // ones a differently-shaped server might send.\n const name = str(r, 'label') ?? str(r, 'id') ?? str(r, 'name') ?? str(r, 'model');\n if (name === null) return null;\n const caps = r['capabilities'];\n const state = str(r, 'state');\n const supportsTools = r['supportsTools'];\n\n // `nativeContextLength` is the architecture maximum; `contextLength` is what\n // the runtime actually configured for the loaded instance. They are two\n // different facts and the panel shows the gap between them, so they must not\n // collapse onto one field.\n const nativeContext = num(r, 'nativeContextLength') ?? num(r, 'nativeContext');\n const configuredContext = num(r, 'contextLength') ?? num(r, 'configuredContext');\n\n const placement = str(r, 'placement');\n\n return {\n name,\n runtime,\n loaded: state !== null ? state === 'loaded' : bool(r, 'loaded') || bool(r, 'resident'),\n sizeBytes: num(r, 'sizeBytes') ?? num(r, 'size'),\n sizeVramBytes: num(r, 'sizeVramBytes') ?? num(r, 'size_vram'),\n placement:\n placement === 'gpu' || placement === 'cpu' || placement === 'split' ? placement : 'unknown',\n gpuPercent: clampPercent(num(r, 'gpuPercent')),\n memoryPercent: clampPercent(num(r, 'memoryPercent')),\n family: str(r, 'family'),\n arch: str(r, 'arch'),\n expiresAt: str(r, 'expiresAt') ?? str(r, 'expires_at'),\n parameterSize: str(r, 'parameterSize') ?? str(r, 'parameter_size'),\n quantization: str(r, 'quantization') ?? str(r, 'quantization_level'),\n nativeContext,\n // Only a genuine narrowing is worth showing. When the runtime reports the\n // same number twice there is no truncation to report.\n configuredContext:\n configuredContext !== null && nativeContext !== null && configuredContext === nativeContext\n ? null\n : configuredContext,\n capabilities: Array.isArray(caps) ? caps.filter((c): c is string => typeof c === 'string') : null,\n supportsTools: typeof supportsTools === 'boolean' ? supportsTools : null,\n };\n}\n\nfunction projectRuntimeReport(\n raw: unknown,\n runtime: NonNullable<LocalModel['runtime']>,\n): { status: LocalRuntimeStatus; models: LocalModel[] } | null {\n const r = record(raw);\n if (!r) return null;\n const rawModels = Array.isArray(r['models']) ? r['models'] : null;\n if (rawModels === null) return null;\n const models = rawModels\n .map((m) => projectLocalModel(m, runtime))\n .filter((m): m is LocalModel => m !== null);\n const stale = bool(r, 'stale');\n return {\n models,\n status: {\n runtime,\n reachable: bool(r, 'reachable'),\n reason: str(r, 'reason'),\n stale,\n // Only meaningful under `stale`. A staleForMs on a fresh report would be\n // a contradiction, and printing it would age a current reading.\n staleForMs: stale ? num(r, 'staleForMs') : null,\n modelCount: models.length,\n },\n };\n}\n\n/**\n * Owner T reports local availability per RUNTIME (`ollama`, `lmStudio`) with a\n * shared `machine` budget. This panel answers one question — \"what can I run\n * right now, and against how much memory\" — so the runtimes are flattened into\n * one list, each row keeping its `runtime` so it stays attributable.\n *\n * Reachability is the OR of the runtimes: one dead runtime is not an unreachable\n * local stack. `reason` is only carried when NOTHING is reachable, because a\n * degradation note beside a working list would misdescribe what is on screen.\n *\n * A flat `{reachable, models, memoryBudgetBytes}` body is still accepted, so an\n * older or differently-shaped server degrades rather than rendering nothing.\n */\nexport function projectLocalModels(raw: unknown): LocalModelsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n\n const ollama = projectRuntimeReport(root['ollama'], 'ollama');\n const lmStudio = projectRuntimeReport(root['lmStudio'] ?? root['lmstudio'], 'lmstudio');\n\n if (ollama !== null || lmStudio !== null) {\n const reports = [ollama, lmStudio].filter((x): x is NonNullable<typeof x> => x !== null);\n const reachable = reports.some((x) => x.status.reachable);\n const machine = record(root['machine']);\n return {\n reachable,\n models: reports.flatMap((x) => x.models),\n memoryBudgetBytes:\n (machine ? num(machine, 'totalMemoryBytes') : null) ??\n num(root, 'memoryBudgetBytes') ??\n num(root, 'memoryBudget'),\n freeMemoryBytes: machine ? num(machine, 'freeMemoryBytes') : null,\n reason: reachable\n ? null\n : (reports.map((x) => x.status.reason).find((x) => x !== null) ?? null),\n runtimes: reports.map((x) => x.status),\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n }\n\n const rawModels = Array.isArray(root['models']) ? root['models'] : null;\n if (rawModels === null) return null;\n return {\n reachable: bool(root, 'reachable', true),\n models: rawModels.map((m) => projectLocalModel(m, null)).filter((m): m is LocalModel => m !== null),\n memoryBudgetBytes: num(root, 'memoryBudgetBytes') ?? num(root, 'memoryBudget'),\n freeMemoryBytes: num(root, 'freeMemoryBytes'),\n reason: str(root, 'reason'),\n // A flat legacy body carries no per-runtime reachability, so there is\n // nothing to attribute and nothing to call stale. An empty list says that\n // honestly; a fabricated entry would not.\n runtimes: [],\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n}\n","/**\n * routes/verse/usage/usage-queries.ts — the reads behind the Usage section.\n *\n * `/api/control` is fetched through the shared `controlSnapshotQuery` so this\n * section rides the same cache (and the same SSE invalidation) as every other\n * view rather than opening a second copy of a large snapshot.\n *\n * `/api/verse/control` is owner B's new route. It is fetched through a\n * NON-throwing wrapper because this section must still render when the route\n * is absent (server started without --allow-dispatch, or B's route not landed\n * yet): a missing configured-caps source is a degraded panel, not a dead\n * section. 401 is the one error that still propagates — an expired read\n * session is an unauthorized state for the whole surface, not a degraded one.\n *\n * The cache key is deliberately NOT shared with the Autonomy section's own\n * read of the same route: this module stores a wrapper shape, and two owners\n * writing different value types under one key would be a real bug.\n */\nimport type { FrontierUsage } from '../../../../core/usage/frontier-usage.js';\nimport { ApiError, apiGet } from '../../../data/client.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { projectLocalModels, type SeriesWindow } from './usage-contract.js';\n\nexport const USAGE_FRONTIER_KEY = 'verse-usage-frontier';\nexport const USAGE_VERSE_CONTROL_KEY = 'verse-usage-control';\n\n/** GET /api/usage — per-engine frontier usage (see core/usage/frontier-usage.ts). */\nexport const frontierUsageQuery: QueryDef<FrontierUsage> = {\n key: USAGE_FRONTIER_KEY,\n fetch: (signal) => apiGet<FrontierUsage>('/api/usage', signal),\n};\n\nexport interface VerseControlRead {\n /** Raw body; narrowed by `projectVerseControl` (owner B's types are not landed). */\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeControlFailure(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return 'This server does not expose /api/verse/control, so configured caps and today’s spend are unavailable here.';\n }\n return `Configured caps unavailable (HTTP ${err.status}).`;\n }\n return 'Configured caps unavailable: the request failed.';\n}\n\nexport const verseControlQuery: QueryDef<VerseControlRead> = {\n key: USAGE_VERSE_CONTROL_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>('/api/verse/control', signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeControlFailure(err) };\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Owner T's routes (GET /api/verse/{accounts,usage-series,local-models})\n// ---------------------------------------------------------------------------\n//\n// These three are fetched through the SAME non-throwing wrapper pattern as\n// /api/verse/control, for the same reason and one more: they are landing in\n// parallel with this section. A server that predates them answers 404, and a\n// 404 here means \"this panel is degraded\", not \"the Usage view is broken\".\n// 401 still propagates, because an expired read session is an unauthorized\n// state for the whole surface.\n//\n// The bodies are narrowed structurally by usage-contract.ts rather than cast,\n// so a field-name drift between T's route and this client degrades to an\n// honest \"unknown\" instead of throwing at render time.\n\nexport const USAGE_ACCOUNTS_KEY = 'verse-usage-accounts';\nexport const USAGE_LOCAL_MODELS_KEY = 'verse-usage-local-models';\nexport const USAGE_SERIES_KEY_PREFIX = 'verse-usage-series';\n\n/** A read that is allowed to be absent. `raw` is null when it was. */\nexport interface OptionalRead {\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeOptionalFailure(path: string, err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This server does not expose ${path} yet, so this panel has no source.`;\n }\n return `${path} answered HTTP ${err.status}.`;\n }\n return `${path} could not be reached.`;\n}\n\nfunction optionalGet(path: string): (signal?: AbortSignal) => Promise<OptionalRead> {\n return async (signal) => {\n try {\n const raw = await apiGet<unknown>(path, signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeOptionalFailure(path, err) };\n }\n };\n}\n\n/** GET /api/verse/accounts — per-account state, windows, credits, plan. */\nexport const verseAccountsQuery: QueryDef<OptionalRead> = {\n key: USAGE_ACCOUNTS_KEY,\n fetch: optionalGet('/api/verse/accounts'),\n};\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models — and why this one read retries\n// ---------------------------------------------------------------------------\n//\n// `/api/verse/local-models` probes the runtimes live on every request, with a\n// 2s per-probe timeout (core/verse/local-models.ts\n// VERSE_LOCAL_PROBE_TIMEOUT_MS). A probe that times out is reported as\n// `{reachable: false, reason: 'ollama-unreachable'}` in a perfectly ordinary\n// HTTP 200 — which is correct on the server's terms (it genuinely did not get\n// an answer) but is NOT the same fact as \"Ollama is not running\", and nothing\n// in the payload distinguishes the two.\n//\n// That distinction matters here because this section is the thing that causes\n// the timeout. Mounting Usage, and every press of its Refresh button, fires\n// seven reads at once, several of which spawn short-lived account-probe\n// processes server-side; measured against a live Ollama with twelve models,\n// roughly one burst in ten starves the 2s probe and comes back\n// `ollama-unreachable`. Nothing re-reads this route afterwards — it has no SSE\n// invalidation key — so that one false negative is what the operator stares\n// at, and pressing Refresh re-creates the very burst that produced it.\n//\n// So a reported-unreachable local stack is RE-READ, up to twice, with a short\n// gap for the burst to drain. This is not \"ignore the failure\": the retries\n// are bounded, each one is a real request, and whatever the last read says is\n// what this section renders — a runtime that is genuinely down answers fast\n// (connection refused, not a timeout) and still reports unreachable, three\n// times, in well under a second.\n//\n// Only an AVAILABLE read is retried. A 404/500 (`available: false`) is a\n// statement about the route, not about the runtime, and re-asking cannot\n// change it.\n\n/** Two extra reads at most, spaced so the section's own request burst drains. */\nconst LOCAL_MODELS_RETRY_DELAYS_MS = [350, 1200] as const;\n\nconst readLocalModels = optionalGet('/api/verse/local-models');\n\nfunction reportsNothingReachable(read: OptionalRead): boolean {\n if (!read.available) return false;\n const snapshot = projectLocalModels(read.raw);\n return snapshot !== null && !snapshot.reachable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** GET /api/verse/local-models — resident vs installed, VRAM split, tools. */\nexport const verseLocalModelsQuery: QueryDef<OptionalRead> = {\n key: USAGE_LOCAL_MODELS_KEY,\n fetch: async (signal) => {\n let read = await readLocalModels(signal);\n for (const delayMs of LOCAL_MODELS_RETRY_DELAYS_MS) {\n if (!reportsNothingReachable(read)) return read;\n await sleep(delayMs, signal);\n read = await readLocalModels(signal);\n }\n return read;\n },\n};\n\n// One QueryDef per window, created once at module scope: useQuery keys on\n// `def.key`, and minting a fresh object per render would be harmless but\n// useRefresh/useRefetch's useCallback deps would churn for no reason.\nconst SERIES_QUERIES: Record<SeriesWindow, QueryDef<OptionalRead>> = {\n '7d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:7d`,\n fetch: optionalGet('/api/verse/usage-series?window=7d'),\n },\n '30d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:30d`,\n fetch: optionalGet('/api/verse/usage-series?window=30d'),\n },\n};\n\nexport function usageSeriesQuery(window: SeriesWindow): QueryDef<OptionalRead> {\n return SERIES_QUERIES[window];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usage-queries-D1SU1t7r.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/usage/usage-contract.ts","../../../../../../src/web-ui/routes/verse/usage/usage-queries.ts"],"sourcesContent":["/**\n * routes/verse/usage/usage-contract.ts\n *\n * ┌───────────────────────────────────────────────────────────────────────┐\n * │ INTEGRATION — RECONCILED AGAINST OWNER T'S REAL ROUTES (V2.1) │\n * │ │\n * │ GET /api/verse/accounts → VerseAccountsSnapshot │\n * │ GET /api/verse/usage-series → {window, byDay, estimated, caveats} │\n * │ GET /api/verse/local-models → VerseLocalModelsSnapshot │\n * │ │\n * │ T's types now exist and are imported below as the WIRE shapes. The │\n * │ interfaces in this file are no longer stand-ins for them: they are │\n * │ the DISPLAY shapes this section renders, and they differ from the │\n * │ wire on purpose in three places the seam actually required — │\n * │ │\n * │ 1. local-models arrives as TWO runtime reports (ollama, lmStudio) │\n * │ plus a `machine` budget. This section shows one list of models │\n * │ against one budget, so `projectLocalModels` flattens them. │\n * │ 2. usage-series arrives as `{byDay}`, not `{days}` (T's documented │\n * │ deviation 1). The projector reads `byDay` and still accepts │\n * │ `days`/a bare array so an older server degrades rather than dies. │\n * │ 3. `unsupported` is not a wire field. T reports the version-pin │\n * │ failure in `reason` as the verbatim probe code, so it is DERIVED │\n * │ here from that code plus T's exported pin constant rather than │\n * │ being added to T's contract late in the run. │\n * │ │\n * │ The `WIRE_*_KEYS` blocks below are the executable seam contract: │\n * │ every canonical field name this module reads is pinned to `keyof` the │\n * │ corresponding core type, so a rename in src/core/verse breaks THIS │\n * │ build instead of silently degrading the panel to \"unknown\" at run │\n * │ time — which is exactly how this seam was broken when integration │\n * │ started. │\n * └───────────────────────────────────────────────────────────────────────┘\n *\n * Why every read goes through a structural narrower instead of a cast:\n *\n * - This section must render correctly against a server that does NOT have\n * T's routes (404) and against one that has an earlier spelling of them.\n * A cast would turn a field-name drift into `undefined.something` at\n * render time; a narrower turns it into an honest \"unknown\" with a reason.\n * - Nothing here is ever coerced. A missing percentage stays `null`, never\n * 0 — `usedPercent: 0` and \"no reading\" are different facts and the UI\n * draws them differently (docs/VERSE-TELEMETRY-V2.md, closing rules).\n *\n * SECURITY (docs/VERSE-CONTRACT-V2.md ground rules): a native-profile\n * launcher command must never reach a surface. `sanitizeCommand` below is a\n * client-side backstop on top of the server's own stripping — if a payload\n * ever carries a launcher path, this module drops it rather than printing it.\n *\n * Pure: no React, no I/O.\n */\n// EVERY import from src/core here MUST be type-only.\n//\n// `core/verse/accounts.ts` is the server's collector: it pulls node:fs,\n// node:child_process, the quota lease and the connection monitor. A VALUE\n// import of even a one-word constant from it drags that entire graph into the\n// browser bundle — `vite build` externalizes the node built-ins and the build\n// fails. Type-only imports are erased, so the seam guards below cost nothing\n// at runtime. The two constants this module needs are therefore re-declared\n// locally and PINNED TO CORE'S LITERAL TYPES (see below), which gives the same\n// drift protection with no emitted import.\nimport type {\n VerseAccountRecord,\n VerseAccountWindow,\n VerseAccountsCollectorStatus,\n VerseAccountsSnapshot,\n VerseCodexCredits,\n} from '../../../../core/verse/accounts.js';\nimport type {\n VerseLocalModel,\n VerseLocalModelsSnapshot,\n VerseLocalRuntimeReport,\n} from '../../../../core/verse/local-models.js';\nimport type { DailyUsage as CoreDailyUsage } from '../../../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Seam contract — compile-time only, zero runtime cost.\n//\n// Each entry pins a field name this module reads off the wire to `keyof` the\n// core type that produces it. Renaming a field in src/core/verse now fails\n// `npm run typecheck:web` here, at the seam, rather than turning a live panel\n// into a silent \"unknown\".\n// ---------------------------------------------------------------------------\n\nconst WIRE_ACCOUNT_KEYS = {\n id: 'id',\n label: 'label',\n provider: 'provider',\n state: 'state',\n authentication: 'authentication',\n health: 'health',\n planType: 'planType',\n observedAt: 'observedAt',\n windows: 'windows',\n binding: 'binding',\n credits: 'credits',\n reason: 'reason',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountRecord>;\n\nconst WIRE_WINDOW_KEYS = {\n id: 'id',\n usedPercent: 'usedPercent',\n resetsAt: 'resetsAt',\n nativeReport: 'nativeReport',\n limitReached: 'limitReached',\n measured: 'measured',\n} as const satisfies Record<string, keyof VerseAccountWindow>;\n\nconst WIRE_CREDITS_KEYS = {\n hasCredits: 'hasCredits',\n unlimited: 'unlimited',\n balance: 'balance',\n} as const satisfies Record<string, keyof VerseCodexCredits>;\n\nconst WIRE_ACCOUNTS_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n refreshing: 'refreshing',\n accounts: 'accounts',\n collector: 'collector',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountsSnapshot>;\n\nconst WIRE_COLLECTOR_KEYS = {\n owner: 'owner',\n note: 'note',\n} as const satisfies Record<string, keyof VerseAccountsCollectorStatus>;\n\nconst WIRE_LOCAL_SNAPSHOT_KEYS = {\n machine: 'machine',\n ollama: 'ollama',\n lmStudio: 'lmStudio',\n} as const satisfies Record<string, keyof VerseLocalModelsSnapshot>;\n\nconst WIRE_LOCAL_RUNTIME_KEYS = {\n reachable: 'reachable',\n models: 'models',\n reason: 'reason',\n // V2.1: a RETAINED known-good reading rather than a fresh probe. Both must\n // be projected — a stale reading presented as fresh is the exact failure\n // this seam exists to prevent.\n stale: 'stale',\n staleForMs: 'staleForMs',\n} as const satisfies Record<string, keyof VerseLocalRuntimeReport>;\n\nconst WIRE_LOCAL_MODEL_KEYS = {\n id: 'id',\n label: 'label',\n state: 'state',\n sizeBytes: 'sizeBytes',\n sizeVramBytes: 'sizeVramBytes',\n placement: 'placement',\n gpuPercent: 'gpuPercent',\n memoryPercent: 'memoryPercent',\n family: 'family',\n arch: 'arch',\n expiresAt: 'expiresAt',\n contextLength: 'contextLength',\n nativeContextLength: 'nativeContextLength',\n parameterSize: 'parameterSize',\n quantization: 'quantization',\n capabilities: 'capabilities',\n supportsTools: 'supportsTools',\n} as const satisfies Record<string, keyof VerseLocalModel>;\n\n/**\n * Claude's version-pin constants, re-declared rather than imported.\n *\n * The annotations are the drift guard: `typeof import(...)` is a TYPE position,\n * so it is erased at build time, but it resolves to core's literal type\n * (`'2.1.257'`, `'usage-version-unsupported'`). Change either constant in\n * `core/verse/accounts.ts` and this file stops compiling — the same protection\n * a value import would give, without pulling node:fs into the browser.\n */\ntype CoreAccountsModule = typeof import('../../../../core/verse/accounts.js');\n\nexport const CLAUDE_VERSION_REASON: CoreAccountsModule['VERSE_CLAUDE_VERSION_REASON'] =\n 'usage-version-unsupported';\n\nexport const CLAUDE_USAGE_PINNED_VERSION: CoreAccountsModule['VERSE_CLAUDE_USAGE_PINNED_VERSION'] =\n '2.1.280';\n\n/** `byDay` is the wire key (T's deviation 1); `DailyUsage` below mirrors core. */\nconst WIRE_DAILY_USAGE_KEYS = {\n day: 'day',\n tokensIn: 'tokensIn',\n tokensOut: 'tokensOut',\n estCostUsd: 'estCostUsd',\n sessions: 'sessions',\n cacheRead: 'cacheRead',\n cacheWrite: 'cacheWrite',\n cacheHitRate: 'cacheHitRate',\n} as const satisfies Record<string, keyof CoreDailyUsage>;\n\n// Referenced so the guards are not dead code under `noUnusedLocals`.\nexport const WIRE_CONTRACT_KEYS = {\n account: WIRE_ACCOUNT_KEYS,\n window: WIRE_WINDOW_KEYS,\n credits: WIRE_CREDITS_KEYS,\n accountsSnapshot: WIRE_ACCOUNTS_SNAPSHOT_KEYS,\n collector: WIRE_COLLECTOR_KEYS,\n localSnapshot: WIRE_LOCAL_SNAPSHOT_KEYS,\n localRuntime: WIRE_LOCAL_RUNTIME_KEYS,\n localModel: WIRE_LOCAL_MODEL_KEYS,\n dailyUsage: WIRE_DAILY_USAGE_KEYS,\n} as const;\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/accounts\n// ---------------------------------------------------------------------------\n\n/** Provider ids this surface knows how to describe. */\nexport type AccountProvider = 'claude' | 'codex' | 'grok';\n\n/**\n * One quota window on an account.\n *\n * `resetsAt` is an ISO string when the provider gave a real timestamp (Codex\n * publishes an epoch the server normalizes). Claude's is STRUCTURALLY always\n * null and the human sentence lives in `nativeReport.resetDescription`, which\n * is rendered verbatim and never turned into a countdown.\n */\nexport interface AccountWindow {\n id: string;\n /** Human label when the server supplies one; otherwise `id` is shown. */\n label: string | null;\n /** 0–100. `null` is \"no reading\", never 0. */\n usedPercent: number | null;\n /** ISO 8601, or null. */\n resetsAt: string | null;\n /** Verbatim provider prose, e.g. \"resets Sep 25 at 7pm (America/New_York)\". */\n resetDescription: string | null;\n /**\n * True when the provider signalled `rateLimitReachedType` — the upstream\n * writes the SENTINEL 100, which is a flag, not a measurement. Rendered as\n * \"limit reached\", never as \"100% used\".\n */\n limitReached: boolean;\n /**\n * False when `usedPercent` is a FLAGGED SENTINEL rather than a reading.\n *\n * Codex writes `rateLimitReachedType` upstream as the value 100, so a bare\n * 100 is indistinguishable from a genuinely measured 100 by the time it\n * arrives. The server distinguishes them; this surface must not collapse\n * them back together. Absent on the wire → assumed measured UNLESS the\n * limit flag is set, which is the only case where the sentinel is written.\n */\n measured: boolean;\n}\n\n/**\n * Codex credits. Independent of the window: a 100%-used week with a spendable\n * balance is NOT blocked, and this surface must not say it is.\n */\nexport interface AccountCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Raw decimal string from the provider, kept verbatim for the title text. */\n balance: string | null;\n /** `balance` parsed, or null when it was absent/unparseable. */\n balanceValue: number | null;\n}\n\nexport interface Account {\n id: string;\n label: string;\n provider: AccountProvider;\n state: 'checking' | 'observed' | 'signed-out' | 'unavailable';\n authentication: 'signed-in' | 'signed-out' | 'unknown';\n /**\n * The connection monitor's own health verdict. Claude's is ALWAYS `unknown`\n * by construction (docs/VERSE-TELEMETRY-V2.md) — that is not a fault and is\n * never rendered as one.\n */\n health: string | null;\n planType: string | null;\n observedAt: string | null;\n windows: AccountWindow[];\n /**\n * The server's computed binding window (highest used percent). Kept as its\n * own field rather than recomputed blindly, but `accounts-model.ts` verifies\n * it against `windows` and falls back to computing it when absent.\n */\n binding: AccountWindow | null;\n credits: AccountCredits | null;\n /** Plain-language reason for a non-observed state. */\n reason: string | null;\n /**\n * Present when a probe failed CLOSED on a version pin (Claude's probe is\n * pinned to a specific Claude Code build). The fix is a one-line constant\n * bump, so the UI names it instead of showing a silent \"unknown\".\n */\n unsupported: { code: string; pinnedVersion: string | null } | null;\n /** Already sanitized — see `sanitizeCommand`. Null when nothing safe to show. */\n reconnectCommand: string | null;\n /**\n * The server's plain-language facts for this account (`VerseAccountRecord.\n * notes`). Grok's \"reconnect through `ashlr resources`, profile path withheld\n * on purpose\" lives here, which is why this surface shows notes rather than\n * only the machine-readable `reason`.\n */\n notes: string[];\n}\n\nexport interface AccountsSnapshot {\n sampledAt: string | null;\n refreshing: boolean;\n accounts: Account[];\n /**\n * Set when another collector process owns the quota-refresh lease, so these\n * readings are read-only and may be staler than this server's poll interval.\n */\n collectorNote: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/usage-series?window=7d|30d\n// ---------------------------------------------------------------------------\n\nexport type SeriesWindow = '7d' | '30d';\n\n/** `buildRollup(window, cfg).byDay` — see docs/VERSE-TELEMETRY-V2.md. */\nexport interface DailyUsage {\n /** YYYY-MM-DD. */\n day: string;\n tokensIn: number;\n tokensOut: number;\n /** ESTIMATED from a static price table. Never a billed figure. */\n estCostUsd: number;\n sessions: number;\n /** Optional: absent means the rollup carried no cache columns for that day. */\n cacheRead: number | null;\n cacheWrite: number | null;\n /** 0–1 fraction, or null. */\n cacheHitRate: number | null;\n}\n\nexport interface UsageSeries {\n window: SeriesWindow;\n days: DailyUsage[];\n generatedAt: string | null;\n /**\n * The server states outright that every cost column here is estimated.\n * Carried through rather than re-asserted locally so the disclosure the UI\n * prints is the one the producer actually made.\n */\n estimated: boolean;\n /** The server's own caveats, rendered verbatim beside the charts. */\n caveats: string[];\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models\n// ---------------------------------------------------------------------------\n\nexport interface LocalModel {\n name: string;\n /** Which runtime reported it, so a flattened list stays attributable. */\n runtime: 'ollama' | 'lmstudio' | null;\n /** Resident in memory right now (Ollama /api/ps), vs merely installed. */\n loaded: boolean;\n /** Total resident bytes, or null when not reported. */\n sizeBytes: number | null;\n /** Of `sizeBytes`, how much sits in VRAM. null = not reported. */\n sizeVramBytes: number | null;\n /**\n * Where the weights actually sit. `split` is the one that matters: a model\n * that only half-fits the GPU runs at a fraction of the speed of one that\n * fits, and that is the difference between usable and not.\n */\n placement: 'gpu' | 'cpu' | 'split' | 'unknown';\n /** The runtime's own GPU share, 0–100. Preferred over recomputing it. */\n gpuPercent: number | null;\n /** Resident size against total machine memory, 0–100, else null. */\n memoryPercent: number | null;\n family: string | null;\n arch: string | null;\n /** Keep-alive expiry (ISO). Only meaningful while `loaded`. */\n expiresAt: string | null;\n /** e.g. \"79.7B\". Provider string, never parsed into a number for display. */\n parameterSize: string | null;\n /** e.g. \"Q4_K_M\". */\n quantization: string | null;\n /** Native context from model_info[\"<arch>.context_length\"]. */\n nativeContext: number | null;\n /** Context Ashlr actually configures for this seat, when it differs. */\n configuredContext: number | null;\n /**\n * `capabilities` from /api/show. `null` means the capability list was not\n * reported — which is NOT the same as \"does not support tools\".\n */\n capabilities: string[] | null;\n /**\n * The runtime's own answer to \"can this drive an agentic session\", which is\n * AUTHORITATIVE over `capabilities` and must be preferred when non-null.\n *\n * This matters: owner T sends `capabilities: []` when a runtime reported no\n * capability list, and reading that array alone would render \"no tools\" —\n * a hard, wrong gate — where T's `supportsTools: null` correctly means\n * \"unknown\". Deriving tool support from the array alone was a real defect\n * at this seam, not a cosmetic one.\n */\n supportsTools: boolean | null;\n}\n\n/**\n * One runtime's own reachability, kept per-runtime rather than folded into the\n * flattened list, because STALENESS is per-runtime and must be stated.\n *\n * `stale` means the server served a RETAINED known-good reading after a probe\n * TIMED OUT (core `VERSE_LOCAL_LAST_GOOD_TTL_MS`). That is the honest choice\n * server-side — a timeout is \"no answer yet\", not \"the runtime is gone\" — but\n * it obliges this surface to say plainly that the numbers are N seconds old\n * rather than presenting them as fresh.\n */\nexport interface LocalRuntimeStatus {\n runtime: 'ollama' | 'lmstudio';\n reachable: boolean;\n /** Machine-readable degradation code; never rendered as a sentence. */\n reason: string | null;\n /** True when this report is a retained reading rather than a fresh probe. */\n stale: boolean;\n /** Age of that retained reading in ms. Null when `stale` is false. */\n staleForMs: number | null;\n modelCount: number;\n}\n\nexport interface LocalModelsSnapshot {\n reachable: boolean;\n models: LocalModel[];\n /** Machine memory budget in bytes, or null when the server did not say. */\n memoryBudgetBytes: number | null;\n /** Machine memory reported free right now, or null. */\n freeMemoryBytes: number | null;\n reason: string | null;\n /** Per-runtime reachability and staleness. Empty on a flat legacy body. */\n runtimes: LocalRuntimeStatus[];\n /** The server's own plain-language caveats for this snapshot. */\n notes: string[];\n sampledAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Narrowing helpers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction str(source: Record<string, unknown>, key: string): string | null {\n const v = source[key];\n return typeof v === 'string' && v.length > 0 ? v : null;\n}\n\nfunction num(source: Record<string, unknown>, key: string): number | null {\n const v = source[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n}\n\nfunction bool(source: Record<string, unknown>, key: string, fallback = false): boolean {\n const v = source[key];\n return typeof v === 'boolean' ? v : fallback;\n}\n\nfunction list(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\n/**\n * Drop anything that looks like a native-profile launcher invocation or an\n * absolute path into the private account store. The server is supposed to\n * strip these; this is the client-side backstop, because the cost of printing\n * one is unacceptable and the cost of showing \"no command\" is a sentence.\n */\nconst FORBIDDEN_COMMAND = /(launcher\\.mjs|native-profiles|account-connections|console-startup|\\/\\.ashlr\\b|Bearer\\s|--token\\b)/i;\n\nexport function sanitizeCommand(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 200) return null;\n if (FORBIDDEN_COMMAND.test(trimmed)) return null;\n // A newline would let a payload smuggle a second command onto the surface.\n if (/[\\r\\n]/.test(trimmed)) return null;\n return trimmed;\n}\n\nfunction clampPercent(value: number | null): number | null {\n if (value === null) return null;\n return Math.max(0, Math.min(100, value));\n}\n\nfunction projectWindow(raw: unknown): AccountWindow | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id') ?? str(r, 'label');\n if (id === null) return null;\n const native = record(r['nativeReport']);\n const limitReached = bool(r, 'limitReached') || bool(r, 'rateLimitReached');\n const measuredRaw = r['measured'];\n return {\n id,\n label: str(r, 'label'),\n usedPercent: clampPercent(num(r, 'usedPercent') ?? num(r, 'used_percent')),\n resetsAt: str(r, 'resetsAt') ?? str(r, 'resets_at'),\n resetDescription:\n (native ? str(native, 'resetDescription') : null) ?? str(r, 'resetDescription'),\n limitReached,\n // Absent → measured, EXCEPT under a limit flag, which is the one case the\n // upstream writes the sentinel 100. Defaulting a flagged window to\n // `measured: true` would let a denial print as \"100% used\".\n measured: typeof measuredRaw === 'boolean' ? measuredRaw : !limitReached,\n };\n}\n\nfunction projectCredits(raw: unknown): AccountCredits | null {\n const r = record(raw);\n if (!r) return null;\n const balance = str(r, 'balance');\n const parsed = balance === null ? num(r, 'balance') : Number.parseFloat(balance);\n return {\n hasCredits: bool(r, 'hasCredits') || bool(r, 'has_credits'),\n unlimited: bool(r, 'unlimited'),\n balance,\n balanceValue: typeof parsed === 'number' && Number.isFinite(parsed) ? parsed : null,\n };\n}\n\nconst PROVIDERS: readonly string[] = ['claude', 'codex', 'grok'];\n\nfunction projectAccount(raw: unknown): Account | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id');\n const provider = str(r, 'provider');\n if (id === null || provider === null || !PROVIDERS.includes(provider)) return null;\n\n const windows = list(r['windows'])\n .map(projectWindow)\n .filter((w): w is AccountWindow => w !== null);\n\n const state = str(r, 'state');\n const auth = str(r, 'authentication');\n const unsupportedRaw = record(r['unsupported']);\n\n return {\n id,\n label: str(r, 'label') ?? id,\n provider: provider as AccountProvider,\n state:\n state === 'checking' || state === 'observed' || state === 'signed-out' || state === 'unavailable'\n ? state\n : 'unavailable',\n authentication: auth === 'signed-in' || auth === 'signed-out' ? auth : 'unknown',\n health: str(r, 'health'),\n planType: str(r, 'planType') ?? str(r, 'plan_type'),\n observedAt: str(r, 'observedAt'),\n windows,\n binding: projectWindow(r['binding']),\n credits: projectCredits(r['credits']),\n reason: str(r, 'reason'),\n unsupported: projectUnsupported(r, unsupportedRaw),\n reconnectCommand: sanitizeCommand(r['reconnectCommand']),\n notes: list(r['notes']).filter((n): n is string => typeof n === 'string'),\n };\n}\n\n/**\n * A version-pinned probe that failed CLOSED, named rather than swallowed.\n *\n * `unsupported` is not a field on the wire. Owner T reports the failure as the\n * verbatim probe code in `reason` (`usage-version-unsupported`) and states the\n * pin in `notes`, so this derives the structured form from those rather than\n * requiring a late contract change. An explicit `unsupported` object is still\n * honoured first, so a server that grows one later wins without a client edit.\n */\nfunction projectUnsupported(\n r: Record<string, unknown>,\n explicit: Record<string, unknown> | null,\n): Account['unsupported'] {\n if (explicit) {\n return {\n code: str(explicit, 'code') ?? CLAUDE_VERSION_REASON,\n pinnedVersion: str(explicit, 'pinnedVersion') ?? str(explicit, 'version'),\n };\n }\n const reason = str(r, 'reason');\n if (reason !== CLAUDE_VERSION_REASON) return null;\n return { code: reason, pinnedVersion: CLAUDE_USAGE_PINNED_VERSION };\n}\n\n/**\n * The read-only banner. Owner T reports lease ownership as a structured\n * `collector` status, not a flat `collectorNote`, so the note is derived from\n * it — and ONLY when another process owns the lease, because that is the one\n * case where these readings may be staler than this server's poll interval.\n * A stray `collectorNote` string is still accepted for forward compatibility.\n */\nfunction projectCollectorNote(root: Record<string, unknown>): string | null {\n const flat = str(root, 'collectorNote');\n if (flat) return flat;\n const collector = record(root['collector']);\n if (!collector) return null;\n if (str(collector, 'owner') !== 'another-collector') return null;\n return (\n str(collector, 'note') ??\n 'Another collector process owns the quota-refresh lease, so these readings are read-only and may be staler than this server’s poll interval.'\n );\n}\n\nexport function projectAccountsSnapshot(raw: unknown): AccountsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n const rawAccounts = Array.isArray(root['accounts']) ? root['accounts'] : Array.isArray(raw) ? raw : null;\n if (rawAccounts === null) return null;\n return {\n sampledAt: str(root, 'sampledAt'),\n refreshing: bool(root, 'refreshing'),\n accounts: rawAccounts.map(projectAccount).filter((a): a is Account => a !== null),\n collectorNote: projectCollectorNote(root),\n };\n}\n\nfunction projectDay(raw: unknown): DailyUsage | null {\n const r = record(raw);\n if (!r) return null;\n const day = str(r, 'day');\n if (day === null || !/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return null;\n return {\n day,\n tokensIn: num(r, 'tokensIn') ?? 0,\n tokensOut: num(r, 'tokensOut') ?? 0,\n estCostUsd: num(r, 'estCostUsd') ?? 0,\n sessions: num(r, 'sessions') ?? 0,\n cacheRead: num(r, 'cacheRead'),\n cacheWrite: num(r, 'cacheWrite'),\n cacheHitRate: num(r, 'cacheHitRate'),\n };\n}\n\n/**\n * `byDay` is the wire key. Owner T wraps the series as\n * `{window, byDay, estimated, caveats}` rather than returning a bare array\n * (documented deviation 1), so `byDay` is read FIRST. `days` and a bare array\n * remain accepted so an older or differently-shaped server degrades to a\n * rendered series instead of a dead panel.\n */\nexport function projectUsageSeries(raw: unknown, requested: SeriesWindow): UsageSeries | null {\n const root = record(raw);\n const rawDays = root\n ? Array.isArray(root['byDay'])\n ? root['byDay']\n : Array.isArray(root['days'])\n ? root['days']\n : null\n : Array.isArray(raw)\n ? raw\n : null;\n if (rawDays === null) return null;\n const windowValue = root ? str(root, 'window') : null;\n return {\n window: windowValue === '7d' || windowValue === '30d' ? windowValue : requested,\n days: rawDays\n .map(projectDay)\n .filter((d): d is DailyUsage => d !== null)\n .sort((a, b) => a.day.localeCompare(b.day)),\n generatedAt: root ? str(root, 'generatedAt') : null,\n // The producer asserts estimation explicitly. Absent → still true: every\n // cost column on this route is price-table derived, and defaulting the\n // disclosure OFF would drop it exactly when the server is older.\n estimated: root ? bool(root, 'estimated', true) : true,\n caveats: root ? list(root['caveats']).filter((c): c is string => typeof c === 'string') : [],\n };\n}\n\nfunction projectLocalModel(raw: unknown, runtime: LocalModel['runtime']): LocalModel | null {\n const r = record(raw);\n if (!r) return null;\n // `label`/`id` are owner T's spellings; `name`/`model` are the Ollama-native\n // ones a differently-shaped server might send.\n const name = str(r, 'label') ?? str(r, 'id') ?? str(r, 'name') ?? str(r, 'model');\n if (name === null) return null;\n const caps = r['capabilities'];\n const state = str(r, 'state');\n const supportsTools = r['supportsTools'];\n\n // `nativeContextLength` is the architecture maximum; `contextLength` is what\n // the runtime actually configured for the loaded instance. They are two\n // different facts and the panel shows the gap between them, so they must not\n // collapse onto one field.\n const nativeContext = num(r, 'nativeContextLength') ?? num(r, 'nativeContext');\n const configuredContext = num(r, 'contextLength') ?? num(r, 'configuredContext');\n\n const placement = str(r, 'placement');\n\n return {\n name,\n runtime,\n loaded: state !== null ? state === 'loaded' : bool(r, 'loaded') || bool(r, 'resident'),\n sizeBytes: num(r, 'sizeBytes') ?? num(r, 'size'),\n sizeVramBytes: num(r, 'sizeVramBytes') ?? num(r, 'size_vram'),\n placement:\n placement === 'gpu' || placement === 'cpu' || placement === 'split' ? placement : 'unknown',\n gpuPercent: clampPercent(num(r, 'gpuPercent')),\n memoryPercent: clampPercent(num(r, 'memoryPercent')),\n family: str(r, 'family'),\n arch: str(r, 'arch'),\n expiresAt: str(r, 'expiresAt') ?? str(r, 'expires_at'),\n parameterSize: str(r, 'parameterSize') ?? str(r, 'parameter_size'),\n quantization: str(r, 'quantization') ?? str(r, 'quantization_level'),\n nativeContext,\n // Only a genuine narrowing is worth showing. When the runtime reports the\n // same number twice there is no truncation to report.\n configuredContext:\n configuredContext !== null && nativeContext !== null && configuredContext === nativeContext\n ? null\n : configuredContext,\n capabilities: Array.isArray(caps) ? caps.filter((c): c is string => typeof c === 'string') : null,\n supportsTools: typeof supportsTools === 'boolean' ? supportsTools : null,\n };\n}\n\nfunction projectRuntimeReport(\n raw: unknown,\n runtime: NonNullable<LocalModel['runtime']>,\n): { status: LocalRuntimeStatus; models: LocalModel[] } | null {\n const r = record(raw);\n if (!r) return null;\n const rawModels = Array.isArray(r['models']) ? r['models'] : null;\n if (rawModels === null) return null;\n const models = rawModels\n .map((m) => projectLocalModel(m, runtime))\n .filter((m): m is LocalModel => m !== null);\n const stale = bool(r, 'stale');\n return {\n models,\n status: {\n runtime,\n reachable: bool(r, 'reachable'),\n reason: str(r, 'reason'),\n stale,\n // Only meaningful under `stale`. A staleForMs on a fresh report would be\n // a contradiction, and printing it would age a current reading.\n staleForMs: stale ? num(r, 'staleForMs') : null,\n modelCount: models.length,\n },\n };\n}\n\n/**\n * Owner T reports local availability per RUNTIME (`ollama`, `lmStudio`) with a\n * shared `machine` budget. This panel answers one question — \"what can I run\n * right now, and against how much memory\" — so the runtimes are flattened into\n * one list, each row keeping its `runtime` so it stays attributable.\n *\n * Reachability is the OR of the runtimes: one dead runtime is not an unreachable\n * local stack. `reason` is only carried when NOTHING is reachable, because a\n * degradation note beside a working list would misdescribe what is on screen.\n *\n * A flat `{reachable, models, memoryBudgetBytes}` body is still accepted, so an\n * older or differently-shaped server degrades rather than rendering nothing.\n */\nexport function projectLocalModels(raw: unknown): LocalModelsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n\n const ollama = projectRuntimeReport(root['ollama'], 'ollama');\n const lmStudio = projectRuntimeReport(root['lmStudio'] ?? root['lmstudio'], 'lmstudio');\n\n if (ollama !== null || lmStudio !== null) {\n const reports = [ollama, lmStudio].filter((x): x is NonNullable<typeof x> => x !== null);\n const reachable = reports.some((x) => x.status.reachable);\n const machine = record(root['machine']);\n return {\n reachable,\n models: reports.flatMap((x) => x.models),\n memoryBudgetBytes:\n (machine ? num(machine, 'totalMemoryBytes') : null) ??\n num(root, 'memoryBudgetBytes') ??\n num(root, 'memoryBudget'),\n freeMemoryBytes: machine ? num(machine, 'freeMemoryBytes') : null,\n reason: reachable\n ? null\n : (reports.map((x) => x.status.reason).find((x) => x !== null) ?? null),\n runtimes: reports.map((x) => x.status),\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n }\n\n const rawModels = Array.isArray(root['models']) ? root['models'] : null;\n if (rawModels === null) return null;\n return {\n reachable: bool(root, 'reachable', true),\n models: rawModels.map((m) => projectLocalModel(m, null)).filter((m): m is LocalModel => m !== null),\n memoryBudgetBytes: num(root, 'memoryBudgetBytes') ?? num(root, 'memoryBudget'),\n freeMemoryBytes: num(root, 'freeMemoryBytes'),\n reason: str(root, 'reason'),\n // A flat legacy body carries no per-runtime reachability, so there is\n // nothing to attribute and nothing to call stale. An empty list says that\n // honestly; a fabricated entry would not.\n runtimes: [],\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n}\n","/**\n * routes/verse/usage/usage-queries.ts — the reads behind the Usage section.\n *\n * `/api/control` is fetched through the shared `controlSnapshotQuery` so this\n * section rides the same cache (and the same SSE invalidation) as every other\n * view rather than opening a second copy of a large snapshot.\n *\n * `/api/verse/control` is owner B's new route. It is fetched through a\n * NON-throwing wrapper because this section must still render when the route\n * is absent (server started without --allow-dispatch, or B's route not landed\n * yet): a missing configured-caps source is a degraded panel, not a dead\n * section. 401 is the one error that still propagates — an expired read\n * session is an unauthorized state for the whole surface, not a degraded one.\n *\n * The cache key is deliberately NOT shared with the Autonomy section's own\n * read of the same route: this module stores a wrapper shape, and two owners\n * writing different value types under one key would be a real bug.\n */\nimport type { FrontierUsage } from '../../../../core/usage/frontier-usage.js';\nimport { ApiError, apiGet } from '../../../data/client.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { projectLocalModels, type SeriesWindow } from './usage-contract.js';\n\nexport const USAGE_FRONTIER_KEY = 'verse-usage-frontier';\nexport const USAGE_VERSE_CONTROL_KEY = 'verse-usage-control';\n\n/** GET /api/usage — per-engine frontier usage (see core/usage/frontier-usage.ts). */\nexport const frontierUsageQuery: QueryDef<FrontierUsage> = {\n key: USAGE_FRONTIER_KEY,\n fetch: (signal) => apiGet<FrontierUsage>('/api/usage', signal),\n};\n\nexport interface VerseControlRead {\n /** Raw body; narrowed by `projectVerseControl` (owner B's types are not landed). */\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeControlFailure(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return 'This server does not expose /api/verse/control, so configured caps and today’s spend are unavailable here.';\n }\n return `Configured caps unavailable (HTTP ${err.status}).`;\n }\n return 'Configured caps unavailable: the request failed.';\n}\n\nexport const verseControlQuery: QueryDef<VerseControlRead> = {\n key: USAGE_VERSE_CONTROL_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>('/api/verse/control', signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeControlFailure(err) };\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Owner T's routes (GET /api/verse/{accounts,usage-series,local-models})\n// ---------------------------------------------------------------------------\n//\n// These three are fetched through the SAME non-throwing wrapper pattern as\n// /api/verse/control, for the same reason and one more: they are landing in\n// parallel with this section. A server that predates them answers 404, and a\n// 404 here means \"this panel is degraded\", not \"the Usage view is broken\".\n// 401 still propagates, because an expired read session is an unauthorized\n// state for the whole surface.\n//\n// The bodies are narrowed structurally by usage-contract.ts rather than cast,\n// so a field-name drift between T's route and this client degrades to an\n// honest \"unknown\" instead of throwing at render time.\n\nexport const USAGE_ACCOUNTS_KEY = 'verse-usage-accounts';\nexport const USAGE_LOCAL_MODELS_KEY = 'verse-usage-local-models';\nexport const USAGE_SERIES_KEY_PREFIX = 'verse-usage-series';\n\n/** A read that is allowed to be absent. `raw` is null when it was. */\nexport interface OptionalRead {\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeOptionalFailure(path: string, err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This server does not expose ${path} yet, so this panel has no source.`;\n }\n return `${path} answered HTTP ${err.status}.`;\n }\n return `${path} could not be reached.`;\n}\n\nfunction optionalGet(path: string): (signal?: AbortSignal) => Promise<OptionalRead> {\n return async (signal) => {\n try {\n const raw = await apiGet<unknown>(path, signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeOptionalFailure(path, err) };\n }\n };\n}\n\n/** GET /api/verse/accounts — per-account state, windows, credits, plan. */\nexport const verseAccountsQuery: QueryDef<OptionalRead> = {\n key: USAGE_ACCOUNTS_KEY,\n fetch: optionalGet('/api/verse/accounts'),\n};\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models — and why this one read retries\n// ---------------------------------------------------------------------------\n//\n// `/api/verse/local-models` probes the runtimes live on every request, with a\n// 2s per-probe timeout (core/verse/local-models.ts\n// VERSE_LOCAL_PROBE_TIMEOUT_MS). A probe that times out is reported as\n// `{reachable: false, reason: 'ollama-unreachable'}` in a perfectly ordinary\n// HTTP 200 — which is correct on the server's terms (it genuinely did not get\n// an answer) but is NOT the same fact as \"Ollama is not running\", and nothing\n// in the payload distinguishes the two.\n//\n// That distinction matters here because this section is the thing that causes\n// the timeout. Mounting Usage, and every press of its Refresh button, fires\n// seven reads at once, several of which spawn short-lived account-probe\n// processes server-side; measured against a live Ollama with twelve models,\n// roughly one burst in ten starves the 2s probe and comes back\n// `ollama-unreachable`. Nothing re-reads this route afterwards — it has no SSE\n// invalidation key — so that one false negative is what the operator stares\n// at, and pressing Refresh re-creates the very burst that produced it.\n//\n// So a reported-unreachable local stack is RE-READ, up to twice, with a short\n// gap for the burst to drain. This is not \"ignore the failure\": the retries\n// are bounded, each one is a real request, and whatever the last read says is\n// what this section renders — a runtime that is genuinely down answers fast\n// (connection refused, not a timeout) and still reports unreachable, three\n// times, in well under a second.\n//\n// Only an AVAILABLE read is retried. A 404/500 (`available: false`) is a\n// statement about the route, not about the runtime, and re-asking cannot\n// change it.\n\n/** Two extra reads at most, spaced so the section's own request burst drains. */\nconst LOCAL_MODELS_RETRY_DELAYS_MS = [350, 1200] as const;\n\nconst readLocalModels = optionalGet('/api/verse/local-models');\n\nfunction reportsNothingReachable(read: OptionalRead): boolean {\n if (!read.available) return false;\n const snapshot = projectLocalModels(read.raw);\n return snapshot !== null && !snapshot.reachable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** GET /api/verse/local-models — resident vs installed, VRAM split, tools. */\nexport const verseLocalModelsQuery: QueryDef<OptionalRead> = {\n key: USAGE_LOCAL_MODELS_KEY,\n fetch: async (signal) => {\n let read = await readLocalModels(signal);\n for (const delayMs of LOCAL_MODELS_RETRY_DELAYS_MS) {\n if (!reportsNothingReachable(read)) return read;\n await sleep(delayMs, signal);\n read = await readLocalModels(signal);\n }\n return read;\n },\n};\n\n// One QueryDef per window, created once at module scope: useQuery keys on\n// `def.key`, and minting a fresh object per render would be harmless but\n// useRefresh/useRefetch's useCallback deps would churn for no reason.\nconst SERIES_QUERIES: Record<SeriesWindow, QueryDef<OptionalRead>> = {\n '7d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:7d`,\n fetch: optionalGet('/api/verse/usage-series?window=7d'),\n },\n '30d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:30d`,\n fetch: optionalGet('/api/verse/usage-series?window=30d'),\n },\n};\n\nexport function usageSeriesQuery(window: SeriesWindow): QueryDef<OptionalRead> {\n return SERIES_QUERIES[window];\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,
|
|
2
|
-
//# sourceMappingURL=use-guarded-action-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";import{O as n,o as r,s as i}from"./global-CNNGMril.js";import{y as a}from"./format-Dk4Fmxax.js";import{n as o}from"./control-queries-DAvlh_YM.js";var s=t(e(),1);function c(e){return e instanceof i?`This server runs without dispatch, so that action is unavailable.`:e instanceof o?e.message:e instanceof r?e.status===401?"The mutation token was rejected. Unlock again with the token `ashlr verse` printed.":e.detail?a(e.detail):e.status===400?a(e.message):e.status===409?`The server refused the action, and sent no reason.`:a(e.message):e instanceof Error?a(e.message):`That action failed. Try again.`}function l(){let[e,t]=(0,s.useState)(!1),[r,a]=(0,s.useState)(null),[o,l]=(0,s.useState)(!1),[u,d]=(0,s.useState)(!1),[f,p]=(0,s.useState)(``),m=(0,s.useRef)(null),h=(0,s.useCallback)(async(e,n)=>{t(!0),a(null);try{let t=await e();n?.(t)}catch(e){e instanceof i?l(!0):a(c(e))}finally{t(!1)}},[]),g=(0,s.useCallback)((e,t,r)=>{a(null);let i=r;if(n()){h(e,i);return}m.current={fn:e,onResult:i},p(t),d(!0)},[h]),_=(0,s.useCallback)(()=>{d(!1);let e=m.current;m.current=null,e&&n()&&h(e.fn,e.onResult)},[h]);return{request:g,busy:e,error:r,clearError:(0,s.useCallback)(()=>a(null),[]),readOnly:o,tokenOpen:u,tokenReason:f,closeToken:_}}export{l as n,c as t};
|
|
2
|
+
//# sourceMappingURL=use-guarded-action-BZmBv7CJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-guarded-action-
|
|
1
|
+
{"version":3,"file":"use-guarded-action-BZmBv7CJ.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/use-guarded-action.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/use-guarded-action.ts — the one place a Verse control\n * surface turns \"the operator clicked something destructive\" into an actual\n * request. Shared by the Autonomy cockpit and the Approvals surface.\n *\n * It folds together the three things every mutating click in this app has to\n * do, which were previously re-implemented per call site:\n *\n * - **Token hand-off.** No mutation hold yet → remember the action, open\n * MutationTokenDialog, and run it once the token lands. The hold is read\n * LIVE on dialog close, never from a render-time snapshot, because\n * MutationTokenDialog's onClose fires before this component re-renders.\n * - **Read-only sessions.** Every POST 404s when the server was started\n * without dispatch. That is a session mode, not a failure, so it flips a\n * `readOnly` flag the surface renders as an explanation — never as an error\n * toast and never as a crash.\n * - **Busy + error state** for exactly one in-flight action at a time.\n */\nimport { useCallback, useRef, useState } from 'react';\nimport { hasMutationHold } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\nimport { VerseControlLockedError } from './control-queries.js';\nimport { tidyProse } from './format.js';\n\nexport function describeControlError(err: unknown): string {\n if (err instanceof DispatchDisabledError) return 'This server runs without dispatch, so that action is unavailable.';\n if (err instanceof VerseControlLockedError) return err.message;\n if (err instanceof ApiError) {\n if (err.status === 401) return 'The mutation token was rejected. Unlock again with the token `ashlr verse` printed.';\n // The control plane writes a careful refusal ladder — \"no repositories are\n // enrolled, so the loop would do nothing. Add scope first.\" — and returns\n // it as `note` on the 409 body. A blanket \"something else is already\n // running\" replaced every one of those with a sentence that was usually\n // false and never actionable. Show the server's own words whenever it\n // sent any; the generic line is now only the last resort. `tidyProse`\n // reads any ISO instant in those words as local time.\n if (err.detail) return tidyProse(err.detail);\n if (err.status === 400) return tidyProse(err.message);\n if (err.status === 409) return 'The server refused the action, and sent no reason.';\n return tidyProse(err.message);\n }\n return err instanceof Error ? tidyProse(err.message) : 'That action failed. Try again.';\n}\n\nexport interface GuardedAction {\n /**\n * Run `fn`, prompting for the mutation token first when none is held.\n *\n * `onResult` receives `fn`'s resolved value when it succeeds. It exists\n * because the value was previously dropped on the floor, and for the daemon\n * routes that value carries the server's own account of what just happened\n * (`VerseDaemonActionResult.note` — e.g. that an ordinary stop also engaged\n * the global kill switch). It is not called when `fn` throws.\n */\n request: <T>(fn: () => Promise<T>, reason: string, onResult?: (result: T) => void) => void;\n busy: boolean;\n error: string | null;\n clearError: () => void;\n /** True once a POST 404'd — the server has no dispatch enabled. */\n readOnly: boolean;\n /** Bind these three to <MutationTokenDialog/>. */\n tokenOpen: boolean;\n tokenReason: string;\n closeToken: () => void;\n}\n\nexport function useGuardedAction(): GuardedAction {\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [readOnly, setReadOnly] = useState(false);\n const [tokenOpen, setTokenOpen] = useState(false);\n const [tokenReason, setTokenReason] = useState('');\n // The deferred action and the callback that wants its result travel together\n // — the token dialog may run it a render later, long after `request` returned.\n const pending = useRef<{ fn: () => Promise<unknown>; onResult?: (result: never) => void } | null>(null);\n\n const perform = useCallback(\n async (fn: () => Promise<unknown>, onResult?: (result: never) => void) => {\n setBusy(true);\n setError(null);\n try {\n const result = await fn();\n onResult?.(result as never);\n } catch (err) {\n if (err instanceof DispatchDisabledError) setReadOnly(true);\n else setError(describeControlError(err));\n } finally {\n setBusy(false);\n }\n },\n [],\n );\n\n const request = useCallback(\n <T,>(fn: () => Promise<T>, reason: string, onResult?: (result: T) => void) => {\n setError(null);\n const handler = onResult as ((result: never) => void) | undefined;\n if (hasMutationHold()) {\n void perform(fn, handler);\n return;\n }\n pending.current = { fn, onResult: handler };\n setTokenReason(reason);\n setTokenOpen(true);\n },\n [perform],\n );\n\n const closeToken = useCallback(() => {\n setTokenOpen(false);\n const next = pending.current;\n pending.current = null;\n // Live read: the dialog closes synchronously after setToken().\n if (next && hasMutationHold()) void perform(next.fn, next.onResult);\n }, [perform]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return { request, busy, error, clearError, readOnly, tokenOpen, tokenReason, closeToken };\n}\n"],"mappings":"gNAwBA,SAAgB,EAAqB,EAAsB,CAiBzD,OAhBI,aAAe,EAA8B,oEAC7C,aAAe,EAAgC,EAAI,QACnD,aAAe,EACb,EAAI,SAAW,IAAY,sFAQ3B,EAAI,OAAe,EAAU,EAAI,MAAM,EACvC,EAAI,SAAW,IAAY,EAAU,EAAI,OAAO,EAChD,EAAI,SAAW,IAAY,qDACxB,EAAU,EAAI,OAAO,EAEvB,aAAe,MAAQ,EAAU,EAAI,OAAO,EAAI,gCACzD,CAwBA,SAAgB,GAAkC,CAChD,GAAM,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,CAAS,EAAK,EAChC,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAwB,IAAI,EAChD,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAS,EAAK,EACxC,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,EAAK,EAC1C,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAS,EAAE,EAG3C,GAAA,EAAU,EAAA,OAAA,CAAkF,IAAI,EAEhG,GAAA,EAAU,EAAA,YAAA,CACd,MAAO,EAA4B,IAAuC,CACxE,EAAQ,EAAI,EACZ,EAAS,IAAI,EACb,GAAI,CACF,IAAM,EAAS,MAAM,EAAG,EACxB,IAAW,CAAe,CAC5B,OAAS,EAAK,CACR,aAAe,EAAuB,EAAY,EAAI,EACrD,EAAS,EAAqB,CAAG,CAAC,CACzC,QAAU,CACR,EAAQ,EAAK,CACf,CACF,EACA,CAAC,CACH,EAEM,GAAA,EAAU,EAAA,YAAA,EACT,EAAsB,EAAgB,IAAmC,CAC5E,EAAS,IAAI,EACb,IAAM,EAAU,EAChB,GAAI,EAAgB,EAAG,CACrB,EAAa,EAAI,CAAO,EACxB,MACF,CACA,EAAQ,QAAU,CAAE,KAAI,SAAU,CAAQ,EAC1C,EAAe,CAAM,EACrB,EAAa,EAAI,CACnB,EACA,CAAC,CAAO,CACV,EAEM,GAAA,EAAa,EAAA,YAAA,KAAkB,CACnC,EAAa,EAAK,EAClB,IAAM,EAAO,EAAQ,QACrB,EAAQ,QAAU,KAEd,GAAQ,EAAgB,GAAG,EAAa,EAAK,GAAI,EAAK,QAAQ,CACpE,EAAG,CAAC,CAAO,CAAC,EAIZ,MAAO,CAAE,UAAS,OAAM,QAAO,YAAA,EAFZ,EAAA,YAAA,KAAkB,EAAS,IAAI,EAAG,CAAC,CAEvB,EAAY,WAAU,YAAW,cAAa,YAAW,CAC1F"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,
|
|
2
|
-
//# sourceMappingURL=use-ticker-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";var n=t(e(),1);function r(e=1e3){let[t,r]=(0,n.useState)(()=>Date.now());return(0,n.useEffect)(()=>{let t=setInterval(()=>r(Date.now()),e);return()=>clearInterval(t)},[e]),t}export{r as t};
|
|
2
|
+
//# sourceMappingURL=use-ticker-CkJ4-0wU.js.map
|
package/dist/core/web/public/next/assets/{use-ticker-D9yi49my.js.map → use-ticker-CkJ4-0wU.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-ticker-
|
|
1
|
+
{"version":3,"file":"use-ticker-CkJ4-0wU.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/use-ticker.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/use-ticker.ts — a shared 1Hz clock for the countdown\n * and the relative ages in the status header — one interval per consumer\n * rather than a bespoke timer inside each panel.\n *\n * It deliberately keeps ticking under `prefers-reduced-motion`: a countdown is\n * information, not decoration. The design language's quiet-motion rule governs\n * transitions and animation, not numbers that have to stay true.\n */\nimport { useEffect, useState } from 'react';\n\nexport function useNow(intervalMs = 1000): number {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), intervalMs);\n return () => clearInterval(id);\n }, [intervalMs]);\n return now;\n}\n"],"mappings":"8DAWA,SAAgB,EAAO,EAAa,IAAc,CAChD,GAAM,CAAC,EAAK,IAAA,EAAU,EAAA,SAAA,KAAe,KAAK,IAAI,CAAC,EAK/C,OAJA,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAK,gBAAkB,EAAO,KAAK,IAAI,CAAC,EAAG,CAAU,EAC3D,UAAa,cAAc,CAAE,CAC/B,EAAG,CAAC,CAAU,CAAC,EACR,CACT"}
|