@ashlr/hub 3.16.0 → 3.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +2 -2
- package/dist/authority-surface.json +5 -5
- package/dist/build-identity.json +2 -2
- package/dist/core/daemon/loop.js +1 -0
- package/dist/core/daemon/loop.js.map +1 -1
- package/dist/core/daemon/tick-hooks.d.ts +2 -0
- package/dist/core/daemon/tick-hooks.js.map +1 -1
- package/dist/core/fleet/tick-hooks-live.d.ts +2 -1
- package/dist/core/fleet/tick-hooks-live.js +49 -7
- package/dist/core/fleet/tick-hooks-live.js.map +1 -1
- package/dist/core/web/public/next/assets/ActionMenu-Bv-kQxD4.js +2 -0
- package/dist/core/web/public/next/assets/ActionMenu-Bv-kQxD4.js.map +1 -0
- package/dist/core/web/public/next/assets/Advanced-Be7Frv-G.js +2 -0
- package/dist/core/web/public/next/assets/Advanced-Be7Frv-G.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentDetailScreen-DzqHmufO.js +2 -0
- package/dist/core/web/public/next/assets/AgentDetailScreen-DzqHmufO.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentToolsSheet-D00kLnIq.js +2 -0
- package/dist/core/web/public/next/assets/AgentToolsSheet-D00kLnIq.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentToolsStrip-CSus9Dr3.js +2 -0
- package/dist/core/web/public/next/assets/AgentToolsStrip-CSus9Dr3.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentsScreen-WoR0oSLZ.js +2 -0
- package/dist/core/web/public/next/assets/AgentsScreen-WoR0oSLZ.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentsSection-D5mKoOhH.js +3 -0
- package/dist/core/web/public/next/assets/AgentsSection-D5mKoOhH.js.map +1 -0
- package/dist/core/web/public/next/assets/App-Uy6lDpKw.js +8 -0
- package/dist/core/web/public/next/assets/App-Uy6lDpKw.js.map +1 -0
- package/dist/core/web/public/next/assets/AppsSection-Cfhmc4r3.js +2 -0
- package/dist/core/web/public/next/assets/AppsSection-Cfhmc4r3.js.map +1 -0
- package/dist/core/web/public/next/assets/AreaTrend-Bz3ETKPk.js +2 -0
- package/dist/core/web/public/next/assets/AreaTrend-Bz3ETKPk.js.map +1 -0
- package/dist/core/web/public/next/assets/AutomationsSection-D4K8db0o.js +2 -0
- package/dist/core/web/public/next/assets/AutomationsSection-D4K8db0o.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-DUiNMgr8.js +3 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-DUiNMgr8.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-wxRZ7vSw.js +2 -0
- package/dist/core/web/public/next/assets/AutonomySection-wxRZ7vSw.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyStatus-B-PCVnFO.js +2 -0
- package/dist/core/web/public/next/assets/AutonomyStatus-B-PCVnFO.js.map +1 -0
- package/dist/core/web/public/next/assets/BranchBar-Bs4r_Vh6.js +2 -0
- package/dist/core/web/public/next/assets/BranchBar-Bs4r_Vh6.js.map +1 -0
- package/dist/core/web/public/next/assets/BrowserPanel-BMQcviI1.js +7 -0
- package/dist/core/web/public/next/assets/BrowserPanel-BMQcviI1.js.map +1 -0
- package/dist/core/web/public/next/assets/BudgetControl-A4TEONtT.js +2 -0
- package/dist/core/web/public/next/assets/BudgetControl-A4TEONtT.js.map +1 -0
- package/dist/core/web/public/next/assets/Button-CMR_Op-0.js +2 -0
- package/dist/core/web/public/next/assets/Button-CMR_Op-0.js.map +1 -0
- package/dist/core/web/public/next/assets/CapacityStrip-B-2NDrA5.js +2 -0
- package/dist/core/web/public/next/assets/CapacityStrip-B-2NDrA5.js.map +1 -0
- package/dist/core/web/public/next/assets/ChangesPaneHost-CS5qGjwM.js +16 -0
- package/dist/core/web/public/next/assets/ChangesPaneHost-CS5qGjwM.js.map +1 -0
- package/dist/core/web/public/next/assets/ChartFrame-sZTnZkVd.js +2 -0
- package/dist/core/web/public/next/assets/ChartFrame-sZTnZkVd.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatPanes-CicgTVpN.js +2 -0
- package/dist/core/web/public/next/assets/ChatPanes-CicgTVpN.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-Cc6sudpF.js +3 -0
- package/dist/core/web/public/next/assets/ChatSection-Cc6sudpF.js.map +1 -0
- package/dist/core/web/public/next/assets/ChecksPanel-BGWgv8Zb.js +5 -0
- package/dist/core/web/public/next/assets/ChecksPanel-BGWgv8Zb.js.map +1 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-CqsidwfU.js +2 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-CqsidwfU.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandPalette-rwEZ20MN.js +3 -0
- package/dist/core/web/public/next/assets/CommandPalette-rwEZ20MN.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandSection-C2CLkVXN.js +3 -0
- package/dist/core/web/public/next/assets/CommandSection-C2CLkVXN.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandWorkflowForm-DAbPIdI3.js +9 -0
- package/dist/core/web/public/next/assets/CommandWorkflowForm-DAbPIdI3.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-fqHtzYXX.js +3 -0
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-fqHtzYXX.js.map +1 -0
- package/dist/core/web/public/next/assets/CompareDialog-Cwfpaa8I.js +4 -0
- package/dist/core/web/public/next/assets/CompareDialog-Cwfpaa8I.js.map +1 -0
- package/dist/core/web/public/next/assets/ComputerControl-DU0cuVSY.js +2 -0
- package/dist/core/web/public/next/assets/ComputerControl-DU0cuVSY.js.map +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-B_wCnbcC.js +2 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-B_wCnbcC.js.map +1 -0
- package/dist/core/web/public/next/assets/DeleteChatDialog-CxMh53yX.js +2 -0
- package/dist/core/web/public/next/assets/DeleteChatDialog-CxMh53yX.js.map +1 -0
- package/dist/core/web/public/next/assets/DevinStopDialog-D9Bziccz.js +2 -0
- package/dist/core/web/public/next/assets/DevinStopDialog-D9Bziccz.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-DI5D6Is2.js +2 -0
- package/dist/core/web/public/next/assets/Dialog-DI5D6Is2.js.map +1 -0
- package/dist/core/web/public/next/assets/DiffPane-Buo19Bqr.js +2 -0
- package/dist/core/web/public/next/assets/DiffPane-Buo19Bqr.js.map +1 -0
- package/dist/core/web/public/next/assets/DiffViewer-dO0RQoqA.js +2 -0
- package/dist/core/web/public/next/assets/DiffViewer-dO0RQoqA.js.map +1 -0
- package/dist/core/web/public/next/assets/DockHost-KJUHjoiG.js +2 -0
- package/dist/core/web/public/next/assets/DockHost-KJUHjoiG.js.map +1 -0
- package/dist/core/web/public/next/assets/EmptyState-C3BUt2Ev.js +2 -0
- package/dist/core/web/public/next/assets/EmptyState-C3BUt2Ev.js.map +1 -0
- package/dist/core/web/public/next/assets/Epistemic-DlG2QqKJ.js +2 -0
- package/dist/core/web/public/next/assets/Epistemic-DlG2QqKJ.js.map +1 -0
- package/dist/core/web/public/next/assets/EvidenceTimeline-D1GB9F-f.js +2 -0
- package/dist/core/web/public/next/assets/EvidenceTimeline-D1GB9F-f.js.map +1 -0
- package/dist/core/web/public/next/assets/FilesPane-icSP5vPt.js +2 -0
- package/dist/core/web/public/next/assets/FilesPane-icSP5vPt.js.map +1 -0
- package/dist/core/web/public/next/assets/FleetScreen-V_X8SeD3.js +2 -0
- package/dist/core/web/public/next/assets/FleetScreen-V_X8SeD3.js.map +1 -0
- package/dist/core/web/public/next/assets/FleetSection-xyhfpRJy.js +5 -0
- package/dist/core/web/public/next/assets/FleetSection-xyhfpRJy.js.map +1 -0
- package/dist/core/web/public/next/assets/Funnel-BlzQ5FOU.js +2 -0
- package/dist/core/web/public/next/assets/Funnel-BlzQ5FOU.js.map +1 -0
- package/dist/core/web/public/next/assets/GearTray-Dvu-ee-h.js +2 -0
- package/dist/core/web/public/next/assets/GearTray-Dvu-ee-h.js.map +1 -0
- package/dist/core/web/public/next/assets/GitDialogs-o0eCEqAN.js +2 -0
- package/dist/core/web/public/next/assets/GitDialogs-o0eCEqAN.js.map +1 -0
- package/dist/core/web/public/next/assets/GrowthSection-CyqJOzob.js +3 -0
- package/dist/core/web/public/next/assets/GrowthSection-CyqJOzob.js.map +1 -0
- package/dist/core/web/public/next/assets/HandoffDialog-0uTNyK99.js +2 -0
- package/dist/core/web/public/next/assets/HandoffDialog-0uTNyK99.js.map +1 -0
- package/dist/core/web/public/next/assets/HomeBody-DJjN3GTV.js +3 -0
- package/dist/core/web/public/next/assets/HomeBody-DJjN3GTV.js.map +1 -0
- package/dist/core/web/public/next/assets/HomeSeats-IJvjh9iH.js +2 -0
- package/dist/core/web/public/next/assets/HomeSeats-IJvjh9iH.js.map +1 -0
- package/dist/core/web/public/next/assets/Input-CsSZI8QC.js +2 -0
- package/dist/core/web/public/next/assets/Input-CsSZI8QC.js.map +1 -0
- package/dist/core/web/public/next/assets/LaunchDialog-DReYqlI0.js +9 -0
- package/dist/core/web/public/next/assets/LaunchDialog-DReYqlI0.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderCard-82indlOE.js +2 -0
- package/dist/core/web/public/next/assets/LeaderCard-82indlOE.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderConversation-8hDF6Gh3.js +3 -0
- package/dist/core/web/public/next/assets/LeaderConversation-8hDF6Gh3.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderScreen-BxPiwHcT.js +2 -0
- package/dist/core/web/public/next/assets/LeaderScreen-BxPiwHcT.js.map +1 -0
- package/dist/core/web/public/next/assets/LessonsPanel-BG558qil.js +2 -0
- package/dist/core/web/public/next/assets/LessonsPanel-BG558qil.js.map +1 -0
- package/dist/core/web/public/next/assets/LiveTimer-DUgUBr49.js +2 -0
- package/dist/core/web/public/next/assets/LiveTimer-DUgUBr49.js.map +1 -0
- package/dist/core/web/public/next/assets/LocalSeatBadge-D6U4Q2P3.js +2 -0
- package/dist/core/web/public/next/assets/LocalSeatBadge-D6U4Q2P3.js.map +1 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-Brn70z84.js +2 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-Brn70z84.js.map +1 -0
- package/dist/core/web/public/next/assets/McpSection-Dz8Ga2Rg.js +2 -0
- package/dist/core/web/public/next/assets/McpSection-Dz8Ga2Rg.js.map +1 -0
- package/dist/core/web/public/next/assets/MessageMarkdown-CQfYQaXB.js +3 -0
- package/dist/core/web/public/next/assets/MessageMarkdown-CQfYQaXB.js.map +1 -0
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-DPaNQMj8.js +72 -0
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-DPaNQMj8.js.map +1 -0
- package/dist/core/web/public/next/assets/Meter-TnD7Ris6.js +2 -0
- package/dist/core/web/public/next/assets/Meter-TnD7Ris6.js.map +1 -0
- package/dist/core/web/public/next/assets/MicButton-Dc9g2Z_E.js +2 -0
- package/dist/core/web/public/next/assets/MicButton-Dc9g2Z_E.js.map +1 -0
- package/dist/core/web/public/next/assets/MindSection-DGpYq8c7.js +3 -0
- package/dist/core/web/public/next/assets/MindSection-DGpYq8c7.js.map +1 -0
- package/dist/core/web/public/next/assets/MobileComposer-DbSZ2rxa.js +2 -0
- package/dist/core/web/public/next/assets/MobileComposer-DbSZ2rxa.js.map +1 -0
- package/dist/core/web/public/next/assets/MobileGuardSheet-qQJev_w3.js +2 -0
- package/dist/core/web/public/next/assets/MobileGuardSheet-qQJev_w3.js.map +1 -0
- package/dist/core/web/public/next/assets/MobileRuntime-BEnY4Uvs.js +3 -0
- package/dist/core/web/public/next/assets/MobileRuntime-BEnY4Uvs.js.map +1 -0
- package/dist/core/web/public/next/assets/MoreScreen-CG0E5S8G.js +2 -0
- package/dist/core/web/public/next/assets/MoreScreen-CG0E5S8G.js.map +1 -0
- package/dist/core/web/public/next/assets/MultiModelBar-DgMyP8IC.js +7 -0
- package/dist/core/web/public/next/assets/MultiModelBar-DgMyP8IC.js.map +1 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-T3r9EtHi.js +2 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-T3r9EtHi.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-BDAcTlK8.js +3 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-BDAcTlK8.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouList-BFubkjzF.js +2 -0
- package/dist/core/web/public/next/assets/NeedsYouList-BFubkjzF.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouScreen-B3Dk15T_.js +2 -0
- package/dist/core/web/public/next/assets/NeedsYouScreen-B3Dk15T_.js.map +1 -0
- package/dist/core/web/public/next/assets/NewAgentScreen-zf1bqGYC.js +2 -0
- package/dist/core/web/public/next/assets/NewAgentScreen-zf1bqGYC.js.map +1 -0
- package/dist/core/web/public/next/assets/NewChatDialog-el95cRTF.js +4 -0
- package/dist/core/web/public/next/assets/NewChatDialog-el95cRTF.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-Bi8gZOuz.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-Bi8gZOuz.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingGate-CRexmMn5.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingGate-CRexmMn5.js.map +1 -0
- package/dist/core/web/public/next/assets/PlaybooksSection-R2_wyVpQ.js +9 -0
- package/dist/core/web/public/next/assets/PlaybooksSection-R2_wyVpQ.js.map +1 -0
- package/dist/core/web/public/next/assets/PreviewPane-Djw_GJ20.js +2 -0
- package/dist/core/web/public/next/assets/PreviewPane-Djw_GJ20.js.map +1 -0
- package/dist/core/web/public/next/assets/ProviderLogo-DIfJXNWf.js +2 -0
- package/dist/core/web/public/next/assets/ProviderLogo-DIfJXNWf.js.map +1 -0
- package/dist/core/web/public/next/assets/RailStatus-B3eI2AaD.js +2 -0
- package/dist/core/web/public/next/assets/RailStatus-B3eI2AaD.js.map +1 -0
- package/dist/core/web/public/next/assets/ReasoningPane-ExT8XgQB.js +2 -0
- package/dist/core/web/public/next/assets/ReasoningPane-ExT8XgQB.js.map +1 -0
- package/dist/core/web/public/next/assets/ReasoningSheet-YF4OS4lM.js +2 -0
- package/dist/core/web/public/next/assets/ReasoningSheet-YF4OS4lM.js.map +1 -0
- package/dist/core/web/public/next/assets/RefreshIndicator-BJoefKSa.js +2 -0
- package/dist/core/web/public/next/assets/RefreshIndicator-BJoefKSa.js.map +1 -0
- package/dist/core/web/public/next/assets/RemoteMobileApp-C2SflRkm.js +2 -0
- package/dist/core/web/public/next/assets/RemoteMobileApp-C2SflRkm.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-FkAdn3Sv.js +7 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-FkAdn3Sv.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-CFHrLqmA.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-CFHrLqmA.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DtnZgDr_.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DtnZgDr_.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-DTz5-ndE.js +2 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-DTz5-ndE.js.map +1 -0
- package/dist/core/web/public/next/assets/RunInCloudAction-DvoDMV54.js +2 -0
- package/dist/core/web/public/next/assets/RunInCloudAction-DvoDMV54.js.map +1 -0
- package/dist/core/web/public/next/assets/RunInDevinAction-BwCkFxLX.js +2 -0
- package/dist/core/web/public/next/assets/RunInDevinAction-BwCkFxLX.js.map +1 -0
- package/dist/core/web/public/next/assets/ScreenHost-jdgnt5U2.js +3 -0
- package/dist/core/web/public/next/assets/ScreenHost-jdgnt5U2.js.map +1 -0
- package/dist/core/web/public/next/assets/SeatSelector-DnpH5D_D.js +3 -0
- package/dist/core/web/public/next/assets/SeatSelector-DnpH5D_D.js.map +1 -0
- package/dist/core/web/public/next/assets/Segmented-BECZDbsg.js +2 -0
- package/dist/core/web/public/next/assets/Segmented-BECZDbsg.js.map +1 -0
- package/dist/core/web/public/next/assets/Select-DjQDkPJU.js +2 -0
- package/dist/core/web/public/next/assets/Select-DjQDkPJU.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionGate-CWuI8dDR.js +2 -0
- package/dist/core/web/public/next/assets/SessionGate-CWuI8dDR.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionInsightChip-DRsIQu29.js +2 -0
- package/dist/core/web/public/next/assets/SessionInsightChip-DRsIQu29.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionSearch-Bya3EXJl.js +2 -0
- package/dist/core/web/public/next/assets/SessionSearch-Bya3EXJl.js.map +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-CXjiHNQb.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-CXjiHNQb.js.map +1 -0
- package/dist/core/web/public/next/assets/SetupChecklist-YUMOJNbk.js +2 -0
- package/dist/core/web/public/next/assets/SetupChecklist-YUMOJNbk.js.map +1 -0
- package/dist/core/web/public/next/assets/ShadowDecisions-BP2WgGMi.js +3 -0
- package/dist/core/web/public/next/assets/ShadowDecisions-BP2WgGMi.js.map +1 -0
- package/dist/core/web/public/next/assets/Sheet-Czuz3h6A.js +2 -0
- package/dist/core/web/public/next/assets/Sheet-Czuz3h6A.js.map +1 -0
- package/dist/core/web/public/next/assets/ShortcutsOverlay-D_ICte5N.js +2 -0
- package/dist/core/web/public/next/assets/ShortcutsOverlay-D_ICte5N.js.map +1 -0
- package/dist/core/web/public/next/assets/Sidebar-CcI1_B9Y.js +3 -0
- package/dist/core/web/public/next/assets/Sidebar-CcI1_B9Y.js.map +1 -0
- package/dist/core/web/public/next/assets/SkipToContent-B0GAKhYQ.js +2 -0
- package/dist/core/web/public/next/assets/SkipToContent-B0GAKhYQ.js.map +1 -0
- package/dist/core/web/public/next/assets/Slider-Dzv55CNY.js +2 -0
- package/dist/core/web/public/next/assets/Slider-Dzv55CNY.js.map +1 -0
- package/dist/core/web/public/next/assets/SourcesPane-rxRCi7cL.js +2 -0
- package/dist/core/web/public/next/assets/SourcesPane-rxRCi7cL.js.map +1 -0
- package/dist/core/web/public/next/assets/SourcesPanel-LyMp7aLt.js +2 -0
- package/dist/core/web/public/next/assets/SourcesPanel-LyMp7aLt.js.map +1 -0
- package/dist/core/web/public/next/assets/StatTile-1_HPOflX.js +2 -0
- package/dist/core/web/public/next/assets/StatTile-1_HPOflX.js.map +1 -0
- package/dist/core/web/public/next/assets/StatusBadge-zR7YgIa8.js +2 -0
- package/dist/core/web/public/next/assets/StatusBadge-zR7YgIa8.js.map +1 -0
- package/dist/core/web/public/next/assets/StepBand-BGX2RpFV.js +2 -0
- package/dist/core/web/public/next/assets/StepBand-BGX2RpFV.js.map +1 -0
- package/dist/core/web/public/next/assets/Surface-BEToBKC3.js +2 -0
- package/dist/core/web/public/next/assets/Surface-BEToBKC3.js.map +1 -0
- package/dist/core/web/public/next/assets/Swimlane-DAf7u5p3.js +2 -0
- package/dist/core/web/public/next/assets/Swimlane-DAf7u5p3.js.map +1 -0
- package/dist/core/web/public/next/assets/Switch-mvc9lQcT.js +2 -0
- package/dist/core/web/public/next/assets/Switch-mvc9lQcT.js.map +1 -0
- package/dist/core/web/public/next/assets/Tag-Chqolzxz.js +2 -0
- package/dist/core/web/public/next/assets/Tag-Chqolzxz.js.map +1 -0
- package/dist/core/web/public/next/assets/TerminalPane-4wn3AxS0.js +3 -0
- package/dist/core/web/public/next/assets/TerminalPane-4wn3AxS0.js.map +1 -0
- package/dist/core/web/public/next/assets/TerminalPane-D7-O0ssr.js +26 -0
- package/dist/core/web/public/next/assets/TerminalPane-D7-O0ssr.js.map +1 -0
- package/dist/core/web/public/next/assets/ThinkingBlock-gWESdTxs.js +2 -0
- package/dist/core/web/public/next/assets/ThinkingBlock-gWESdTxs.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-XqJvgt7b.js +2 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-XqJvgt7b.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseView-D0j9HVku.js +9 -0
- package/dist/core/web/public/next/assets/UniverseView-D0j9HVku.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-DnSPo4Ua.js +3 -0
- package/dist/core/web/public/next/assets/UsageSection-DnSPo4Ua.js.map +1 -0
- package/dist/core/web/public/next/assets/UsePlaybookAction-71M3gO7g.js +2 -0
- package/dist/core/web/public/next/assets/UsePlaybookAction-71M3gO7g.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DO84Xscn.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DO84Xscn.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseMobileApp-CrCDQcw5.js +3 -0
- package/dist/core/web/public/next/assets/VerseMobileApp-CrCDQcw5.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseShared-CFE5B-IY.js +2 -0
- package/dist/core/web/public/next/assets/VerseShared-CFE5B-IY.js.map +1 -0
- package/dist/core/web/public/next/assets/VoiceHud-CumHX7If.js +2 -0
- package/dist/core/web/public/next/assets/VoiceHud-CumHX7If.js.map +1 -0
- package/dist/core/web/public/next/assets/VoiceInput-CWTVwTwV.js +2 -0
- package/dist/core/web/public/next/assets/VoiceInput-CWTVwTwV.js.map +1 -0
- package/dist/core/web/public/next/assets/WikiSection-BIGSx4z-.js +2 -0
- package/dist/core/web/public/next/assets/WikiSection-BIGSx4z-.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-5sa9Xggd.js +6 -0
- package/dist/core/web/public/next/assets/Workspace-5sa9Xggd.js.map +1 -0
- package/dist/core/web/public/next/assets/actions-BPyW8QC-.js +2 -0
- package/dist/core/web/public/next/assets/actions-BPyW8QC-.js.map +1 -0
- package/dist/core/web/public/next/assets/agent-tools-client-Si2ncqwV.js +2 -0
- package/dist/core/web/public/next/assets/agent-tools-client-Si2ncqwV.js.map +1 -0
- package/dist/core/web/public/next/assets/agent-transcript-model-D-34Ll59.js +7 -0
- package/dist/core/web/public/next/assets/agent-transcript-model-D-34Ll59.js.map +1 -0
- package/dist/core/web/public/next/assets/agents-focus-E_TBTTmZ.js +2 -0
- package/dist/core/web/public/next/assets/agents-focus-E_TBTTmZ.js.map +1 -0
- package/dist/core/web/public/next/assets/app-version-y5sfMXiE.js +2 -0
- package/dist/core/web/public/next/assets/app-version-y5sfMXiE.js.map +1 -0
- package/dist/core/web/public/next/assets/apps-model-BnjwUIUH.js +2 -0
- package/dist/core/web/public/next/assets/apps-model-BnjwUIUH.js.map +1 -0
- package/dist/core/web/public/next/assets/ask-seat-CWE-jY2D.js +2 -0
- package/dist/core/web/public/next/assets/ask-seat-CWE-jY2D.js.map +1 -0
- package/dist/core/web/public/next/assets/authority-model-DVMxkDV4.js +2 -0
- package/dist/core/web/public/next/assets/authority-model-DVMxkDV4.js.map +1 -0
- package/dist/core/web/public/next/assets/automations-focus-B-lklYid.js +2 -0
- package/dist/core/web/public/next/assets/automations-focus-B-lklYid.js.map +1 -0
- package/dist/core/web/public/next/assets/budget-model-Bwv4MZSa.js +2 -0
- package/dist/core/web/public/next/assets/budget-model-Bwv4MZSa.js.map +1 -0
- package/dist/core/web/public/next/assets/budget-queries-t-Bdoly3.js +2 -0
- package/dist/core/web/public/next/assets/budget-queries-t-Bdoly3.js.map +1 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-CJ5F-CtB.js +2 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-CJ5F-CtB.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-Di0_Q980.js +2 -0
- package/dist/core/web/public/next/assets/charts-Di0_Q980.js.map +1 -0
- package/dist/core/web/public/next/assets/chat-pane-data-5MDEsLff.js +2 -0
- package/dist/core/web/public/next/assets/chat-pane-data-5MDEsLff.js.map +1 -0
- package/dist/core/web/public/next/assets/checkpoint-queries-6thqsAiE.js +2 -0
- package/dist/core/web/public/next/assets/checkpoint-queries-6thqsAiE.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-model-CzKeuxfm.js +2 -0
- package/dist/core/web/public/next/assets/cloud-model-CzKeuxfm.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-queries-DrR_QeUK.js +2 -0
- package/dist/core/web/public/next/assets/cloud-queries-DrR_QeUK.js.map +1 -0
- package/dist/core/web/public/next/assets/command-catalog-COH2G2xv.js +2 -0
- package/dist/core/web/public/next/assets/command-catalog-COH2G2xv.js.map +1 -0
- package/dist/core/web/public/next/assets/composer-queries-GxFt1UQm.js +2 -0
- package/dist/core/web/public/next/assets/composer-queries-GxFt1UQm.js.map +1 -0
- package/dist/core/web/public/next/assets/composer-state-DTAoie2b.js +2 -0
- package/dist/core/web/public/next/assets/composer-state-DTAoie2b.js.map +1 -0
- package/dist/core/web/public/next/assets/connectivity-zM4_O-XZ.js +2 -0
- package/dist/core/web/public/next/assets/connectivity-zM4_O-XZ.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-CKXUZd0O.js +2 -0
- package/dist/core/web/public/next/assets/context-model-CKXUZd0O.js.map +1 -0
- package/dist/core/web/public/next/assets/context-model-DYkDKK6C.js +3 -0
- package/dist/core/web/public/next/assets/context-model-DYkDKK6C.js.map +1 -0
- package/dist/core/web/public/next/assets/context-queries-D0Aydl5L.js +2 -0
- package/dist/core/web/public/next/assets/context-queries-D0Aydl5L.js.map +1 -0
- package/dist/core/web/public/next/assets/control-queries-C5uQTzJi.js +2 -0
- package/dist/core/web/public/next/assets/control-queries-C5uQTzJi.js.map +1 -0
- package/dist/core/web/public/next/assets/copy-setup-IHGsNfkz.js +2 -0
- package/dist/core/web/public/next/assets/copy-setup-IHGsNfkz.js.map +1 -0
- package/dist/core/web/public/next/assets/deep-link-DgTIAuc2.js +2 -0
- package/dist/core/web/public/next/assets/deep-link-DgTIAuc2.js.map +1 -0
- package/dist/core/web/public/next/assets/device-permissions-BplZgouU.js +2 -0
- package/dist/core/web/public/next/assets/device-permissions-BplZgouU.js.map +1 -0
- package/dist/core/web/public/next/assets/devin-queries-Bltl6Jz2.js +2 -0
- package/dist/core/web/public/next/assets/devin-queries-Bltl6Jz2.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-icons-DPXFt10d.js +2 -0
- package/dist/core/web/public/next/assets/dock-icons-DPXFt10d.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-panes-DNSv-1Tq.js +2 -0
- package/dist/core/web/public/next/assets/dock-panes-DNSv-1Tq.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-control-queries-DZEa-aFz.js +2 -0
- package/dist/core/web/public/next/assets/fleet-control-queries-DZEa-aFz.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-model-D4n8ErhA.js +2 -0
- package/dist/core/web/public/next/assets/fleet-model-D4n8ErhA.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-queries-BO1MHMFz.js +2 -0
- package/dist/core/web/public/next/assets/fleet-queries-BO1MHMFz.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-state-yM0mV9_P.js +3 -0
- package/dist/core/web/public/next/assets/fleet-state-yM0mV9_P.js.map +1 -0
- package/dist/core/web/public/next/assets/focus-trap-C2rynI8q.js +2 -0
- package/dist/core/web/public/next/assets/focus-trap-C2rynI8q.js.map +1 -0
- package/dist/core/web/public/next/assets/format-V6IiIMAL.js +2 -0
- package/dist/core/web/public/next/assets/format-V6IiIMAL.js.map +1 -0
- package/dist/core/web/public/next/assets/git-model-rVA0Jd0g.js +5 -0
- package/dist/core/web/public/next/assets/git-model-rVA0Jd0g.js.map +1 -0
- package/dist/core/web/public/next/assets/global-CYfRwH6t.js +3 -0
- package/dist/core/web/public/next/assets/global-CYfRwH6t.js.map +1 -0
- package/dist/core/web/public/next/assets/guarded-action-A9ZsIE8S.js +3 -0
- package/dist/core/web/public/next/assets/guarded-action-A9ZsIE8S.js.map +1 -0
- package/dist/core/web/public/next/assets/guarded-runners-xMakDn92.js +2 -0
- package/dist/core/web/public/next/assets/guarded-runners-xMakDn92.js.map +1 -0
- package/dist/core/web/public/next/assets/headroom-C4dyfw7P.js +2 -0
- package/dist/core/web/public/next/assets/headroom-C4dyfw7P.js.map +1 -0
- package/dist/core/web/public/next/assets/health-queries-BHoSyIcL.js +2 -0
- package/dist/core/web/public/next/assets/health-queries-BHoSyIcL.js.map +1 -0
- package/dist/core/web/public/next/assets/icons-BBm_Cy62.js +2 -0
- package/dist/core/web/public/next/assets/icons-BBm_Cy62.js.map +1 -0
- package/dist/core/web/public/next/assets/index-_izD07R9.js +11 -0
- package/dist/core/web/public/next/assets/index-_izD07R9.js.map +1 -0
- package/dist/core/web/public/next/assets/jev-queries-D-AMM0sw.js +2 -0
- package/dist/core/web/public/next/assets/jev-queries-D-AMM0sw.js.map +1 -0
- package/dist/core/web/public/next/assets/ladder-queries-BIpJVqxu.js +2 -0
- package/dist/core/web/public/next/assets/ladder-queries-BIpJVqxu.js.map +1 -0
- package/dist/core/web/public/next/assets/leader-focus-Dh4gXTSi.js +2 -0
- package/dist/core/web/public/next/assets/leader-focus-Dh4gXTSi.js.map +1 -0
- package/dist/core/web/public/next/assets/live-model-D97AfBFz.js +2 -0
- package/dist/core/web/public/next/assets/live-model-D97AfBFz.js.map +1 -0
- package/dist/core/web/public/next/assets/mind.module-rVKz51LB.js +2 -0
- package/dist/core/web/public/next/assets/mind.module-rVKz51LB.js.map +1 -0
- package/dist/core/web/public/next/assets/mobile-actions-V26-lGbH.js +2 -0
- package/dist/core/web/public/next/assets/mobile-actions-V26-lGbH.js.map +1 -0
- package/dist/core/web/public/next/assets/mobile-toast-9-WQbWQu.js +2 -0
- package/dist/core/web/public/next/assets/mobile-toast-9-WQbWQu.js.map +1 -0
- package/dist/core/web/public/next/assets/multimodel-flows-D309YXSk.js +7 -0
- package/dist/core/web/public/next/assets/multimodel-flows-D309YXSk.js.map +1 -0
- package/dist/core/web/public/next/assets/multimodel-queries-BuslyWtq.js +2 -0
- package/dist/core/web/public/next/assets/multimodel-queries-BuslyWtq.js.map +1 -0
- package/dist/core/web/public/next/assets/mutations-B9AZoqNR.js +2 -0
- package/dist/core/web/public/next/assets/mutations-B9AZoqNR.js.map +1 -0
- package/dist/core/web/public/next/assets/nav-DC0ynjdb.js +2 -0
- package/dist/core/web/public/next/assets/nav-DC0ynjdb.js.map +1 -0
- package/dist/core/web/public/next/assets/needs-you-actions-BOHN9fg7.js +2 -0
- package/dist/core/web/public/next/assets/needs-you-actions-BOHN9fg7.js.map +1 -0
- package/dist/core/web/public/next/assets/needs-you-model-ChGg3r5r.js +2 -0
- package/dist/core/web/public/next/assets/needs-you-model-ChGg3r5r.js.map +1 -0
- package/dist/core/web/public/next/assets/open-terminal-5F1FNUEB.js +2 -0
- package/dist/core/web/public/next/assets/open-terminal-5F1FNUEB.js.map +1 -0
- package/dist/core/web/public/next/assets/open-terminal-request-SjPIZmAt.js +2 -0
- package/dist/core/web/public/next/assets/open-terminal-request-SjPIZmAt.js.map +1 -0
- package/dist/core/web/public/next/assets/overnight-queries-Dc46kMfg.js +2 -0
- package/dist/core/web/public/next/assets/overnight-queries-Dc46kMfg.js.map +1 -0
- package/dist/core/web/public/next/assets/palette-handoff-xkWF9v2M.js +2 -0
- package/dist/core/web/public/next/assets/palette-handoff-xkWF9v2M.js.map +1 -0
- package/dist/core/web/public/next/assets/panes-DOXM13lF.js +3 -0
- package/dist/core/web/public/next/assets/panes-DOXM13lF.js.map +1 -0
- package/dist/core/web/public/next/assets/path-display-C6BmdnBS.js +2 -0
- package/dist/core/web/public/next/assets/path-display-C6BmdnBS.js.map +1 -0
- package/dist/core/web/public/next/assets/percent-text-CSk89zQF.js +2 -0
- package/dist/core/web/public/next/assets/percent-text-CSk89zQF.js.map +1 -0
- package/dist/core/web/public/next/assets/playbook-composer-Bz-fFxXW.js +2 -0
- package/dist/core/web/public/next/assets/playbook-composer-Bz-fFxXW.js.map +1 -0
- package/dist/core/web/public/next/assets/playbook-focus-BXu0yrHF.js +2 -0
- package/dist/core/web/public/next/assets/playbook-focus-BXu0yrHF.js.map +1 -0
- package/dist/core/web/public/next/assets/playbooks-queries-Cpnl3avl.js +2 -0
- package/dist/core/web/public/next/assets/playbooks-queries-Cpnl3avl.js.map +1 -0
- package/dist/core/web/public/next/assets/preloaded-E_jepvvg.js +2 -0
- package/dist/core/web/public/next/assets/preloaded-E_jepvvg.js.map +1 -0
- package/dist/core/web/public/next/assets/primitives-Bynv7bPl.js +1 -0
- package/dist/core/web/public/next/assets/pwa-D2lyCiGV.js +2 -0
- package/dist/core/web/public/next/assets/pwa-D2lyCiGV.js.map +1 -0
- package/dist/core/web/public/next/assets/queries-C0Bs3TOo.js +2 -0
- package/dist/core/web/public/next/assets/queries-C0Bs3TOo.js.map +1 -0
- package/dist/core/web/public/next/assets/reasoning-pref-DDPtfTM3.js +2 -0
- package/dist/core/web/public/next/assets/reasoning-pref-DDPtfTM3.js.map +1 -0
- package/dist/core/web/public/next/assets/remote-session-Dj27m1xb.js +3 -0
- package/dist/core/web/public/next/assets/remote-session-Dj27m1xb.js.map +1 -0
- package/dist/core/web/public/next/assets/resolved-store-B2iJa5C2.js +2 -0
- package/dist/core/web/public/next/assets/resolved-store-B2iJa5C2.js.map +1 -0
- package/dist/core/web/public/next/assets/resources-queries-pVRhOTEt.js +2 -0
- package/dist/core/web/public/next/assets/resources-queries-pVRhOTEt.js.map +1 -0
- package/dist/core/web/public/next/assets/reveal-anchor-BAMmxMeu.js +2 -0
- package/dist/core/web/public/next/assets/reveal-anchor-BAMmxMeu.js.map +1 -0
- package/dist/core/web/public/next/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/dist/core/web/public/next/assets/seat-readiness-a5B9iqP-.js +2 -0
- package/dist/core/web/public/next/assets/seat-readiness-a5B9iqP-.js.map +1 -0
- package/dist/core/web/public/next/assets/seat-subscription-Cut6eC-8.js +2 -0
- package/dist/core/web/public/next/assets/seat-subscription-Cut6eC-8.js.map +1 -0
- package/dist/core/web/public/next/assets/sheet-BxZSmdad.js +2 -0
- package/dist/core/web/public/next/assets/sheet-BxZSmdad.js.map +1 -0
- package/dist/core/web/public/next/assets/sidebar-model-COzIPSiP.js +2 -0
- package/dist/core/web/public/next/assets/sidebar-model-COzIPSiP.js.map +1 -0
- package/dist/core/web/public/next/assets/slots-BJc3RJkV.js +3 -0
- package/dist/core/web/public/next/assets/slots-BJc3RJkV.js.map +1 -0
- package/dist/core/web/public/next/assets/sources-queries-DCKiXNAt.js +4 -0
- package/dist/core/web/public/next/assets/sources-queries-DCKiXNAt.js.map +1 -0
- package/dist/core/web/public/next/assets/sse-It4xa040.js +2 -0
- package/dist/core/web/public/next/assets/sse-It4xa040.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-data-NFl_uS--.js +2 -0
- package/dist/core/web/public/next/assets/surface-data-NFl_uS--.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-prefetch-jMaLNI6z.js +2 -0
- package/dist/core/web/public/next/assets/surface-prefetch-jMaLNI6z.js.map +1 -0
- package/dist/core/web/public/next/assets/tasks-model-CbmPgWL8.js +2 -0
- package/dist/core/web/public/next/assets/tasks-model-CbmPgWL8.js.map +1 -0
- package/dist/core/web/public/next/assets/terminal-client-DTXAf2-x.js +2 -0
- package/dist/core/web/public/next/assets/terminal-client-DTXAf2-x.js.map +1 -0
- package/dist/core/web/public/next/assets/terminal-icons-qBCOwqu-.js +2 -0
- package/dist/core/web/public/next/assets/terminal-icons-qBCOwqu-.js.map +1 -0
- package/dist/core/web/public/next/assets/terminal-view-CksH3CsK.js +6 -0
- package/dist/core/web/public/next/assets/terminal-view-CksH3CsK.js.map +1 -0
- package/dist/core/web/public/next/assets/thread-data-C8z55msn.js +2 -0
- package/dist/core/web/public/next/assets/thread-data-C8z55msn.js.map +1 -0
- package/dist/core/web/public/next/assets/ui-parts-CcpmRBwj.js +2 -0
- package/dist/core/web/public/next/assets/ui-parts-CcpmRBwj.js.map +1 -0
- package/dist/core/web/public/next/assets/usage-queries-BxrTLCaJ.js +2 -0
- package/dist/core/web/public/next/assets/usage-queries-BxrTLCaJ.js.map +1 -0
- package/dist/core/web/public/next/assets/use-chat-activity-O8I0Ho0m.js +2 -0
- package/dist/core/web/public/next/assets/use-chat-activity-O8I0Ho0m.js.map +1 -0
- package/dist/core/web/public/next/assets/use-guarded-action-BZ6Bye9l.js +2 -0
- package/dist/core/web/public/next/assets/use-guarded-action-BZ6Bye9l.js.map +1 -0
- package/dist/core/web/public/next/assets/use-ticker-CUsNALmP.js +2 -0
- package/dist/core/web/public/next/assets/use-ticker-CUsNALmP.js.map +1 -0
- package/dist/core/web/public/next/assets/use-token-gate-DgnO9fbv.js +2 -0
- package/dist/core/web/public/next/assets/use-token-gate-DgnO9fbv.js.map +1 -0
- package/dist/core/web/public/next/assets/useAutoSeat-CIEXM-Q5.js +2 -0
- package/dist/core/web/public/next/assets/useAutoSeat-CIEXM-Q5.js.map +1 -0
- package/dist/core/web/public/next/assets/useOnboarding-BAmRBxkI.js +2 -0
- package/dist/core/web/public/next/assets/useOnboarding-BAmRBxkI.js.map +1 -0
- package/dist/core/web/public/next/assets/useSeatHealth-DPkSSddF.js +2 -0
- package/dist/core/web/public/next/assets/useSeatHealth-DPkSSddF.js.map +1 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-CpsRhfmt.js +2 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-CpsRhfmt.js.map +1 -0
- package/dist/core/web/public/next/assets/useVerseSession-DeW1iFpw.js +2 -0
- package/dist/core/web/public/next/assets/useVerseSession-DeW1iFpw.js.map +1 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-CvUqjRmZ.js +2 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-CvUqjRmZ.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-bootstrap-query-ANtL2OPN.js +2 -0
- package/dist/core/web/public/next/assets/verse-bootstrap-query-ANtL2OPN.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-icons-C92Qt7rh.js +2 -0
- package/dist/core/web/public/next/assets/verse-icons-C92Qt7rh.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-model-DAOz9LrY.js +2 -0
- package/dist/core/web/public/next/assets/verse-model-DAOz9LrY.js.map +1 -0
- package/dist/core/web/public/next/assets/warmup-B2DWWeeC.js +3 -0
- package/dist/core/web/public/next/assets/warmup-B2DWWeeC.js.map +1 -0
- package/dist/core/web/public/next/assets/why-seat-model-Bn6O26JJ.js +2 -0
- package/dist/core/web/public/next/assets/why-seat-model-Bn6O26JJ.js.map +1 -0
- package/dist/core/web/public/next/assets/wiki-focus-CwC-yoT9.js +2 -0
- package/dist/core/web/public/next/assets/wiki-focus-CwC-yoT9.js.map +1 -0
- package/dist/core/web/public/next/assets/workspace-model-C-q_I8xN.js +2 -0
- package/dist/core/web/public/next/assets/workspace-model-C-q_I8xN.js.map +1 -0
- package/dist/core/web/public/next/index.html +2 -1
- package/dist/core/web/remote-gateway-policy.js +5 -0
- package/dist/core/web/remote-gateway-policy.js.map +1 -1
- package/dist/core/web/static.d.ts +4 -3
- package/dist/core/web/static.js +8 -5
- package/dist/core/web/static.js.map +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/node_modules/fast-uri/index.js +20 -5
- package/node_modules/fast-uri/lib/utils.js +8 -1
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/component-safe-serialization.test.js +58 -0
- package/node_modules/fast-uri/test/ipv6-validation.test.js +34 -0
- package/node_modules/ip-address/README.md +134 -134
- package/node_modules/ip-address/dist/address-error.d.ts +11 -0
- package/node_modules/ip-address/dist/address-error.js.map +1 -1
- package/node_modules/ip-address/dist/ipv4.d.ts +22 -6
- package/node_modules/ip-address/dist/ipv4.js +22 -6
- package/node_modules/ip-address/dist/ipv4.js.map +1 -1
- package/node_modules/ip-address/dist/ipv6.d.ts +26 -8
- package/node_modules/ip-address/dist/ipv6.js +46 -29
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/dist/v6/constants.js +1 -0
- package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
- package/node_modules/ip-address/package.json +1 -1
- package/package.json +5 -4
- package/dist/core/web/public/next/assets/ActionMenu-Bia8Re6u.js +0 -2
- package/dist/core/web/public/next/assets/ActionMenu-Bia8Re6u.js.map +0 -1
- package/dist/core/web/public/next/assets/Advanced-C1LtnA8c.js +0 -2
- package/dist/core/web/public/next/assets/Advanced-C1LtnA8c.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentDetailScreen-DuoXrbol.js +0 -2
- package/dist/core/web/public/next/assets/AgentDetailScreen-DuoXrbol.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentToolsSheet-Bdfk4SF-.js +0 -2
- package/dist/core/web/public/next/assets/AgentToolsSheet-Bdfk4SF-.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentToolsStrip-BN1otiqC.js +0 -2
- package/dist/core/web/public/next/assets/AgentToolsStrip-BN1otiqC.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentsScreen-BxHFaI48.js +0 -2
- package/dist/core/web/public/next/assets/AgentsScreen-BxHFaI48.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentsSection-mYIA8Lyk.js +0 -3
- package/dist/core/web/public/next/assets/AgentsSection-mYIA8Lyk.js.map +0 -1
- package/dist/core/web/public/next/assets/App-DebYuj1v.js +0 -8
- package/dist/core/web/public/next/assets/App-DebYuj1v.js.map +0 -1
- package/dist/core/web/public/next/assets/AppsSection-W30duGQA.js +0 -2
- package/dist/core/web/public/next/assets/AppsSection-W30duGQA.js.map +0 -1
- package/dist/core/web/public/next/assets/AreaTrend-ZnnIjBGU.js +0 -2
- package/dist/core/web/public/next/assets/AreaTrend-ZnnIjBGU.js.map +0 -1
- package/dist/core/web/public/next/assets/AutomationsSection-B4N0V-vz.js +0 -2
- package/dist/core/web/public/next/assets/AutomationsSection-B4N0V-vz.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomyOffState-C9S_FXc0.js +0 -3
- package/dist/core/web/public/next/assets/AutonomyOffState-C9S_FXc0.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-oMQfNEQN.js +0 -2
- package/dist/core/web/public/next/assets/AutonomySection-oMQfNEQN.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomyStatus-CdHOyhrV.js +0 -2
- package/dist/core/web/public/next/assets/AutonomyStatus-CdHOyhrV.js.map +0 -1
- package/dist/core/web/public/next/assets/BranchBar-Bo5b8-hr.js +0 -2
- package/dist/core/web/public/next/assets/BranchBar-Bo5b8-hr.js.map +0 -1
- package/dist/core/web/public/next/assets/BrowserPanel-D02omBK0.js +0 -7
- package/dist/core/web/public/next/assets/BrowserPanel-D02omBK0.js.map +0 -1
- package/dist/core/web/public/next/assets/BudgetControl-BtPTi8qI.js +0 -2
- package/dist/core/web/public/next/assets/BudgetControl-BtPTi8qI.js.map +0 -1
- package/dist/core/web/public/next/assets/Button-DP2ImS5n.js +0 -2
- package/dist/core/web/public/next/assets/Button-DP2ImS5n.js.map +0 -1
- package/dist/core/web/public/next/assets/CapacityStrip-ChYPcr23.js +0 -2
- package/dist/core/web/public/next/assets/CapacityStrip-ChYPcr23.js.map +0 -1
- package/dist/core/web/public/next/assets/ChangesPaneHost-C53_94Kn.js +0 -16
- package/dist/core/web/public/next/assets/ChangesPaneHost-C53_94Kn.js.map +0 -1
- package/dist/core/web/public/next/assets/ChartFrame-CtFLETWA.js +0 -2
- package/dist/core/web/public/next/assets/ChartFrame-CtFLETWA.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatPanes-CyAK9VAi.js +0 -2
- package/dist/core/web/public/next/assets/ChatPanes-CyAK9VAi.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatSection-DV9smoPe.js +0 -3
- package/dist/core/web/public/next/assets/ChatSection-DV9smoPe.js.map +0 -1
- package/dist/core/web/public/next/assets/ChecksPanel-B6T2sjc_.js +0 -5
- package/dist/core/web/public/next/assets/ChecksPanel-B6T2sjc_.js.map +0 -1
- package/dist/core/web/public/next/assets/CloudBudgetForm-D8RbdAC7.js +0 -2
- package/dist/core/web/public/next/assets/CloudBudgetForm-D8RbdAC7.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandPalette-C04gGTES.js +0 -3
- package/dist/core/web/public/next/assets/CommandPalette-C04gGTES.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandSection-Be8VFAEU.js +0 -3
- package/dist/core/web/public/next/assets/CommandSection-Be8VFAEU.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandWorkflowForm-D5A7c2PE.js +0 -9
- package/dist/core/web/public/next/assets/CommandWorkflowForm-D5A7c2PE.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-CGrRWfzQ.js +0 -3
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-CGrRWfzQ.js.map +0 -1
- package/dist/core/web/public/next/assets/CompareDialog-C2ryiEtF.js +0 -4
- package/dist/core/web/public/next/assets/CompareDialog-C2ryiEtF.js.map +0 -1
- package/dist/core/web/public/next/assets/ComputerControl-C4oW7Zim.js +0 -2
- package/dist/core/web/public/next/assets/ComputerControl-C4oW7Zim.js.map +0 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-J8CszPmj.js +0 -2
- package/dist/core/web/public/next/assets/ConfirmDialog-J8CszPmj.js.map +0 -1
- package/dist/core/web/public/next/assets/DeleteChatDialog-BT5y9cR2.js +0 -2
- package/dist/core/web/public/next/assets/DeleteChatDialog-BT5y9cR2.js.map +0 -1
- package/dist/core/web/public/next/assets/DevinStopDialog-CADdSqha.js +0 -2
- package/dist/core/web/public/next/assets/DevinStopDialog-CADdSqha.js.map +0 -1
- package/dist/core/web/public/next/assets/Dialog-BYIKNPcH.js +0 -2
- package/dist/core/web/public/next/assets/Dialog-BYIKNPcH.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffPane-D_CC9a5x.js +0 -2
- package/dist/core/web/public/next/assets/DiffPane-D_CC9a5x.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffViewer-DjtLl7ro.js +0 -2
- package/dist/core/web/public/next/assets/DiffViewer-DjtLl7ro.js.map +0 -1
- package/dist/core/web/public/next/assets/DockHost-BHbosAjM.js +0 -2
- package/dist/core/web/public/next/assets/DockHost-BHbosAjM.js.map +0 -1
- package/dist/core/web/public/next/assets/EmptyState-BEXDoNZd.js +0 -2
- package/dist/core/web/public/next/assets/EmptyState-BEXDoNZd.js.map +0 -1
- package/dist/core/web/public/next/assets/Epistemic-BPBAmLNh.js +0 -2
- package/dist/core/web/public/next/assets/Epistemic-BPBAmLNh.js.map +0 -1
- package/dist/core/web/public/next/assets/EvidenceTimeline-D2nuo6Oo.js +0 -2
- package/dist/core/web/public/next/assets/EvidenceTimeline-D2nuo6Oo.js.map +0 -1
- package/dist/core/web/public/next/assets/FilesPane-BQBcWyxr.js +0 -2
- package/dist/core/web/public/next/assets/FilesPane-BQBcWyxr.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetScreen-YXDuVwKd.js +0 -2
- package/dist/core/web/public/next/assets/FleetScreen-YXDuVwKd.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetSection-D2M7u9zG.js +0 -5
- package/dist/core/web/public/next/assets/FleetSection-D2M7u9zG.js.map +0 -1
- package/dist/core/web/public/next/assets/Funnel-rnPUaoN7.js +0 -2
- package/dist/core/web/public/next/assets/Funnel-rnPUaoN7.js.map +0 -1
- package/dist/core/web/public/next/assets/GearTray-Cc14h572.js +0 -2
- package/dist/core/web/public/next/assets/GearTray-Cc14h572.js.map +0 -1
- package/dist/core/web/public/next/assets/GitDialogs-BSTlyNJR.js +0 -2
- package/dist/core/web/public/next/assets/GitDialogs-BSTlyNJR.js.map +0 -1
- package/dist/core/web/public/next/assets/GrowthSection-BK63EJn9.js +0 -3
- package/dist/core/web/public/next/assets/GrowthSection-BK63EJn9.js.map +0 -1
- package/dist/core/web/public/next/assets/HandoffDialog-DD4M-C7v.js +0 -2
- package/dist/core/web/public/next/assets/HandoffDialog-DD4M-C7v.js.map +0 -1
- package/dist/core/web/public/next/assets/HomeBody-OEhTpkk9.js +0 -3
- package/dist/core/web/public/next/assets/HomeBody-OEhTpkk9.js.map +0 -1
- package/dist/core/web/public/next/assets/HomeSeats-CJCxRUlD.js +0 -2
- package/dist/core/web/public/next/assets/HomeSeats-CJCxRUlD.js.map +0 -1
- package/dist/core/web/public/next/assets/Input-BEF-ScuG.js +0 -2
- package/dist/core/web/public/next/assets/Input-BEF-ScuG.js.map +0 -1
- package/dist/core/web/public/next/assets/LaunchDialog-CERI717u.js +0 -9
- package/dist/core/web/public/next/assets/LaunchDialog-CERI717u.js.map +0 -1
- package/dist/core/web/public/next/assets/LeaderCard-3P95vgVU.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-3P95vgVU.js.map +0 -1
- package/dist/core/web/public/next/assets/LeaderConversation-DjZS2PrX.js +0 -3
- package/dist/core/web/public/next/assets/LeaderConversation-DjZS2PrX.js.map +0 -1
- package/dist/core/web/public/next/assets/LeaderScreen-Dw5jDfWv.js +0 -2
- package/dist/core/web/public/next/assets/LeaderScreen-Dw5jDfWv.js.map +0 -1
- package/dist/core/web/public/next/assets/LessonsPanel-Wy6TVWEv.js +0 -2
- package/dist/core/web/public/next/assets/LessonsPanel-Wy6TVWEv.js.map +0 -1
- package/dist/core/web/public/next/assets/LiveTimer-c18lVIBC.js +0 -2
- package/dist/core/web/public/next/assets/LiveTimer-c18lVIBC.js.map +0 -1
- package/dist/core/web/public/next/assets/LocalSeatBadge-BfUUuXE5.js +0 -2
- package/dist/core/web/public/next/assets/LocalSeatBadge-BfUUuXE5.js.map +0 -1
- package/dist/core/web/public/next/assets/MatrixHeatmap-DTOumwCS.js +0 -2
- package/dist/core/web/public/next/assets/MatrixHeatmap-DTOumwCS.js.map +0 -1
- package/dist/core/web/public/next/assets/McpSection-D9eJislZ.js +0 -2
- package/dist/core/web/public/next/assets/McpSection-D9eJislZ.js.map +0 -1
- package/dist/core/web/public/next/assets/MessageMarkdown-Dkw4V24c.js +0 -3
- package/dist/core/web/public/next/assets/MessageMarkdown-Dkw4V24c.js.map +0 -1
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-VOSfkJpd.js +0 -72
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-VOSfkJpd.js.map +0 -1
- package/dist/core/web/public/next/assets/Meter-dMqKBaVV.js +0 -2
- package/dist/core/web/public/next/assets/Meter-dMqKBaVV.js.map +0 -1
- package/dist/core/web/public/next/assets/MicButton-92I_NsaT.js +0 -2
- package/dist/core/web/public/next/assets/MicButton-92I_NsaT.js.map +0 -1
- package/dist/core/web/public/next/assets/MindSection-CaGckJiR.js +0 -3
- package/dist/core/web/public/next/assets/MindSection-CaGckJiR.js.map +0 -1
- package/dist/core/web/public/next/assets/MobileComposer-BOFWmkku.js +0 -2
- package/dist/core/web/public/next/assets/MobileComposer-BOFWmkku.js.map +0 -1
- package/dist/core/web/public/next/assets/MobileGuardSheet-CY3Iulte.js +0 -2
- package/dist/core/web/public/next/assets/MobileGuardSheet-CY3Iulte.js.map +0 -1
- package/dist/core/web/public/next/assets/MobileRuntime-C-GtV4jT.js +0 -3
- package/dist/core/web/public/next/assets/MobileRuntime-C-GtV4jT.js.map +0 -1
- package/dist/core/web/public/next/assets/MoreScreen-BaH8iEnb.js +0 -2
- package/dist/core/web/public/next/assets/MoreScreen-BaH8iEnb.js.map +0 -1
- package/dist/core/web/public/next/assets/MultiModelBar-7DHuXGht.js +0 -7
- package/dist/core/web/public/next/assets/MultiModelBar-7DHuXGht.js.map +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-D522NXsm.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-D522NXsm.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-6ud1RHOU.js +0 -3
- package/dist/core/web/public/next/assets/NeedsYouDrawer-6ud1RHOU.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouList-E-yy-xKE.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouList-E-yy-xKE.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouScreen-D13Q7iU8.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouScreen-D13Q7iU8.js.map +0 -1
- package/dist/core/web/public/next/assets/NewAgentScreen-BLtU1u-d.js +0 -2
- package/dist/core/web/public/next/assets/NewAgentScreen-BLtU1u-d.js.map +0 -1
- package/dist/core/web/public/next/assets/NewChatDialog-BL15LCaj.js +0 -4
- package/dist/core/web/public/next/assets/NewChatDialog-BL15LCaj.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-7LRC7FlX.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingFlow-7LRC7FlX.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingGate-DRlv8QZ5.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingGate-DRlv8QZ5.js.map +0 -1
- package/dist/core/web/public/next/assets/PlaybooksSection-D_uQ-NB3.js +0 -9
- package/dist/core/web/public/next/assets/PlaybooksSection-D_uQ-NB3.js.map +0 -1
- package/dist/core/web/public/next/assets/PreviewPane-DubyNi8H.js +0 -2
- package/dist/core/web/public/next/assets/PreviewPane-DubyNi8H.js.map +0 -1
- package/dist/core/web/public/next/assets/ProviderLogo-CWrojWjI.js +0 -2
- package/dist/core/web/public/next/assets/ProviderLogo-CWrojWjI.js.map +0 -1
- package/dist/core/web/public/next/assets/RailStatus-xjOcjL0v.js +0 -2
- package/dist/core/web/public/next/assets/RailStatus-xjOcjL0v.js.map +0 -1
- package/dist/core/web/public/next/assets/ReasoningPane-M7ZfvEc5.js +0 -2
- package/dist/core/web/public/next/assets/ReasoningPane-M7ZfvEc5.js.map +0 -1
- package/dist/core/web/public/next/assets/ReasoningSheet-RLLj2oys.js +0 -2
- package/dist/core/web/public/next/assets/ReasoningSheet-RLLj2oys.js.map +0 -1
- package/dist/core/web/public/next/assets/RefreshIndicator-CEMRNruu.js +0 -2
- package/dist/core/web/public/next/assets/RefreshIndicator-CEMRNruu.js.map +0 -1
- package/dist/core/web/public/next/assets/RemoteMobileApp-BcXsVw0z.js +0 -2
- package/dist/core/web/public/next/assets/RemoteMobileApp-BcXsVw0z.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-BC_Q_i0I.js +0 -7
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-BC_Q_i0I.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-CPcTYvZR.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesChrome-CPcTYvZR.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-C6VzGCSv.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesDrawer-C6VzGCSv.js.map +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-Cc9GsjZz.js +0 -2
- package/dist/core/web/public/next/assets/RouteErrorBoundary-Cc9GsjZz.js.map +0 -1
- package/dist/core/web/public/next/assets/RunInCloudAction-P_hDsqjX.js +0 -2
- package/dist/core/web/public/next/assets/RunInCloudAction-P_hDsqjX.js.map +0 -1
- package/dist/core/web/public/next/assets/RunInDevinAction-CfNpQCP3.js +0 -2
- package/dist/core/web/public/next/assets/RunInDevinAction-CfNpQCP3.js.map +0 -1
- package/dist/core/web/public/next/assets/ScreenHost-BBYihlNQ.js +0 -3
- package/dist/core/web/public/next/assets/ScreenHost-BBYihlNQ.js.map +0 -1
- package/dist/core/web/public/next/assets/SeatSelector-DSd_pxg2.js +0 -3
- package/dist/core/web/public/next/assets/SeatSelector-DSd_pxg2.js.map +0 -1
- package/dist/core/web/public/next/assets/Segmented-CtwuFlbY.js +0 -2
- package/dist/core/web/public/next/assets/Segmented-CtwuFlbY.js.map +0 -1
- package/dist/core/web/public/next/assets/Select-zXMdgblm.js +0 -2
- package/dist/core/web/public/next/assets/Select-zXMdgblm.js.map +0 -1
- package/dist/core/web/public/next/assets/SessionGate-88QiSoXo.js +0 -2
- package/dist/core/web/public/next/assets/SessionGate-88QiSoXo.js.map +0 -1
- package/dist/core/web/public/next/assets/SessionInsightChip-CaPvisvI.js +0 -2
- package/dist/core/web/public/next/assets/SessionInsightChip-CaPvisvI.js.map +0 -1
- package/dist/core/web/public/next/assets/SessionSearch-Ch3veGxY.js +0 -2
- package/dist/core/web/public/next/assets/SessionSearch-Ch3veGxY.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-DLSYZEFc.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-DLSYZEFc.js.map +0 -1
- package/dist/core/web/public/next/assets/SetupChecklist-DFAVVLpJ.js +0 -2
- package/dist/core/web/public/next/assets/SetupChecklist-DFAVVLpJ.js.map +0 -1
- package/dist/core/web/public/next/assets/ShadowDecisions-Gtrbo4US.js +0 -3
- package/dist/core/web/public/next/assets/ShadowDecisions-Gtrbo4US.js.map +0 -1
- package/dist/core/web/public/next/assets/Sheet-D72WH4mP.js +0 -2
- package/dist/core/web/public/next/assets/Sheet-D72WH4mP.js.map +0 -1
- package/dist/core/web/public/next/assets/ShortcutsOverlay-DKetDlCR.js +0 -2
- package/dist/core/web/public/next/assets/ShortcutsOverlay-DKetDlCR.js.map +0 -1
- package/dist/core/web/public/next/assets/Sidebar-CqOJle0q.js +0 -3
- package/dist/core/web/public/next/assets/Sidebar-CqOJle0q.js.map +0 -1
- package/dist/core/web/public/next/assets/SkipToContent-C7UObcP2.js +0 -2
- package/dist/core/web/public/next/assets/SkipToContent-C7UObcP2.js.map +0 -1
- package/dist/core/web/public/next/assets/Slider-Bi5q-21C.js +0 -2
- package/dist/core/web/public/next/assets/Slider-Bi5q-21C.js.map +0 -1
- package/dist/core/web/public/next/assets/SourcesPane-D7Raaor0.js +0 -2
- package/dist/core/web/public/next/assets/SourcesPane-D7Raaor0.js.map +0 -1
- package/dist/core/web/public/next/assets/SourcesPanel-CCSdY5Os.js +0 -2
- package/dist/core/web/public/next/assets/SourcesPanel-CCSdY5Os.js.map +0 -1
- package/dist/core/web/public/next/assets/StatTile-BS_dzInS.js +0 -2
- package/dist/core/web/public/next/assets/StatTile-BS_dzInS.js.map +0 -1
- package/dist/core/web/public/next/assets/StatusBadge-CJbb9DhR.js +0 -2
- package/dist/core/web/public/next/assets/StatusBadge-CJbb9DhR.js.map +0 -1
- package/dist/core/web/public/next/assets/StepBand-Bfj1YYTl.js +0 -2
- package/dist/core/web/public/next/assets/StepBand-Bfj1YYTl.js.map +0 -1
- package/dist/core/web/public/next/assets/Surface-CV-NXGIM.js +0 -2
- package/dist/core/web/public/next/assets/Surface-CV-NXGIM.js.map +0 -1
- package/dist/core/web/public/next/assets/Swimlane-DbUp4tjD.js +0 -2
- package/dist/core/web/public/next/assets/Swimlane-DbUp4tjD.js.map +0 -1
- package/dist/core/web/public/next/assets/Switch-BtEo9Cku.js +0 -2
- package/dist/core/web/public/next/assets/Switch-BtEo9Cku.js.map +0 -1
- package/dist/core/web/public/next/assets/Tag-CMFqY2MP.js +0 -2
- package/dist/core/web/public/next/assets/Tag-CMFqY2MP.js.map +0 -1
- package/dist/core/web/public/next/assets/TerminalPane-BCjlhc3t.js +0 -26
- package/dist/core/web/public/next/assets/TerminalPane-BCjlhc3t.js.map +0 -1
- package/dist/core/web/public/next/assets/TerminalPane-DIwGSCA9.js +0 -3
- package/dist/core/web/public/next/assets/TerminalPane-DIwGSCA9.js.map +0 -1
- package/dist/core/web/public/next/assets/ThinkingBlock-Db8qnuKz.js +0 -2
- package/dist/core/web/public/next/assets/ThinkingBlock-Db8qnuKz.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-ksreONXM.js +0 -2
- package/dist/core/web/public/next/assets/UniverseConsoleApp-ksreONXM.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseView-CfT9Dsl7.js +0 -9
- package/dist/core/web/public/next/assets/UniverseView-CfT9Dsl7.js.map +0 -1
- package/dist/core/web/public/next/assets/UsageSection-DypcdQys.js +0 -3
- package/dist/core/web/public/next/assets/UsageSection-DypcdQys.js.map +0 -1
- package/dist/core/web/public/next/assets/UsePlaybookAction-Bxwqrpwe.js +0 -2
- package/dist/core/web/public/next/assets/UsePlaybookAction-Bxwqrpwe.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-kFOEmnGC.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-kFOEmnGC.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseMobileApp-BTGF5yuZ.js +0 -3
- package/dist/core/web/public/next/assets/VerseMobileApp-BTGF5yuZ.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseShared-_pMXKs8m.js +0 -2
- package/dist/core/web/public/next/assets/VerseShared-_pMXKs8m.js.map +0 -1
- package/dist/core/web/public/next/assets/VoiceHud-B_hiHfnQ.js +0 -2
- package/dist/core/web/public/next/assets/VoiceHud-B_hiHfnQ.js.map +0 -1
- package/dist/core/web/public/next/assets/VoiceInput-B7yrGchr.js +0 -2
- package/dist/core/web/public/next/assets/VoiceInput-B7yrGchr.js.map +0 -1
- package/dist/core/web/public/next/assets/WikiSection-BXu4aZyr.js +0 -2
- package/dist/core/web/public/next/assets/WikiSection-BXu4aZyr.js.map +0 -1
- package/dist/core/web/public/next/assets/Workspace-BYT3iuNM.js +0 -6
- package/dist/core/web/public/next/assets/Workspace-BYT3iuNM.js.map +0 -1
- package/dist/core/web/public/next/assets/actions-CyO4R-IO.js +0 -2
- package/dist/core/web/public/next/assets/actions-CyO4R-IO.js.map +0 -1
- package/dist/core/web/public/next/assets/agent-tools-client-FgVNokGh.js +0 -2
- package/dist/core/web/public/next/assets/agent-tools-client-FgVNokGh.js.map +0 -1
- package/dist/core/web/public/next/assets/agent-transcript-model-CRa_I3eR.js +0 -7
- package/dist/core/web/public/next/assets/agent-transcript-model-CRa_I3eR.js.map +0 -1
- package/dist/core/web/public/next/assets/agents-focus-D2hd-RNJ.js +0 -2
- package/dist/core/web/public/next/assets/agents-focus-D2hd-RNJ.js.map +0 -1
- package/dist/core/web/public/next/assets/app-version-DDlXX8-W.js +0 -2
- package/dist/core/web/public/next/assets/app-version-DDlXX8-W.js.map +0 -1
- package/dist/core/web/public/next/assets/apps-model-DLQgiczq.js +0 -2
- package/dist/core/web/public/next/assets/apps-model-DLQgiczq.js.map +0 -1
- package/dist/core/web/public/next/assets/ask-seat-zMpqJABI.js +0 -2
- package/dist/core/web/public/next/assets/ask-seat-zMpqJABI.js.map +0 -1
- package/dist/core/web/public/next/assets/authority-model-BvLFgPaX.js +0 -2
- package/dist/core/web/public/next/assets/authority-model-BvLFgPaX.js.map +0 -1
- package/dist/core/web/public/next/assets/automations-focus-zqI9oIl8.js +0 -2
- package/dist/core/web/public/next/assets/automations-focus-zqI9oIl8.js.map +0 -1
- package/dist/core/web/public/next/assets/budget-model-CKd0d1Cj.js +0 -2
- package/dist/core/web/public/next/assets/budget-model-CKd0d1Cj.js.map +0 -1
- package/dist/core/web/public/next/assets/budget-queries-q7mCG9Ek.js +0 -2
- package/dist/core/web/public/next/assets/budget-queries-q7mCG9Ek.js.map +0 -1
- package/dist/core/web/public/next/assets/capacity-strip-model-pdIEweaZ.js +0 -2
- package/dist/core/web/public/next/assets/capacity-strip-model-pdIEweaZ.js.map +0 -1
- package/dist/core/web/public/next/assets/charts-D3I0q4hG.js +0 -2
- package/dist/core/web/public/next/assets/charts-D3I0q4hG.js.map +0 -1
- package/dist/core/web/public/next/assets/chat-pane-data-DIDV7uIU.js +0 -2
- package/dist/core/web/public/next/assets/chat-pane-data-DIDV7uIU.js.map +0 -1
- package/dist/core/web/public/next/assets/checkpoint-queries-DjrDEsN-.js +0 -2
- package/dist/core/web/public/next/assets/checkpoint-queries-DjrDEsN-.js.map +0 -1
- package/dist/core/web/public/next/assets/cloud-model-DuboHWPT.js +0 -2
- package/dist/core/web/public/next/assets/cloud-model-DuboHWPT.js.map +0 -1
- package/dist/core/web/public/next/assets/cloud-queries-DQF1a_R-.js +0 -2
- package/dist/core/web/public/next/assets/cloud-queries-DQF1a_R-.js.map +0 -1
- package/dist/core/web/public/next/assets/command-catalog-BzHSIzIS.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-BzHSIzIS.js.map +0 -1
- package/dist/core/web/public/next/assets/composer-queries-BEYuD6Qr.js +0 -2
- package/dist/core/web/public/next/assets/composer-queries-BEYuD6Qr.js.map +0 -1
- package/dist/core/web/public/next/assets/composer-state-B4KVc2ZZ.js +0 -2
- package/dist/core/web/public/next/assets/composer-state-B4KVc2ZZ.js.map +0 -1
- package/dist/core/web/public/next/assets/connectivity-Svn7iy2K.js +0 -2
- package/dist/core/web/public/next/assets/connectivity-Svn7iy2K.js.map +0 -1
- package/dist/core/web/public/next/assets/context-model-C9EIuPJ_.js +0 -2
- package/dist/core/web/public/next/assets/context-model-C9EIuPJ_.js.map +0 -1
- package/dist/core/web/public/next/assets/context-model-DU3OPiBC.js +0 -3
- package/dist/core/web/public/next/assets/context-model-DU3OPiBC.js.map +0 -1
- package/dist/core/web/public/next/assets/context-queries-Cgb_XvRv.js +0 -2
- package/dist/core/web/public/next/assets/context-queries-Cgb_XvRv.js.map +0 -1
- package/dist/core/web/public/next/assets/control-queries-Clgsy_eH.js +0 -2
- package/dist/core/web/public/next/assets/control-queries-Clgsy_eH.js.map +0 -1
- package/dist/core/web/public/next/assets/copy-setup-C-hDt9sS.js +0 -2
- package/dist/core/web/public/next/assets/copy-setup-C-hDt9sS.js.map +0 -1
- package/dist/core/web/public/next/assets/deep-link-Cgvchdy7.js +0 -2
- package/dist/core/web/public/next/assets/deep-link-Cgvchdy7.js.map +0 -1
- package/dist/core/web/public/next/assets/device-permissions-JmqkyrDw.js +0 -2
- package/dist/core/web/public/next/assets/device-permissions-JmqkyrDw.js.map +0 -1
- package/dist/core/web/public/next/assets/devin-queries-DKgeD4_S.js +0 -2
- package/dist/core/web/public/next/assets/devin-queries-DKgeD4_S.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-icons-CRHjXBWm.js +0 -2
- package/dist/core/web/public/next/assets/dock-icons-CRHjXBWm.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-panes-C98u13Bi.js +0 -2
- package/dist/core/web/public/next/assets/dock-panes-C98u13Bi.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-control-queries-BLoc5Gza.js +0 -2
- package/dist/core/web/public/next/assets/fleet-control-queries-BLoc5Gza.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-model-CPTadBFK.js +0 -2
- package/dist/core/web/public/next/assets/fleet-model-CPTadBFK.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-queries-69WuY-dt.js +0 -2
- package/dist/core/web/public/next/assets/fleet-queries-69WuY-dt.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-state-CCdBRK-m.js +0 -3
- package/dist/core/web/public/next/assets/fleet-state-CCdBRK-m.js.map +0 -1
- package/dist/core/web/public/next/assets/focus-trap-C8MiYlLZ.js +0 -2
- package/dist/core/web/public/next/assets/focus-trap-C8MiYlLZ.js.map +0 -1
- package/dist/core/web/public/next/assets/format-CcEKjUou.js +0 -2
- package/dist/core/web/public/next/assets/format-CcEKjUou.js.map +0 -1
- package/dist/core/web/public/next/assets/git-model-DL3MwN93.js +0 -5
- package/dist/core/web/public/next/assets/git-model-DL3MwN93.js.map +0 -1
- package/dist/core/web/public/next/assets/global-BWc2NPzv.js +0 -3
- package/dist/core/web/public/next/assets/global-BWc2NPzv.js.map +0 -1
- package/dist/core/web/public/next/assets/guarded-action-BK2_U5ho.js +0 -3
- package/dist/core/web/public/next/assets/guarded-action-BK2_U5ho.js.map +0 -1
- package/dist/core/web/public/next/assets/guarded-runners-Q0UkoY3H.js +0 -2
- package/dist/core/web/public/next/assets/guarded-runners-Q0UkoY3H.js.map +0 -1
- package/dist/core/web/public/next/assets/headroom-CP99UxyV.js +0 -2
- package/dist/core/web/public/next/assets/headroom-CP99UxyV.js.map +0 -1
- package/dist/core/web/public/next/assets/health-queries-D8TwNTDQ.js +0 -2
- package/dist/core/web/public/next/assets/health-queries-D8TwNTDQ.js.map +0 -1
- package/dist/core/web/public/next/assets/icons-U34oiN9M.js +0 -2
- package/dist/core/web/public/next/assets/icons-U34oiN9M.js.map +0 -1
- package/dist/core/web/public/next/assets/index-BbDqdepe.js +0 -11
- package/dist/core/web/public/next/assets/index-BbDqdepe.js.map +0 -1
- package/dist/core/web/public/next/assets/jev-queries-CiQDnM5r.js +0 -2
- package/dist/core/web/public/next/assets/jev-queries-CiQDnM5r.js.map +0 -1
- package/dist/core/web/public/next/assets/ladder-queries-Cf64JB04.js +0 -2
- package/dist/core/web/public/next/assets/ladder-queries-Cf64JB04.js.map +0 -1
- package/dist/core/web/public/next/assets/leader-focus-azN19kfO.js +0 -2
- package/dist/core/web/public/next/assets/leader-focus-azN19kfO.js.map +0 -1
- package/dist/core/web/public/next/assets/live-model-DHX_2gOu.js +0 -2
- package/dist/core/web/public/next/assets/live-model-DHX_2gOu.js.map +0 -1
- package/dist/core/web/public/next/assets/mind.module-BJpuH2JT.js +0 -2
- package/dist/core/web/public/next/assets/mind.module-BJpuH2JT.js.map +0 -1
- package/dist/core/web/public/next/assets/mobile-actions-CvGouAAH.js +0 -2
- package/dist/core/web/public/next/assets/mobile-actions-CvGouAAH.js.map +0 -1
- package/dist/core/web/public/next/assets/mobile-toast-C_UP13GQ.js +0 -2
- package/dist/core/web/public/next/assets/mobile-toast-C_UP13GQ.js.map +0 -1
- package/dist/core/web/public/next/assets/multimodel-flows-C377w9oZ.js +0 -7
- package/dist/core/web/public/next/assets/multimodel-flows-C377w9oZ.js.map +0 -1
- package/dist/core/web/public/next/assets/multimodel-queries-_Y1QXAqq.js +0 -2
- package/dist/core/web/public/next/assets/multimodel-queries-_Y1QXAqq.js.map +0 -1
- package/dist/core/web/public/next/assets/mutations-DL4u2kRQ.js +0 -2
- package/dist/core/web/public/next/assets/mutations-DL4u2kRQ.js.map +0 -1
- package/dist/core/web/public/next/assets/nav-CM-mJcSq.js +0 -2
- package/dist/core/web/public/next/assets/nav-CM-mJcSq.js.map +0 -1
- package/dist/core/web/public/next/assets/needs-you-actions-DF2zEltF.js +0 -2
- package/dist/core/web/public/next/assets/needs-you-actions-DF2zEltF.js.map +0 -1
- package/dist/core/web/public/next/assets/needs-you-model-DqmU5YOe.js +0 -2
- package/dist/core/web/public/next/assets/needs-you-model-DqmU5YOe.js.map +0 -1
- package/dist/core/web/public/next/assets/open-terminal-BAnwAOoA.js +0 -2
- package/dist/core/web/public/next/assets/open-terminal-BAnwAOoA.js.map +0 -1
- package/dist/core/web/public/next/assets/open-terminal-request-f5_ItEpF.js +0 -2
- package/dist/core/web/public/next/assets/open-terminal-request-f5_ItEpF.js.map +0 -1
- package/dist/core/web/public/next/assets/overnight-queries-BP6viiM5.js +0 -2
- package/dist/core/web/public/next/assets/overnight-queries-BP6viiM5.js.map +0 -1
- package/dist/core/web/public/next/assets/palette-handoff-Bmq98lDl.js +0 -2
- package/dist/core/web/public/next/assets/palette-handoff-Bmq98lDl.js.map +0 -1
- package/dist/core/web/public/next/assets/panes-BjUzIDw6.js +0 -3
- package/dist/core/web/public/next/assets/panes-BjUzIDw6.js.map +0 -1
- package/dist/core/web/public/next/assets/path-display-HyxETV-f.js +0 -2
- package/dist/core/web/public/next/assets/path-display-HyxETV-f.js.map +0 -1
- package/dist/core/web/public/next/assets/playbook-composer-DwuBBP4I.js +0 -2
- package/dist/core/web/public/next/assets/playbook-composer-DwuBBP4I.js.map +0 -1
- package/dist/core/web/public/next/assets/playbook-focus-B9xzeUMw.js +0 -2
- package/dist/core/web/public/next/assets/playbook-focus-B9xzeUMw.js.map +0 -1
- package/dist/core/web/public/next/assets/playbooks-queries-C8j1Aswo.js +0 -2
- package/dist/core/web/public/next/assets/playbooks-queries-C8j1Aswo.js.map +0 -1
- package/dist/core/web/public/next/assets/preloaded-CLDUOHXJ.js +0 -2
- package/dist/core/web/public/next/assets/preloaded-CLDUOHXJ.js.map +0 -1
- package/dist/core/web/public/next/assets/primitives-BEXDE-HP.js +0 -1
- package/dist/core/web/public/next/assets/pwa-lVT_VRkK.js +0 -2
- package/dist/core/web/public/next/assets/pwa-lVT_VRkK.js.map +0 -1
- package/dist/core/web/public/next/assets/queries-T7ZUVqyA.js +0 -2
- package/dist/core/web/public/next/assets/queries-T7ZUVqyA.js.map +0 -1
- package/dist/core/web/public/next/assets/reasoning-pref-CWEri5xB.js +0 -2
- package/dist/core/web/public/next/assets/reasoning-pref-CWEri5xB.js.map +0 -1
- package/dist/core/web/public/next/assets/remote-session-BPULIfdG.js +0 -3
- package/dist/core/web/public/next/assets/remote-session-BPULIfdG.js.map +0 -1
- package/dist/core/web/public/next/assets/resolved-store-Ba-W6Uhy.js +0 -2
- package/dist/core/web/public/next/assets/resolved-store-Ba-W6Uhy.js.map +0 -1
- package/dist/core/web/public/next/assets/resources-queries-CKyXyaDY.js +0 -2
- package/dist/core/web/public/next/assets/resources-queries-CKyXyaDY.js.map +0 -1
- package/dist/core/web/public/next/assets/reveal-anchor-Djk1vGLl.js +0 -2
- package/dist/core/web/public/next/assets/reveal-anchor-Djk1vGLl.js.map +0 -1
- package/dist/core/web/public/next/assets/seat-readiness-CvEmMBol.js +0 -2
- package/dist/core/web/public/next/assets/seat-readiness-CvEmMBol.js.map +0 -1
- package/dist/core/web/public/next/assets/seat-subscription-BClqZwau.js +0 -2
- package/dist/core/web/public/next/assets/seat-subscription-BClqZwau.js.map +0 -1
- package/dist/core/web/public/next/assets/sheet-D0ciShoy.js +0 -2
- package/dist/core/web/public/next/assets/sheet-D0ciShoy.js.map +0 -1
- package/dist/core/web/public/next/assets/sidebar-model-BZ9Wh1lR.js +0 -2
- package/dist/core/web/public/next/assets/sidebar-model-BZ9Wh1lR.js.map +0 -1
- package/dist/core/web/public/next/assets/slots-m3L6Ints.js +0 -3
- package/dist/core/web/public/next/assets/slots-m3L6Ints.js.map +0 -1
- package/dist/core/web/public/next/assets/sources-queries-DeIlxb3A.js +0 -4
- package/dist/core/web/public/next/assets/sources-queries-DeIlxb3A.js.map +0 -1
- package/dist/core/web/public/next/assets/sse-CK65-Cun.js +0 -2
- package/dist/core/web/public/next/assets/sse-CK65-Cun.js.map +0 -1
- package/dist/core/web/public/next/assets/surface-data-DoN8peNV.js +0 -2
- package/dist/core/web/public/next/assets/surface-data-DoN8peNV.js.map +0 -1
- package/dist/core/web/public/next/assets/surface-prefetch-CVNIptSl.js +0 -2
- package/dist/core/web/public/next/assets/surface-prefetch-CVNIptSl.js.map +0 -1
- package/dist/core/web/public/next/assets/tasks-model-BueAhEAf.js +0 -2
- package/dist/core/web/public/next/assets/tasks-model-BueAhEAf.js.map +0 -1
- package/dist/core/web/public/next/assets/terminal-client-DO0eRhRi.js +0 -2
- package/dist/core/web/public/next/assets/terminal-client-DO0eRhRi.js.map +0 -1
- package/dist/core/web/public/next/assets/terminal-icons-COMoAiDd.js +0 -2
- package/dist/core/web/public/next/assets/terminal-icons-COMoAiDd.js.map +0 -1
- package/dist/core/web/public/next/assets/terminal-view-DkVXx7Xk.js +0 -6
- package/dist/core/web/public/next/assets/terminal-view-DkVXx7Xk.js.map +0 -1
- package/dist/core/web/public/next/assets/thread-data-Dq7QugaD.js +0 -2
- package/dist/core/web/public/next/assets/thread-data-Dq7QugaD.js.map +0 -1
- package/dist/core/web/public/next/assets/ui-parts-2JLq2ZSq.js +0 -2
- package/dist/core/web/public/next/assets/ui-parts-2JLq2ZSq.js.map +0 -1
- package/dist/core/web/public/next/assets/usage-queries-CDKUE4e0.js +0 -2
- package/dist/core/web/public/next/assets/usage-queries-CDKUE4e0.js.map +0 -1
- package/dist/core/web/public/next/assets/use-chat-activity-BaNWmI2A.js +0 -2
- package/dist/core/web/public/next/assets/use-chat-activity-BaNWmI2A.js.map +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-D4m4Mlzr.js +0 -2
- package/dist/core/web/public/next/assets/use-guarded-action-D4m4Mlzr.js.map +0 -1
- package/dist/core/web/public/next/assets/use-ticker-PQ_oYxn5.js +0 -2
- package/dist/core/web/public/next/assets/use-ticker-PQ_oYxn5.js.map +0 -1
- package/dist/core/web/public/next/assets/use-token-gate-_JPjMD5z.js +0 -2
- package/dist/core/web/public/next/assets/use-token-gate-_JPjMD5z.js.map +0 -1
- package/dist/core/web/public/next/assets/useAutoSeat-CkyqgwX9.js +0 -2
- package/dist/core/web/public/next/assets/useAutoSeat-CkyqgwX9.js.map +0 -1
- package/dist/core/web/public/next/assets/useOnboarding-3r8T1GBP.js +0 -2
- package/dist/core/web/public/next/assets/useOnboarding-3r8T1GBP.js.map +0 -1
- package/dist/core/web/public/next/assets/useSeatHealth-C08b9zut.js +0 -2
- package/dist/core/web/public/next/assets/useSeatHealth-C08b9zut.js.map +0 -1
- package/dist/core/web/public/next/assets/useSeatsRefresh-BGsdylUl.js +0 -2
- package/dist/core/web/public/next/assets/useSeatsRefresh-BGsdylUl.js.map +0 -1
- package/dist/core/web/public/next/assets/useVerseSession-0MnfpcHg.js +0 -2
- package/dist/core/web/public/next/assets/useVerseSession-0MnfpcHg.js.map +0 -1
- package/dist/core/web/public/next/assets/useVerseTranscript-B6wLDOv8.js +0 -2
- package/dist/core/web/public/next/assets/useVerseTranscript-B6wLDOv8.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-bootstrap-query-BR5ypA8b.js +0 -2
- package/dist/core/web/public/next/assets/verse-bootstrap-query-BR5ypA8b.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-icons-BQxBZk9k.js +0 -2
- package/dist/core/web/public/next/assets/verse-icons-BQxBZk9k.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-model-CkF3q2IH.js +0 -2
- package/dist/core/web/public/next/assets/verse-model-CkF3q2IH.js.map +0 -1
- package/dist/core/web/public/next/assets/warmup-CqTK8yIn.js +0 -3
- package/dist/core/web/public/next/assets/warmup-CqTK8yIn.js.map +0 -1
- package/dist/core/web/public/next/assets/why-seat-model-Dh4-Ty9n.js +0 -2
- package/dist/core/web/public/next/assets/why-seat-model-Dh4-Ty9n.js.map +0 -1
- package/dist/core/web/public/next/assets/wiki-focus-CisQb_pM.js +0 -2
- package/dist/core/web/public/next/assets/wiki-focus-CisQb_pM.js.map +0 -1
- package/dist/core/web/public/next/assets/workspace-model-DRGckE8q.js +0 -2
- package/dist/core/web/public/next/assets/workspace-model-DRGckE8q.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-model-DYkDKK6C.js","names":[],"sources":["../../../../../../src/core/verse/types.ts","../../../../../../src/web-ui/routes/verse/context/context-model.ts"],"sourcesContent":["/**\n * Ashlr Verse — interactive multi-turn session contract (V1).\n *\n * A Verse session binds one project directory to one execution seat\n * (engine + account + model). Each user turn spawns ONE vendor CLI process\n * that resumes the vendor-native conversation by id, streams normalized\n * events, and exits. No long-lived stdin is held between turns.\n *\n * Seats:\n * claude -> `claude -p ... --output-format stream-json` via a native-profile launcher (account pinned by CLAUDE_CONFIG_DIR)\n * local -> the plain `claude` binary with ANTHROPIC_BASE_URL pointed at Ollama (Anthropic-compatible API); model = Ollama tag\n * codex -> `codex exec --json` / `codex exec resume <threadId> --json` via a native-profile launcher (CODEX_HOME pinned)\n * grok -> `grok -p ... --output-format streaming-messages-json` via a native-profile launcher (GROK_HOME pinned)\n *\n * Nothing in this module reads secrets. Account identity is pinned by the\n * launcher command recorded in ~/.ashlr/account-connections/connections.json.\n */\nimport type { TRANSIENT_EVENT_TYPE_LIST } from './transient-events.js';\n\nexport type VerseEngine = 'claude' | 'codex' | 'grok' | 'local' | 'devin';\n\n/**\n * 3.15. Devin (Cognition) seats. Unlike the other engines Devin is not one CLI\n * spawned per turn in the project folder — or not only:\n * devin (lane `cloud`) — an async remote session via the v3 API; the\n * turn process is Verse's own runner (core/devin/chat-turn.ts),\n * which creates / messages the session and streams its messages\n * back by polling.\n * devin-cli (lane `cli`) — the local `devin` CLI driven over the Agent\n * Client Protocol (`devin acp`, JSON-RPC on stdio) by the same\n * runner, in the project folder.\n * Both are the operator's own chats: they never count as fleet work.\n */\nexport type VerseDevinLane = 'cloud' | 'cli';\n\n/** 3.15. Where a remote (Devin) session stands, as the transcript and header show it. */\nexport const VERSE_REMOTE_STATES = ['starting', 'working', 'waiting', 'suspended', 'finished', 'terminated', 'error'] as const;\nexport type VerseRemoteState = (typeof VERSE_REMOTE_STATES)[number];\n\n/**\n * 3.15 ADDITIVE. What a Devin chat's header shows: the live remote state, the\n * link to the session and (cloud lane) the ACU meter. Absent on every other\n * engine's records.\n */\nexport interface VerseRemoteInfo {\n provider: 'devin';\n lane: VerseDevinLane;\n /** https URL of the Devin session (cloud lane), else null. */\n url: string | null;\n state: VerseRemoteState | null;\n /** ACUs the session has used, as Devin reports them; null = not read yet / not reported (CLI lane). */\n acusConsumed: number | null;\n /** The session's hard cap (max_acu_limit); null when none applies. */\n acuCap: number | null;\n}\n\nexport type VerseSessionStatus = 'idle' | 'running' | 'error';\n\n/** One selectable execution seat shown in the model/account picker. */\nexport interface VerseSeat {\n /** Stable id, e.g. `claude`, `codex-personal`, `grok`, `local:qwen3-coder-next:ctx64k`. */\n id: string;\n engine: VerseEngine;\n /** Human label, e.g. \"Claude Code\", \"Personal Codex\", \"Grok\", \"Qwen3-Coder-Next (local)\". */\n label: string;\n /** Account id from connections.json for native seats; `local` for Ollama seats. */\n accountId: string;\n /** Models this seat can run. First entry is the default. */\n models: VerseModelOption[];\n /** Best-known context window in tokens for the default model (null when unknown). */\n contextWindow: number | null;\n /** Latest health/usage evidence, if any. Never an admission input in V1. */\n health: VerseSeatHealth;\n /**\n * V2.1 ADDITIVE. The subscription capacity behind this seat, so the seat\n * list can render a meter without a second request.\n *\n * Absent (`undefined`) for LOCAL seats: an Ollama tag has no subscription\n * and no provider window. Its real constraint is machine memory, which is\n * reported by `VerseBootstrap.localRuntime`, not by a quota. Absent on a\n * native seat means the server could not build a record for that account\n * at all — `health.state` says what it does know.\n */\n capacity?: VerseSeatCapacity;\n /**\n * V3.9 ADDITIVE. The version of the CLI binary this seat is PINNED to (its\n * native-profile launcher execs one exact file). Absent when unknown and on\n * local seats. A pinned binary never updates itself, so a model that needs a\n * newer CLI is listed with `unavailableReason` rather than silently failing.\n */\n cliVersion?: string;\n /**\n * V3.9 ADDITIVE. Plain-language facts about this seat's context setup the UI\n * must show rather than imply (binary skew, catalog not yet fetched, …).\n * Absent when there is nothing to say, so ordinary seats keep their shape.\n */\n notes?: string[];\n /**\n * 3.15 ADDITIVE (routing/tiers.ts `CostBasis`). What one more turn on this\n * seat costs when it is NOT the engine's default basis — e.g. \"Devin\n * (cloud)\" spends ACU credits. Absent = the engine default (local free,\n * everything else subscription).\n */\n costBasis?: 'subscription' | 'credits' | 'per-token' | 'free';\n}\n\n/**\n * Where a context-window figure came from, so nothing on screen implies more\n * certainty than it has (docs/VERSE-CONTEXT.md §1).\n *\n * - `runtime` — the CLI reported it for THIS turn (claude/grok\n * `result.modelUsage.<m>.contextWindow`, codex rollout\n * `token_count.info.model_context_window`, Ollama\n * `/api/ps`). Wins over everything else.\n * - `provider-catalog` — the seat's own served catalog on disk (codex/grok\n * `native-state/models_cache.json`).\n * - `cli-catalog` — read out of the pinned CLI binary's embedded catalog\n * and recorded here with the version it was read from.\n * - `documented` — the provider's published model table.\n * - `fallback` — a named default; the UI marks it as an estimate.\n */\nexport type VerseWindowSource = 'runtime' | 'provider-catalog' | 'cli-catalog' | 'documented' | 'fallback';\n\n/**\n * How much context a session is allowed to accumulate before the CLI compacts.\n *\n * - `standard` — the default. Evidence-based budget per engine: Claude 1M\n * models compact near 400k instead of ~967k; Codex, Grok and\n * local run their native windows.\n * - `expansive` — opt-in. Claude runs its full native window (CLI `auto`),\n * Codex raises `model_context_window` to the model's catalog\n * maximum (872k on GPT-6 / GPT-5.6). Costs more usage per turn,\n * buys simultaneous visibility for coupled, cross-cutting work.\n *\n * A mode that does not exist for a model (Grok, local, 200k Claude models,\n * GPT-5.5) is simply absent from that model's option — never faked.\n */\nexport type VerseContextMode = 'standard' | 'expansive';\n\nexport const VERSE_CONTEXT_MODES: readonly VerseContextMode[] = ['standard', 'expansive'];\n\n/** One mode's budget for a model on a seat. */\nexport interface VerseContextBudget {\n /** The window the CLI measures against in this mode (the meter's denominator). */\n contextWindow: number;\n /** Token count at which the CLI auto-compacts in this mode; null when unknown. */\n autoCompactAt: number | null;\n /**\n * The RAW window value the CLI must be TOLD to reach this budget, when that\n * differs from `contextWindow` — codex measures against 95% of the window it\n * is configured with, so expansive GPT-6 is `providerWindow: 872_000`\n * (`-c model_context_window=872000`) but `contextWindow: 828_400`.\n */\n providerWindow?: number | null;\n}\n\nexport interface VerseModelOption {\n id: string;\n label: string;\n /** Standard-mode window the CLI measures against (codex: the 95% effective window). */\n contextWindow: number | null;\n /**\n * V3.9 ADDITIVE — every field below is optional so records and fixtures\n * written before it keep validating. Absent means \"not known\", never zero.\n */\n /** Standard-mode auto-compaction point. */\n autoCompactAt?: number | null;\n /** Present ONLY when this model on this seat has a real expansive mode. */\n expansive?: VerseContextBudget | null;\n /** The CLI's default max output for this model, when known. */\n maxOutputTokens?: number | null;\n windowSource?: VerseWindowSource;\n /** Minimum CLI version that knows this model id (e.g. '2.1.280'); null when any. */\n minCliVersion?: string | null;\n /**\n * Why this model cannot run on this seat right now, in plain language (e.g.\n * \"needs Claude Code 2.1.280; this seat runs 2.1.257\"). Null/absent = runnable.\n * Listed rather than hidden so the operator learns WHY a model is missing.\n */\n unavailableReason?: string | null;\n /**\n * 3.15 ADDITIVE. The model family this option belongs to (\"SWE-2\",\n * \"Claude Opus 5.5\") on a seat whose catalog is grouped by family (the\n * Devin CLI seat). Pickers group consecutive options by it. Absent = none.\n */\n group?: string | null;\n /** 3.15 ADDITIVE. What the model costs, as the vendor lists it (\"Free\", \"$4 in · $20 out per 1M\"). Absent = not known. */\n priceNote?: string | null;\n}\n\nexport interface VerseSeatHealth {\n state: 'ready' | 'degraded' | 'unavailable' | 'unknown';\n /** e.g. \"5h window 72% used, resets 14:00\" — plain text, already sanitized. */\n summary: string | null;\n windows: Array<{ id: string; usedPercent: number | null; resetsAt: string | null }>;\n observedAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Seat capacity (V2.1, additive) — see docs/VERSE-TELEMETRY-V2.md, which is\n// the authority for every honesty rule encoded in these shapes.\n//\n// This file is imported by the BROWSER bundle, so it may not import\n// `core/verse/accounts.ts` (node:fs). The shapes below therefore restate the\n// provider-record shapes structurally. `seats.ts` assigns the account record's\n// values straight into them, so a divergence in `core/verse/accounts.ts` stops\n// `seats.ts` compiling — that assignment is the drift guard.\n// ---------------------------------------------------------------------------\n\n/** One provider-reported quota window, as carried on a seat. */\nexport interface VerseSeatWindow {\n id: string;\n /** Provider-reported percent, or null for NO SIGNAL — which is not zero. */\n usedPercent: number | null;\n /**\n * Machine-readable reset instant. STRUCTURALLY ALWAYS NULL for Claude: that\n * provider publishes only a sentence, which lives in `resetDescription` and\n * is rendered verbatim. The server never synthesizes an instant from it.\n * (3.10.1: the Command burn-down chart may place the reset on its time axis\n * via `resetInstantFromWords` in web-ui command-model, but only for the\n * collector's exact \"Mon D at H:MMam (Area/Zone)\" form and only when the\n * result lands within one window of now; anything else stays words.)\n */\n resetsAt: string | null;\n /** The provider's own reset wording, verbatim (\"resets Sep 25 at 7pm (America/New_York)\"). */\n resetDescription: string | null;\n /**\n * TRUE only when the provider explicitly FLAGGED the limit. Such a window's\n * `usedPercent` is the SENTINEL 100 — a denial, not a measurement — and must\n * be labelled \"limit reached\", never \"100% used\".\n */\n limitReached: boolean;\n /** False when `usedPercent` is a flagged sentinel rather than a reading. */\n measured: boolean;\n}\n\n/**\n * Codex credits, INDEPENDENT of the window: a fully used weekly window with a\n * spendable balance is not blocked. `null` is \"no signal\", never \"no credits\".\n */\nexport interface VerseSeatCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Provider-reported decimal string, kept verbatim — never rounded. */\n balance: string | null;\n}\n\n/**\n * The coarse \"can I use this seat right now\" verdict. Deliberately coarse: the\n * exact numbers are in `windows`, and a verdict that pretended to more\n * precision than the providers give would be a lie.\n *\n * - `ready` — a reading exists and the binding window has headroom.\n * - `tight` — the binding window is at/above the warn threshold, OR it is\n * spent while Codex credits remain spendable (not blocked).\n * - `exhausted` — the binding window is spent and nothing else is left.\n * - `signed-out` — the account is not authenticated; reconnect it.\n * - `unknown` — NO window carried a percent. Not zero, not healthy.\n */\nexport type VerseSeatUsability = 'ready' | 'tight' | 'exhausted' | 'signed-out' | 'unknown';\n\n/**\n * Where a seat's windows came from, so nothing implies freshness it lacks.\n * Mirrors `VerseEvidenceSource` in `core/verse/accounts.ts`.\n */\nexport type VerseSeatEvidenceSource = 'collector' | 'shared-evidence' | 'baseline' | 'none';\n\n/** Everything the seat list needs to draw a capacity meter honestly. */\nexport interface VerseSeatCapacity {\n /** e.g. \"max\", \"pro\", \"SuperGrok\". Null when the provider gave none. */\n planType: string | null;\n /**\n * THE CONSTRAINT THAT ACTUALLY BLOCKS WORK: the window with the highest\n * `usedPercent`. Null when no window carried a percent at all.\n */\n binding: VerseSeatWindow | null;\n /** Every window the provider reported, in provider order. */\n windows: VerseSeatWindow[];\n /** Codex only; null for every other provider and when no signal exists. */\n credits: VerseSeatCredits | null;\n usability: VerseSeatUsability;\n observedAt: string | null;\n evidenceSource: VerseSeatEvidenceSource;\n /** Plain-language provider facts the UI must show instead of implying a fault. */\n notes: string[];\n}\n\nexport interface VerseProject {\n path: string;\n name: string;\n /** From ~/.ashlr/enrollment.json when present. */\n enrolled: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Workspaces (V2.2, ADDITIVE) — see docs/VERSE-WORKSPACES.md §1.\n//\n// A session bound to ONE directory cannot express \"this service plus the\n// shared library it depends on\", which is most real work. A workspace is a\n// NAMED set of roots with exactly one marked primary.\n//\n// `VerseSession.projectPath` keeps its meaning — it IS the primary root — so\n// every session record, adapter and test written before workspaces existed\n// still loads and still runs. Nothing rewrites saved chat history.\n//\n// ENROLLMENT IS NOT PART OF THIS SHAPE ON PURPOSE. A workspace says what a\n// session may REACH; `~/.ashlr/enrollment.json` says what the AUTONOMOUS lane\n// may mutate, and the two are deliberately separate registries. Membership in\n// a workspace grants no enrollment: `enrolled` below is READ from the\n// registry per root and is never written by anything in this feature.\n// ---------------------------------------------------------------------------\n\n/** One directory in a workspace. Exactly one root in a workspace is primary. */\nexport interface VerseWorkspaceRoot {\n /** Absolute, physically resolved path (symlinks followed). */\n path: string;\n /** Display name; defaults to the basename. */\n name: string;\n /**\n * The session's cwd and the value `projectPath` carries. Exactly one root\n * per workspace has this set.\n */\n primary: boolean;\n}\n\n/**\n * A named set of roots.\n *\n * ONE TYPE, TWO USES, DELIBERATELY. An interactive session binds to a\n * workspace to decide what it can reach; the autonomous lane reads the same\n * workspace as a SECTION — \"these repositories collaborate, work on them\n * together\" — when `section` is true. They were not split because the thing\n * being named is identical in both: a set of directories that belong to one\n * piece of work. Two registries of named repo groups would drift.\n *\n * What is NOT on this type is priority. A repo may belong to several\n * workspaces, so a per-membership rank would give one repo several\n * contradictory ranks. Priority is therefore an attribute OF THE REPO, held\n * once per path in the same registry — see `VerseRootPriority`.\n */\nexport interface VerseWorkspace {\n id: string;\n name: string;\n /** Primary first, then the extras in the order they were added. */\n roots: VerseWorkspaceRoot[];\n /**\n * Offer this workspace to the autonomous lane as a section.\n *\n * GRANTS NOTHING. The fleet still reaches only what\n * `~/.ashlr/enrollment.json` permits; a section can group and order those\n * repos and nothing else. A member that is not enrolled stays unreachable.\n */\n section: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Relative standing of one repository in the autonomous lane's attention.\n *\n * ORDERING ONLY, NEVER ADMISSION. `critical` on an unenrolled repo is still\n * refused by `assertMayMutate`; `low` on an enrolled one is still permitted.\n * An ordinal rather than a number because the operator's judgement here is\n * \"this matters more than that\", and a 0-100 score would invent a precision\n * nobody holds.\n *\n * Absent means `normal`, which is how every repo already behaves — so a\n * registry with no priorities at all reproduces today's flat list exactly.\n */\nexport type VerseRootPriority = 'critical' | 'high' | 'normal' | 'low';\n\nexport const VERSE_ROOT_PRIORITIES: readonly VerseRootPriority[] =\n ['critical', 'high', 'normal', 'low'];\n\nexport const VERSE_DEFAULT_ROOT_PRIORITY: VerseRootPriority = 'normal';\n\n/** Sort weight; lower sorts first. Never a budget, never a multiplier. */\nexport const VERSE_ROOT_PRIORITY_RANK: Record<VerseRootPriority, number> = {\n critical: 0,\n high: 1,\n normal: 2,\n low: 3,\n};\n\n/** One enrolled repository as the autonomy scope view ranks it. */\nexport interface VerseAutonomyScopeEntry {\n path: string;\n name: string;\n priority: VerseRootPriority;\n /** Sections (workspaces with `section: true`) this repo belongs to. */\n sections: Array<{ id: string; name: string }>;\n /** True when a focus section is set and this repo is outside it. */\n outsideFocus: boolean;\n}\n\n/**\n * The autonomous lane's scope, ORDERED.\n *\n * Built by INTERSECTING section membership with the enrollment registry, so\n * it can only ever be a subset of what enrollment already allows. Sections\n * add ordering and grouping; they never add reach.\n */\nexport interface VerseAutonomyScopeView {\n focusSectionId: string | null;\n focusSectionName: string | null;\n /** Enrolled repos, most important first. */\n entries: VerseAutonomyScopeEntry[];\n /**\n * Paths a section names that are NOT enrolled. Listed so the blast radius\n * is legible in both directions — these are exactly the repos a section\n * does NOT give the fleet.\n */\n unenrolledSectionRoots: string[];\n}\n\n/**\n * Per-root git identity. A turn that edits two repos produces two diffs, so\n * the transcript has to be able to attribute each file to the right one.\n *\n * `remote` is the canonical `owner/repo` for a GitHub origin and null for\n * anything else — deliberately NOT the raw remote URL, which can carry a\n * token in its userinfo and would then reach an API response.\n */\nexport interface VerseRootGit {\n branch: string;\n /** Count of porcelain entries; 0 is clean. */\n dirty: number;\n ahead: number;\n behind: number;\n remote: string | null;\n}\n\n/** A root as the client sees it: identity, reachability and honest scope. */\nexport interface VerseRootStatus {\n path: string;\n name: string;\n primary: boolean;\n exists: boolean;\n /**\n * Read live from the enrollment registry. FALSE means the interactive lane\n * still works on this root while the autonomous lane refuses it — being in\n * a workspace never changes this.\n */\n enrolled: boolean;\n /** Null when the root is not a git repository, or git is unavailable. */\n git: VerseRootGit | null;\n /**\n * False when the session's engine has no way to be granted this root (Grok's\n * CLI exposes `--cwd` and nothing else). The root is still listed, because\n * hiding it would misrepresent what the workspace is.\n */\n reachable: boolean;\n}\n\n/** GET /api/verse/sessions/:id/roots */\nexport interface VerseSessionRootsResponse {\n sessionId: string;\n workspaceId: string | null;\n workspaceName: string | null;\n roots: VerseRootStatus[];\n /**\n * Plain-language facts the UI must show rather than imply: an unreachable\n * root on a Grok seat, or a root the autonomous lane will refuse.\n */\n notes: string[];\n}\n\n/** GET /api/verse/workspaces */\nexport interface VerseWorkspacesResponse {\n workspaces: VerseWorkspace[];\n /** Live per-root facts, keyed by workspace id, so one read draws the list. */\n status: Record<string, VerseRootStatus[]>;\n /** Per-repo priority, keyed by canonical path. Absent key means `normal`. */\n priorities: Record<string, VerseRootPriority>;\n focusSectionId: string | null;\n}\n\n/** POST /api/verse/workspaces */\nexport interface VerseWorkspaceCreateRequest {\n name: string;\n /** Absolute paths. The first is the primary. */\n roots: string[];\n /** Also offer this set to the autonomous lane as a section. Default false. */\n section?: boolean;\n}\n\n/** POST /api/verse/workspaces/:id/update */\nexport interface VerseWorkspaceUpdateRequest {\n name?: string;\n /** When present, replaces the root set wholesale. First entry is primary. */\n roots?: string[];\n section?: boolean;\n}\n\n/** POST /api/verse/workspaces/priority */\nexport interface VerseRootPriorityRequest {\n path: string;\n priority: VerseRootPriority;\n}\n\n/** POST /api/verse/workspaces/focus — `sectionId: null` clears the focus. */\nexport interface VerseFocusSectionRequest {\n sectionId: string | null;\n}\n\n/** Hard cap on roots per workspace — a blast radius, not a UI limit. */\nexport const VERSE_MAX_WORKSPACE_ROOTS = 8;\n\n/**\n * Every root a session can reach, primary first.\n *\n * Pure and total: a record written before workspaces existed has no\n * `extraRoots` and yields exactly `[projectPath]`, which is what every caller\n * assumed before this existed.\n */\nexport function verseSessionRoots(\n session: Pick<VerseSession, 'projectPath' | 'extraRoots'>,\n): string[] {\n const out = [session.projectPath];\n for (const root of session.extraRoots ?? []) {\n if (typeof root === 'string' && root.length > 0 && !out.includes(root)) out.push(root);\n }\n return out;\n}\n\nexport interface VerseUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n /**\n * Prompt size of the most recent assistant call = live context occupancy.\n * Stored UNCLAMPED: a reading above the window is information (the CLI is\n * about to compact or overflow), and only the UI decides how to draw it.\n */\n contextTokens: number;\n contextWindow: number | null;\n /** V3.9 ADDITIVE. Where `contextWindow` came from; absent on old records. */\n contextWindowSource?: VerseWindowSource;\n /** V3.9 ADDITIVE. Auto-compaction point for the session's current mode. */\n autoCompactAt?: number | null;\n /**\n * V3.9 ADDITIVE. False when `contextTokens` is an UPPER BOUND rather than a\n * measurement (codex before its rollout is readable: the turn total sums\n * every model call). Absent means exact.\n */\n contextTokensExact?: boolean;\n}\n\nexport interface VerseSession {\n id: string;\n title: string;\n /**\n * The PRIMARY root: the process cwd and the folder every pre-workspace\n * client already reads. Unchanged in meaning, which is why no session\n * record ever has to be rewritten.\n */\n projectPath: string;\n /**\n * V2.2 ADDITIVE. Roots BEYOND the primary, pinned at creation time.\n *\n * Absent on every record written before workspaces existed, and absent on\n * a single-root session today — so the on-disk shape of an ordinary chat\n * does not change at all.\n *\n * PINNED, not referenced: a session keeps the roots it was created with\n * even if the named workspace is later edited or deleted, for the same\n * reason `launch.anthropicBaseUrl` is pinned — a conversation must not\n * silently gain reach because config moved underneath it.\n */\n extraRoots?: string[];\n /** V2.2 ADDITIVE. Provenance of the pinned roots; absent for an ad-hoc set. */\n workspaceId?: string;\n workspaceName?: string;\n engine: VerseEngine;\n accountId: string;\n seatId: string;\n model: string;\n /** Vendor conversation id used for resume (claude/grok: our uuid; codex: thread id from output). */\n nativeSessionId: string | null;\n createdAt: string;\n updatedAt: string;\n status: VerseSessionStatus;\n turnCount: number;\n usage: VerseUsage;\n lastError: string | null;\n /**\n * V3.9 ADDITIVE. The session's context budget. Every record written by 3.9+\n * carries it explicitly, so ABSENT means a pre-3.9 record: the engine\n * materializes it on first touch — `expansive` for a Claude 1M model (that\n * is the native ~967k compaction those chats always ran with, so upgrading\n * never forces a paid compaction), `standard` otherwise (= native).\n * Changeable mid-session (POST /sessions/:id/context-mode): it changes CLI\n * flags, not prompt content — but switching DOWN below the current\n * occupancy makes the CLI compact on its next turn.\n */\n contextMode?: VerseContextMode;\n /** V3.9 ADDITIVE. Native compactions observed so far (claude/grok compact_boundary, codex rollout `compacted`). */\n compactionCount?: number;\n /** V3.9 ADDITIVE. Set when this session was started as a handoff from another. */\n handoffFrom?: { sessionId: string; title: string };\n /**\n * V3.9 ADDITIVE. Shared project memory was offered to this session's CLI at\n * creation. Pinned, like the roots: a conversation must not silently gain a\n * writable directory because a preference moved underneath it.\n */\n memoryEnabled?: boolean;\n /**\n * V3.10 ADDITIVE (contract: unit C0; written by C3's engine). The operator's\n * per-chat effort and permission choices, applied from the NEXT turn — a\n * running turn keeps the argv it was launched with. Absent (every record\n * before 3.10, and any key never set) = the engine default: permission mode\n * `accept-edits`, effort = the CLI's own default.\n *\n * A MODEL change is deliberately NOT stored here: it rewrites `model` above,\n * which every launch already reads — one field, one truth.\n */\n controls?: VerseSessionControls;\n /** 3.15 ADDITIVE. Devin seats only — the latest `remote-status` reading (see VerseRemoteInfo). */\n remote?: VerseRemoteInfo;\n}\n\n/**\n * V3.10. Permission modes a chat can run in (SPEC-310C §0.6), in picker order.\n * - `plan` — the CLI plans and edits nothing.\n * - `accept-edits` — the default: edits applied without asking.\n * - `auto` — the CLI's own auto mode.\n * - `bypass` — every check skipped. Shown red and confirmed PER CHAT:\n * never a default, never inherited by a new chat.\n * Adapters map these to each CLI's spelling (claude `acceptEdits` /\n * `bypassPermissions`, grok `dontAsk`, …). An engine that cannot honour one\n * reports it unavailable WITH a reason rather than approximating it. The\n * in-page \"Ask\" mode (answering permission prompts in the UI) is 3.11.\n */\nexport const VERSE_PERMISSION_MODES = ['plan', 'accept-edits', 'auto', 'bypass'] as const;\nexport type VersePermissionMode = (typeof VERSE_PERMISSION_MODES)[number];\nexport const VERSE_DEFAULT_PERMISSION_MODE: VersePermissionMode = 'accept-edits';\n\n/**\n * V3.10. Reasoning effort, the union across engines — claude `--effort`\n * (low · medium · high · xhigh · max) and codex `model_reasoning_effort`\n * (minimal · low · medium · high · xhigh). Each seat offers only the subset\n * its CLI accepts; the rest come back unavailable with a reason.\n */\nexport const VERSE_EFFORTS = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const;\nexport type VerseEffort = (typeof VERSE_EFFORTS)[number];\n\n/** V3.10. `VerseSession.controls` — absent key = engine default (see there). */\nexport interface VerseSessionControls {\n effort?: VerseEffort;\n permissionMode?: VersePermissionMode;\n}\n\n/**\n * 3.15: the playbook a chat message's `!macro` ran (any seat). The message's\n * `text` stays exactly as typed; the seat got the playbook's block appended.\n */\nexport interface VerseMessagePlaybook {\n id: string;\n version: number;\n name: string;\n macro: string;\n}\n\n/** Normalized event stream. `seq` is monotonic per session and is the SSE id. */\nexport type VerseEvent =\n | { seq: number; at: string; type: 'user-message'; turnId: string; text: string; playbook?: VerseMessagePlaybook }\n | { seq: number; at: string; type: 'turn-started'; turnId: string; pid: number | null }\n | { seq: number; at: string; type: 'text-delta'; turnId: string; text: string }\n | { seq: number; at: string; type: 'assistant-message'; turnId: string; text: string }\n /**\n * Reasoning the CLI chose to show. V3.10 ADDITIVE optional fields (absent on\n * older records = unknown, never \"false\"/\"0\"):\n * - `redacted` the CLI sent a signature-only / redacted block, so `text` is\n * empty but the model DID think (the UI says \"Thought 12s\").\n * - `durationMs` wall time the block took to stream, when measured.\n * - `kind` see VerseThinkingKind.\n */\n | {\n seq: number;\n at: string;\n type: 'thinking';\n turnId: string;\n text: string;\n redacted?: boolean;\n durationMs?: number;\n kind?: VerseThinkingKind;\n }\n | { seq: number; at: string; type: 'tool-use'; turnId: string; toolUseId: string; name: string; input: unknown }\n | { seq: number; at: string; type: 'tool-result'; turnId: string; toolUseId: string; output: string; isError: boolean }\n | { seq: number; at: string; type: 'usage'; turnId: string; usage: VerseUsage }\n | { seq: number; at: string; type: 'turn-done'; turnId: string; ok: boolean; nativeSessionId: string | null; durationMs: number }\n /**\n * `code` (V3.10 ADDITIVE, optional) is a stable machine key for errors the UI\n * or engine acts on — see VERSE_ERROR_CODES. Absent = uncategorised.\n */\n | { seq: number; at: string; type: 'error'; turnId: string | null; message: string; code?: string }\n | { seq: number; at: string; type: 'cancelled'; turnId: string }\n /**\n * V3.9. The CLI compacted its own conversation. Token counts are the CLI's\n * own (`compact_metadata.pre_tokens/post_tokens` on claude/grok). Codex\n * rollouts mark only THAT a compaction happened, so its counts are the last\n * `token_count` reading before the marker and the first one after it —\n * measured, but by Verse, not stated by the CLI; its `durationMs` is null.\n * Any count may be null when no reading brackets the compaction.\n */\n | {\n seq: number;\n at: string;\n type: 'compaction';\n turnId: string | null;\n trigger: 'auto' | 'manual';\n preTokens: number | null;\n postTokens: number | null;\n durationMs: number | null;\n }\n /**\n * V3.9. A context-occupancy READING that is not a usage delta — e.g. codex's\n * rollout `token_count` (exact last-call prompt size and the window the CLI\n * measured it against), polled mid-turn and read again after it. Replaces\n * the session's `contextTokens`; never summed. The engine fills\n * `autoCompactAt` for the window in force.\n */\n | {\n seq: number;\n at: string;\n type: 'context';\n turnId: string | null;\n contextTokens: number;\n contextWindow: number | null;\n exact: boolean;\n autoCompactAt?: number | null;\n /**\n * Where `contextWindow` came from. A CLI reading is `runtime`; the event\n * the engine writes after a MODE SWITCH carries the new budget's catalog\n * source, so a client never relabels a catalog figure as a measurement.\n * Absent on events from before this field existed (treat as `runtime`).\n */\n contextWindowSource?: VerseWindowSource;\n }\n // ── V3.10 TRANSIENT events ────────────────────────────────────────────────\n // Never written to the session log; fanned out to live SSE listeners only\n // (see VERSE_TRANSIENT_EVENT_TYPES for the wire rules). A reload therefore\n // never shows them — everything they convey is either ephemeral (a spinner)\n // or re-stated by a persisted event at turn end (`thinking`, `usage`).\n /** A chunk of streamed reasoning text for the in-flight thinking block. */\n | { seq: number; at: string; type: 'thinking-delta'; turnId: string; text: string }\n /**\n * The CLI reports reasoning volume without text (claude\n * `system/thinking_tokens`). An ESTIMATE, rate-limited by the adapter.\n */\n | { seq: number; at: string; type: 'thinking-progress'; turnId: string; estimatedTokens: number }\n /**\n * What the running turn is doing right now. `tool` names the running tool\n * when phase is `tool`. `outTokens`/`tokPerSec` are absent when unmeasured.\n */\n | {\n seq: number;\n at: string;\n type: 'progress';\n turnId: string;\n phase: VerseProgressPhase;\n tool?: string;\n elapsedMs: number;\n outTokens?: number;\n tokPerSec?: number;\n }\n /** A human-readable notice about the turn's plumbing (API retry, preflight, no-output watchdog). */\n | { seq: number; at: string; type: 'status'; turnId: string | null; kind: VerseStatusKind; message: string }\n // ── V3.10 PERSISTED events ────────────────────────────────────────────────\n /**\n * The engine recovered from a lost native conversation (e.g. the vendor\n * thread vanished) by starting a new native session seeded with the handoff\n * note (`how: 'handoff'`) or a bare new session (`new-native-session`).\n */\n | { seq: number; at: string; type: 'recovered'; turnId: string | null; how: VerseRecoveryHow; message: string }\n /**\n * The log hit its cap and events with `seq < droppedBefore` were dropped at\n * a TURN boundary (never mid-turn). `turnId` is always null — it is present\n * only so code reading `event.turnId` across the union keeps typechecking.\n */\n | { seq: number; at: string; type: 'history-truncated'; turnId: null; droppedBefore: number }\n // ── V3.15 PERSISTED (additive) ────────────────────────────────────────────\n /**\n * Where information reached the agent from, when that is NOT already\n * visible as a tool call: context the engine injected, or a source a\n * remote seat (Devin) reported. Sources a tool call proves — a Read, a\n * WebFetch — are DERIVED from the call at read time (core/verse/trace.ts\n * `sourcesFromToolCall`) and never persisted twice. `turnId` null = the\n * whole chat. Older clients drop an unknown type; older logs never carry it.\n */\n | { seq: number; at: string; type: 'source'; turnId: string | null; source: VerseSource }\n // ── 3.15 PERSISTED events (Devin seats) ───────────────────────────────────\n /**\n * The remote session changed state (\"Devin is working…\", \"waiting for you\",\n * finished, suspended, terminated) and/or reported ACUs. Persisted so a\n * reload shows where the session stood; the engine folds the latest one into\n * `VerseSession.remote` for the header meter.\n */\n | {\n seq: number;\n at: string;\n type: 'remote-status';\n turnId: string | null;\n provider: 'devin';\n state: VerseRemoteState;\n message: string;\n url: string | null;\n acusConsumed: number | null;\n acuCap: number | null;\n }\n /** Devin opened (or updated) a pull request. `url` is always an https GitHub URL. */\n | {\n seq: number;\n at: string;\n type: 'remote-pr';\n turnId: string | null;\n provider: 'devin';\n url: string;\n state: string | null;\n };\n\nexport type VerseEventType = VerseEvent['type'];\n\n/**\n * V3.15. What kind of thing an agent drew on.\n * - `file` a file in (or near) the workspace it read;\n * - `url` a web page it fetched (or a search result it was handed);\n * - `search` a web search it ran (the query is the source);\n * - `doc` documentation: a repo doc (*.md) or a repo-wiki page (#537);\n * - `memory` shared project memory (MEMORY.md) offered to the chat;\n * - `knowledge` approved lessons / playbooks (#535) put in front of it.\n */\nexport type VerseSourceKind = 'file' | 'url' | 'search' | 'doc' | 'memory' | 'knowledge';\n\n/**\n * V3.15. One source, normalized across seats. Everything but `kind`, `ref`,\n * `title` and `origin` is optional and ABSENT when unknown — never guessed.\n */\nexport interface VerseSource {\n kind: VerseSourceKind;\n /** Dedupe key within a chat: the path for file-ish kinds, the normalized URL, `search:<query>`. */\n ref: string;\n /** Short human label (a basename, a page title, the query). */\n title: string;\n /** Who vouches for it: derived from a tool call, injected by the engine, or reported by the seat. */\n origin: 'tool' | 'engine' | 'agent';\n path?: string;\n /** 1-based inclusive line range the agent actually saw, when the call (or its output) says so. */\n lineStart?: number;\n lineEnd?: number;\n url?: string;\n /** `example.com` (no `www.`), for URL sources. */\n domain?: string;\n query?: string;\n /** The tool call that produced it (origin `tool`). */\n toolUseId?: string;\n /** One plain-language line of context (\"offered on every turn\"). */\n detail?: string;\n}\n\n/** V3.10. `summary` = vendor-summarised reasoning, `raw` = verbatim, `progress` = a heading/placeholder only. */\nexport type VerseThinkingKind = 'summary' | 'raw' | 'progress';\n\n/** V3.10. Phase of a running turn, carried by the transient `progress` event. */\nexport type VerseProgressPhase = 'thinking' | 'tool' | 'writing' | 'waiting';\n\n/** V3.10. What a transient `status` notice is about. */\nexport type VerseStatusKind = 'retry' | 'preflight' | 'watchdog';\n\n/** V3.10. How a `recovered` event restored the conversation. */\nexport type VerseRecoveryHow = 'new-native-session' | 'handoff';\n\n/**\n * V3.10. Known `error.code` values. `code` stays `string` on the wire so an\n * older client never rejects a newer code; these are the ones Verse acts on.\n * - `native-thread-missing` — the vendor conversation to resume no longer exists.\n * - `session-in-use` — the CLI refused because the native session id is locked.\n */\nexport const VERSE_ERROR_CODES = ['native-thread-missing', 'session-in-use'] as const;\nexport type VerseErrorCode = (typeof VERSE_ERROR_CODES)[number];\n\n/**\n * V3.10. Event types that are NEVER persisted — emitted to live SSE listeners\n * only. The list and its guard live in ./transient-events.ts (re-exported\n * here): the web chat's first-paint store needs the guard, and importing it\n * from this module put every runtime value exported here — the handoff\n * prompt, the effort tables — into the chat's first-paint chunk.\n */\nexport { VERSE_TRANSIENT_EVENT_TYPES, isTransientVerseEvent } from './transient-events.js';\n\nexport type VerseTransientEventType = (typeof TRANSIENT_EVENT_TYPE_LIST)[number];\nexport type VerseTransientEvent = Extract<VerseEvent, { type: VerseTransientEventType }>;\nexport type VersePersistedEvent = Exclude<VerseEvent, { type: VerseTransientEventType }>;\n\n/**\n * Which endpoint a LOCAL seat sends its turns to.\n *\n * - `ollama` — the historical lane: the plain `claude` binary with\n * ANTHROPIC_BASE_URL pointed straight at Ollama's\n * Anthropic-compatible endpoint on :11434. Ollama\n * serialises this model architecture, so a fleet of local\n * agents on this lane is a queue (docs/LOCAL-FLEET.md).\n * - `llama-server` — the same binary pointed at the local Anthropic\n * normalising proxy that fronts llama-server. That proxy\n * is the ONLY way to reach llama-server's parallel slots\n * and the prompt-cache fix, because Qwen3.8's chat\n * template rejects Claude Code's request shape unless the\n * proxy rewrites it on the way through.\n *\n * DISPATCH ONLY. Model DISCOVERY stays on Ollama in both lanes — llama-server\n * implements neither `/api/tags` nor `/api/show`, which is where every local\n * seat's identity, context window and `tools` capability comes from.\n */\nexport type VerseLocalDispatch = 'ollama' | 'llama-server';\n\n/** What a client is told about this machine's local serving situation. */\nexport interface VerseLocalRuntimeSummary {\n /** Ollama reachable? Drives the local seats and an inline hint when false. */\n ollama: { reachable: boolean; baseUrl: string; models: string[] };\n /**\n * Where local seats DISPATCH turns, reported only when that is NOT the\n * default Ollama lane.\n *\n * Absent means `ollama`, i.e. exactly what every existing client already\n * assumes — so opting in is visible on the wire and NOT opting in changes no\n * payload at all.\n */\n dispatch?: { lane: VerseLocalDispatch; baseUrl: string };\n}\n\n/** GET /api/verse/bootstrap */\nexport interface VerseBootstrap {\n seats: VerseSeat[];\n projects: VerseProject[];\n sessions: VerseSession[];\n /** Whether POST routes are enabled on this server (`ashlr serve --allow-dispatch` / `ashlr verse`). */\n dispatchEnabled: boolean;\n localRuntime: VerseLocalRuntimeSummary;\n}\n\n/**\n * GET /api/verse/seats (V2.1)\n *\n * WHY THIS ROUTE EXISTS: `bootstrap` is a MOUNT-TIME snapshot. A client that\n * opened the app before the collector's first cycle finished would show\n * \"unknown\" forever. This is the same seat list, cheap enough to poll, and it\n * always reflects the collector's CURRENT state rather than a cached one.\n */\nexport interface VerseSeatsResponse {\n /** When this body was built. */\n sampledAt: string;\n seats: VerseSeat[];\n localRuntime: VerseBootstrap['localRuntime'];\n}\n\n/**\n * POST /api/verse/sessions\n *\n * Two spellings, never mixed (the API rejects the mix rather than silently\n * preferring one):\n * - `workspaceId` alone — the named workspace supplies primary and extras.\n * - `projectPath` (+ optional `extraRoots`) — an ad-hoc set, which is also\n * exactly the pre-workspace request shape.\n */\nexport interface VerseCreateSessionRequest {\n projectPath: string;\n seatId: string;\n model?: string;\n title?: string;\n /** V2.2 ADDITIVE. Absolute paths beyond the primary. */\n extraRoots?: string[];\n /** V2.2 ADDITIVE. Bind to a named workspace instead of naming paths. */\n workspaceId?: string;\n /**\n * SERVER-FILLED. The API resolves this from the registry once `workspaceId`\n * is validated, and never reads it off the request body — so a session can\n * not be labelled with a workspace name that is not the one it was built\n * from.\n */\n workspaceName?: string;\n /**\n * V3.9 ADDITIVE. Absent → the seat's preferred mode (preferences.json), else\n * `standard`. `expansive` on a model with no expansive budget is rejected.\n */\n contextMode?: VerseContextMode;\n /**\n * V3.9 ADDITIVE. Start this session as a handoff from an existing one. The\n * server resolves the source's title itself (never from the body) and pins\n * `handoffFrom`; the handoff TEXT is sent by the client as turn 1, after the\n * operator has read it — nothing is spent on their behalf.\n */\n handoffFromSessionId?: string;\n}\n\n/** POST /api/verse/sessions/:id/turns */\nexport interface VerseTurnRequest {\n text: string;\n}\nexport interface VerseTurnResponse {\n turnId: string;\n session: VerseSession;\n}\n\n/** GET /api/verse/sessions/:id */\nexport interface VerseSessionDetail {\n session: VerseSession;\n events: VerseEvent[];\n}\n\n/** Adapter input: how to launch one turn. Pure data, produced by the engine, consumed by the spawner. */\nexport interface VerseTurnLaunch {\n argv: string[];\n cwd: string;\n /** Extra env layered over a minimal base (PATH/HOME/TMPDIR/LANG). Never contains secrets. */\n env: Record<string, string>;\n /** Text written to stdin (codex); null when the prompt is in argv. */\n stdin: string | null;\n}\n\nexport const VERSE_MAX_TURN_TEXT_BYTES = 64 * 1024;\nexport const VERSE_MAX_EVENTS_PER_SESSION = 20_000;\nexport const VERSE_TURN_TIMEOUT_MS = 30 * 60 * 1000;\n/**\n * LAST-RESORT fallbacks, used only when neither the runtime, the seat's own\n * catalog, nor the verified per-model table (core/verse/model-windows.ts) knows\n * the model. Each mirrors what the CLI ITSELF assumes for an unknown id, so the\n * meter never claims more than the CLI will allow:\n *\n * - claude 200_000 — Claude Code's `Mg()` default for an unrecognized model.\n * Every KNOWN Claude id carries its real window (1M for the 5.x family,\n * Opus 4.8 and Sonnet 5) in the per-model table instead.\n * - codex 258_400 — 272_000 × the 95% `effective_context_window_percent`\n * every codex catalog entry carries; the figure codex's own rollouts report\n * as `model_context_window` (65,440 of 65,440 observed events).\n * - grok 500_000 — `context_window` for every grok-4.x id in the seat catalog.\n * - local 65_536 — the num_ctx the default local tag pins.\n */\nexport const VERSE_DEFAULT_CONTEXT_WINDOWS: Record<string, number> = {\n claude: 200_000,\n codex: 258_400,\n grok: 500_000,\n local: 65_536,\n};\n\n// ---------------------------------------------------------------------------\n// V3.9 context orchestration — request/response shapes (docs/VERSE-CONTEXT.md)\n// ---------------------------------------------------------------------------\n\n/** GET /api/verse/preferences — the operator's standing context choices. */\nexport interface VersePreferences {\n version: 1;\n /** Per-seat default context mode for NEW sessions. Absent = `standard`. */\n seats: Record<string, { contextMode?: VerseContextMode }>;\n /** Shared project memory. On by default; listed canonical paths opt out. */\n memory: { enabled: boolean; disabledProjects: string[] };\n /**\n * V3.10 ADDITIVE. Stream vendor-summarised reasoning on non-local seats\n * (claude `--thinking-display summarized`). Absent = on (Mason's default).\n */\n thinkingDisplay?: boolean;\n}\n\n/**\n * POST /api/verse/preferences — exactly ONE of the three forms per request, so\n * a body can never change more than the operator clicked.\n */\nexport type VersePreferencesUpdate =\n | { seatId: string; contextMode: VerseContextMode }\n | { memoryEnabled: boolean }\n | { projectPath: string; memoryEnabled: boolean };\n\n/** POST /api/verse/sessions/:id/context-mode */\nexport interface VerseContextModeRequest {\n mode: VerseContextMode;\n}\n\n/** POST /api/verse/sessions/:id/handoff-preview */\nexport interface VerseHandoffPreviewRequest {\n /**\n * Include the latest assistant message verbatim (capped) as the agent's own\n * summary — used after \"Ask this seat to summarize\" produced one.\n */\n includeLastAssistant?: boolean;\n /** Optional operator focus line, e.g. \"finish the migration of X\". ≤ 500 chars. */\n focus?: string;\n}\n\n/** Deterministic, zero-spend handoff note built from the session's event log. */\nexport interface VerseHandoffPreview {\n sourceSessionId: string;\n sourceTitle: string;\n /** The exact text to send as turn 1 of the new session. ≤ VERSE_HANDOFF_MAX_CHARS. */\n text: string;\n stats: {\n chars: number;\n /** chars / 4, rounded up — the same estimator the fit badges use. */\n estTokens: number;\n turnsCovered: number;\n filesTouched: number;\n /** Sections dropped to respect the cap, by name; empty when nothing was cut. */\n truncated: string[];\n };\n}\n\nexport const VERSE_HANDOFF_MAX_CHARS = 12_000;\n\n/**\n * The canned turn behind \"Ask this seat to summarize first\". Shared by the UI\n * (which sends it as an ordinary turn through the normal spend chokepoint) and\n * the handoff builder (which must NOT carry it into the new session as the\n * operator's \"latest ask\" — the new chat would otherwise be told to write a\n * handoff note instead of continuing the work).\n *\n * Written so the reply is useful as turn 1 of a session that has NONE of this\n * context. It asks for no tool use on purpose: a summary that starts editing\n * files is not a summary, and a read-only turn is also the cheapest one.\n */\nexport const VERSE_HANDOFF_SUMMARY_REQUEST = [\n 'This conversation is about to continue in a fresh session that has none of its context.',\n 'Write the handoff note that new session should start from. Do not edit files or run commands for this — only write the note.',\n '',\n 'Cover, concretely:',\n '- The goal, and what \"done\" looks like.',\n '- Decisions made so far, each with the reason it was made.',\n '- Current state: what is finished, what is half-done, what is untested.',\n '- Files changed and anything not yet committed.',\n '- How to verify the work (exact commands).',\n '- Open questions, risks, and approaches already tried that did not work.',\n '',\n 'Keep it under 600 words. Prefer file paths and commands over prose.',\n].join('\\n');\n\n/** GET /api/verse/context-fit — how big the reachable code is, in tokens. */\nexport interface VerseContextFitRoot {\n path: string;\n /** Tracked text files counted (git ls-files, binaries and >1 MB files skipped). */\n files: number;\n bytes: number;\n estTokens: number;\n /** True when the scan hit its file or time cap; estTokens is then a floor. */\n truncated: boolean;\n}\n\nexport interface VerseContextFit {\n roots: VerseContextFitRoot[];\n totalEstTokens: number;\n /** Always 'bytes/4' today; named so a better estimator can be introduced honestly. */\n estimator: 'bytes/4';\n sampledAt: string;\n}\n\n/**\n * Per-model verdict for a working set (see context-math.ts `fitVerdict`):\n * fits in standard, tight in standard, fits only in expansive, or too big for\n * any single context (split the work).\n */\nexport type VerseFitVerdict = 'fits' | 'tight' | 'expansive' | 'split';\n\n/** GET /api/verse/search?q=&limit= — keyword search over past sessions. Zero spend. */\nexport interface VerseSearchHit {\n sessionId: string;\n title: string;\n projectPath: string;\n engine: VerseEngine;\n seq: number;\n at: string;\n kind: 'user' | 'assistant';\n /** ≤ 240 chars around the first match, whitespace-collapsed. */\n snippet: string;\n score: number;\n}\n\nexport interface VerseSearchResponse {\n query: string;\n hits: VerseSearchHit[];\n /** Sessions actually scanned (the scan is bounded; see session-search.ts). */\n scannedSessions: number;\n truncated: boolean;\n}\n\n/** GET/POST /api/verse/memory — shared project memory for one project. */\nexport interface VerseProjectMemory {\n projectPath: string;\n enabled: boolean;\n /** Contents of MEMORY.md ('' when absent). */\n content: string;\n bytes: number;\n updatedAt: string | null;\n /** Other files the agents created in the memory directory (names only). */\n files: string[];\n /**\n * Present (true) only when `content` as SENT differs from the bytes on disk:\n * the public-JSON sanitizer rewrote the home path to `~` or replaced a\n * secret-looking value with `[REDACTED]`. The file itself is untouched; a\n * save that would write placeholders over real values is refused (409\n * VERSE_MEMORY_REDACTED), so the editor must say so before the operator types.\n */\n contentSanitized?: boolean;\n}\n\n/** POST /api/verse/memory */\nexport interface VerseProjectMemoryWrite {\n projectPath: string;\n content: string;\n}\n\nexport const VERSE_MEMORY_MAX_BYTES = 64 * 1024;\n\n/**\n * POST /api/verse/memory's own JSON body cap: JSON escaping can double the\n * content (every newline becomes `\\\\n`), plus room for the other fields. Every\n * other route keeps the 64 KiB default. Shared so the browser's pre-check can\n * never refuse a save the server would accept.\n */\nexport const VERSE_MEMORY_BODY_MAX_BYTES = 2 * VERSE_MEMORY_MAX_BYTES + 8 * 1024;\n\n/** Cap on the memory block appended to each session's system prompt. */\nexport const VERSE_MEMORY_BLOCK_MAX_BYTES = 6 * 1024;\n","/**\n * routes/verse/context/context-model.ts — the pure half of the context\n * components (handoff dialog, memory panel, session search). No React, no\n * I/O, so every rule the components render is pinned by a plain unit test.\n *\n * Every number shown here comes from context-math.ts (the one module the\n * server and the browser share), so \"compacts ≈367k\" in the handoff dialog is\n * the same figure the meter and the seat picker show.\n */\nimport type { VerseEngine, VerseModelOption, VerseSeat, VerseSession } from '../../../data/api-types.js';\nimport type {\n VerseContextMode,\n VerseFitVerdict,\n VersePreferences,\n VerseSearchHit,\n} from '../../../../core/verse/types.js';\nimport { VERSE_MEMORY_BLOCK_MAX_BYTES, VERSE_MEMORY_BODY_MAX_BYTES } from '../../../../core/verse/types.js';\nimport {\n budgetFor,\n canonicalModelId,\n estimateTokensFromChars,\n fitVerdict,\n hasExpansiveMode,\n sessionOverheadTokens,\n} from '../../../../core/verse/context-math.js';\nimport { formatContextWindow, formatRelative } from '../verse-model.js';\nimport { asClause, percentText, tidyProse } from '../autonomy/format.js';\nimport { formatTokens } from '../verse-readouts.js';\n\n// ---------------------------------------------------------------------------\n// Handoff\n// ---------------------------------------------------------------------------\n\n// The canned \"Ask this seat to summarize first\" turn is\n// VERSE_HANDOFF_SUMMARY_REQUEST in core/verse/types.ts, not a copy here: the\n// handoff builder on the server matches that exact text to keep it OUT of the\n// new session's \"latest requests\" (otherwise the new chat is told to write\n// another handoff note). A local copy that drifted by one character would\n// silently defeat that filter.\n\n/** Mirrors session-engine's TITLE_MAX so a title we send is never cut by the server instead. */\nexport const TITLE_MAX_CHARS = 120;\n\nconst PART_SUFFIX = /\\s·\\spart\\s(\\d+)$/;\n\n/**\n * Title for the session a handoff continues in: \"Fix the login bug · part 2\".\n * A continuation of a continuation counts up rather than stacking suffixes, so\n * the sidebar reads \"part 3\", never \"part 2 · part 2\".\n */\nexport function handoffTitle(sourceTitle: string): string {\n const collapsed = sourceTitle.replace(/\\s+/g, ' ').trim();\n const match = PART_SUFFIX.exec(collapsed);\n const base = (match ? collapsed.slice(0, match.index) : collapsed) || 'Untitled chat';\n const next = match ? Number.parseInt(match[1]!, 10) + 1 : 2;\n const suffix = ` · part ${next}`;\n const room = TITLE_MAX_CHARS - suffix.length;\n const clipped = base.length > room ? `${base.slice(0, room - 1).trimEnd()}…` : base;\n return `${clipped}${suffix}`;\n}\n\n/**\n * A seat's catalog entry for a model id. Exact id first, then canonical — a\n * session created before the alias fix stores `claude-opus-5.5` while the\n * catalog now lists `claude-opus-5-5` (context-math VERSE_MODEL_ID_ALIASES).\n */\nexport function modelOption(seat: VerseSeat | null | undefined, modelId: string): VerseModelOption | null {\n if (!seat) return null;\n const exact = seat.models.find((m) => m.id === modelId);\n if (exact) return exact;\n const canonical = canonicalModelId(modelId);\n return seat.models.find((m) => canonicalModelId(m.id) === canonical) ?? null;\n}\n\n/**\n * Why a seat+model cannot take a new session right now; null when it can.\n *\n * The seat's own reason is embedded as a clause: its closing period is\n * dropped (no \"exhausted..\") and any ISO instant in it — a health summary\n * saying when usage resets — is read as the viewer's local time.\n */\nexport function targetUnavailableReason(\n seat: VerseSeat | null | undefined,\n option: VerseModelOption | null,\n now: number = Date.now(),\n): string | null {\n if (!seat) return 'Pick a seat to continue on.';\n if (seat.health.state === 'unavailable') {\n return `${seat.label} is unavailable: ${asClause(tidyProse(seat.health.summary ?? 'no reason given', now))}.`;\n }\n if (!option) return 'Pick a model on this seat.';\n if (option.unavailableReason) {\n return `${option.label} cannot run on ${seat.label}: ${asClause(tidyProse(option.unavailableReason, now))}.`;\n }\n return null;\n}\n\nexport interface HandoffTarget {\n seatId: string;\n model: string;\n}\n\n/**\n * Where a handoff lands by default: the SAME seat and model (the common case\n * is \"same agent, fresh context\"). When that model can no longer run there,\n * the seat's first runnable model; when the seat itself is gone or\n * unavailable, the first runnable model on any available seat, in the seat\n * list's own order.\n */\nexport function defaultHandoffTarget(seats: readonly VerseSeat[], source: Pick<VerseSession, 'seatId' | 'model'>): HandoffTarget | null {\n const own = seats.find((s) => s.id === source.seatId);\n if (own && own.health.state !== 'unavailable') {\n const same = modelOption(own, source.model);\n if (same && !same.unavailableReason) return { seatId: own.id, model: same.id };\n const runnable = own.models.find((m) => !m.unavailableReason);\n if (runnable) return { seatId: own.id, model: runnable.id };\n }\n for (const seat of seats) {\n if (seat.health.state === 'unavailable') continue;\n const runnable = seat.models.find((m) => !m.unavailableReason);\n if (runnable) return { seatId: seat.id, model: runnable.id };\n }\n return null;\n}\n\n/**\n * The mode a handoff starts in. Only a mode that EXISTS for the target model\n * is ever returned (a mode with no budget would be refused by the server).\n *\n * 1. Same seat and model as the source → keep the source's mode. \"Continue in\n * a fresh chat\" means the same settings with a clean context; an operator\n * who chose expansive for this work chose it for the work.\n * 2. Otherwise the target seat's standing preference (preferences.json).\n * 3. Otherwise standard.\n */\nexport function defaultHandoffMode(input: {\n option: VerseModelOption | null;\n target: HandoffTarget | null;\n source: Pick<VerseSession, 'seatId' | 'model' | 'contextMode'>;\n preferences: VersePreferences | null | undefined;\n}): VerseContextMode {\n const { option, target, source, preferences } = input;\n const valid = (mode: VerseContextMode | undefined): mode is VerseContextMode =>\n mode !== undefined && budgetFor(option, mode) !== null;\n const sameModel = target !== null && target.seatId === source.seatId\n && canonicalModelId(target.model) === canonicalModelId(source.model);\n if (sameModel && valid(source.contextMode ?? 'standard')) return source.contextMode ?? 'standard';\n const preferred = target ? preferences?.seats[target.seatId]?.contextMode : undefined;\n if (valid(preferred)) return preferred;\n return 'standard';\n}\n\n/**\n * The mode to put on the create request, or undefined to leave it to the\n * server. A mode is sent only when the model has a budget for it — which is\n * exactly the server's acceptance rule — so what the dialog shows is what is\n * created, and an unknown-window model is never refused over a mode it could\n * not have.\n */\nexport function requestMode(option: VerseModelOption | null, mode: VerseContextMode): VerseContextMode | undefined {\n return budgetFor(option, mode) !== null ? mode : undefined;\n}\n\n/** \"1M window · compacts ≈367k\" for a model in a mode; null when the budget is unknown. */\nexport function budgetLine(option: VerseModelOption | null, mode: VerseContextMode): string | null {\n const budget = budgetFor(option, mode);\n if (!budget) return null;\n const window = `${formatContextWindow(budget.contextWindow)} window`;\n return budget.autoCompactAt === null ? window : `${window} · compacts ≈${formatTokens(budget.autoCompactAt)}`;\n}\n\nexport interface HandoffFit {\n verdict: VerseFitVerdict | null;\n /** The handoff text's own estimate (chars / 4). */\n handoffTokens: number;\n /** The target engine's estimated fixed prompt (context-math `sessionOverheadTokens`). */\n overheadTokens: number;\n /** Handoff + that fixed prompt: what the new session holds before its first reply. */\n needTokens: number;\n /** One sentence for the dialog. */\n text: string;\n tone: 'ok' | 'warn' | 'danger' | 'unknown';\n}\n\n/**\n * Will the new session START comfortably? The handoff is small by design\n * (≤ 12k chars ≈ 3k tokens), but every fresh session also carries the CLI's\n * fixed prompt — a large share of a 64k local slot — so this is a real\n * question on small windows, and the sentence shows both halves of the sum\n * rather than a bare verdict.\n *\n * The fixed prompt is the TARGET seat's engine estimate (local ≈15k measured,\n * claude ≈25k, …), not one flat figure: a flat 30k called every handoff to a\n * 64k local seat \"too big for one context\" when the real sum was ~20k. It is\n * still an estimate — no CLI reports its base prompt before the first turn —\n * so the sentence says \"estimated\" rather than presenting it as a reading.\n * `engine` null (target seat not known yet) falls back to the largest estimate.\n */\nexport function handoffFit(\n textChars: number,\n option: VerseModelOption | null,\n mode: VerseContextMode,\n engine: VerseEngine | null,\n): HandoffFit {\n const handoffTokens = estimateTokensFromChars(textChars);\n const overheadTokens = sessionOverheadTokens(engine);\n const needTokens = handoffTokens + overheadTokens;\n const verdict = fitVerdict(handoffTokens, option, overheadTokens);\n const sum = `~${formatTokens(handoffTokens)} tokens of handoff + an estimated ~${formatTokens(overheadTokens)} of fixed prompt`;\n const standard = budgetFor(option, 'standard');\n const standardCap = standard ? standard.autoCompactAt ?? standard.contextWindow : null;\n const base = { verdict, handoffTokens, overheadTokens, needTokens };\n switch (verdict) {\n case 'fits':\n return { ...base, tone: 'ok', text: `Fits: ${sum} leaves most of the budget before the first compaction.` };\n case 'tight':\n return {\n ...base,\n tone: 'warn',\n text: `Tight: ${sum} is ${percentText((needTokens / (standardCap ?? needTokens)) * 100)} of where this model compacts — the new chat will compact early.`,\n };\n case 'expansive':\n return mode === 'expansive'\n ? { ...base, tone: 'warn', text: `Fits only the expansive budget: ${sum}.` }\n : { ...base, tone: 'danger', text: `Too big for the standard budget (${sum}). Switch to Expansive, or trim the handoff.` };\n case 'split':\n return { ...base, tone: 'danger', text: `Too big for one context on this model (${sum}). Trim the handoff or pick a seat with a larger window.` };\n default:\n return { ...base, verdict: null, tone: 'unknown', text: 'This model’s window is not known, so there is no fit estimate.' };\n }\n}\n\n/** True when the target model has a real expansive budget (context-math, re-exported for the dialog). */\nexport function offersExpansive(option: VerseModelOption | null): boolean {\n return hasExpansiveMode(option);\n}\n\n/** A local turn runs on this machine; every other engine spends subscription usage. */\nexport function turnCostSentence(engine: VerseEngine, seatLabel: string): string {\n return engine === 'local'\n ? `Runs on this machine with ${seatLabel}; it spends no subscription usage.`\n : `Sends one turn to ${seatLabel} and spends from its usage. The automatic preview costs nothing.`;\n}\n\n// ---------------------------------------------------------------------------\n// Bytes\n// ---------------------------------------------------------------------------\n\nconst encoder = typeof TextEncoder === 'function' ? new TextEncoder() : null;\n\n/** UTF-8 byte length — the unit the server's caps (64 KB memory content, 64 KB turn) are written in. */\nexport function utf8Bytes(text: string): number {\n if (encoder) return encoder.encode(text).length;\n // Fallback for an environment with no TextEncoder: count code points by width.\n let bytes = 0;\n for (const ch of text) {\n const cp = ch.codePointAt(0) ?? 0;\n bytes += cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;\n }\n return bytes;\n}\n\n/**\n * The API's default request-body cap: `readBody` in src/core/web/api.ts, which\n * every /api/verse POST uses unless its route passes a larger one (only\n * POST /memory does — see MEMORY_BODY_MAX_BYTES). A write travels as JSON, so what must fit is\n * the ENCODED body — every `\\n` and `\"` escaped to two bytes — not the text\n * alone; the editors measure it so a refusal happens on screen instead of as\n * \"request body too large\".\n */\nexport const API_BODY_MAX_BYTES = 65_536;\n\n/**\n * POST /api/verse/memory's own body cap — mirrors `VERSE_MEMORY_BODY_MAX_BYTES`\n * in src/core/verse/verse-api.ts (a server module the browser cannot import):\n * room for 64 KiB of content in which EVERY byte escapes to two, plus the\n * project path and the JSON around it. The server still holds the CONTENT to\n * VERSE_MEMORY_MAX_BYTES after parsing. Guarding the memory editor with the\n * 64 KiB default instead blocked saves the server accepts — a 60–64 KB\n * MEMORY.md with ordinary line breaks could not be edited from the panel,\n * which is the exact case the server's larger cap exists for.\n */\nexport const MEMORY_BODY_MAX_BYTES = VERSE_MEMORY_BODY_MAX_BYTES;\n\n/** UTF-8 size of `body` exactly as the client will send it. */\nexport function jsonBodyBytes(body: unknown): number {\n return utf8Bytes(JSON.stringify(body) ?? '');\n}\n\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return '—';\n if (bytes < 1024) return `${bytes} B`;\n const kb = bytes / 1024;\n return `${kb < 10 ? kb.toFixed(1).replace(/\\.0$/, '') : Math.round(kb)} KB`;\n}\n\n/**\n * A relative time that reads as a phrase: \"just now\", \"5m ago\", \"on Sep 19\".\n * `formatRelative` (verse-model) is sized for a 5ch sidebar column and reads\n * as a bare token; prose needs the preposition.\n */\nexport function relativePhrase(iso: string | null | undefined, now: number = Date.now()): string | null {\n if (!iso) return null;\n const short = formatRelative(iso, now);\n if (!short) return null;\n if (short === 'now') return 'just now';\n // Only the relative tokens (\"5m\", \"3h\", \"2d\") take \"ago\". Anything else is a\n // DATE, whatever the locale prints: \"Sep 1\" (en-US) but \"1 Sept\" (en-GB)\n // and \"1. Sept.\" (de) start with a digit — testing for a leading digit\n // printed \"Last completed 1 Sept ago.\" outside the US.\n return /^\\d+[mhd]$/.test(short) ? `${short} ago` : `on ${short}`;\n}\n\n// ---------------------------------------------------------------------------\n// Memory\n// ---------------------------------------------------------------------------\n\n/**\n * Shapes that are almost certainly credentials. MEMORY.md is sent to every\n * seat's model on every turn, so a pasted key would travel to every provider\n * — the panel warns BEFORE the save rather than trusting the server's scrub\n * to catch it on the way out. Conservative on purpose: a false alarm on prose\n * would teach the operator to ignore the warning.\n */\nconst SECRET_PATTERNS: ReadonlyArray<{ label: string; re: RegExp }> = [\n { label: 'a private key', re: /-----BEGIN [A-Z ]*PRIVATE KEY-----/ },\n { label: 'an Anthropic API key', re: /\\bsk-ant-[A-Za-z0-9_-]{20,}/ },\n { label: 'an OpenAI-style API key', re: /\\bsk-(?:proj-)?[A-Za-z0-9_-]{32,}/ },\n { label: 'an xAI API key', re: /\\bxai-[A-Za-z0-9]{32,}/ },\n { label: 'a GitHub token', re: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{30,}|\\bgithub_pat_[A-Za-z0-9_]{40,}/ },\n { label: 'an AWS access key', re: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/ },\n { label: 'a Slack token', re: /\\bxox[abprs]-[A-Za-z0-9-]{10,}/ },\n { label: 'a Google API key', re: /\\bAIza[0-9A-Za-z_-]{35}\\b/ },\n { label: 'a Stripe secret key', re: /\\b(?:sk|rk)_live_[0-9A-Za-z]{20,}/ },\n];\n\n/**\n * Mirrors `VERSE_MEMORY_BLOCK_MAX_BYTES` in src/core/verse/project-memory.ts\n * (a node module the browser cannot import): the most memory text a chat's\n * instructions carry, however large MEMORY.md itself is.\n */\nexport const MEMORY_BLOCK_MAX_BYTES = VERSE_MEMORY_BLOCK_MAX_BYTES;\n\n/**\n * What memory costs, in the one wording the memory panel and the resources\n * panel share. Memory is ON by default and snapshotted into every new chat's\n * system prompt (claude `--append-system-prompt`, codex `developer_instructions`,\n * grok `--rules`), which re-rides every turn, and it asks writable seats to\n * read and update MEMORY.md — tool calls and output. On a paid seat that is\n * real (if small, mostly cached) usage, so \"nothing here spends\" would be\n * false for exactly the operator deciding whether to leave it on near a limit.\n * Reading and editing the file from the panel is still free.\n */\nexport const MEMORY_SPEND_NOTE =\n `Reading and editing memory here spends nothing. On a paid seat it is not free to use: each new chat’s system prompt carries a memory block of up to ${MEMORY_BLOCK_MAX_BYTES / 1024} KB, re-sent every turn (cached after the first), and the agent reads and updates MEMORY.md as it works. Local seats spend nothing.`;\n\n/** The first credential shape found, as a phrase (\"a GitHub token\"), or null. */\nexport function secretLike(text: string): string | null {\n for (const { label, re } of SECRET_PATTERNS) if (re.test(text)) return label;\n return null;\n}\n\n/**\n * The placeholder the server's scrubber (src/core/util/scrub.ts) writes over\n * secret-shaped text in every rule. In a memory view flagged\n * `contentSanitized`, each one stands for a REAL value still in MEMORY.md.\n */\nexport const REDACTION_MARKER = '[REDACTED]';\n\n/** How many redaction placeholders a text carries. */\nexport function redactionMarkers(text: string): number {\n return text.split(REDACTION_MARKER).length - 1;\n}\n\n// ---------------------------------------------------------------------------\n// Search\n// ---------------------------------------------------------------------------\n\n/** Below this many characters a keyword search over every message is noise, not recall. */\nexport const SEARCH_MIN_CHARS = 2;\n/** Keystrokes inside this window collapse into one request. */\nexport const SEARCH_DEBOUNCE_MS = 250;\n/** Hits asked for per search — enough to fill the sidebar twice over. */\nexport const SEARCH_LIMIT = 30;\n\n/** Whitespace-separated terms, lowercased and de-duplicated (the server ANDs them). */\nexport function searchTerms(query: string): string[] {\n const out: string[] = [];\n for (const raw of query.toLowerCase().split(/\\s+/)) {\n if (raw && !out.includes(raw)) out.push(raw);\n }\n return out;\n}\n\nexport interface HighlightSegment {\n text: string;\n match: boolean;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Split `text` into plain and matched runs for every term, case-insensitive.\n * Longest terms first so \"migrate\" wins over \"migrat\" at the same position.\n */\nexport function highlightSegments(text: string, terms: readonly string[]): HighlightSegment[] {\n const usable = [...terms].filter((t) => t.length > 0).sort((a, b) => b.length - a.length);\n if (usable.length === 0 || text.length === 0) return text ? [{ text, match: false }] : [];\n const re = new RegExp(usable.map(escapeRegExp).join('|'), 'gi');\n const out: HighlightSegment[] = [];\n let last = 0;\n for (const m of text.matchAll(re)) {\n const start = m.index ?? 0;\n if (m[0].length === 0) continue;\n if (start > last) out.push({ text: text.slice(last, start), match: false });\n out.push({ text: m[0], match: true });\n last = start + m[0].length;\n }\n if (last < text.length) out.push({ text: text.slice(last), match: false });\n return out;\n}\n\nexport interface SessionSearchGroup {\n sessionId: string;\n title: string;\n projectPath: string;\n engine: VerseEngine;\n /** The best-scoring hit in this session (the server returns hits best-first). */\n top: VerseSearchHit;\n /** Every hit this session contributed to the response. */\n count: number;\n /** Newest hit time, for the row's relative time. */\n latestAt: string;\n}\n\n/**\n * One row per session. The server ranks MESSAGES; the sidebar lists CHATS,\n * and five rows for one chat would push every other match off screen. Order\n * is the order each session first appears, i.e. by its best hit.\n */\nexport function groupSearchHits(hits: readonly VerseSearchHit[]): SessionSearchGroup[] {\n const groups = new Map<string, SessionSearchGroup>();\n for (const hit of hits) {\n const existing = groups.get(hit.sessionId);\n if (!existing) {\n groups.set(hit.sessionId, {\n sessionId: hit.sessionId,\n title: hit.title,\n projectPath: hit.projectPath,\n engine: hit.engine,\n top: hit,\n count: 1,\n latestAt: hit.at,\n });\n continue;\n }\n existing.count += 1;\n if (hit.at > existing.latestAt) existing.latestAt = hit.at;\n }\n return [...groups.values()];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{C as e,H as t,M as n,O as r,V as i,a,t as o,w as s}from"./global-CYfRwH6t.js";import{C as c,d as l,n as u,r as d}from"./VerseShared-CFE5B-IY.js";import{l as f}from"./verse-store-DAqqNIyD.js";import{t as p}from"./format-V6IiIMAL.js";var m=`verse-preferences`,h=`verse-memory:`;async function g(e){try{let t=await e.json();if(typeof t.error==`string`&&t.error)return t.error;if(typeof t.note==`string`&&t.note)return t.note}catch{}return null}async function _(e,t){let n=await fetch(e,{method:`GET`,credentials:`same-origin`,headers:{"x-ashlr-read-client":s()},signal:t});if(n.status===401)throw r(),new o(`Read session expired.`,401,e);if(!n.ok){let t=await g(n);throw new o(`GET ${e} failed (HTTP ${n.status})${t?`: ${p(t)}`:``}.`,n.status,e,t)}return await n.json()}async function v(t,r){let i=e();if(!i)throw new d;let o=await a(t,r,i);return n(),o}function y(e,t){let n=t.toString();return n?`${e}?${n}`:e}async function b(e,t){let n={mode:t},r=await v(c(e,`/context-mode`),n);return f(e,r),i(u),r}async function x(e,t={}){let n={};t.includeLastAssistant===!0&&(n.includeLastAssistant=!0);let r=typeof t.focus==`string`?t.focus.trim().slice(0,500):``;return r&&(n.focus=r),v(c(e,`/handoff-preview`),n)}async function S(e){let{source:t}=e,n={projectPath:t.projectPath,seatId:e.seatId,handoffFromSessionId:t.id},r=(t.extraRoots??[]).filter(e=>typeof e==`string`&&e.length>0&&e!==t.projectPath);r.length>0&&(n.extraRoots=r),e.model&&(n.model=e.model),e.contextMode&&(n.contextMode=e.contextMode);let i=e.title?.trim();i&&(n.title=i);let a=await v(`/api/verse/sessions`,n);return l(),a}function C(e){return _(`/api/verse/preferences`,e)}var w={key:m,fetch:e=>C(e)};async function T(e){let n=await v(`/api/verse/preferences`,e);return i(m),t(h),n}function E(e){let t=new URLSearchParams,n=e.workspaceId?.trim()??``,r=e.projectPath?.trim()??``,i=(e.extraRoots??[]).map(e=>e.trim()).filter(e=>e.length>0);if(n){if(r||i.length>0)throw Error(`Estimate a workspace or a folder set, not both.`);t.set(`workspaceId`,n)}else if(r){t.set(`projectPath`,r);for(let e of i)t.append(`extraRoots`,e)}else throw Error(`Pick a project or a workspace to estimate.`);return y(`/api/verse/context-fit`,t)}function D(e,t){return _(E(e),t)}function O(e,t,n){let r=new URLSearchParams({q:e});return typeof t==`number`&&Number.isFinite(t)&&r.set(`limit`,String(Math.max(1,Math.min(50,Math.floor(t))))),_(y(`/api/verse/search`,r),n)}function k(e){return`${h}${e}`}function A(e,t){return _(y(`/api/verse/memory`,new URLSearchParams({projectPath:e})),t)}function j(e){return{key:k(e),fetch:t=>A(e,t)}}async function M(e,t){let n=await v(`/api/verse/memory`,{projectPath:e,content:t});return i(k(e)),n}export{A as a,T as c,M as d,C as i,w as l,D as n,O as o,x as r,b as s,S as t,j as u};
|
|
2
|
+
//# sourceMappingURL=context-queries-D0Aydl5L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-queries-D0Aydl5L.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/context/context-queries.ts"],"sourcesContent":["/**\n * routes/verse/context/context-queries.ts — every V3.9 context-orchestration\n * call the Verse console makes (docs/VERSE-CONTEXT.md): context mode, handoff\n * preview + handoff creation, preferences, context fit, session search and\n * shared project memory.\n *\n * Same conventions as ../verse-queries.ts, deliberately:\n *\n * - WRITES pull the held mutation token from auth-store, throw\n * `VerseMutationLockedError` (the SAME class, so ChatSection's `fail`\n * recognises it) when none is held, touch the hold on success, and\n * invalidate exactly the cache keys they obviously change.\n * - READS carry the per-tab read-client proof and report an expired read\n * session, exactly like `apiGet`. They are written out here rather than\n * routed through `apiGet` for one reason: `apiGet` discards the response\n * body on a non-2xx, and the routes below answer a refused read (\"path is\n * not a directory\", \"q must be at least 2 characters\") with a sentence\n * written for a person. Those sentences travel as `ApiError.detail`, the\n * field `describeControlError` already prefers.\n *\n * NOTHING HERE SPENDS. Every route below is deterministic server work\n * (preferences file, git ls-files, events.jsonl scans, a memory file). The\n * one model call a context feature can cause — \"ask this seat to summarize\"\n * — goes through the ordinary `sendVerseTurn`, i.e. through the engine's\n * `startTurn` chokepoint and the local-only policy, never through this file.\n *\n * `handoff-preview` is a POST although it only reads: it spawns\n * `git diff --stat` per root, and the API keeps every spawning route behind\n * the dispatch flag and the mutation token. It therefore needs the token like\n * any write, and the dialog says so.\n */\nimport type { VerseCreateSessionRequest, VerseSession } from '../../../data/api-types.js';\nimport type {\n VerseContextFit,\n VerseContextMode,\n VerseContextModeRequest,\n VerseHandoffPreview,\n VerseHandoffPreviewRequest,\n VersePreferences,\n VersePreferencesUpdate,\n VerseProjectMemory,\n VerseProjectMemoryWrite,\n VerseSearchResponse,\n} from '../../../../core/verse/types.js';\nimport { getMutationToken, reportSessionExpired, getReadClientProof, touchMutationHold } from '../../../data/auth-store.js';\nimport { invalidate, invalidatePrefix } from '../../../data/cache.js';\nimport { ApiError, apiPost } from '../../../data/client.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { invalidateVerseLists, verseSessionPath, VERSE_SESSIONS_KEY, VerseMutationLockedError } from '../verse-queries.js';\nimport { setVerseSession } from '../verse-store.js';\nimport { asClause } from '../autonomy/format.js';\n\nexport const VERSE_PREFERENCES_KEY = 'verse-preferences';\n/** Prefix of every per-project memory key; `invalidatePrefix` reaches all of them. */\nexport const VERSE_MEMORY_KEY_PREFIX = 'verse-memory:';\n/** Prefix of every context-fit key (one per root set). */\nexport const VERSE_CONTEXT_FIT_KEY_PREFIX = 'verse-context-fit:';\n\n// ---------------------------------------------------------------------------\n// Transport\n// ---------------------------------------------------------------------------\n\n/** The server's own refusal sentence, when the body carried one. */\nasync function refusalDetail(res: Response): Promise<string | null> {\n try {\n const body = (await res.json()) as { error?: unknown; note?: unknown };\n if (typeof body.error === 'string' && body.error) return body.error;\n if (typeof body.note === 'string' && body.note) return body.note;\n } catch {\n /* not JSON — the status alone has to do */\n }\n return null;\n}\n\n/**\n * GET with the read-client proof. Behaves like `apiGet` (401 reports the\n * expired read session) but keeps the server's refusal sentence.\n */\nasync function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(path, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { 'x-ashlr-read-client': getReadClientProof() },\n signal,\n });\n if (res.status === 401) {\n reportSessionExpired();\n throw new ApiError('Read session expired.', 401, path);\n }\n if (!res.ok) {\n const detail = await refusalDetail(res);\n // asClause: a detail ending in its own period would otherwise read \"…..\".\n throw new ApiError(`GET ${path} failed (HTTP ${res.status})${detail ? `: ${asClause(detail)}` : ''}.`, res.status, path, detail);\n }\n return (await res.json()) as T;\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseMutationLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\nfunction withQuery(path: string, params: URLSearchParams): string {\n const query = params.toString();\n return query ? `${path}?${query}` : path;\n}\n\n// ---------------------------------------------------------------------------\n// Context mode\n// ---------------------------------------------------------------------------\n\n/**\n * Switch a session between `standard` and `expansive`. Applies from the next\n * turn (it only changes CLI flags, never prompt content, so the provider's\n * prompt cache survives the switch).\n *\n * The returned record is also written into verse-store, so the meter, the\n * mode chip and the composer hint all move on this response rather than on\n * the next list refresh — whichever component made the call.\n */\nexport async function setSessionContextMode(sessionId: string, mode: VerseContextMode): Promise<VerseSession> {\n const body: VerseContextModeRequest = { mode };\n const session = await post<VerseSession>(verseSessionPath(sessionId, '/context-mode'), body);\n setVerseSession(sessionId, session);\n invalidate(VERSE_SESSIONS_KEY);\n return session;\n}\n\n// ---------------------------------------------------------------------------\n// Handoff\n// ---------------------------------------------------------------------------\n\n/** Longest focus line the API accepts (types.ts VerseHandoffPreviewRequest). */\nexport const HANDOFF_FOCUS_MAX_CHARS = 500;\n\n/**\n * Build the deterministic handoff note for a session. Zero spend: the server\n * reads events.jsonl and a bounded `git diff --stat` per root.\n *\n * Only keys that carry a value are sent — the route rejects unknown keys, and\n * `includeLastAssistant: false` is the default anyway, so omitting it keeps\n * the body minimal and the server's validation the single authority.\n */\nexport async function fetchHandoffPreview(sessionId: string, req: VerseHandoffPreviewRequest = {}): Promise<VerseHandoffPreview> {\n const body: VerseHandoffPreviewRequest = {};\n if (req.includeLastAssistant === true) body.includeLastAssistant = true;\n const focus = typeof req.focus === 'string' ? req.focus.trim().slice(0, HANDOFF_FOCUS_MAX_CHARS) : '';\n if (focus) body.focus = focus;\n return post<VerseHandoffPreview>(verseSessionPath(sessionId, '/handoff-preview'), body);\n}\n\nexport interface HandoffSessionInput {\n /** The session being handed off. Its PINNED roots are reused, see below. */\n source: VerseSession;\n seatId: string;\n model?: string;\n contextMode?: VerseContextMode;\n /** Optional title; absent → the server titles it from the first message. */\n title?: string;\n}\n\n/**\n * Create the session a handoff continues in. FREE: creating a session spawns\n * nothing. The handoff text is NOT sent here — the caller pre-fills the new\n * chat's composer and the operator presses send, so the first (spent) turn is\n * always one the operator read.\n *\n * Roots: the source's PINNED roots (`projectPath` + `extraRoots`), never its\n * `workspaceId`. A session keeps the roots it was created with even if the\n * named workspace was later edited or deleted (types.ts VerseSession\n * `extraRoots`); re-resolving the workspace here would let the continuation\n * silently gain or lose a folder the conversation was about — or fail\n * outright on a deleted workspace. The API also refuses the two spellings\n * mixed, so it is one or the other, and the pinned set is the honest one.\n *\n * The server resolves `handoffFrom.title` from `handoffFromSessionId` itself;\n * nothing about provenance is taken from this body.\n */\nexport async function createHandoffSession(input: HandoffSessionInput): Promise<VerseSession> {\n const { source } = input;\n const req: VerseCreateSessionRequest = {\n projectPath: source.projectPath,\n seatId: input.seatId,\n handoffFromSessionId: source.id,\n };\n const extras = (source.extraRoots ?? []).filter((root) => typeof root === 'string' && root.length > 0 && root !== source.projectPath);\n if (extras.length > 0) req.extraRoots = extras;\n if (input.model) req.model = input.model;\n if (input.contextMode) req.contextMode = input.contextMode;\n const title = input.title?.trim();\n if (title) req.title = title;\n const session = await post<VerseSession>('/api/verse/sessions', req);\n invalidateVerseLists();\n return session;\n}\n\n// ---------------------------------------------------------------------------\n// Preferences\n// ---------------------------------------------------------------------------\n\nexport function fetchPreferences(signal?: AbortSignal): Promise<VersePreferences> {\n return getJson<VersePreferences>('/api/verse/preferences', signal);\n}\n\nexport const versePreferencesQuery: QueryDef<VersePreferences> = {\n key: VERSE_PREFERENCES_KEY,\n fetch: (signal) => fetchPreferences(signal),\n};\n\n/**\n * Change ONE standing preference (the three request forms are exclusive, so a\n * body never changes more than the operator clicked). Memory records carry an\n * `enabled` flag derived from these preferences, so every cached memory read\n * is refreshed too.\n */\nexport async function updatePreferences(update: VersePreferencesUpdate): Promise<VersePreferences> {\n const prefs = await post<VersePreferences>('/api/verse/preferences', update);\n invalidate(VERSE_PREFERENCES_KEY);\n invalidatePrefix(VERSE_MEMORY_KEY_PREFIX);\n return prefs;\n}\n\n// ---------------------------------------------------------------------------\n// Context fit\n// ---------------------------------------------------------------------------\n\nexport interface ContextFitQuery {\n workspaceId?: string;\n projectPath?: string;\n extraRoots?: string[];\n}\n\n/**\n * The query string for a fit request: a workspace id ALONE, or a project path\n * with each extra root as its own repeated `extraRoots` parameter (a path may\n * contain a comma, so a joined list could not be split back honestly). The\n * API refuses the two spellings mixed — refused here first, with the reason.\n */\nexport function contextFitPath(q: ContextFitQuery): string {\n const params = new URLSearchParams();\n const workspaceId = q.workspaceId?.trim() ?? '';\n const projectPath = q.projectPath?.trim() ?? '';\n const extras = (q.extraRoots ?? []).map((r) => r.trim()).filter((r) => r.length > 0);\n if (workspaceId) {\n if (projectPath || extras.length > 0) throw new Error('Estimate a workspace or a folder set, not both.');\n params.set('workspaceId', workspaceId);\n } else if (projectPath) {\n params.set('projectPath', projectPath);\n for (const root of extras) params.append('extraRoots', root);\n } else {\n throw new Error('Pick a project or a workspace to estimate.');\n }\n return withQuery('/api/verse/context-fit', params);\n}\n\n/** How big the reachable code is, in estimated tokens. Zero spend (git ls-files + stat). */\nexport function fetchContextFit(q: ContextFitQuery, signal?: AbortSignal): Promise<VerseContextFit> {\n return getJson<VerseContextFit>(contextFitPath(q), signal);\n}\n\n/** Cache-backed form, keyed by the exact root set, for pickers that re-render often. */\nexport function verseContextFitQuery(q: ContextFitQuery): QueryDef<VerseContextFit> {\n const path = contextFitPath(q);\n return { key: `${VERSE_CONTEXT_FIT_KEY_PREFIX}${path}`, fetch: (signal) => getJson<VerseContextFit>(path, signal) };\n}\n\n// ---------------------------------------------------------------------------\n// Session search\n// ---------------------------------------------------------------------------\n\n/** The API caps `limit` at 50 (session-search.ts); asking for more is refused, so clamp. */\nexport const SEARCH_LIMIT_MAX = 50;\n\n/** Keyword search over past sessions' messages. Zero spend — a bounded scan of events.jsonl. */\nexport function searchSessions(q: string, limit?: number, signal?: AbortSignal): Promise<VerseSearchResponse> {\n const params = new URLSearchParams({ q });\n if (typeof limit === 'number' && Number.isFinite(limit)) {\n params.set('limit', String(Math.max(1, Math.min(SEARCH_LIMIT_MAX, Math.floor(limit)))));\n }\n return getJson<VerseSearchResponse>(withQuery('/api/verse/search', params), signal);\n}\n\n// ---------------------------------------------------------------------------\n// Shared project memory\n// ---------------------------------------------------------------------------\n\n/**\n * The memory record as the browser receives it. The server's public-JSON\n * sanitizer rewrites the home folder as `~` and secret-shaped text as\n * `[REDACTED]` on the way out, so `content` can differ from the file on disk;\n * the route then adds `contentSanitized: true` (absent otherwise). Declared\n * here, not in types.ts: that contract is frozen and the flag is additive.\n */\nexport type VerseProjectMemoryView = VerseProjectMemory & { contentSanitized?: boolean };\n\nexport function verseProjectMemoryKey(projectPath: string): string {\n return `${VERSE_MEMORY_KEY_PREFIX}${projectPath}`;\n}\n\nexport function fetchProjectMemory(projectPath: string, signal?: AbortSignal): Promise<VerseProjectMemoryView> {\n return getJson<VerseProjectMemoryView>(withQuery('/api/verse/memory', new URLSearchParams({ projectPath })), signal);\n}\n\nexport function verseProjectMemoryQuery(projectPath: string): QueryDef<VerseProjectMemoryView> {\n return { key: verseProjectMemoryKey(projectPath), fetch: (signal) => fetchProjectMemory(projectPath, signal) };\n}\n\n/**\n * Replace MEMORY.md for a project (atomic, 0600 on the server, capped at\n * VERSE_MEMORY_MAX_BYTES). `''` clears it. Chats already open keep the block\n * pinned in their instructions at creation; they see the change when they\n * next read the file.\n */\nexport async function writeProjectMemory(projectPath: string, content: string): Promise<VerseProjectMemoryView> {\n const body: VerseProjectMemoryWrite = { projectPath, content };\n const memory = await post<VerseProjectMemoryView>('/api/verse/memory', body);\n invalidate(verseProjectMemoryKey(projectPath));\n return memory;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-hePW80VL.js";import{C as t,M as n,V as r,a as i,i as a}from"./global-CYfRwH6t.js";import{i as o,n as s}from"./mutations-B9AZoqNR.js";var c={dailyBudgetUsd:{min:0,max:1e3},perTickItems:{min:1,max:50},parallel:{min:1,max:16},intervalMs:{min:3e4,max:864e5},maxConcurrent:{min:1,max:32},concurrency:{min:1,max:32},subscriptionMaxPercent:{min:1,max:100},foundryLimitMax:{min:0,max:1e6}},l=e({VERSE_AUDIT_DEFAULT_LIMIT:()=>200,VERSE_AUDIT_MAX:()=>h,VERSE_AUDIT_PREFIX:()=>m,VERSE_CAPS_KEY:()=>d,VERSE_CONTROL_KEY:()=>u,VERSE_SAFETY_KEY:()=>p,VERSE_SCOPE_KEY:()=>f,VerseControlLockedError:()=>T,engageEmergencyStop:()=>j,invalidateControl:()=>D,normalizeBacklog:()=>C,releaseEmergencyStop:()=>M,runDaemonAction:()=>A,updateVerseCaps:()=>O,updateVerseScope:()=>k,verseAuditQuery:()=>x,verseBacklogQuery:()=>w,verseCapsQuery:()=>_,verseControlQuery:()=>g,verseGoalsQuery:()=>S,verseSafetyQuery:()=>v,verseScopeQuery:()=>b}),u=`verse-control`,d=`verse-caps`,f=`verse-scope`,p=`verse-safety`,m=`verse-audit:`,h=500,g={key:u,fetch:e=>a(`/api/verse/control`,e)},_={key:d,fetch:e=>a(`/api/verse/caps`,e)},v={key:p,fetch:e=>a(`/api/verse/safety`,e)};function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var b={key:f,fetch:e=>a(`/api/verse/scope`,e)};function x(e={}){let t=Math.min(e.limit??200,h),n=new URLSearchParams;return n.set(`limit`,String(t)),e.action&&n.set(`action`,e.action),e.result&&n.set(`result`,e.result),{key:`${m}${t}:${e.action??``}:${e.result??``}`,fetch:e=>a(`/api/verse/audit?${n.toString()}`,e)}}var S={key:`goals`,fetch:e=>a(`/api/goals`,e)};function C(e){return e==null?{items:[],absent:!0}:Array.isArray(e)?{items:e,absent:!1}:y(e)&&Array.isArray(e.items)?{items:e.items,absent:!1}:{items:[],absent:!0}}var w={key:`backlog`,fetch:e=>a(`/api/backlog`,e).then(C)},T=class extends Error{constructor(){super(`Unlock actions with the mutation token before changing the loop.`),this.name=`VerseControlLockedError`}};async function E(e,r){let a=t();if(!a)throw new T;let o=await i(e,r,a);return n(),o}function D(){r(u)}async function O(e){let t=await E(`/api/verse/caps`,e);return r(d),D(),t}async function k(e){await E(`/api/verse/scope`,e),r(f),D()}async function A(e){let t=await E(`/api/verse/daemon`,{action:e});return D(),r(`daemon`),t}async function j(){await s(),D()}async function M(){await o(),D()}export{M as a,k as c,_ as d,g as f,c as g,b as h,j as i,x as l,v as m,T as n,A as o,S as p,l as r,O as s,u as t,w as u};
|
|
2
|
+
//# sourceMappingURL=control-queries-C5uQTzJi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-queries-C5uQTzJi.js","names":[],"sources":["../../../../../../src/core/verse/control-types.ts","../../../../../../src/web-ui/routes/verse/autonomy/control-queries.ts"],"sourcesContent":["/**\n * Ashlr Verse — autonomy control-plane contract (V2).\n *\n * V1 (`./types.ts`) is frozen: it describes interactive chat sessions. This\n * module adds the shapes the Autonomy cockpit needs to run the hub's existing\n * autonomous fleet without a terminal — the CONFIGURED caps, the enrollment\n * scope, the audit trail, the kill switch, and the daemon lifecycle.\n *\n * Two hard rules are encoded here rather than left to the UI:\n *\n * 1. The global kill switch (`~/.ashlr/KILL`) is an EMERGENCY STOP, not a\n * pause. It also refuses the agent's own `mcp-native` write tools. Every\n * shape that carries it is named `killSwitch`, and the action that engages\n * it is named `emergencyStop`. It is never called \"pause\".\n *\n * V2.1 adds the control that name was being withheld from: the\n * DAEMON-SCOPED pause (`~/.ashlr/daemon.paused`, see core/daemon/pause.ts).\n * It halts autonomous dispatch and NOTHING else — `assertMayMutate`,\n * `mcp-native`, and `mcp-native-engineer` do not read it. It travels as\n * `pause: VerseDaemonPause`, always a FIELD OF ITS OWN, never merged into\n * `killSwitch`, because the whole point is that the two have different\n * blast radii and the operator must be able to see which one is on.\n * 2. Nothing in this module is a secret. Launcher commands, tokens, and env\n * values never appear in any of these shapes — the daemon lifecycle result\n * carries a pid, never an argv.\n *\n * Everything is a projection of state the hub already computes; nothing here\n * introduces a new source of truth.\n */\n\nimport type { AuditEntry } from '../types.js';\nimport type { PublicDaemonObservation } from '../daemon/public-observation.js';\nimport type { FrontierEngineUsage } from '../usage/frontier-usage.js';\nimport type { SafetyReport } from '../../cli/verify-safety.js';\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/**\n * Error codes for `/api/verse/{control,caps,scope,audit,daemon,safety}`.\n * `VERSE_INVALID` / `VERSE_TOO_LARGE` are deliberately the SAME codes V1 uses,\n * so one client error mapper covers both halves of the Verse API.\n */\nexport type VerseControlErrorCode =\n | 'VERSE_INVALID'\n | 'VERSE_REFUSED'\n | 'VERSE_TOO_LARGE'\n | 'VERSE_UNAVAILABLE';\n\n/** Every error body on these routes. */\nexport interface VerseControlError {\n error: string;\n code: VerseControlErrorCode;\n}\n\n// ---------------------------------------------------------------------------\n// Caps — the CONFIGURED limits (GET/POST /api/verse/caps)\n// ---------------------------------------------------------------------------\n\n/** One `cfg.foundry.limits[engine]` entry, flattened for transport. */\nexport interface VerseFoundryLimit {\n /** EngineId key, e.g. 'claude' | 'codex'. */\n engine: string;\n /** Rolling window label, e.g. '1m' | '5m' | '1h' | '1d'. */\n window: string;\n /** Max dispatches per window. 0 means \"no dispatches allowed\". */\n max: number;\n}\n\n/** `cfg.daemon.concurrency` — null per tier means \"not configured, using the default\". */\nexport interface VerseCapsConcurrency {\n local: number | null;\n cloud: number | null;\n total: number | null;\n}\n\n/**\n * The configured autonomy limits. These are the values the daemon actually\n * reads — no route exposed them before V2, which is why the cockpit could not\n * show a cap next to the usage burning against it.\n */\nexport interface VerseCaps {\n /** HARD daily spend ceiling (USD). 0 means the daemon is stopped by budget. */\n dailyBudgetUsd: number;\n /** Backlog items processed per tick. */\n perTickItems: number;\n /** Concurrent sandboxed swarms per tick (batch mode). */\n parallel: number;\n /** Tick interval in loop mode (ms). */\n intervalMs: number;\n /** Daemon execution mode. */\n mode: 'batch' | 'continuous';\n /** Ceiling on in-flight dispatches in continuous mode; null when unset. */\n maxConcurrent: number | null;\n /** Per-tier concurrency budgets; null per tier when unset. */\n concurrency: VerseCapsConcurrency;\n /** Subscription-window throttle percentage (1–100). */\n subscriptionMaxPercent: number;\n /** Per-engine dispatch limits, sorted by engine id. */\n foundryLimits: VerseFoundryLimit[];\n /**\n * HONEST STATE: the cap keys whose value is a built-in default rather than\n * something configured on disk. The UI renders these as \"default\", never as\n * a deliberate choice the operator made. Sorted, stable.\n */\n defaulted: VerseCapKey[];\n}\n\n/** The scalar cap keys a client may update. `foundryLimits` is handled separately. */\nexport type VerseCapKey =\n | 'dailyBudgetUsd'\n | 'perTickItems'\n | 'parallel'\n | 'intervalMs'\n | 'mode'\n | 'maxConcurrent'\n | 'concurrency'\n | 'subscriptionMaxPercent'\n | 'foundryLimits';\n\n/** POST /api/verse/caps — a partial update. Unknown keys are rejected. */\nexport interface VerseCapsUpdate {\n dailyBudgetUsd?: number;\n perTickItems?: number;\n parallel?: number;\n intervalMs?: number;\n mode?: 'batch' | 'continuous';\n maxConcurrent?: number;\n concurrency?: { local?: number; cloud?: number; total?: number };\n subscriptionMaxPercent?: number;\n /** Replaces the named engines' limits; engines not listed are left alone. */\n foundryLimits?: VerseFoundryLimit[];\n}\n\n/**\n * POST /api/verse/caps result. `live: true` is not decoration — the daemon\n * re-reads config at the top of every tick, so a saved cap binds on the next\n * tick without a restart.\n */\nexport interface VerseCapsUpdateResult {\n ok: true;\n /** The cap keys this request actually changed, in request order. */\n applied: VerseCapKey[];\n live: true;\n /** The full caps AFTER the write, re-read from disk. */\n caps: VerseCaps;\n}\n\n// ---------------------------------------------------------------------------\n// Scope — the enrollment registry (GET/POST /api/verse/scope)\n// ---------------------------------------------------------------------------\n\nexport interface VerseScopeRepo {\n path: string;\n name: string;\n /** False when the registry still lists a directory that is gone. */\n exists: boolean;\n}\n\n/**\n * GET /api/verse/scope. An EMPTY `repos` with no `degradedReason` is the\n * valid default state and means the daemon will do nothing at all — the UI\n * must say that plainly rather than rendering an innocuous empty list.\n */\nexport interface VerseScope {\n repos: VerseScopeRepo[];\n /** Present only when enrollment authority could not be read at all. */\n degradedReason?: string;\n}\n\nexport type VerseScopeAction = 'enroll' | 'unenroll';\n\n/** POST /api/verse/scope body. */\nexport interface VerseScopeRequest {\n action: VerseScopeAction;\n path: string;\n}\n\nexport interface VerseScopeResult {\n ok: boolean;\n action: VerseScopeAction;\n /** The canonical (realpath'd) registry path this acted on. */\n path: string;\n /** False when the registry already had the requested state (idempotent). */\n changed: boolean;\n /** Policy reason string, e.g. 'enrolled' | 'already-unenrolled'. */\n reason: string;\n /** The scope AFTER the mutation. */\n scope: VerseScope;\n}\n\n// ---------------------------------------------------------------------------\n// Audit (GET /api/verse/audit)\n// ---------------------------------------------------------------------------\n\nexport type VerseAuditResult = AuditEntry['result'];\n\n/** GET /api/verse/audit?limit=&action=&result= */\nexport interface VerseAuditResponse {\n /** Newest first, already filtered, at most `limit` entries. */\n entries: AuditEntry[];\n /** The effective cap applied to `entries` (never above 500). */\n limit: number;\n /** Echo of the applied filter so the UI cannot drift from what it shows. */\n filter: { action: string | null; result: VerseAuditResult | null };\n /** How many raw entries were scanned before filtering. */\n scanned: number;\n /**\n * True when the scan filled its own ceiling, so older entries MAY exist\n * beyond what was read. Conservative by design: it never claims the reader\n * reached the end of history when it cannot prove that.\n */\n truncated: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Kill switch\n// ---------------------------------------------------------------------------\n\n/**\n * The GLOBAL kill switch (`~/.ashlr/KILL`). `state: 'unknown'` is a real,\n * distinct outcome — the sentinel was uninspectable — and must never be\n * rendered as \"off\".\n */\nexport interface VerseKillSwitch {\n state: 'active' | 'inactive' | 'unknown';\n sourceState: 'healthy' | 'degraded';\n reason: string;\n /**\n * Plain-language statement of blast radius, shipped with the state so no\n * surface can show the switch without the warning.\n */\n note: string;\n}\n\n// ---------------------------------------------------------------------------\n// Daemon pause — the NARROW stop (POST /api/verse/daemon {action:'pause'})\n// ---------------------------------------------------------------------------\n\n/**\n * The DAEMON-SCOPED pause sentinel (`~/.ashlr/daemon.paused`), projected for\n * transport. Shares `VerseKillSwitch`'s shape on purpose — both are sentinels\n * read the same way, and both keep `'unknown'` as a real third state that must\n * never render as \"off\".\n *\n * `state: 'unknown'` is treated by the daemon as PAUSED (fail safe), so the UI\n * must say \"paused — the sentinel could not be read\", not \"running\".\n *\n * The sentinel PATH is deliberately absent: it is machine-local detail the\n * cockpit has no use for, the same omission `VerseKillSwitch` makes.\n */\nexport interface VerseDaemonPause {\n /** 'paused' = dispatch halted. 'running' = proven not paused. */\n state: 'paused' | 'running' | 'unknown';\n sourceState: 'healthy' | 'degraded';\n reason: string;\n /** ISO time the pause was requested; null when not paused or unknown. */\n pausedAt: string | null;\n /** Which surface paused it ('cli' | 'verse-control-plane' | 'unknown'). */\n by: string | null;\n /** Plain-language statement of the NARROW blast radius, shipped with the state. */\n note: string;\n}\n\n// ---------------------------------------------------------------------------\n// Daemon lifecycle (POST /api/verse/daemon)\n// ---------------------------------------------------------------------------\n\n/**\n * 'start' launches the autonomous loop detached (exactly `ashlr daemon start`).\n * 'once' runs a single tick the same way.\n *\n * Three stops, three honestly different scopes:\n * - 'pause' — halts autonomous DISPATCH only. Reversible with 'resume'.\n * Leaves the agent's own write tools alone. The default choice.\n * - 'stop' — the ordinary stop, which today engages the GLOBAL kill switch\n * (`stopDaemon()` is `setKill(true)`), so it is wider than a\n * pause and the result's `note` says so.\n * - emergency stop — not on this route at all (`POST /api/fleet/pause`).\n */\nexport type VerseDaemonAction = 'start' | 'stop' | 'once' | 'pause' | 'resume';\n\n/** Non-secret projection of `~/.ashlr/daemon.json`. */\nexport interface VerseDaemonStateProjection {\n running: boolean;\n pid: number | null;\n startedAt: string | null;\n lastTickAt: string | null;\n todayDate: string | null;\n todaySpentUsd: number;\n itemsProcessed: number;\n}\n\n/**\n * POST /api/verse/daemon result. `pid` is the only thing that ever escapes the\n * spawn — the argv, the env, and the resolved launcher path never do.\n */\nexport interface VerseDaemonActionResult {\n ok: boolean;\n action: VerseDaemonAction;\n /** True when a detached child was launched by this request. */\n spawned: boolean;\n /** The detached child's pid for 'start'/'once'; null otherwise. */\n pid: number | null;\n state: VerseDaemonStateProjection;\n killSwitch: VerseKillSwitch;\n /** The daemon-scoped pause AFTER this action. Never folded into killSwitch. */\n pause: VerseDaemonPause;\n /** One line of plain language about what just happened, for the UI to echo. */\n note: string;\n}\n\n// ---------------------------------------------------------------------------\n// Fleet essentials + control aggregate (GET /api/verse/control)\n// ---------------------------------------------------------------------------\n\n/**\n * The small honest slice of FleetStatus/ControlSnapshot the cockpit needs.\n * Deliberately excludes service file paths and error-log paths: the cockpit\n * does not need them, and keeping them out keeps this payload trivially\n * provable as free of machine-local command detail.\n */\nexport interface VerseFleetEssentials {\n /** Mode the autonomy control loop last directed, when known. */\n directionMode: string | null;\n directionAt: string | null;\n directionReason: string | null;\n autonomyControlLoop: boolean;\n autonomyControlMode: string;\n service: {\n registrationState: 'present' | 'absent' | 'unknown';\n installed: boolean;\n running: boolean;\n runtimeState: string | null;\n };\n /** Freshness of the shared fleet-status cache backing these values. */\n freshness: { stale: boolean; ageMs: number };\n}\n\n/** Today's spend against the configured ceiling. */\nexport interface VerseSpend {\n /** null when the daemon ledger could not be read (NOT zero). */\n todayUsd: number | null;\n /** Calendar day the counter applies to; null before the first tick. */\n todayDate: string | null;\n dailyBudgetUsd: number;\n}\n\n/**\n * GET /api/verse/control — the ONE aggregate the Autonomy view reads.\n * Every field is a projection of an existing snapshot; nothing is recomputed.\n */\nexport interface VerseControlSnapshot {\n generatedAt: string;\n daemon: PublicDaemonObservation;\n fleet: VerseFleetEssentials;\n caps: VerseCaps;\n scope: VerseScope;\n killSwitch: VerseKillSwitch;\n /**\n * The DAEMON-SCOPED pause, as its own field. A cockpit that folded this into\n * `killSwitch` would be back to one control with two names; keeping them\n * separate is what lets the Autonomy view render \"paused\" and \"kill switch\n * engaged\" as the different situations they are.\n */\n pause: VerseDaemonPause;\n /** Pending inbox proposals awaiting a human decision. */\n pendingApprovals: number;\n spend: VerseSpend;\n /** Per-engine quota usage against the configured foundry limits. */\n quota: FrontierEngineUsage[];\n /** False when this server was started without --allow-dispatch: all POSTs 404. */\n dispatchEnabled: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Safety (GET /api/verse/safety)\n// ---------------------------------------------------------------------------\n\n/** GET /api/verse/safety — the `ashlr verify-safety --json` report, unmodified. */\nexport type VerseSafetyReport = SafetyReport;\n\n// ---------------------------------------------------------------------------\n// Bounds (single source of truth — the API validator and the UI share these)\n// ---------------------------------------------------------------------------\n\nexport const VERSE_CAPS_BOUNDS = {\n dailyBudgetUsd: { min: 0, max: 1_000 },\n perTickItems: { min: 1, max: 50 },\n parallel: { min: 1, max: 16 },\n intervalMs: { min: 30_000, max: 86_400_000 },\n maxConcurrent: { min: 1, max: 32 },\n /**\n * DELIBERATE DEVIATION from VERSE-CONTRACT-V2's \"concurrency 0-32 each\".\n *\n * The daemon cannot honour a zero tier. `resolveCfg` (daemon/loop.ts) only\n * adopts a tier when it is `> 0`, and `TieredPool`'s constructor floors\n * every cap at `Math.max(1, …)` on top of that — so a stored 0 came back as\n * the built-in 2/6/8 while the cockpit displayed 0. Teaching the pool to\n * accept 0 is not a fix either: `tieredBounded` would then never start a\n * task on that tier and never resolve, i.e. a hung tick.\n *\n * A floor of 1 is therefore the only value that is true in both places. To\n * stop dispatch entirely, the honest lever is `dailyBudgetUsd: 0`, which the\n * daemon now really does obey.\n */\n concurrency: { min: 1, max: 32 },\n subscriptionMaxPercent: { min: 1, max: 100 },\n foundryLimitMax: { min: 0, max: 1_000_000 },\n} as const;\n\n/** Hard ceiling on GET /api/verse/audit `limit`. */\nexport const VERSE_AUDIT_MAX_LIMIT = 500;\n/** Default `limit` when the query omits one. */\nexport const VERSE_AUDIT_DEFAULT_LIMIT = 100;\n/**\n * Hard ceiling on how many raw audit entries a single request will read before\n * filtering. Bounds the work a filtered query can ask of the disk.\n */\nexport const VERSE_AUDIT_MAX_SCAN = 5_000;\n\n/** The kill switch's blast-radius warning — one string, used everywhere. */\nexport const VERSE_KILL_SWITCH_NOTE =\n 'Emergency stop: the global kill switch also refuses the agent\\'s own write tools, not just the daemon. Use the daemon pause action for an ordinary, reversible halt.';\n\n/**\n * The pause's blast-radius statement — the counterpart to\n * VERSE_KILL_SWITCH_NOTE, shipped with every pause projection so no surface\n * can show the state without the scope. Says what it does NOT do, because\n * that is the entire difference from the control next to it.\n */\nexport const VERSE_DAEMON_PAUSE_NOTE =\n 'Pause: halts autonomous dispatch only. Your own write tools keep working, nothing in flight is rolled back, and Resume restores the loop without a restart.';\n","/**\n * routes/verse/autonomy/control-queries.ts — every `/api/verse/{control,caps,\n * scope,audit,daemon,safety}` call the Autonomy cockpit makes, plus the two\n * existing read-only feeds it borrows (`/api/goals`, `/api/backlog`).\n *\n * Same contract as routes/verse/verse-queries.ts: reads are QueryDefs consumed\n * through useQuery (cache-backed, so a background refresh never blanks a\n * populated panel); writes pull the held mutation token from auth-store, touch\n * the hold on success, and invalidate exactly the keys they affect.\n *\n * Two deliberate choices worth knowing before editing:\n *\n * 1. **The envelopes are now fixed, so nothing is normalized.**\n * `/api/verse/scope` and `/api/verse/audit` are declared in\n * `src/core/verse/control-types.ts` (`VerseScope`, `VerseAuditResponse`)\n * and the handlers serialize exactly those, so these fetchers are typed\n * straight through. The speculative bare-array/wrapper normalization that\n * let this surface ship before the routes existed has been deleted.\n * `/api/backlog` keeps its normalizer — that route really does answer\n * `loadBacklog() ?? null` and is not part of the V2 contract.\n * 2. **Emergency stop is not a route of its own.** The global kill switch is\n * `POST /api/fleet/pause` (and `/resume` to clear), already wrapped in\n * data/mutations.ts. It is re-exported here under honest names so no call\n * site in this folder can accidentally call it \"pause\".\n */\nimport { VERSE_AUDIT_MAX_LIMIT } from './control-types.js';\nimport type { GoalSummary, QueryDef } from '../../../data/queries.js';\nimport { getMutationToken, touchMutationHold } from '../../../data/auth-store.js';\nimport { apiGet, apiPost } from '../../../data/client.js';\nimport { invalidate } from '../../../data/cache.js';\nimport { pauseFleet, resumeFleet } from '../../../data/mutations.js';\nimport type {\n VerseAuditFilters,\n VerseAuditPage,\n VerseCaps,\n VerseCapsApplyResult,\n VerseCapsPatch,\n VerseControlSnapshot,\n VerseDaemonAction,\n VerseDaemonActionResult,\n VerseSafetyReport,\n VerseScope,\n VerseScopePatch,\n} from './control-types.js';\n\nexport const VERSE_CONTROL_KEY = 'verse-control';\nexport const VERSE_CAPS_KEY = 'verse-caps';\nexport const VERSE_SCOPE_KEY = 'verse-scope';\nexport const VERSE_SAFETY_KEY = 'verse-safety';\nexport const VERSE_AUDIT_PREFIX = 'verse-audit:';\n\n/**\n * Server-side cap on `/api/verse/audit`, re-exported from the backend\n * contract module so the client cannot drift from the value the route\n * actually clamps to.\n */\nexport const VERSE_AUDIT_MAX = VERSE_AUDIT_MAX_LIMIT;\n/** Enough rows that the table is the real \"while I was asleep\" view. */\nexport const VERSE_AUDIT_DEFAULT_LIMIT = 200;\n\nexport const verseControlQuery: QueryDef<VerseControlSnapshot> = {\n key: VERSE_CONTROL_KEY,\n fetch: (signal) => apiGet<VerseControlSnapshot>('/api/verse/control', signal),\n};\n\nexport const verseCapsQuery: QueryDef<VerseCaps> = {\n key: VERSE_CAPS_KEY,\n fetch: (signal) => apiGet<VerseCaps>('/api/verse/caps', signal),\n};\n\nexport const verseSafetyQuery: QueryDef<VerseSafetyReport> = {\n key: VERSE_SAFETY_KEY,\n fetch: (signal) => apiGet<VerseSafetyReport>('/api/verse/safety', signal),\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport const verseScopeQuery: QueryDef<VerseScope> = {\n key: VERSE_SCOPE_KEY,\n fetch: (signal) => apiGet<VerseScope>('/api/verse/scope', signal),\n};\n\nexport function verseAuditQuery(filters: VerseAuditFilters = {}): QueryDef<VerseAuditPage> {\n const limit = Math.min(filters.limit ?? VERSE_AUDIT_DEFAULT_LIMIT, VERSE_AUDIT_MAX);\n const params = new URLSearchParams();\n params.set('limit', String(limit));\n if (filters.action) params.set('action', filters.action);\n if (filters.result) params.set('result', filters.result);\n return {\n key: `${VERSE_AUDIT_PREFIX}${limit}:${filters.action ?? ''}:${filters.result ?? ''}`,\n fetch: (signal) => apiGet<VerseAuditPage>(`/api/verse/audit?${params.toString()}`, signal),\n };\n}\n\n/**\n * Read-only in V2 — the contract is explicit that no goal-mutation routes get\n * built here. `/api/goals` returns a bare array; `/api/backlog` returns\n * `loadBacklog() ?? null`, i.e. `null` is \"no backlog on disk\", not an error.\n */\nexport const verseGoalsQuery: QueryDef<GoalSummary[]> = {\n key: 'goals',\n fetch: (signal) => apiGet<GoalSummary[]>('/api/goals', signal),\n};\n\n/** One backlog row, narrowed to what the read-only summary renders. */\nexport interface VerseBacklogItem {\n id?: string;\n title?: string;\n repo?: string;\n score?: number;\n source?: string;\n}\n\nexport interface VerseBacklogSummary {\n items: VerseBacklogItem[];\n /** True when the server answered `null` — no backlog has been built yet. */\n absent: boolean;\n}\n\nexport function normalizeBacklog(raw: unknown): VerseBacklogSummary {\n if (raw === null || raw === undefined) return { items: [], absent: true };\n if (Array.isArray(raw)) return { items: raw as VerseBacklogItem[], absent: false };\n if (isRecord(raw) && Array.isArray(raw['items'])) {\n return { items: raw['items'] as VerseBacklogItem[], absent: false };\n }\n return { items: [], absent: true };\n}\n\nexport const verseBacklogQuery: QueryDef<VerseBacklogSummary> = {\n key: 'backlog',\n fetch: (signal) => apiGet<unknown>('/api/backlog', signal).then(normalizeBacklog),\n};\n\n// ---------------------------------------------------------------------------\n// Writes\n// ---------------------------------------------------------------------------\n\n/** Thrown before any network call when no mutation token is held. */\nexport class VerseControlLockedError extends Error {\n constructor() {\n super('Unlock actions with the mutation token before changing the loop.');\n this.name = 'VerseControlLockedError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseControlLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\n/** Every panel in the cockpit reads through one of these three. */\nexport function invalidateControl(): void {\n invalidate(VERSE_CONTROL_KEY);\n}\n\nexport async function updateVerseCaps(patch: VerseCapsPatch): Promise<VerseCapsApplyResult> {\n const result = await post<VerseCapsApplyResult>('/api/verse/caps', patch);\n invalidate(VERSE_CAPS_KEY);\n invalidateControl();\n return result;\n}\n\nexport async function updateVerseScope(patch: VerseScopePatch): Promise<void> {\n await post<unknown>('/api/verse/scope', patch);\n invalidate(VERSE_SCOPE_KEY);\n invalidateControl();\n}\n\nexport async function runDaemonAction(action: VerseDaemonAction): Promise<VerseDaemonActionResult> {\n const result = await post<VerseDaemonActionResult>('/api/verse/daemon', { action });\n invalidateControl();\n invalidate('daemon');\n return result;\n}\n\n/**\n * ENGAGE the global kill switch (`~/.ashlr/KILL`). This is `POST\n * /api/fleet/pause` under its honest name: it stops the daemon AND refuses\n * the agent's own mcp-native write tools. Never surface it as \"pause\".\n */\nexport async function engageEmergencyStop(): Promise<void> {\n await pauseFleet();\n invalidateControl();\n}\n\n/** Clear the kill switch — writes become possible again fleet-wide. */\nexport async function releaseEmergencyStop(): Promise<void> {\n await resumeFleet();\n invalidateControl();\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{f as e}from"./VerseConsoleApp-DO84Xscn.js";import{t}from"./command-catalog-COH2G2xv.js";import{t as n}from"./clipboard-DkZdqlxf.js";async function r(r=t){let i=await n(r),a=r===`ashlr authority setup`?`add --dry-run to see every step first.`:`then rerun \`${t}\`.`;return e(i?`Copied \`${r}\`. Run it in a terminal; ${a}`:`Could not reach the clipboard. Run \`${r}\` in a terminal.`,i?`success`:`neutral`),i}export{r as copyAutonomySetupCommand};
|
|
2
|
+
//# sourceMappingURL=copy-setup-IHGsNfkz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-setup-IHGsNfkz.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/copy-setup.ts"],"sourcesContent":["/**\n * routes/verse/shell/copy-setup.ts — ⌘K \"Copy autonomy setup command\" and\n * onboarding's Copy button: put `ashlr authority setup` (or the setup\n * checklist's next command) on the clipboard and say what to do with it.\n *\n * Split from run-command.ts for the same reason guarded-runners.ts is:\n * run-command is on the chat first-paint path (the shell's key handler runs\n * through it), and nothing here is needed until someone asks to copy — so\n * run-command loads this module with import() when the command runs.\n */\nimport { copyText } from '../../../components/primitives/clipboard.js';\nimport { AUTONOMY_SETUP_COMMAND } from './command-catalog.js';\nimport { shellNotify } from './run-command.js';\n\n/** Copy the setup command (or the checklist's next one) and toast the outcome; resolves to whether it was copied. */\nexport async function copyAutonomySetupCommand(command: string = AUTONOMY_SETUP_COMMAND): Promise<boolean> {\n const ok = await copyText(command);\n const then = command === AUTONOMY_SETUP_COMMAND\n ? 'add --dry-run to see every step first.'\n : `then rerun \\`${AUTONOMY_SETUP_COMMAND}\\`.`;\n shellNotify(\n ok\n ? `Copied \\`${command}\\`. Run it in a terminal; ${then}`\n : `Could not reach the clipboard. Run \\`${command}\\` in a terminal.`,\n ok ? 'success' : 'neutral',\n );\n return ok;\n}\n"],"mappings":"2IAeA,eAAsB,EAAyB,EAAkB,EAA0C,CACzG,IAAM,EAAK,MAAM,EAAS,CAAO,EAC3B,EAAO,IAAA,wBACT,yCACA,gBAAgB,EAAuB,KAO3C,OANA,EACE,EACI,YAAY,EAAQ,4BAA4B,IAChD,wCAAwC,EAAQ,mBACpD,EAAK,UAAY,SACnB,EACO,CACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-hePW80VL.js";import{pt as t}from"./VerseConsoleApp-DO84Xscn.js";var n=e({TERMINAL_BLOCK_ID_RE:()=>a,TERMINAL_TAB_ID_RE:()=>i,consumeDeepLink:()=>d,deepLinkUrl:()=>f,hasDeepLink:()=>u,parseDeepLink:()=>l,parseTerminalLink:()=>c}),r=/^[A-Za-z0-9._-]{1,128}$/,i=/^t-[a-z0-9]{1,32}$/,a=/^b-\d{1,9}$/,o=[`chat`,`pane`,`terminal`,`block`],s=/^verse:\/\/terminal\/(t-[a-z0-9]{1,32})(?:\/(b-\d{1,9}))?\/?$/;function c(e){if(typeof e!=`string`)return null;let t=s.exec(e.trim());return t?{tabId:t[1],blockId:t[2]??null}:null}function l(e){let n;try{n=new URLSearchParams(e)}catch{return null}let o=n.get(`chat`),s=o!==null&&r.test(o)?o:null,c=t(n.get(`pane`)),l=n.get(`terminal`);if(l!==null&&i.test(l)){let e=n.get(`block`);return{sessionId:s,paneId:c,terminal:{tabId:l,blockId:e!==null&&a.test(e)?e:null}}}return s===null&&c===null?null:{sessionId:s,paneId:c}}function u(e){return/[?&](?:chat|pane|terminal)=/.test(e)}function d(e=window){let t=l(e.location.search);if(!u(e.location.search))return t;try{let t=new URL(e.location.href);for(let e of o)t.searchParams.delete(e);e.history.replaceState(e.history.state,``,`${t.pathname}${t.search}${t.hash}`)}catch{}return t}function f(e,n=typeof window>`u`?`http://127.0.0.1:7777/verse/`:window.location.href){let s=new URL(n);for(let e of o)s.searchParams.delete(e);s.hash=``,e.sessionId&&r.test(e.sessionId)&&s.searchParams.set(`chat`,e.sessionId);let c=t(e.paneId??null);return c&&s.searchParams.set(`pane`,c),e.terminal&&i.test(e.terminal.tabId)&&(s.searchParams.set(`terminal`,e.terminal.tabId),e.terminal.blockId&&a.test(e.terminal.blockId)&&s.searchParams.set(`block`,e.terminal.blockId)),s.toString()}export{n,c as r,f as t};
|
|
2
|
+
//# sourceMappingURL=deep-link-DgTIAuc2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-link-DgTIAuc2.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/deep-link.ts"],"sourcesContent":["/**\n * routes/verse/shell/deep-link.ts — links INTO the workbench: a chat, and\n * optionally a pane in its panel area — or a terminal tab.\n *\n * /verse/?chat=<sessionId> open that chat\n * /verse/?chat=<sessionId>&pane=terminal …with its Terminal showing\n * /verse/?pane=reasoning the Chat surface, Reasoning open\n * /verse/?terminal=<tabId>[&block=<id>] a terminal tab, in its chat, with\n * that command block shown (3.15)\n *\n * The desktop app sends the same thing as a command (`open-pane:<paneId>` or\n * `open-pane:<paneId>@<sessionId>`, `open-terminal:<tabId>[/<blockId>]` —\n * command-keys.ts parseDesktopCommand) — a notification can land on the diff\n * or the command it is about. In chat text a terminal tab is written\n * `verse://terminal/<tabId>[/<blockId>]` (parseTerminalLink below).\n *\n * A link is consumed ONCE: read on load, then stripped from the address bar\n * (history.replaceState) so a reload does not re-open it over whatever the\n * operator did since. Anything malformed is ignored, never guessed.\n *\n * Loaded on demand by the shell (only when the URL carries a link), never\n * on the first-paint path.\n */\nimport { normalizePaneId } from './dock-catalog.js';\n\n/** A terminal tab, and optionally one of its command blocks. */\nexport interface TerminalLink {\n tabId: string;\n blockId: string | null;\n}\n\nexport interface VerseDeepLink {\n sessionId: string | null;\n paneId: string | null;\n /** Present only when the link names a terminal tab (`?terminal=`). */\n terminal?: TerminalLink;\n}\n\n/** The same shape `open-session:<id>` accepts. */\nconst SESSION_ID_RE = /^[A-Za-z0-9._-]{1,128}$/;\n/** The server's terminal tab and block ids (workbench-types VERSE_TERMINAL_AGENT_STATE_PATH_RE; blocks are `b-<n>`). */\nexport const TERMINAL_TAB_ID_RE = /^t-[a-z0-9]{1,32}$/;\nexport const TERMINAL_BLOCK_ID_RE = /^b-\\d{1,9}$/;\nconst PARAMS = ['chat', 'pane', 'terminal', 'block'] as const;\n\n/** `verse://terminal/<tabId>` or `verse://terminal/<tabId>/<blockId>` (a trailing slash is tolerated). */\nconst TERMINAL_LINK_RE = /^verse:\\/\\/terminal\\/(t-[a-z0-9]{1,32})(?:\\/(b-\\d{1,9}))?\\/?$/;\n\n/** Read a `verse://terminal/…` link; null for anything else (never guessed). */\nexport function parseTerminalLink(href: string): TerminalLink | null {\n if (typeof href !== 'string') return null;\n const match = TERMINAL_LINK_RE.exec(href.trim());\n return match ? { tabId: match[1]!, blockId: match[2] ?? null } : null;\n}\n\n/** The `verse://terminal/<tab>[/<block>]` link of a tab (a block id that is not one is left off). */\nexport function terminalLinkUrl(tabId: string, blockId?: string | null): string {\n if (!TERMINAL_TAB_ID_RE.test(tabId)) throw new RangeError('not a terminal tab id');\n const block = blockId && TERMINAL_BLOCK_ID_RE.test(blockId) ? `/${blockId}` : '';\n return `verse://terminal/${tabId}${block}`;\n}\n\n/** Read a link from a query string (`?chat=…&pane=…`, `?terminal=…&block=…`); null when it names nothing valid. */\nexport function parseDeepLink(search: string): VerseDeepLink | null {\n let params: URLSearchParams;\n try {\n params = new URLSearchParams(search);\n } catch {\n return null;\n }\n const chat = params.get('chat');\n const sessionId = chat !== null && SESSION_ID_RE.test(chat) ? chat : null;\n const paneId = normalizePaneId(params.get('pane'));\n const tab = params.get('terminal');\n if (tab !== null && TERMINAL_TAB_ID_RE.test(tab)) {\n const block = params.get('block');\n return { sessionId, paneId, terminal: { tabId: tab, blockId: block !== null && TERMINAL_BLOCK_ID_RE.test(block) ? block : null } };\n }\n return sessionId === null && paneId === null ? null : { sessionId, paneId };\n}\n\n/** Does this query string carry a link at all? (The shell's cheap check before loading this module.) */\nexport function hasDeepLink(search: string): boolean {\n return /[?&](?:chat|pane|terminal)=/.test(search);\n}\n\n/**\n * Take the link out of the current URL: parse it, then remove its params\n * (keeping every other param and the hash). Null when there is none.\n */\nexport function consumeDeepLink(win: Pick<Window, 'location' | 'history'> = window): VerseDeepLink | null {\n const link = parseDeepLink(win.location.search);\n if (!hasDeepLink(win.location.search)) return link;\n try {\n const url = new URL(win.location.href);\n for (const name of PARAMS) url.searchParams.delete(name);\n win.history.replaceState(win.history.state, '', `${url.pathname}${url.search}${url.hash}`);\n } catch {\n /* an opaque origin (tests, file://): the link still opens */\n }\n return link;\n}\n\n/** The shareable URL of a chat (and optionally a pane), on this page's origin and path. */\nexport function deepLinkUrl(link: Partial<VerseDeepLink>, base: string = typeof window === 'undefined' ? 'http://127.0.0.1:7777/verse/' : window.location.href): string {\n const url = new URL(base);\n for (const name of PARAMS) url.searchParams.delete(name);\n url.hash = '';\n if (link.sessionId && SESSION_ID_RE.test(link.sessionId)) url.searchParams.set('chat', link.sessionId);\n const pane = normalizePaneId(link.paneId ?? null);\n if (pane) url.searchParams.set('pane', pane);\n if (link.terminal && TERMINAL_TAB_ID_RE.test(link.terminal.tabId)) {\n url.searchParams.set('terminal', link.terminal.tabId);\n if (link.terminal.blockId && TERMINAL_BLOCK_ID_RE.test(link.terminal.blockId)) url.searchParams.set('block', link.terminal.blockId);\n }\n return url.toString();\n}\n"],"mappings":"2QAuCM,EAAgB,0BAET,EAAqB,qBACrB,EAAuB,cAC9B,EAAS,CAAC,OAAQ,OAAQ,WAAY,OAAO,EAG7C,EAAmB,gEAGzB,SAAgB,EAAkB,EAAmC,CACnE,GAAI,OAAO,GAAS,SAAU,OAAO,KACrC,IAAM,EAAQ,EAAiB,KAAK,EAAK,KAAK,CAAC,EAC/C,OAAO,EAAQ,CAAE,MAAO,EAAM,GAAK,QAAS,EAAM,IAAM,IAAK,EAAI,IACnE,CAUA,SAAgB,EAAc,EAAsC,CAClE,IAAI,EACJ,GAAI,CACF,EAAS,IAAI,gBAAgB,CAAM,CACrC,MAAQ,CACN,OAAO,IACT,CACA,IAAM,EAAO,EAAO,IAAI,MAAM,EACxB,EAAY,IAAS,MAAQ,EAAc,KAAK,CAAI,EAAI,EAAO,KAC/D,EAAS,EAAgB,EAAO,IAAI,MAAM,CAAC,EAC3C,EAAM,EAAO,IAAI,UAAU,EACjC,GAAI,IAAQ,MAAQ,EAAmB,KAAK,CAAG,EAAG,CAChD,IAAM,EAAQ,EAAO,IAAI,OAAO,EAChC,MAAO,CAAE,YAAW,SAAQ,SAAU,CAAE,MAAO,EAAK,QAAS,IAAU,MAAQ,EAAqB,KAAK,CAAK,EAAI,EAAQ,IAAK,CAAE,CACnI,CACA,OAAO,IAAc,MAAQ,IAAW,KAAO,KAAO,CAAE,YAAW,QAAO,CAC5E,CAGA,SAAgB,EAAY,EAAyB,CACnD,MAAO,8BAA8B,KAAK,CAAM,CAClD,CAMA,SAAgB,EAAgB,EAA4C,OAA8B,CACxG,IAAM,EAAO,EAAc,EAAI,SAAS,MAAM,EAC9C,GAAI,CAAC,EAAY,EAAI,SAAS,MAAM,EAAG,OAAO,EAC9C,GAAI,CACF,IAAM,EAAM,IAAI,IAAI,EAAI,SAAS,IAAI,EACrC,IAAK,IAAM,KAAQ,EAAQ,EAAI,aAAa,OAAO,CAAI,EACvD,EAAI,QAAQ,aAAa,EAAI,QAAQ,MAAO,GAAI,GAAG,EAAI,WAAW,EAAI,SAAS,EAAI,MAAM,CAC3F,MAAQ,CAER,CACA,OAAO,CACT,CAGA,SAAgB,EAAY,EAA8B,EAAe,OAAO,OAAW,IAAc,+BAAiC,OAAO,SAAS,KAAc,CACtK,IAAM,EAAM,IAAI,IAAI,CAAI,EACxB,IAAK,IAAM,KAAQ,EAAQ,EAAI,aAAa,OAAO,CAAI,EACvD,EAAI,KAAO,GACP,EAAK,WAAa,EAAc,KAAK,EAAK,SAAS,GAAG,EAAI,aAAa,IAAI,OAAQ,EAAK,SAAS,EACrG,IAAM,EAAO,EAAgB,EAAK,QAAU,IAAI,EAMhD,OALI,GAAM,EAAI,aAAa,IAAI,OAAQ,CAAI,EACvC,EAAK,UAAY,EAAmB,KAAK,EAAK,SAAS,KAAK,IAC9D,EAAI,aAAa,IAAI,WAAY,EAAK,SAAS,KAAK,EAChD,EAAK,SAAS,SAAW,EAAqB,KAAK,EAAK,SAAS,OAAO,GAAG,EAAI,aAAa,IAAI,QAAS,EAAK,SAAS,OAAO,GAE7H,EAAI,SAAS,CACtB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{s as t}from"./index-_izD07R9.js";import{c as n,s as r}from"./global-CYfRwH6t.js";import"./VerseMobileApp-CrCDQcw5.js";var i=e(t(),1);function a(e){let{authenticated:t,dispatchEnabled:n,holdsMutation:r,scopes:i}=e,a=t&&(i?.read??!0),o={read:a,source:i?`device`:`session`,deviceLabel:i?.label??null};return a?i?.gatewayWritesEnabled===!1?{...o,act:`unavailable`,actReason:`The phone gateway is read-only. Actions are available on your Mac.`}:i&&!i.act?{...o,act:`unavailable`,actReason:`This device was paired read-only. Pair it again with act permission to approve or start work.`}:n===null?{...o,act:`unavailable`,actReason:`Checking whether this Mac allows actions. Wait for it to answer.`}:n===!1?{...o,act:`unavailable`,actReason:"Your Mac started Verse without dispatch, so nothing can be changed from here. Run `ashlr verse` on the Mac to act."}:r?{...o,act:`unlocked`,actReason:null}:{...o,act:`locked`,actReason:"Actions ask for the mutation token `ashlr verse` printed. It stays in memory for 20 idle minutes, never on disk."}:{...o,act:`unavailable`,actReason:`This device is not signed in to your Mac.`}}var o=null,s=new Set;function c(e){o=e;for(let e of[...s])e()}function l(e){return s.add(e),()=>s.delete(e)}function u(){return o}function d(e){let t=r(),o=n(),s=(0,i.useSyncExternalStore)(l,u,u);return a({authenticated:t===`authenticated`,dispatchEnabled:e,holdsMutation:o.hasHold,scopes:s})}async function f(e){return!0}export{f as n,d as r,c as t};
|
|
2
|
+
//# sourceMappingURL=device-permissions-BplZgouU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-permissions-BplZgouU.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/mobile/device-permissions.ts"],"sourcesContent":["/**\n * routes/verse/mobile/device-permissions.ts — what THIS device may do, said\n * out loud, and the two seams the remote transport plugs into.\n *\n * The phone app uses exactly the web UI's token model (data/auth-store.ts):\n *\n * READ — the HttpOnly read-session cookie (15 min, silently renewed from\n * the in-memory read token). Every screen needs it.\n * ACT — the raw mutation token, memory-only, in a 20-minute idle hold,\n * sent as `x-ashlr-token` on every POST. Never stored.\n *\n * So \"can this phone act?\" has three answers:\n *\n * 'unavailable' — the server was started without dispatch, or the device's\n * scopes say read-only. Action controls are HIDDEN: showing\n * a button that can only fail is a lie about the device.\n * 'locked' — acting is possible but the token is not held. Controls\n * show; the first one asks for the token (after its\n * confirmation, never before — guard-store.ts).\n * 'unlocked' — the hold is live.\n *\n * TRANSPORT SEAMS (the relay / tunnel / pairing work lands separately):\n *\n * - registerDeviceScopes({ read, act, label }) — a paired device's token\n * scopes. A read-only pairing must make `act` 'unavailable' even on a\n * dispatch-enabled server. Absent (today), scopes come from the session.\n * - registerStepUpProvider(fn) — called before any irreversible or\n * autonomy-widening action (Land, Veto, Start fleet, Stop fleet, Delete).\n * Resolve false to refuse. Absent (today), the held mutation token IS the\n * step-up, exactly as on the desktop.\n *\n * Neither seam can widen anything: scopes only ever REMOVE `act`, and a\n * step-up provider only ever adds a refusal before the unchanged\n * confirm → token → POST path.\n */\nimport { useSyncExternalStore } from 'react';\nimport { useAuthPhase, useMutationHold } from '../../../data/hooks.js';\n\nexport type ActPermission = 'unlocked' | 'locked' | 'unavailable';\n\nexport interface DeviceScopes {\n read: boolean;\n act: boolean;\n /** How the transport names this device (\"Mason's iPhone\"), shown on More. */\n label?: string;\n /** An act grant does not imply the remote gateway has mounted writes. */\n gatewayWritesEnabled?: boolean;\n}\n\nexport interface DevicePermissions {\n read: boolean;\n act: ActPermission;\n /** Why acting is unavailable or locked, in operator language; null when unlocked. */\n actReason: string | null;\n /** Where the answer came from: this browser session, or a paired device's scopes. */\n source: 'session' | 'device';\n deviceLabel: string | null;\n}\n\nexport interface PermissionInput {\n authenticated: boolean;\n /** Bootstrap's `dispatchEnabled`; null while it has not answered. */\n dispatchEnabled: boolean | null;\n holdsMutation: boolean;\n scopes: DeviceScopes | null;\n}\n\nexport function resolveDevicePermissions(input: PermissionInput): DevicePermissions {\n const { authenticated, dispatchEnabled, holdsMutation, scopes } = input;\n const read = authenticated && (scopes?.read ?? true);\n const base = { read, source: scopes ? ('device' as const) : ('session' as const), deviceLabel: scopes?.label ?? null };\n if (!read) return { ...base, act: 'unavailable', actReason: 'This device is not signed in to your Mac.' };\n if (scopes?.gatewayWritesEnabled === false) return { ...base, act: 'unavailable', actReason: 'The phone gateway is read-only. Actions are available on your Mac.' };\n if (scopes && !scopes.act) return { ...base, act: 'unavailable', actReason: 'This device was paired read-only. Pair it again with act permission to approve or start work.' };\n if (dispatchEnabled === null) return { ...base, act: 'unavailable', actReason: 'Checking whether this Mac allows actions. Wait for it to answer.' };\n if (dispatchEnabled === false) return { ...base, act: 'unavailable', actReason: 'Your Mac started Verse without dispatch, so nothing can be changed from here. Run `ashlr verse` on the Mac to act.' };\n if (!holdsMutation) return { ...base, act: 'locked', actReason: 'Actions ask for the mutation token `ashlr verse` printed. It stays in memory for 20 idle minutes, never on disk.' };\n return { ...base, act: 'unlocked', actReason: null };\n}\n\nexport { canShowActions } from './mobile-context.js';\n\n// ---------------------------------------------------------------------------\n// Device scopes (transport seam)\n// ---------------------------------------------------------------------------\n\nlet scopes: DeviceScopes | null = null;\nconst scopeListeners = new Set<() => void>();\n\nexport function registerDeviceScopes(next: DeviceScopes | null): void {\n scopes = next;\n for (const l of [...scopeListeners]) l();\n}\n\nfunction subscribeScopes(listener: () => void): () => void {\n scopeListeners.add(listener);\n return () => scopeListeners.delete(listener);\n}\n\nfunction getScopes(): DeviceScopes | null {\n return scopes;\n}\n\nexport function useDevicePermissions(dispatchEnabled: boolean | null): DevicePermissions {\n const phase = useAuthPhase();\n const hold = useMutationHold();\n const current = useSyncExternalStore(subscribeScopes, getScopes, getScopes);\n return resolveDevicePermissions({ authenticated: phase === 'authenticated', dispatchEnabled, holdsMutation: hold.hasHold, scopes: current });\n}\n\n// ---------------------------------------------------------------------------\n// Step-up (transport seam)\n// ---------------------------------------------------------------------------\n\nexport interface StepUpRequest {\n /** The button the operator pressed: \"Land\", \"Stop the fleet\". */\n action: string;\n /** Cannot be undone from the phone (a merge, a veto, the kill switch). */\n irreversible: boolean;\n}\n\nexport type StepUpProvider = (request: StepUpRequest) => Promise<boolean>;\n\nlet stepUp: StepUpProvider | null = null;\n\nexport function registerStepUpProvider(provider: StepUpProvider | null): void {\n stepUp = provider;\n}\n\n/**\n * Ask the registered provider; true = proceed. With none registered the\n * answer is true: the mutation token (asked for next, if not held) is the\n * step-up this build has. A provider that throws refuses.\n */\nexport async function requestStepUp(request: StepUpRequest): Promise<boolean> {\n if (!stepUp || !request.irreversible) return true;\n try {\n return (await stepUp(request)) === true;\n } catch {\n return false;\n }\n}\n"],"mappings":"+LAmEA,SAAgB,EAAyB,EAA2C,CAClF,GAAM,CAAE,gBAAe,kBAAiB,gBAAe,UAAW,EAC5D,EAAO,IAAkB,GAAQ,MAAQ,IACzC,EAAO,CAAE,OAAM,OAAQ,EAAU,SAAsB,UAAqB,YAAa,GAAQ,OAAS,IAAK,EAOrH,OANK,EACD,GAAQ,uBAAyB,GAAc,CAAE,GAAG,EAAM,IAAK,cAAe,UAAW,oEAAqE,EAC9J,GAAU,CAAC,EAAO,IAAY,CAAE,GAAG,EAAM,IAAK,cAAe,UAAW,+FAAgG,EACxK,IAAoB,KAAa,CAAE,GAAG,EAAM,IAAK,cAAe,UAAW,kEAAmE,EAC9I,IAAoB,GAAc,CAAE,GAAG,EAAM,IAAK,cAAe,UAAW,oHAAqH,EAChM,EACE,CAAE,GAAG,EAAM,IAAK,WAAY,UAAW,IAAK,EADxB,CAAE,GAAG,EAAM,IAAK,SAAU,UAAW,kHAAmH,EALjK,CAAE,GAAG,EAAM,IAAK,cAAe,UAAW,2CAA4C,CAO1G,CAQA,IAAI,EAA8B,KAC5B,EAAiB,IAAI,IAE3B,SAAgB,EAAqB,EAAiC,CACpE,EAAS,EACT,IAAK,IAAM,IAAK,CAAC,GAAG,CAAc,EAAG,EAAE,CACzC,CAEA,SAAS,EAAgB,EAAkC,CAEzD,OADA,EAAe,IAAI,CAAQ,MACd,EAAe,OAAO,CAAQ,CAC7C,CAEA,SAAS,GAAiC,CACxC,OAAO,CACT,CAEA,SAAgB,EAAqB,EAAoD,CACvF,IAAM,EAAQ,EAAa,EACrB,EAAO,EAAgB,EACvB,GAAA,EAAU,EAAA,qBAAA,CAAqB,EAAiB,EAAW,CAAS,EAC1E,OAAO,EAAyB,CAAE,cAAe,IAAU,gBAAiB,kBAAiB,cAAe,EAAK,QAAS,OAAQ,CAAQ,CAAC,CAC7I,CA0BA,eAAsB,EAAc,EAA0C,CACtC,MAAO,EAM/C"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{C as e,M as t,V as n,a as r,i,t as a}from"./global-CYfRwH6t.js";import{O as o}from"./VerseShared-CFE5B-IY.js";import{a as s,i as c,n as l,o as u,r as d,t as f}from"./types-BGCo0sbt.js";function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var m=e=>p(e)&&typeof e.ready==`boolean`&&typeof e.tone==`string`&&typeof e.word==`string`&&typeof e.detail==`string`;function h(e){if(!p(e))return null;let{status:t,budget:n,tasks:r}=e;if(!p(t)||typeof t.enabled!=`boolean`||typeof t.connected!=`boolean`||typeof t.state!=`string`||!m(t.chat)||!m(t.fleet)||!p(n)||!p(n.canLaunch)||!p(n.budget))return null;for(let e of[`acuBudgetTotal`,`acuUsed`,`acuRemaining`,`acuToday`,`acuInFlight`,`estimatedUsdUsed`,`sessionsToday`,`running`])if(typeof n[e]!=`number`||!Number.isFinite(n[e]))return null;return!Array.isArray(r)||!r.every(e=>p(e)&&typeof e.id==`string`&&typeof e.state==`string`)?null:e}function g(e){if(!p(e))return null;let t=Array.isArray(e.freeFamilies)?e.freeFamilies.filter(e=>typeof e==`string`&&e.length>0&&e.length<=120):null,n=e.paidFamilyCount,r=e.defaultModel;if(t===null||typeof n!=`number`||!Number.isInteger(n)||n<0||!p(r)||typeof r.label!=`string`)return null;let i=`Models: ${[t.length>0?t.map(e=>`${e} (free)`).join(`, `):null,n>0?`${n} paid famil${n===1?`y`:`ies`}`:null].filter(Boolean).join(` + `)||`none listed`}`,a=r.free===!0?`Free`:typeof r.price==`string`&&r.price?r.price:null;return{catalog:i,defaultLine:`Default: ${r.label}${a?` (${a})`:``}`,stale:e.source===`fallback`}}function _(e){let t=Math.max(0,Math.round(e*100)/100);return`${t} ACU${t===1?``:`s`}`}function v(e,t){if(typeof e!=`string`||e.length>2048)return null;try{let n=new URL(e);return n.protocol===`https:`&&n.hostname===t?n.toString():null}catch{return null}}var y=d;function b(e){return e.paused||e.acuRemaining<=0||e.acuBudgetTotal<=0?`limit`:e.acuRemaining/e.acuBudgetTotal*100<20?`tight`:`ok`}function x(e){switch(e.state){case`ready`:return{word:`Connected`,tone:`success`};case`unreachable`:return{word:`Key refused`,tone:`danger`};case`not-connected`:return{word:`Not connected`,tone:`warning`};default:return{word:e.connected?`Turned off`:`Not set up`,tone:`neutral`}}}function S(e){return{id:`devin`,label:`Devin`,engine:`devin`,kind:`cloud`,reading:{state:`live`,at:null,note:null},chat:e.chat,fleet:e.fleet}}function C(e){return e.filter(e=>e.state===`blocked`&&e.sessionId!==null).slice(0,5)}var w=new Intl.NumberFormat(`en-US`);function T(e){if(!e.overview)return e.overviewReason??`The Devin lane did not answer.`;let{status:t,budget:n}=e.overview;return t.connected?t.enabled?t.state===`unreachable`?t.reason:e.repo?n.canLaunch.ok?e.prompt.trim()?e.prompt.trim().length>2e4?`The message is over ${w.format(f)} characters — trim it to run it in Devin.`:null:`Type the task in the message box first.`:n.canLaunch.reason??`The Devin budget does not allow another session right now.`:e.rootsLoading?`Reading this chat's project…`:`This chat's project has no GitHub origin, so Devin has nothing to work on.`:"The Devin lane is turned off (`ashlr devin enable`).":"Devin is not connected. Run `ashlr devin connect` in a terminal."}var E=`verse-devin`,D=6e4,O=`The Devin lane is not in this build yet.`,k=class extends Error{constructor(){super(`Unlock actions with the mutation token first.`),this.name=`DevinLockedError`}},A=class extends Error{failure;constructor(e,t){super(e),this.failure=t,this.name=`DevinLaunchRefusedError`}};function j(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function M(e){return e instanceof a?e.status===404?O:e.status===503?`The Devin lane failed to load on the server.`:`The Devin lane answered HTTP ${e.status}.`:`The Devin lane could not be reached.`}var N={key:E,fetch:async e=>{try{let t=h(await i(s,e));return t===null?{value:null,available:!0,reason:`Unrecognized response — update Ashlr.`}:{value:t,available:!0,reason:null}}catch(e){if(e instanceof a&&e.status===401||e instanceof DOMException&&e.name===`AbortError`)throw e;return{value:null,available:!1,reason:M(e)}}}};async function P(n,i){let a=e();if(!a)throw new k;let o=await r(n,i,a);return t(),o}function F(){n(E),o()}async function I(e){try{let t=await P(c,e);if(!j(t)||t.ok!==!0||!j(t.task))throw new A(j(t)&&typeof t.error==`string`&&t.error?t.error:`The Devin session was not started, and the server sent no reason.`,j(t)&&typeof t.failure==`string`?t.failure:null);return t}finally{F()}}async function L(e,t){if(!l.test(e))throw Error(`That is not a Devin task id.`);try{return await P(`${u}/${e}/message`,{message:t})}finally{F()}}export{y as a,g as c,T as d,v as f,L as i,S as l,N as n,b as o,C as p,I as r,x as s,D as t,_ as u};
|
|
2
|
+
//# sourceMappingURL=devin-queries-Bltl6Jz2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devin-queries-Bltl6Jz2.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/devin/devin-model.ts","../../../../../../src/web-ui/routes/verse/devin/devin-queries.ts"],"sourcesContent":["/**\n * routes/verse/devin/devin-model.ts — pure view logic for the Devin lane\n * (3.15; server: core/devin/devin-api.ts).\n *\n * The overview is narrowed field by field: a server without the route (404)\n * is \"not in this build\", an unknown shape shows nothing rather than a guess.\n * Browser-safe: type-only imports from core.\n */\nimport {\n DEVIN_PROMPT_MAX_CHARS,\n DEVIN_USAGE_URL,\n type DevinBudgetView,\n type DevinOverviewResponse,\n type DevinStatus,\n type DevinTaskV1,\n} from '../../../../core/devin/types.js';\nimport type { ResourceReadinessRow } from '../../../../core/routing/readiness-types.js';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nconst isVerdict = (value: unknown): boolean =>\n isRecord(value) && typeof value['ready'] === 'boolean' && typeof value['tone'] === 'string' && typeof value['word'] === 'string' && typeof value['detail'] === 'string';\n\n/** Just enough structure that no render can crash; null when it is not a Devin overview. */\nexport function narrowDevinOverview(raw: unknown): DevinOverviewResponse | null {\n if (!isRecord(raw)) return null;\n const { status, budget, tasks } = raw;\n if (!isRecord(status) || typeof status['enabled'] !== 'boolean' || typeof status['connected'] !== 'boolean' || typeof status['state'] !== 'string') return null;\n if (!isVerdict(status['chat']) || !isVerdict(status['fleet'])) return null;\n if (!isRecord(budget) || !isRecord(budget['canLaunch']) || !isRecord(budget['budget'])) return null;\n for (const key of ['acuBudgetTotal', 'acuUsed', 'acuRemaining', 'acuToday', 'acuInFlight', 'estimatedUsdUsed', 'sessionsToday', 'running']) {\n if (typeof budget[key] !== 'number' || !Number.isFinite(budget[key])) return null;\n }\n if (!Array.isArray(tasks) || !tasks.every((t) => isRecord(t) && typeof t['id'] === 'string' && typeof t['state'] === 'string')) return null;\n return raw as unknown as DevinOverviewResponse;\n}\n\n/**\n * 3.15: the Devin CLI's model catalog in one line for the Resources card —\n * \"Models: SWE-2 (free) + 51 paid families\" and \"Default: SWE-2 High (Free)\".\n * Null when the server sent no (or a malformed) summary. Pure.\n */\nexport function devinModelsLines(models: unknown): { catalog: string; defaultLine: string; stale: boolean } | null {\n if (!isRecord(models)) return null;\n const free = Array.isArray(models['freeFamilies']) ? models['freeFamilies'].filter((f): f is string => typeof f === 'string' && f.length > 0 && f.length <= 120) : null;\n const paid = models['paidFamilyCount'];\n const def = models['defaultModel'];\n if (free === null || typeof paid !== 'number' || !Number.isInteger(paid) || paid < 0 || !isRecord(def) || typeof def['label'] !== 'string') return null;\n const freePart = free.length > 0 ? free.map((f) => `${f} (free)`).join(', ') : null;\n const paidPart = paid > 0 ? `${paid} paid famil${paid === 1 ? 'y' : 'ies'}` : null;\n const catalog = `Models: ${[freePart, paidPart].filter(Boolean).join(' + ') || 'none listed'}`;\n const price = def['free'] === true ? 'Free' : typeof def['price'] === 'string' && def['price'] ? def['price'] : null;\n const defaultLine = `Default: ${def['label']}${price ? ` (${price})` : ''}`;\n return { catalog, defaultLine, stale: models['source'] === 'fallback' };\n}\n\n/** \"12 ACUs\", \"1 ACU\", \"2.5 ACUs\". */\nexport function formatAcu(value: number): string {\n const v = Math.max(0, Math.round(value * 100) / 100);\n return `${v} ACU${v === 1 ? '' : 's'}`;\n}\n\n/** https only, on the expected host — a link the page may open. */\nexport function safeDevinHref(url: string | null | undefined, host: 'app.devin.ai' | 'github.com'): string | null {\n if (typeof url !== 'string' || url.length > 2_048) return null;\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'https:' && parsed.hostname === host ? parsed.toString() : null;\n } catch {\n return null;\n }\n}\n\nexport const DEVIN_USAGE_LINK = DEVIN_USAGE_URL;\n\n/** ok / tight / limit for the meter, from what is left. */\nexport function acuLevel(budget: Pick<DevinBudgetView, 'acuBudgetTotal' | 'acuRemaining' | 'paused'>): 'ok' | 'tight' | 'limit' {\n if (budget.paused || budget.acuRemaining <= 0 || budget.acuBudgetTotal <= 0) return 'limit';\n return (budget.acuRemaining / budget.acuBudgetTotal) * 100 < 20 ? 'tight' : 'ok';\n}\n\n/** The card's headline state. */\nexport function devinHeadline(status: Pick<DevinStatus, 'state' | 'enabled' | 'connected'>): { word: string; tone: 'success' | 'warning' | 'danger' | 'neutral' } {\n switch (status.state) {\n case 'ready': return { word: 'Connected', tone: 'success' };\n case 'unreachable': return { word: 'Key refused', tone: 'danger' };\n case 'not-connected': return { word: 'Not connected', tone: 'warning' };\n default: return { word: status.connected ? 'Turned off' : 'Not set up', tone: 'neutral' };\n }\n}\n\n/**\n * The drawer's readiness row for Devin, built from the server's own verdicts\n * (core/devin/service.ts devinStatus) so ReadinessLines lays it out exactly\n * like every other resource. `engine` is not shown by the lines; `kind`\n * 'cloud' keeps the reading caveat hidden (Devin has no usage window).\n */\nexport function devinReadinessRow(status: Pick<DevinStatus, 'chat' | 'fleet'>): ResourceReadinessRow {\n return {\n id: 'devin',\n label: 'Devin',\n engine: 'devin',\n kind: 'cloud',\n reading: { state: 'live', at: null, note: null },\n chat: status.chat,\n fleet: status.fleet,\n };\n}\n\n/** Sessions waiting for Mason (a reply box on the card). */\nexport function waitingTasks(tasks: readonly DevinTaskV1[]): DevinTaskV1[] {\n return tasks.filter((task) => task.state === 'blocked' && task.sessionId !== null).slice(0, 5);\n}\n\nexport interface RunInDevinInputs {\n overview: DevinOverviewResponse | null;\n overviewReason: string | null;\n repo: string | null;\n rootsLoading: boolean;\n prompt: string;\n}\n\nconst COUNT = new Intl.NumberFormat('en-US');\n\n/** Null when \"Run in Devin\" may be pressed; otherwise the sentence saying why not. */\nexport function runInDevinBlock(inputs: RunInDevinInputs): string | null {\n if (!inputs.overview) return inputs.overviewReason ?? 'The Devin lane did not answer.';\n const { status, budget } = inputs.overview;\n if (!status.connected) return 'Devin is not connected. Run `ashlr devin connect` in a terminal.';\n if (!status.enabled) return 'The Devin lane is turned off (`ashlr devin enable`).';\n if (status.state === 'unreachable') return status.reason;\n if (!inputs.repo) {\n return inputs.rootsLoading ? \"Reading this chat's project…\" : \"This chat's project has no GitHub origin, so Devin has nothing to work on.\";\n }\n if (!budget.canLaunch.ok) return budget.canLaunch.reason ?? 'The Devin budget does not allow another session right now.';\n if (!inputs.prompt.trim()) return 'Type the task in the message box first.';\n if (inputs.prompt.trim().length > DEVIN_PROMPT_MAX_CHARS) {\n return `The message is over ${COUNT.format(DEVIN_PROMPT_MAX_CHARS)} characters — trim it to run it in Devin.`;\n }\n return null;\n}\n","/**\n * routes/verse/devin/devin-queries.ts — the read and writes behind the Devin\n * lane's UI (3.15; server: core/devin/devin-api.ts).\n *\n * GET /api/verse/devin DevinOverviewResponse\n * POST /api/verse/devin/launch DevinLaunchRequest → DevinLaunchResponse\n * POST /api/verse/devin/tasks/<id>/message { message } (reply to a waiting session)\n *\n * The read is OPTIONAL: a server without the lane answers 404 — \"not in this\n * build\", a designed state. 401 and aborts propagate. There is no write that\n * carries an API key: the key is entered only in a terminal.\n *\n * LAZY ONLY: everything importing this file sits behind an import().\n */\nimport {\n DEVIN_TASK_ID_PATTERN,\n VERSE_DEVIN_LAUNCH_PATH,\n VERSE_DEVIN_PATH,\n VERSE_DEVIN_TASKS_PATH,\n type DevinFailureCode,\n type DevinLaunchRequest,\n type DevinLaunchResponse,\n type DevinOverviewResponse,\n} from '../../../../core/devin/types.js';\nimport { ApiError, apiGet, apiPost } from '../../../data/client.js';\nimport { getMutationToken, touchMutationHold } from '../../../data/auth-store.js';\nimport { invalidate } from '../../../data/cache.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { refreshActivity } from '../shell/useActivity.js';\nimport type { OptionalRead } from '../command/surface-data.js';\nimport { narrowDevinOverview } from './devin-model.js';\n\nexport const DEVIN_KEY = 'verse-devin';\nexport const DEVIN_POLL_MS = 60_000;\nexport const DEVIN_NOT_IN_BUILD = 'The Devin lane is not in this build yet.';\n\nexport class DevinLockedError extends Error {\n constructor() {\n super('Unlock actions with the mutation token first.');\n this.name = 'DevinLockedError';\n }\n}\n\nexport class DevinLaunchRefusedError extends Error {\n constructor(message: string, public readonly failure: DevinFailureCode | null) {\n super(message);\n this.name = 'DevinLaunchRefusedError';\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction absence(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) return DEVIN_NOT_IN_BUILD;\n if (err.status === 503) return 'The Devin lane failed to load on the server.';\n return `The Devin lane answered HTTP ${err.status}.`;\n }\n return 'The Devin lane could not be reached.';\n}\n\nexport const devinQuery: QueryDef<OptionalRead<DevinOverviewResponse>> = {\n key: DEVIN_KEY,\n fetch: async (signal) => {\n try {\n const value = narrowDevinOverview(await apiGet<unknown>(VERSE_DEVIN_PATH, signal));\n if (value === null) return { value: null, available: true, reason: 'Unrecognized response — update Ashlr.' };\n return { value, 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 { value: null, available: false, reason: absence(err) };\n }\n },\n};\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new DevinLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\nfunction settled(): void {\n invalidate(DEVIN_KEY);\n void refreshActivity();\n}\n\n/** Launch one Devin session; resolves only on `ok: true` with a task. */\nexport async function launchDevinTask(request: DevinLaunchRequest): Promise<DevinLaunchResponse & { task: NonNullable<DevinLaunchResponse['task']> }> {\n try {\n const response = await post<DevinLaunchResponse>(VERSE_DEVIN_LAUNCH_PATH, request);\n if (!isRecord(response) || response.ok !== true || !isRecord(response.task)) {\n const error = isRecord(response) && typeof response.error === 'string' && response.error ? response.error : 'The Devin session was not started, and the server sent no reason.';\n const failure = isRecord(response) && typeof response.failure === 'string' ? (response.failure as DevinFailureCode) : null;\n throw new DevinLaunchRefusedError(error, failure);\n }\n return response as DevinLaunchResponse & { task: NonNullable<DevinLaunchResponse['task']> };\n } finally {\n settled();\n }\n}\n\n/** Reply to a waiting session. The id is re-checked before it is spliced into a path. */\nexport async function messageDevinTask(taskId: string, message: string): Promise<unknown> {\n if (!DEVIN_TASK_ID_PATTERN.test(taskId)) throw new Error('That is not a Devin task id.');\n try {\n return await post<unknown>(`${VERSE_DEVIN_TASKS_PATH}/${taskId}/message`, { message });\n } finally {\n settled();\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{n as e}from"./index-_izD07R9.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.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M5 2.5v5M2.5 5h5M9 11h4.5`}),(0,t.jsx)(`path`,{d:`M11.5 2.5 4.5 13.5`})]})}function o(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M6.5 4h7M6.5 8h7M6.5 12h7`}),(0,t.jsx)(`path`,{d:`m2.25 4 1 1 1.5-2M2.5 8h1.75M2.5 12h1.75`})]})}function s(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`m8 2 6 3-6 3-6-3 6-3Z`}),(0,t.jsx)(`path`,{d:`m2 8 6 3 6-3M2 11l6 3 6-3`})]})}function c(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`2.25`,y:`2.25`,width:`11.5`,height:`11.5`,rx:`1.5`}),(0,t.jsx)(`path`,{d:`M2.25 8h11.5`})]})}function l(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`m4 4 8 8M12 4l-8 8`})})}function u(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`circle`,{cx:`3.5`,cy:`8`,r:`0.9`,fill:`currentColor`,stroke:`none`}),(0,t.jsx)(`circle`,{cx:`8`,cy:`8`,r:`0.9`,fill:`currentColor`,stroke:`none`}),(0,t.jsx)(`circle`,{cx:`12.5`,cy:`8`,r:`0.9`,fill:`currentColor`,stroke:`none`})]})}function d(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M9.75 2.25 13.75 6.25 11 7.5 8.5 10l.25 2.75-5-5L6.5 8 9 5.25Z`}),(0,t.jsx)(`path`,{d:`m5 11-2.75 2.75`})]})}function f(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`1.75`,y:`2.75`,width:`12.5`,height:`3`,rx:`1`}),(0,t.jsx)(`path`,{d:`M2.75 5.75v6.5a1 1 0 0 0 1 1h8.5a1 1 0 0 0 1-1v-6.5M6.5 8.5h3`})]})}function p(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M10.5 2.75 13.25 5.5 6 12.75H3.25V10Z`})})}function m(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M2.5 8h9M8.5 4.5 12 8l-3.5 3.5`}),(0,t.jsx)(`path`,{d:`M13.75 3v10`})]})}function h(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`rect`,{x:`5.25`,y:`5.25`,width:`8.5`,height:`8.5`,rx:`1.5`}),(0,t.jsx)(`path`,{d:`M10.75 5.25V3.75a1.5 1.5 0 0 0-1.5-1.5h-5.5a1.5 1.5 0 0 0-1.5 1.5v5.5a1.5 1.5 0 0 0 1.5 1.5h1.5`})]})}function g(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M2.75 4.25h10.5M6.25 4.25V2.75h3.5v1.5M4.25 4.25l.6 9h6.3l.6-9`})})}function _(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M2.25 4.25a1.5 1.5 0 0 1 1.5-1.5h2.5l1.5 1.75h4.5a1.5 1.5 0 0 1 1.5 1.5v5.75a1.5 1.5 0 0 1-1.5 1.5h-8.5a1.5 1.5 0 0 1-1.5-1.5Z`})})}function v(e){return(0,t.jsxs)(n,{...e,children:[(0,t.jsx)(`path`,{d:`M3.25 2.75h6l3.5 3.5v7a1 1 0 0 1-1 1h-8.5a1 1 0 0 1-1-1v-9.5a1 1 0 0 1 1-1Z`}),(0,t.jsx)(`path`,{d:`M9 2.75v3.5h3.75M5 9h6M5 11.5h4`})]})}function y(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M6 13.25h4M6.5 11.25h3M8 1.75a4.25 4.25 0 0 0-2.4 7.76c.3.2.5.55.5.92v.82h3.8v-.82c0-.37.2-.72.5-.92A4.25 4.25 0 0 0 8 1.75Z`})})}function b(e){return(0,t.jsx)(n,{...e,children:(0,t.jsx)(`path`,{d:`M2.25 5.5V3.25a1 1 0 0 1 1-1H5.5M10.5 2.25h2.25a1 1 0 0 1 1 1V5.5M13.75 10.5v2.25a1 1 0 0 1-1 1H10.5M5.5 13.75H3.25a1 1 0 0 1-1-1V10.5`})})}function x(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:`M9.75 2.75v10.5`})]})}function S(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 9.5h12.5`})]})}export{c as _,_ as a,g as b,u as c,d,i as f,v as g,a as h,h as i,S as l,p as m,l as n,b as o,y as p,s as r,m as s,f as t,x as u,o as v,r as y};
|
|
2
|
+
//# sourceMappingURL=dock-icons-DPXFt10d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dock-icons-DPXFt10d.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/dock/dock-icons.tsx"],"sourcesContent":["/**\n * routes/verse/dock/dock-icons.tsx — the chat surface's own 16px glyphs\n * (unit C2): the dock's pane tabs and the header's pane toggles, the ⋯\n * menu, pin and archive. Same drawing grammar as components/primitives/icons\n * (16-unit box, 1.5 stroke, round caps, currentColor) so they sit beside the\n * shared set without looking borrowed; kept here because verse-icons.tsx is\n * the shell's file.\n */\nimport type { ReactNode, SVGProps } from 'react';\nimport type { BuiltinPaneId } from '../shell/dock-catalog.js';\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 ReviewGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M5 2.5v5M2.5 5h5M9 11h4.5\" /><path d=\"M11.5 2.5 4.5 13.5\" /></Glyph>;\n}\n\nexport function TasksGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M6.5 4h7M6.5 8h7M6.5 12h7\" /><path d=\"m2.25 4 1 1 1.5-2M2.5 8h1.75M2.5 12h1.75\" /></Glyph>;\n}\n\nexport function ContextGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"m8 2 6 3-6 3-6-3 6-3Z\" /><path d=\"m2 8 6 3 6-3M2 11l6 3 6-3\" /></Glyph>;\n}\n\nexport function SplitGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"2.25\" y=\"2.25\" width=\"11.5\" height=\"11.5\" rx=\"1.5\" /><path d=\"M2.25 8h11.5\" /></Glyph>;\n}\n\nexport function CloseGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"m4 4 8 8M12 4l-8 8\" /></Glyph>;\n}\n\nexport function MoreGlyph(p: GlyphProps) {\n return (\n <Glyph {...p}>\n <circle cx=\"3.5\" cy=\"8\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"8\" cy=\"8\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"12.5\" cy=\"8\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n </Glyph>\n );\n}\n\nexport function PinGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M9.75 2.25 13.75 6.25 11 7.5 8.5 10l.25 2.75-5-5L6.5 8 9 5.25Z\" /><path d=\"m5 11-2.75 2.75\" /></Glyph>;\n}\n\nexport function ArchiveGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"1.75\" y=\"2.75\" width=\"12.5\" height=\"3\" rx=\"1\" /><path d=\"M2.75 5.75v6.5a1 1 0 0 0 1 1h8.5a1 1 0 0 0 1-1v-6.5M6.5 8.5h3\" /></Glyph>;\n}\n\nexport function RenameGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M10.5 2.75 13.25 5.5 6 12.75H3.25V10Z\" /></Glyph>;\n}\n\nexport function HandoffGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M2.5 8h9M8.5 4.5 12 8l-3.5 3.5\" /><path d=\"M13.75 3v10\" /></Glyph>;\n}\n\nexport function CopyGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"5.25\" y=\"5.25\" width=\"8.5\" height=\"8.5\" rx=\"1.5\" /><path d=\"M10.75 5.25V3.75a1.5 1.5 0 0 0-1.5-1.5h-5.5a1.5 1.5 0 0 0-1.5 1.5v5.5a1.5 1.5 0 0 0 1.5 1.5h1.5\" /></Glyph>;\n}\n\nexport function TrashGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M2.75 4.25h10.5M6.25 4.25V2.75h3.5v1.5M4.25 4.25l.6 9h6.3l.6-9\" /></Glyph>;\n}\n\nexport function FilesGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M2.25 4.25a1.5 1.5 0 0 1 1.5-1.5h2.5l1.5 1.75h4.5a1.5 1.5 0 0 1 1.5 1.5v5.75a1.5 1.5 0 0 1-1.5 1.5h-8.5a1.5 1.5 0 0 1-1.5-1.5Z\" /></Glyph>;\n}\n\nexport function SourcesGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M3.25 2.75h6l3.5 3.5v7a1 1 0 0 1-1 1h-8.5a1 1 0 0 1-1-1v-9.5a1 1 0 0 1 1-1Z\" /><path d=\"M9 2.75v3.5h3.75M5 9h6M5 11.5h4\" /></Glyph>;\n}\n\nexport function ReasoningGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M6 13.25h4M6.5 11.25h3M8 1.75a4.25 4.25 0 0 0-2.4 7.76c.3.2.5.55.5.92v.82h3.8v-.82c0-.37.2-.72.5-.92A4.25 4.25 0 0 0 8 1.75Z\" /></Glyph>;\n}\n\n/** Focus mode: four corners closing in on the conversation. */\nexport function FocusGlyph(p: GlyphProps) {\n return <Glyph {...p}><path d=\"M2.25 5.5V3.25a1 1 0 0 1 1-1H5.5M10.5 2.25h2.25a1 1 0 0 1 1 1V5.5M13.75 10.5v2.25a1 1 0 0 1-1 1H10.5M5.5 13.75H3.25a1 1 0 0 1-1-1V10.5\" /></Glyph>;\n}\n\n/** The panel docked beside the chat. */\nexport function PanelRightGlyph(p: GlyphProps) {\n return <Glyph {...p}><rect x=\"1.75\" y=\"2.75\" width=\"12.5\" height=\"10.5\" rx=\"1.5\" /><path d=\"M9.75 2.75v10.5\" /></Glyph>;\n}\n\n/** The panel docked under the chat. */\nexport function PanelBottomGlyph(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 9.5h12.5\" /></Glyph>;\n}\n\nexport const DOCK_PANE_GLYPH: Readonly<Record<BuiltinPaneId, (p: GlyphProps) => ReactNode>> = {\n terminal: TerminalGlyph,\n browser: PreviewGlyph,\n diff: ReviewGlyph,\n files: FilesGlyph,\n sources: SourcesGlyph,\n reasoning: ReasoningGlyph,\n tasks: TasksGlyph,\n context: ContextGlyph,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,s as n}from"./index-_izD07R9.js";import{s as r}from"./tool-semantics-DtFU7rvB.js";import{c as i,i as a,n as o,t as s}from"./sources-queries-DCKiXNAt.js";import{n as c}from"./verse-transcript-Dc-bk9l2.js";import{t as l}from"./useVerseTranscript-CvUqjRmZ.js";import{n as u,t as d}from"./SourcesPanel-LyMp7aLt.js";import{a as f}from"./ChatSection-Cc6sudpF.js";var p=e(n(),1);function m(e,t=!0){let n=l(t?e:null),r=(0,p.useRef)({sessionId:e,cache:a()}),i=(0,p.useRef)({sessionId:e,turns:[]});return(0,p.useMemo)(()=>{if(!t)return i.current.sessionId===e?i.current.turns:[];r.current.sessionId!==e&&(r.current={sessionId:e,cache:a()});let s=o(c(n.items),r.current.cache).turns;return i.current={sessionId:e,turns:s},s},[n,t,e])}function h(e){let t=(0,p.useCallback)(async(t,n)=>{if(!e)throw Error(`no chat is open`);await s(e,t,n)},[e]),n=(0,p.useCallback)(e=>{f(r(e))},[]),a=(0,p.useCallback)(e=>{f(i(e))},[]);return(0,p.useMemo)(()=>({openFile:t,jumpToTool:n,jumpToTurn:a}),[t,n,a])}var g=t();function _({sessionId:e,session:t,visible:n,host:r}){let i=m(e,n),a=h(e),o=r.addToMessage,s=(0,p.useCallback)(e=>o(e),[o]);return(0,g.jsx)(d,{turns:i,session:t,...a,onCite:s})}function v({sessionId:e,session:t,visible:n}){let r=m(e,n),{jumpToTurn:i}=h(e);return(0,g.jsx)(u,{turns:r,engine:t?.engine??null,jumpToTurn:i})}export{v as ReasoningDockPane,_ as SourcesDockPane};
|
|
2
|
+
//# sourceMappingURL=dock-panes-DNSv-1Tq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dock-panes-DNSv-1Tq.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/reasoning/pane-data.ts","../../../../../../src/web-ui/routes/verse/reasoning/dock-panes.tsx"],"sourcesContent":["/**\n * routes/verse/reasoning/pane-data.ts — what a Sources / Reasoning pane needs\n * when it is mounted OUTSIDE the transcript (a dock pane, a split), from\n * nothing but the session id.\n *\n * Turns are derived with the same pipeline the transcript uses\n * (groupTranscriptItems → buildTurns) over the same memoized transcript, with\n * a per-hook TurnCache so a streamed token re-derives only the live turn.\n * Jumps go through the transcript's own bus (chat/transcript-jump.ts), so a\n * click in a pane lands on the call or turn with the same reveal machinery\n * (opening a folded activity group, the locator flash).\n */\nimport { useCallback, useMemo, useRef } from 'react';\nimport { requestTranscriptJump } from '../chat/transcript-jump.js';\nimport { toolAnchorId } from '../chat/tool-semantics.js';\nimport { buildTurns, createTurnCache, turnAnchorId, type TurnBlock, type TurnCache } from '../chat/turn-model.js';\nimport { useVerseTranscript } from '../useVerseTranscript.js';\nimport { groupTranscriptItems } from '../verse-transcript.js';\nimport { openSourceFile } from './sources-queries.js';\n\n/**\n * The chat's turns. `active: false` (a pane kept alive behind another tab)\n * unsubscribes from the stream and keeps the last turns it derived, so a\n * hidden pane does no work per token; it catches up when shown again.\n */\nexport function useChatTurns(sessionId: string | null, active = true): TurnBlock[] {\n const transcript = useVerseTranscript(active ? sessionId : null);\n const cache = useRef<{ sessionId: string | null; cache: TurnCache }>({ sessionId, cache: createTurnCache() });\n const last = useRef<{ sessionId: string | null; turns: TurnBlock[] }>({ sessionId, turns: [] });\n return useMemo(() => {\n if (!active) return last.current.sessionId === sessionId ? last.current.turns : [];\n if (cache.current.sessionId !== sessionId) cache.current = { sessionId, cache: createTurnCache() };\n const turns = buildTurns(groupTranscriptItems(transcript.items), cache.current.cache).turns;\n last.current = { sessionId, turns };\n return turns;\n }, [transcript, active, sessionId]);\n}\n\nexport interface PaneActions {\n openFile: (path: string, line: number | undefined) => Promise<void>;\n jumpToTool: (toolUseId: string) => void;\n jumpToTurn: (turnKey: string) => void;\n}\n\nexport function usePaneActions(sessionId: string | null): PaneActions {\n const openFile = useCallback(async (path: string, line: number | undefined) => {\n if (!sessionId) throw new Error('no chat is open');\n await openSourceFile(sessionId, path, line);\n }, [sessionId]);\n const jumpToTool = useCallback((toolUseId: string) => { requestTranscriptJump(toolAnchorId(toolUseId)); }, []);\n const jumpToTurn = useCallback((turnKey: string) => { requestTranscriptJump(turnAnchorId(turnKey)); }, []);\n return useMemo(() => ({ openFile, jumpToTool, jumpToTurn }), [openFile, jumpToTool, jumpToTurn]);\n}\n","/**\n * routes/verse/reasoning/dock-panes.tsx — the Sources and Reasoning panels as\n * registry panes (reasoning.pane.tsx registers them).\n *\n * Adapters only: the panels are presentational over derived turns\n * (SourcesPanel / ReasoningPanel); this is where the dock's PaneProps meet\n * them. A pane kept alive behind another tab (`visible: false`) stops\n * following the stream and keeps what it last showed, so a hidden pane costs\n * nothing per token.\n */\nimport { useCallback } from 'react';\nimport type { PaneProps } from '../panes/pane-registry.js';\nimport { useChatTurns, usePaneActions } from './pane-data.js';\nimport { ReasoningPanel } from './ReasoningPanel.js';\nimport { SourcesPanel } from './SourcesPanel.js';\n\nexport function SourcesDockPane({ sessionId, session, visible, host }: PaneProps) {\n const turns = useChatTurns(sessionId, visible);\n const actions = usePaneActions(sessionId);\n const addToMessage = host.addToMessage;\n const onCite = useCallback((text: string) => addToMessage(text), [addToMessage]);\n return <SourcesPanel turns={turns} session={session} {...actions} onCite={onCite} />;\n}\n\nexport function ReasoningDockPane({ sessionId, session, visible }: PaneProps) {\n const turns = useChatTurns(sessionId, visible);\n const { jumpToTurn } = usePaneActions(sessionId);\n return <ReasoningPanel turns={turns} engine={session?.engine ?? null} jumpToTurn={jumpToTurn} />;\n}\n"],"mappings":"qbAyBA,SAAgB,EAAa,EAA0B,EAAS,GAAmB,CACjF,IAAM,EAAa,EAAmB,EAAS,EAAY,IAAI,EACzD,GAAA,EAAQ,EAAA,OAAA,CAAuD,CAAE,YAAW,MAAO,EAAgB,CAAE,CAAC,EACtG,GAAA,EAAO,EAAA,OAAA,CAAyD,CAAE,YAAW,MAAO,CAAC,CAAE,CAAC,EAC9F,OAAA,EAAO,EAAA,QAAA,KAAc,CACnB,GAAI,CAAC,EAAQ,OAAO,EAAK,QAAQ,YAAc,EAAY,EAAK,QAAQ,MAAQ,CAAC,EAC7E,EAAM,QAAQ,YAAc,IAAW,EAAM,QAAU,CAAE,YAAW,MAAO,EAAgB,CAAE,GACjG,IAAM,EAAQ,EAAW,EAAqB,EAAW,KAAK,EAAG,EAAM,QAAQ,KAAK,CAAC,CAAC,MAEtF,MADA,GAAK,QAAU,CAAE,YAAW,OAAM,EAC3B,CACT,EAAG,CAAC,EAAY,EAAQ,CAAS,CAAC,CACpC,CAQA,SAAgB,EAAe,EAAuC,CACpE,IAAM,GAAA,EAAW,EAAA,YAAA,CAAY,MAAO,EAAc,IAA6B,CAC7E,GAAI,CAAC,EAAW,MAAU,MAAM,iBAAiB,EACjD,MAAM,EAAe,EAAW,EAAM,CAAI,CAC5C,EAAG,CAAC,CAAS,CAAC,EACR,GAAA,EAAa,EAAA,YAAA,CAAa,GAAsB,CAAE,EAAsB,EAAa,CAAS,CAAC,CAAG,EAAG,CAAC,CAAC,EACvG,GAAA,EAAa,EAAA,YAAA,CAAa,GAAoB,CAAE,EAAsB,EAAa,CAAO,CAAC,CAAG,EAAG,CAAC,CAAC,EACzG,OAAA,EAAO,EAAA,QAAA,MAAe,CAAE,WAAU,aAAY,YAAW,GAAI,CAAC,EAAU,EAAY,CAAU,CAAC,CACjG,WCpCA,SAAgB,EAAgB,CAAE,YAAW,UAAS,UAAS,QAAmB,CAChF,IAAM,EAAQ,EAAa,EAAW,CAAO,EACvC,EAAU,EAAe,CAAS,EAClC,EAAe,EAAK,aACpB,GAAA,EAAS,EAAA,YAAA,CAAa,GAAiB,EAAa,CAAI,EAAG,CAAC,CAAY,CAAC,EAC/E,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAqB,QAAgB,UAAS,GAAI,EAAiB,QAAS,CAAA,CACrF,CAEA,SAAgB,EAAkB,CAAE,YAAW,UAAS,WAAsB,CAC5E,IAAM,EAAQ,EAAa,EAAW,CAAO,EACvC,CAAE,cAAe,EAAe,CAAS,EAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAuB,QAAO,OAAQ,GAAS,QAAU,KAAkB,YAAa,CAAA,CACjG"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{C as e,M as t,V as n,a as r,i}from"./global-CYfRwH6t.js";import{O as a}from"./VerseShared-CFE5B-IY.js";import{n as o}from"./control-queries-C5uQTzJi.js";import{n as s,u as c}from"./surface-data-NFl_uS--.js";var l=`/api/verse/fleet/control`,u=`/api/verse/fleet/control/queue`,d=`/api/verse/leader/directives`,f=Object.freeze({state:`verse-fleet-control`,queue:`verse-fleet-control-queue`});function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){return p(e)&&e.v===1&&typeof e.state==`string`&&typeof e.headline==`string`&&p(e.controls)&&p(e.grant)&&p(e.daemon)?e:null}function h(e){return p(e)&&e.v===1&&Array.isArray(e.tasks)&&Array.isArray(e.goals)&&p(e.targets)?e:null}var g=c(f.state,l,`The fleet controls`,m),_=c(f.queue,u,`The fleet queue`,h);async function v(n,i){let a=e();if(!a)throw new o;let s=await r(n,i,a);return t(),s}async function y(e){let t=await v(l,e);return n(f.state),n(f.queue),n(s.fleetLive),n(s.authority),a(),t}async function b(e,t){return i(`${l}/runs/${encodeURIComponent(e)}/log`,t)}async function x(e){let t=await v(d,{text:e});return n(s.leader),t}export{x as a,y as i,g as n,_ as r,b as t};
|
|
2
|
+
//# sourceMappingURL=fleet-control-queries-DZEa-aFz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-control-queries-DZEa-aFz.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/fleet/fleet-control-queries.ts"],"sourcesContent":["/**\n * routes/verse/fleet/fleet-control-queries.ts — reads and writes behind the\n * Fleet control surface (3.15):\n *\n * GET /api/verse/fleet/control FleetControlStateV1\n * GET /api/verse/fleet/control/queue FleetControlQueueV1\n * GET /api/verse/fleet/control/runs/<id>/log FleetRunLogV1\n * POST /api/verse/fleet/control one FleetControlAction\n * POST /api/verse/leader/directives a Leader directive\n *\n * Reads are optional like every surface read (a server without the route is\n * \"not available here\", never a broken page). Writes pull the held mutation\n * token and invalidate exactly what they change.\n */\nimport { apiGet, apiPost } from '../../../data/client.js';\nimport { getMutationToken, touchMutationHold } from '../../../data/auth-store.js';\nimport { invalidate } from '../../../data/cache.js';\nimport { VerseControlLockedError } from '../autonomy/control-queries.js';\nimport { refreshActivity } from '../shell/useActivity.js';\nimport { SURFACE_KEYS, optionalQuery } from '../command/surface-data.js';\nimport type {\n FleetControlAction,\n FleetControlActionResultV1,\n FleetControlQueueV1,\n FleetControlStateV1,\n FleetRunLogV1,\n} from '../../../../core/fleet/fleet-control-types.js';\n\nexport const FLEET_CONTROL_PATH = '/api/verse/fleet/control';\nexport const FLEET_CONTROL_QUEUE_PATH = '/api/verse/fleet/control/queue';\nexport const LEADER_DIRECTIVES_PATH = '/api/verse/leader/directives';\n\nexport const FLEET_CONTROL_KEYS = Object.freeze({\n state: 'verse-fleet-control',\n queue: 'verse-fleet-control-queue',\n});\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function narrowFleetControl(raw: unknown): FleetControlStateV1 | null {\n return isRecord(raw) && raw['v'] === 1 && typeof raw['state'] === 'string' && typeof raw['headline'] === 'string'\n && isRecord(raw['controls']) && isRecord(raw['grant']) && isRecord(raw['daemon'])\n ? (raw as unknown as FleetControlStateV1)\n : null;\n}\n\nexport function narrowFleetQueue(raw: unknown): FleetControlQueueV1 | null {\n return isRecord(raw) && raw['v'] === 1 && Array.isArray(raw['tasks']) && Array.isArray(raw['goals']) && isRecord(raw['targets'])\n ? (raw as unknown as FleetControlQueueV1)\n : null;\n}\n\nexport const fleetControlQuery = optionalQuery(FLEET_CONTROL_KEYS.state, FLEET_CONTROL_PATH, 'The fleet controls', narrowFleetControl);\nexport const fleetQueueQuery = optionalQuery(FLEET_CONTROL_KEYS.queue, FLEET_CONTROL_QUEUE_PATH, 'The fleet queue', narrowFleetQueue);\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseControlLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\n/** One control action; the answer carries the state READ BACK after it. */\nexport async function postFleetControl(action: FleetControlAction): Promise<FleetControlActionResultV1> {\n const result = await post<FleetControlActionResultV1>(FLEET_CONTROL_PATH, action);\n invalidate(FLEET_CONTROL_KEYS.state);\n invalidate(FLEET_CONTROL_KEYS.queue);\n invalidate(SURFACE_KEYS.fleetLive);\n invalidate(SURFACE_KEYS.authority);\n void refreshActivity();\n return result;\n}\n\nexport async function fetchRunLog(runId: string, signal?: AbortSignal): Promise<FleetRunLogV1> {\n return apiGet<FleetRunLogV1>(`${FLEET_CONTROL_PATH}/runs/${encodeURIComponent(runId)}/log`, signal);\n}\n\nexport async function postLeaderDirective(text: string): Promise<unknown> {\n const result = await post<unknown>(LEADER_DIRECTIVES_PATH, { text });\n invalidate(SURFACE_KEYS.leader);\n return result;\n}\n"],"mappings":"sNA4BA,IAAa,EAAqB,2BACrB,EAA2B,iCAC3B,EAAyB,+BAEzB,EAAqB,OAAO,OAAO,CAC9C,MAAO,sBACP,MAAO,2BACT,CAAC,EAED,SAAS,EAAS,EAAkD,CAClE,OAAyB,OAAO,GAAU,YAAnC,GAA+C,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,SAAgB,EAAmB,EAA0C,CAC3E,OAAO,EAAS,CAAG,GAAK,EAAI,IAAS,GAAK,OAAO,EAAI,OAAa,UAAY,OAAO,EAAI,UAAgB,UACpG,EAAS,EAAI,QAAW,GAAK,EAAS,EAAI,KAAQ,GAAK,EAAS,EAAI,MAAS,EAC7E,EACD,IACN,CAEA,SAAgB,EAAiB,EAA0C,CACzE,OAAO,EAAS,CAAG,GAAK,EAAI,IAAS,GAAK,MAAM,QAAQ,EAAI,KAAQ,GAAK,MAAM,QAAQ,EAAI,KAAQ,GAAK,EAAS,EAAI,OAAU,EAC1H,EACD,IACN,CAEA,IAAa,EAAoB,EAAc,EAAmB,MAAO,EAAoB,qBAAsB,CAAkB,EACxH,EAAkB,EAAc,EAAmB,MAAO,EAA0B,kBAAmB,CAAgB,EAEpI,eAAe,EAAQ,EAAc,EAA2B,CAC9D,IAAM,EAAQ,EAAiB,EAC/B,GAAI,CAAC,EAAO,MAAM,IAAI,EACtB,IAAM,EAAS,MAAM,EAAW,EAAM,EAAM,CAAK,EAEjD,OADA,EAAkB,EACX,CACT,CAGA,eAAsB,EAAiB,EAAiE,CACtG,IAAM,EAAS,MAAM,EAAiC,EAAoB,CAAM,EAMhF,OALA,EAAW,EAAmB,KAAK,EACnC,EAAW,EAAmB,KAAK,EACnC,EAAW,EAAa,SAAS,EACjC,EAAW,EAAa,SAAS,EACjC,EAAqB,EACd,CACT,CAEA,eAAsB,EAAY,EAAe,EAA8C,CAC7F,OAAO,EAAsB,GAAG,EAAmB,QAAQ,mBAAmB,CAAK,EAAE,MAAO,CAAM,CACpG,CAEA,eAAsB,EAAoB,EAAgC,CACxE,IAAM,EAAS,MAAM,EAAc,EAAwB,CAAE,MAAK,CAAC,EAEnE,OADA,EAAW,EAAa,MAAM,EACvB,CACT"}
|