@ashlr/hub 3.22.0 → 3.22.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 +27 -0
- package/README.md +5 -5
- package/dist/authority-surface.json +16 -11
- package/dist/build-identity.json +2 -2
- package/dist/cli/verify-safety-sources.d.ts +4 -0
- package/dist/cli/verify-safety-sources.js +41 -0
- package/dist/cli/verify-safety-sources.js.map +1 -0
- package/dist/cli/verify-safety.js +16 -1
- package/dist/cli/verify-safety.js.map +1 -1
- package/dist/core/decide/needs-you.d.ts +3 -1
- package/dist/core/decide/needs-you.js +52 -28
- package/dist/core/decide/needs-you.js.map +1 -1
- package/dist/core/fleet/fleet-control-model.d.ts +2 -1
- package/dist/core/fleet/fleet-control-model.js +5 -0
- package/dist/core/fleet/fleet-control-model.js.map +1 -1
- package/dist/core/fleet/fleet-control-types.d.ts +11 -1
- package/dist/core/fleet/fleet-control.d.ts +4 -0
- package/dist/core/fleet/fleet-control.js +23 -1
- package/dist/core/fleet/fleet-control.js.map +1 -1
- package/dist/core/fleet/quota.js +1 -1
- package/dist/core/fleet/quota.js.map +1 -1
- package/dist/core/universe/builtins/preparation/manifest.json +1 -1
- package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +4 -2
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +3 -1
- package/dist/core/web/public/next/assets/ActionMenu-Z14OhnFI.js +2 -0
- package/dist/core/web/public/next/assets/ActionMenu-Z14OhnFI.js.map +1 -0
- package/dist/core/web/public/next/assets/Advanced-fUyq-fpH.js +2 -0
- package/dist/core/web/public/next/assets/Advanced-fUyq-fpH.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentDetailScreen-C8h--Nah.js +2 -0
- package/dist/core/web/public/next/assets/AgentDetailScreen-C8h--Nah.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentToolsSheet-BP3h-UbZ.js +2 -0
- package/dist/core/web/public/next/assets/AgentToolsSheet-BP3h-UbZ.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentToolsStrip--hf18knJ.js +2 -0
- package/dist/core/web/public/next/assets/AgentToolsStrip--hf18knJ.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentsScreen-BR-j0Fzd.js +2 -0
- package/dist/core/web/public/next/assets/AgentsScreen-BR-j0Fzd.js.map +1 -0
- package/dist/core/web/public/next/assets/AgentsSection-OKKOuYed.js +3 -0
- package/dist/core/web/public/next/assets/AgentsSection-OKKOuYed.js.map +1 -0
- package/dist/core/web/public/next/assets/App-ttVrZYp5.js +8 -0
- package/dist/core/web/public/next/assets/App-ttVrZYp5.js.map +1 -0
- package/dist/core/web/public/next/assets/AppsSection-sqsXqENO.js +2 -0
- package/dist/core/web/public/next/assets/AppsSection-sqsXqENO.js.map +1 -0
- package/dist/core/web/public/next/assets/AreaTrend-LVgaB49b.js +2 -0
- package/dist/core/web/public/next/assets/AreaTrend-LVgaB49b.js.map +1 -0
- package/dist/core/web/public/next/assets/AutomationsSection-BITmxjuB.js +2 -0
- package/dist/core/web/public/next/assets/AutomationsSection-BITmxjuB.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-nO9lIcCv.js +3 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-nO9lIcCv.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-DWYUPDP6.js +2 -0
- package/dist/core/web/public/next/assets/AutonomySection-DWYUPDP6.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyStatus-C4Yp1JTY.js +2 -0
- package/dist/core/web/public/next/assets/AutonomyStatus-C4Yp1JTY.js.map +1 -0
- package/dist/core/web/public/next/assets/BranchBar-CkiZSNqB.js +2 -0
- package/dist/core/web/public/next/assets/BranchBar-CkiZSNqB.js.map +1 -0
- package/dist/core/web/public/next/assets/BrowserPanel-CECVGJBS.js +7 -0
- package/dist/core/web/public/next/assets/BrowserPanel-CECVGJBS.js.map +1 -0
- package/dist/core/web/public/next/assets/BudgetControl-De1TPzvX.js +2 -0
- package/dist/core/web/public/next/assets/BudgetControl-De1TPzvX.js.map +1 -0
- package/dist/core/web/public/next/assets/Button-CstSJwha.js +2 -0
- package/dist/core/web/public/next/assets/Button-CstSJwha.js.map +1 -0
- package/dist/core/web/public/next/assets/CapacityStrip-nIJcB_lA.js +2 -0
- package/dist/core/web/public/next/assets/CapacityStrip-nIJcB_lA.js.map +1 -0
- package/dist/core/web/public/next/assets/ChangesPaneHost-Bnj_NcRa.js +16 -0
- package/dist/core/web/public/next/assets/ChangesPaneHost-Bnj_NcRa.js.map +1 -0
- package/dist/core/web/public/next/assets/ChartFrame-Dljee9y6.js +2 -0
- package/dist/core/web/public/next/assets/ChartFrame-Dljee9y6.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatPanes-x_ySUIyR.js +2 -0
- package/dist/core/web/public/next/assets/ChatPanes-x_ySUIyR.js.map +1 -0
- package/dist/core/web/public/next/assets/ChatSection-CXJa8QOi.js +3 -0
- package/dist/core/web/public/next/assets/ChatSection-CXJa8QOi.js.map +1 -0
- package/dist/core/web/public/next/assets/ChecksPanel-D9r8koxq.js +5 -0
- package/dist/core/web/public/next/assets/ChecksPanel-D9r8koxq.js.map +1 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-D5ajpoMe.js +2 -0
- package/dist/core/web/public/next/assets/CloudBudgetForm-D5ajpoMe.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandPalette-ONyqYZzt.js +3 -0
- package/dist/core/web/public/next/assets/CommandPalette-ONyqYZzt.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandSection-DxNIibnI.js +3 -0
- package/dist/core/web/public/next/assets/CommandSection-DxNIibnI.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandWorkflowForm-Bz3PuZXH.js +9 -0
- package/dist/core/web/public/next/assets/CommandWorkflowForm-Bz3PuZXH.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-COVyeer0.js +3 -0
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-COVyeer0.js.map +1 -0
- package/dist/core/web/public/next/assets/CompareDialog-PVqv0Tx9.js +4 -0
- package/dist/core/web/public/next/assets/CompareDialog-PVqv0Tx9.js.map +1 -0
- package/dist/core/web/public/next/assets/ComputerControl-DkSIUrYm.js +2 -0
- package/dist/core/web/public/next/assets/ComputerControl-DkSIUrYm.js.map +1 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-CdCzzk0I.js +2 -0
- package/dist/core/web/public/next/assets/ConfirmDialog-CdCzzk0I.js.map +1 -0
- package/dist/core/web/public/next/assets/DeleteChatDialog-BTzOgqho.js +2 -0
- package/dist/core/web/public/next/assets/DeleteChatDialog-BTzOgqho.js.map +1 -0
- package/dist/core/web/public/next/assets/DevinStopDialog-CGsDqfan.js +2 -0
- package/dist/core/web/public/next/assets/DevinStopDialog-CGsDqfan.js.map +1 -0
- package/dist/core/web/public/next/assets/Dialog-DDHg9cuT.js +2 -0
- package/dist/core/web/public/next/assets/Dialog-DDHg9cuT.js.map +1 -0
- package/dist/core/web/public/next/assets/DiffPane-BR3HU7pC.js +2 -0
- package/dist/core/web/public/next/assets/DiffPane-BR3HU7pC.js.map +1 -0
- package/dist/core/web/public/next/assets/DiffViewer-hJK75qko.js +2 -0
- package/dist/core/web/public/next/assets/DiffViewer-hJK75qko.js.map +1 -0
- package/dist/core/web/public/next/assets/DockHost-DhOosHbo.js +2 -0
- package/dist/core/web/public/next/assets/DockHost-DhOosHbo.js.map +1 -0
- package/dist/core/web/public/next/assets/EmptyState-CGVr0VO2.js +2 -0
- package/dist/core/web/public/next/assets/EmptyState-CGVr0VO2.js.map +1 -0
- package/dist/core/web/public/next/assets/Epistemic-tp0ZNAKZ.js +2 -0
- package/dist/core/web/public/next/assets/Epistemic-tp0ZNAKZ.js.map +1 -0
- package/dist/core/web/public/next/assets/EvidenceTimeline-YmKIoxNx.js +2 -0
- package/dist/core/web/public/next/assets/EvidenceTimeline-YmKIoxNx.js.map +1 -0
- package/dist/core/web/public/next/assets/FilesPane-CoNjfkPP.js +2 -0
- package/dist/core/web/public/next/assets/FilesPane-CoNjfkPP.js.map +1 -0
- package/dist/core/web/public/next/assets/FleetScreen-CstwycnB.js +2 -0
- package/dist/core/web/public/next/assets/FleetScreen-CstwycnB.js.map +1 -0
- package/dist/core/web/public/next/assets/FleetSection-D0xk0s5J.js +5 -0
- package/dist/core/web/public/next/assets/FleetSection-D0xk0s5J.js.map +1 -0
- package/dist/core/web/public/next/assets/Funnel-UPrk7fcy.js +2 -0
- package/dist/core/web/public/next/assets/Funnel-UPrk7fcy.js.map +1 -0
- package/dist/core/web/public/next/assets/GearTray-BSjga1J_.js +2 -0
- package/dist/core/web/public/next/assets/GearTray-BSjga1J_.js.map +1 -0
- package/dist/core/web/public/next/assets/GitDialogs-ekwzxl76.js +2 -0
- package/dist/core/web/public/next/assets/GitDialogs-ekwzxl76.js.map +1 -0
- package/dist/core/web/public/next/assets/GrowthSection-Dh-gnkgc.js +3 -0
- package/dist/core/web/public/next/assets/GrowthSection-Dh-gnkgc.js.map +1 -0
- package/dist/core/web/public/next/assets/HandoffDialog-BDiyA3u-.js +2 -0
- package/dist/core/web/public/next/assets/HandoffDialog-BDiyA3u-.js.map +1 -0
- package/dist/core/web/public/next/assets/HomeBody-Ce3HBIEb.js +3 -0
- package/dist/core/web/public/next/assets/HomeBody-Ce3HBIEb.js.map +1 -0
- package/dist/core/web/public/next/assets/HomeSeats-BFLCWCFp.js +2 -0
- package/dist/core/web/public/next/assets/HomeSeats-BFLCWCFp.js.map +1 -0
- package/dist/core/web/public/next/assets/Input-Cpn9uYj2.js +2 -0
- package/dist/core/web/public/next/assets/Input-Cpn9uYj2.js.map +1 -0
- package/dist/core/web/public/next/assets/LaunchDialog-CrPEf652.js +9 -0
- package/dist/core/web/public/next/assets/LaunchDialog-CrPEf652.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderCard-Dhq-w_Mf.js +2 -0
- package/dist/core/web/public/next/assets/LeaderCard-Dhq-w_Mf.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderConversation-CiWqhsoa.js +3 -0
- package/dist/core/web/public/next/assets/LeaderConversation-CiWqhsoa.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderScreen-Z5KPjxBV.js +2 -0
- package/dist/core/web/public/next/assets/LeaderScreen-Z5KPjxBV.js.map +1 -0
- package/dist/core/web/public/next/assets/LessonsPanel-B6XVKAPE.js +2 -0
- package/dist/core/web/public/next/assets/LessonsPanel-B6XVKAPE.js.map +1 -0
- package/dist/core/web/public/next/assets/LiveTimer-B8t2iX5h.js +2 -0
- package/dist/core/web/public/next/assets/LiveTimer-B8t2iX5h.js.map +1 -0
- package/dist/core/web/public/next/assets/LocalSeatBadge-HMxIrMiL.js +2 -0
- package/dist/core/web/public/next/assets/LocalSeatBadge-HMxIrMiL.js.map +1 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-BlFI5oao.js +2 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-BlFI5oao.js.map +1 -0
- package/dist/core/web/public/next/assets/McpSection-snZNKexW.js +2 -0
- package/dist/core/web/public/next/assets/McpSection-snZNKexW.js.map +1 -0
- package/dist/core/web/public/next/assets/MessageMarkdown-CS0mAtSs.js +3 -0
- package/dist/core/web/public/next/assets/MessageMarkdown-CS0mAtSs.js.map +1 -0
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-D5R-zr-W.js +72 -0
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-D5R-zr-W.js.map +1 -0
- package/dist/core/web/public/next/assets/Meter-VXI75VNe.js +2 -0
- package/dist/core/web/public/next/assets/Meter-VXI75VNe.js.map +1 -0
- package/dist/core/web/public/next/assets/MicButton-DORAXsUU.js +2 -0
- package/dist/core/web/public/next/assets/MicButton-DORAXsUU.js.map +1 -0
- package/dist/core/web/public/next/assets/MindSection-DZLHz29Q.js +3 -0
- package/dist/core/web/public/next/assets/MindSection-DZLHz29Q.js.map +1 -0
- package/dist/core/web/public/next/assets/MobileComposer-B8nWsIJO.js +2 -0
- package/dist/core/web/public/next/assets/MobileComposer-B8nWsIJO.js.map +1 -0
- package/dist/core/web/public/next/assets/MobileGuardSheet-BRwOfD9o.js +2 -0
- package/dist/core/web/public/next/assets/MobileGuardSheet-BRwOfD9o.js.map +1 -0
- package/dist/core/web/public/next/assets/MobileRuntime-kMob_MjB.js +3 -0
- package/dist/core/web/public/next/assets/MobileRuntime-kMob_MjB.js.map +1 -0
- package/dist/core/web/public/next/assets/MoreScreen-92dC6Bj7.js +2 -0
- package/dist/core/web/public/next/assets/MoreScreen-92dC6Bj7.js.map +1 -0
- package/dist/core/web/public/next/assets/MultiModelBar-BhAUUQOq.js +7 -0
- package/dist/core/web/public/next/assets/MultiModelBar-BhAUUQOq.js.map +1 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-DlY2VLVh.js +2 -0
- package/dist/core/web/public/next/assets/MutationTokenDialog-DlY2VLVh.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-BH0ffbht.js +3 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-BH0ffbht.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouList-CI_Dy-hi.js +2 -0
- package/dist/core/web/public/next/assets/NeedsYouList-CI_Dy-hi.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouScreen-CvDiEphJ.js +2 -0
- package/dist/core/web/public/next/assets/NeedsYouScreen-CvDiEphJ.js.map +1 -0
- package/dist/core/web/public/next/assets/NewAgentScreen-BpTRKp9z.js +2 -0
- package/dist/core/web/public/next/assets/NewAgentScreen-BpTRKp9z.js.map +1 -0
- package/dist/core/web/public/next/assets/NewChatDialog-O1LwwBc4.js +4 -0
- package/dist/core/web/public/next/assets/NewChatDialog-O1LwwBc4.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-uMNBVHvK.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-uMNBVHvK.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingGate-sdzxSPZF.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingGate-sdzxSPZF.js.map +1 -0
- package/dist/core/web/public/next/assets/PlaybooksSection-CnWfwZv8.js +9 -0
- package/dist/core/web/public/next/assets/PlaybooksSection-CnWfwZv8.js.map +1 -0
- package/dist/core/web/public/next/assets/PreviewPane-D1WaefIG.js +2 -0
- package/dist/core/web/public/next/assets/PreviewPane-D1WaefIG.js.map +1 -0
- package/dist/core/web/public/next/assets/ProviderLogo-g2YWCmNY.js +2 -0
- package/dist/core/web/public/next/assets/ProviderLogo-g2YWCmNY.js.map +1 -0
- package/dist/core/web/public/next/assets/RailStatus-OrvAuyzs.js +2 -0
- package/dist/core/web/public/next/assets/RailStatus-OrvAuyzs.js.map +1 -0
- package/dist/core/web/public/next/assets/ReasoningPane-BARDPl4-.js +2 -0
- package/dist/core/web/public/next/assets/ReasoningPane-BARDPl4-.js.map +1 -0
- package/dist/core/web/public/next/assets/ReasoningSheet-rPTXyt-b.js +2 -0
- package/dist/core/web/public/next/assets/ReasoningSheet-rPTXyt-b.js.map +1 -0
- package/dist/core/web/public/next/assets/RefreshIndicator-D96C9qiH.js +2 -0
- package/dist/core/web/public/next/assets/RefreshIndicator-D96C9qiH.js.map +1 -0
- package/dist/core/web/public/next/assets/RemoteMobileApp-DfDjiBTR.js +2 -0
- package/dist/core/web/public/next/assets/RemoteMobileApp-DfDjiBTR.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-CcfULh_p.js +7 -0
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-CcfULh_p.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-DuEa7WOo.css +1 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-e9ifgnWf.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-e9ifgnWf.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DOv_mxpe.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DOv_mxpe.js.map +1 -0
- package/dist/core/web/public/next/assets/ReviewMenu-Ba3saQlX.js +2 -0
- package/dist/core/web/public/next/assets/ReviewMenu-Ba3saQlX.js.map +1 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-BaJ1ZePy.js +2 -0
- package/dist/core/web/public/next/assets/RouteErrorBoundary-BaJ1ZePy.js.map +1 -0
- package/dist/core/web/public/next/assets/RunInCloudAction-DRSX84Jy.js +2 -0
- package/dist/core/web/public/next/assets/RunInCloudAction-DRSX84Jy.js.map +1 -0
- package/dist/core/web/public/next/assets/RunInDevinAction-BMji-YN2.js +2 -0
- package/dist/core/web/public/next/assets/RunInDevinAction-BMji-YN2.js.map +1 -0
- package/dist/core/web/public/next/assets/SchedulingEvidence-xxjV6HF_.js +2 -0
- package/dist/core/web/public/next/assets/SchedulingEvidence-xxjV6HF_.js.map +1 -0
- package/dist/core/web/public/next/assets/ScreenHost-Dv6z76Ta.js +3 -0
- package/dist/core/web/public/next/assets/ScreenHost-Dv6z76Ta.js.map +1 -0
- package/dist/core/web/public/next/assets/SeatSelector-YRNdNpP8.js +3 -0
- package/dist/core/web/public/next/assets/SeatSelector-YRNdNpP8.js.map +1 -0
- package/dist/core/web/public/next/assets/Segmented-BA8RmKYq.js +2 -0
- package/dist/core/web/public/next/assets/Segmented-BA8RmKYq.js.map +1 -0
- package/dist/core/web/public/next/assets/Select-B8GqZOX9.js +2 -0
- package/dist/core/web/public/next/assets/Select-B8GqZOX9.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionGate-CnASHl7g.js +2 -0
- package/dist/core/web/public/next/assets/SessionGate-CnASHl7g.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionInsightChip-DIKfih6i.js +2 -0
- package/dist/core/web/public/next/assets/SessionInsightChip-DIKfih6i.js.map +1 -0
- package/dist/core/web/public/next/assets/SessionSearch-K6lvMlji.js +2 -0
- package/dist/core/web/public/next/assets/SessionSearch-K6lvMlji.js.map +1 -0
- package/dist/core/web/public/next/assets/SettingsSection-C-c3f_6J.js +2 -0
- package/dist/core/web/public/next/assets/SettingsSection-C-c3f_6J.js.map +1 -0
- package/dist/core/web/public/next/assets/SetupChecklist-DAbAdrX4.js +2 -0
- package/dist/core/web/public/next/assets/SetupChecklist-DAbAdrX4.js.map +1 -0
- package/dist/core/web/public/next/assets/ShadowDecisions-C41uRSw4.js +3 -0
- package/dist/core/web/public/next/assets/ShadowDecisions-C41uRSw4.js.map +1 -0
- package/dist/core/web/public/next/assets/Sheet-Bk64-Hlt.js +2 -0
- package/dist/core/web/public/next/assets/Sheet-Bk64-Hlt.js.map +1 -0
- package/dist/core/web/public/next/assets/ShortcutsOverlay-CcP96zqy.js +2 -0
- package/dist/core/web/public/next/assets/ShortcutsOverlay-CcP96zqy.js.map +1 -0
- package/dist/core/web/public/next/assets/Sidebar-sSNKd57n.js +3 -0
- package/dist/core/web/public/next/assets/Sidebar-sSNKd57n.js.map +1 -0
- package/dist/core/web/public/next/assets/SkipToContent-BynsXs9i.js +2 -0
- package/dist/core/web/public/next/assets/SkipToContent-BynsXs9i.js.map +1 -0
- package/dist/core/web/public/next/assets/Slider-DS5HrVzl.js +2 -0
- package/dist/core/web/public/next/assets/Slider-DS5HrVzl.js.map +1 -0
- package/dist/core/web/public/next/assets/SourcesPane-QffcyDfA.js +2 -0
- package/dist/core/web/public/next/assets/SourcesPane-QffcyDfA.js.map +1 -0
- package/dist/core/web/public/next/assets/SourcesPanel-DlttePk7.js +2 -0
- package/dist/core/web/public/next/assets/SourcesPanel-DlttePk7.js.map +1 -0
- package/dist/core/web/public/next/assets/StatTile-mYm1GPj7.js +2 -0
- package/dist/core/web/public/next/assets/StatTile-mYm1GPj7.js.map +1 -0
- package/dist/core/web/public/next/assets/StatusBadge-Yz7S3kZ2.js +2 -0
- package/dist/core/web/public/next/assets/StatusBadge-Yz7S3kZ2.js.map +1 -0
- package/dist/core/web/public/next/assets/StepBand-Bdkv7iGd.js +2 -0
- package/dist/core/web/public/next/assets/StepBand-Bdkv7iGd.js.map +1 -0
- package/dist/core/web/public/next/assets/Surface-DVOAKl2g.js +2 -0
- package/dist/core/web/public/next/assets/Surface-DVOAKl2g.js.map +1 -0
- package/dist/core/web/public/next/assets/Swimlane-CeMBD_FC.js +2 -0
- package/dist/core/web/public/next/assets/Swimlane-CeMBD_FC.js.map +1 -0
- package/dist/core/web/public/next/assets/Switch-Cqc_bSoh.js +2 -0
- package/dist/core/web/public/next/assets/Switch-Cqc_bSoh.js.map +1 -0
- package/dist/core/web/public/next/assets/Tag-BvOxSxYi.js +2 -0
- package/dist/core/web/public/next/assets/Tag-BvOxSxYi.js.map +1 -0
- package/dist/core/web/public/next/assets/TerminalPane-D3f02aI4.js +3 -0
- package/dist/core/web/public/next/assets/TerminalPane-D3f02aI4.js.map +1 -0
- package/dist/core/web/public/next/assets/TerminalPane-XZ5n3Pns.js +26 -0
- package/dist/core/web/public/next/assets/TerminalPane-XZ5n3Pns.js.map +1 -0
- package/dist/core/web/public/next/assets/ThinkingBlock-DZNlOGaV.js +2 -0
- package/dist/core/web/public/next/assets/ThinkingBlock-DZNlOGaV.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-CzBI6Upl.js +2 -0
- package/dist/core/web/public/next/assets/UniverseConsoleApp-CzBI6Upl.js.map +1 -0
- package/dist/core/web/public/next/assets/UniverseView-Dsi3Kk8o.js +9 -0
- package/dist/core/web/public/next/assets/UniverseView-Dsi3Kk8o.js.map +1 -0
- package/dist/core/web/public/next/assets/UsageSection-rVvLat9z.js +3 -0
- package/dist/core/web/public/next/assets/UsageSection-rVvLat9z.js.map +1 -0
- package/dist/core/web/public/next/assets/UsePlaybookAction-B4XAzSeI.js +2 -0
- package/dist/core/web/public/next/assets/UsePlaybookAction-B4XAzSeI.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-BmckthwC.css +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DjPpZLo1.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-DjPpZLo1.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseMobileApp-ePNuVERe.js +3 -0
- package/dist/core/web/public/next/assets/VerseMobileApp-ePNuVERe.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseShared-Bf-XTHCh.js +2 -0
- package/dist/core/web/public/next/assets/VerseShared-Bf-XTHCh.js.map +1 -0
- package/dist/core/web/public/next/assets/VoiceHud-BG5FV2h0.js +2 -0
- package/dist/core/web/public/next/assets/VoiceHud-BG5FV2h0.js.map +1 -0
- package/dist/core/web/public/next/assets/VoiceInput-k3vB_FxV.js +2 -0
- package/dist/core/web/public/next/assets/VoiceInput-k3vB_FxV.js.map +1 -0
- package/dist/core/web/public/next/assets/WikiSection-DeBKNqd6.js +2 -0
- package/dist/core/web/public/next/assets/WikiSection-DeBKNqd6.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-CvwS2-RN.js +6 -0
- package/dist/core/web/public/next/assets/Workspace-CvwS2-RN.js.map +1 -0
- package/dist/core/web/public/next/assets/actions-Dg6UJTLn.js +2 -0
- package/dist/core/web/public/next/assets/actions-Dg6UJTLn.js.map +1 -0
- package/dist/core/web/public/next/assets/agent-tools-client-DmJq7zlr.js +2 -0
- package/dist/core/web/public/next/assets/agent-tools-client-DmJq7zlr.js.map +1 -0
- package/dist/core/web/public/next/assets/agents-focus-B1LKhUVg.js +2 -0
- package/dist/core/web/public/next/assets/agents-focus-B1LKhUVg.js.map +1 -0
- package/dist/core/web/public/next/assets/app-version-Cb1z8iCO.js +2 -0
- package/dist/core/web/public/next/assets/app-version-Cb1z8iCO.js.map +1 -0
- package/dist/core/web/public/next/assets/apps-model-_chbcQeN.js +2 -0
- package/dist/core/web/public/next/assets/apps-model-_chbcQeN.js.map +1 -0
- package/dist/core/web/public/next/assets/ask-seat-O60AydbV.js +2 -0
- package/dist/core/web/public/next/assets/ask-seat-O60AydbV.js.map +1 -0
- package/dist/core/web/public/next/assets/authority-model-BeDDHF22.js +2 -0
- package/dist/core/web/public/next/assets/authority-model-BeDDHF22.js.map +1 -0
- package/dist/core/web/public/next/assets/automations-focus-BXaRZ8nX.js +2 -0
- package/dist/core/web/public/next/assets/automations-focus-BXaRZ8nX.js.map +1 -0
- package/dist/core/web/public/next/assets/budget-queries-Nvx0H2XE.js +2 -0
- package/dist/core/web/public/next/assets/budget-queries-Nvx0H2XE.js.map +1 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-CBMJ2U-w.js +2 -0
- package/dist/core/web/public/next/assets/capacity-strip-model-CBMJ2U-w.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-DT9PYS49.js +2 -0
- package/dist/core/web/public/next/assets/charts-DT9PYS49.js.map +1 -0
- package/dist/core/web/public/next/assets/chat-pane-data-CfbpeAYX.js +2 -0
- package/dist/core/web/public/next/assets/chat-pane-data-CfbpeAYX.js.map +1 -0
- package/dist/core/web/public/next/assets/checkpoint-queries-BKD2evmX.js +2 -0
- package/dist/core/web/public/next/assets/checkpoint-queries-BKD2evmX.js.map +1 -0
- package/dist/core/web/public/next/assets/cloud-queries-CsU54eNn.js +2 -0
- package/dist/core/web/public/next/assets/cloud-queries-CsU54eNn.js.map +1 -0
- package/dist/core/web/public/next/assets/command-catalog-B0ApAGD0.js +2 -0
- package/dist/core/web/public/next/assets/command-catalog-B0ApAGD0.js.map +1 -0
- package/dist/core/web/public/next/assets/composer-queries-D1H4E0Ye.js +2 -0
- package/dist/core/web/public/next/assets/composer-queries-D1H4E0Ye.js.map +1 -0
- package/dist/core/web/public/next/assets/connectivity-xQ0Nh0j3.js +2 -0
- package/dist/core/web/public/next/assets/connectivity-xQ0Nh0j3.js.map +1 -0
- package/dist/core/web/public/next/assets/context-queries-bnI3P0Wt.js +2 -0
- package/dist/core/web/public/next/assets/context-queries-bnI3P0Wt.js.map +1 -0
- package/dist/core/web/public/next/assets/control-queries-BG53otwz.js +2 -0
- package/dist/core/web/public/next/assets/control-queries-BG53otwz.js.map +1 -0
- package/dist/core/web/public/next/assets/copy-setup-COMDnur3.js +2 -0
- package/dist/core/web/public/next/assets/copy-setup-COMDnur3.js.map +1 -0
- package/dist/core/web/public/next/assets/deep-link-CqOP-JEm.js +2 -0
- package/dist/core/web/public/next/assets/deep-link-CqOP-JEm.js.map +1 -0
- package/dist/core/web/public/next/assets/device-permissions-DpsJJcUW.js +2 -0
- package/dist/core/web/public/next/assets/device-permissions-DpsJJcUW.js.map +1 -0
- package/dist/core/web/public/next/assets/devin-queries-BSEOfLuZ.js +2 -0
- package/dist/core/web/public/next/assets/devin-queries-BSEOfLuZ.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-icons-DK7QcBXJ.js +2 -0
- package/dist/core/web/public/next/assets/dock-icons-DK7QcBXJ.js.map +1 -0
- package/dist/core/web/public/next/assets/dock-panes-DvQ6t4Nl.js +2 -0
- package/dist/core/web/public/next/assets/dock-panes-DvQ6t4Nl.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-control-queries-BL-Vlf85.js +2 -0
- package/dist/core/web/public/next/assets/fleet-control-queries-BL-Vlf85.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-queries-eacERnLm.js +2 -0
- package/dist/core/web/public/next/assets/fleet-queries-eacERnLm.js.map +1 -0
- package/dist/core/web/public/next/assets/fleet-state-DfKcuo4A.js +3 -0
- package/dist/core/web/public/next/assets/fleet-state-DfKcuo4A.js.map +1 -0
- package/dist/core/web/public/next/assets/focus-trap-BZeH0rVB.js +2 -0
- package/dist/core/web/public/next/assets/focus-trap-BZeH0rVB.js.map +1 -0
- package/dist/core/web/public/next/assets/git-model-C1I4z_iQ.js +5 -0
- package/dist/core/web/public/next/assets/git-model-C1I4z_iQ.js.map +1 -0
- package/dist/core/web/public/next/assets/global-w7KDTTi0.js +3 -0
- package/dist/core/web/public/next/assets/global-w7KDTTi0.js.map +1 -0
- package/dist/core/web/public/next/assets/guarded-action-J9umcJgI.js +3 -0
- package/dist/core/web/public/next/assets/guarded-action-J9umcJgI.js.map +1 -0
- package/dist/core/web/public/next/assets/guarded-runners-Da5yA9Im.js +2 -0
- package/dist/core/web/public/next/assets/guarded-runners-Da5yA9Im.js.map +1 -0
- package/dist/core/web/public/next/assets/health-queries-D3HgrdU_.js +2 -0
- package/dist/core/web/public/next/assets/health-queries-D3HgrdU_.js.map +1 -0
- package/dist/core/web/public/next/assets/icons-C3G-y5j2.js +2 -0
- package/dist/core/web/public/next/assets/icons-C3G-y5j2.js.map +1 -0
- package/dist/core/web/public/next/assets/index-BC5Uslm5.js +11 -0
- package/dist/core/web/public/next/assets/index-BC5Uslm5.js.map +1 -0
- package/dist/core/web/public/next/assets/jev-queries-D6JNU-s6.js +2 -0
- package/dist/core/web/public/next/assets/jev-queries-D6JNU-s6.js.map +1 -0
- package/dist/core/web/public/next/assets/ladder-queries-BnYWjJoi.js +2 -0
- package/dist/core/web/public/next/assets/ladder-queries-BnYWjJoi.js.map +1 -0
- package/dist/core/web/public/next/assets/leader-focus-C6LVWgYI.js +2 -0
- package/dist/core/web/public/next/assets/leader-focus-C6LVWgYI.js.map +1 -0
- package/dist/core/web/public/next/assets/live-model-BPyZCTr1.js +2 -0
- package/dist/core/web/public/next/assets/live-model-BPyZCTr1.js.map +1 -0
- package/dist/core/web/public/next/assets/mobile-actions-avKNGddD.js +2 -0
- package/dist/core/web/public/next/assets/mobile-actions-avKNGddD.js.map +1 -0
- package/dist/core/web/public/next/assets/mobile-toast-BqSzGmw1.js +2 -0
- package/dist/core/web/public/next/assets/mobile-toast-BqSzGmw1.js.map +1 -0
- package/dist/core/web/public/next/assets/multimodel-flows-DOHsEKUG.js +7 -0
- package/dist/core/web/public/next/assets/multimodel-flows-DOHsEKUG.js.map +1 -0
- package/dist/core/web/public/next/assets/multimodel-queries-xmBBUT6n.js +2 -0
- package/dist/core/web/public/next/assets/multimodel-queries-xmBBUT6n.js.map +1 -0
- package/dist/core/web/public/next/assets/mutations-CdLi0erM.js +2 -0
- package/dist/core/web/public/next/assets/mutations-CdLi0erM.js.map +1 -0
- package/dist/core/web/public/next/assets/nav-CUXtg-Iw.js +2 -0
- package/dist/core/web/public/next/assets/nav-CUXtg-Iw.js.map +1 -0
- package/dist/core/web/public/next/assets/needs-you-actions-B2tjWO-0.js +2 -0
- package/dist/core/web/public/next/assets/needs-you-actions-B2tjWO-0.js.map +1 -0
- package/dist/core/web/public/next/assets/needs-you-model-DL9EEd2L.js +2 -0
- package/dist/core/web/public/next/assets/needs-you-model-DL9EEd2L.js.map +1 -0
- package/dist/core/web/public/next/assets/open-terminal-BfbxGoYQ.js +2 -0
- package/dist/core/web/public/next/assets/open-terminal-BfbxGoYQ.js.map +1 -0
- package/dist/core/web/public/next/assets/open-terminal-request-BT1UE0fz.js +2 -0
- package/dist/core/web/public/next/assets/open-terminal-request-BT1UE0fz.js.map +1 -0
- package/dist/core/web/public/next/assets/overnight-queries-cjjogTzn.js +2 -0
- package/dist/core/web/public/next/assets/overnight-queries-cjjogTzn.js.map +1 -0
- package/dist/core/web/public/next/assets/palette-handoff-XL2WWc9I.js +2 -0
- package/dist/core/web/public/next/assets/palette-handoff-XL2WWc9I.js.map +1 -0
- package/dist/core/web/public/next/assets/panes-5GU8cuI9.js +3 -0
- package/dist/core/web/public/next/assets/panes-5GU8cuI9.js.map +1 -0
- package/dist/core/web/public/next/assets/path-display-ZSzKoo8T.js +2 -0
- package/dist/core/web/public/next/assets/path-display-ZSzKoo8T.js.map +1 -0
- package/dist/core/web/public/next/assets/playbook-composer-D04tqOmU.js +2 -0
- package/dist/core/web/public/next/assets/playbook-composer-D04tqOmU.js.map +1 -0
- package/dist/core/web/public/next/assets/playbook-focus-DD1VIfkd.js +2 -0
- package/dist/core/web/public/next/assets/playbook-focus-DD1VIfkd.js.map +1 -0
- package/dist/core/web/public/next/assets/playbooks-queries-X7NGzpIn.js +2 -0
- package/dist/core/web/public/next/assets/playbooks-queries-X7NGzpIn.js.map +1 -0
- package/dist/core/web/public/next/assets/preloaded-6hKNGuRp.js +2 -0
- package/dist/core/web/public/next/assets/preloaded-6hKNGuRp.js.map +1 -0
- package/dist/core/web/public/next/assets/primitives-6nAFZkcg.js +1 -0
- package/dist/core/web/public/next/assets/pwa-BzXJXtDt.js +2 -0
- package/dist/core/web/public/next/assets/pwa-BzXJXtDt.js.map +1 -0
- package/dist/core/web/public/next/assets/queries-PgZlvFqO.js +2 -0
- package/dist/core/web/public/next/assets/queries-PgZlvFqO.js.map +1 -0
- package/dist/core/web/public/next/assets/reasoning-pref-BS0PSZ8d.js +2 -0
- package/dist/core/web/public/next/assets/reasoning-pref-BS0PSZ8d.js.map +1 -0
- package/dist/core/web/public/next/assets/remote-session-Bu-dtRcS.js +3 -0
- package/dist/core/web/public/next/assets/remote-session-Bu-dtRcS.js.map +1 -0
- package/dist/core/web/public/next/assets/resolved-store-UYN2k9My.js +2 -0
- package/dist/core/web/public/next/assets/resolved-store-UYN2k9My.js.map +1 -0
- package/dist/core/web/public/next/assets/resources-queries-XfQ8w9In.js +2 -0
- package/dist/core/web/public/next/assets/resources-queries-XfQ8w9In.js.map +1 -0
- package/dist/core/web/public/next/assets/reveal-anchor-3ZUTtB8Q.js +2 -0
- package/dist/core/web/public/next/assets/reveal-anchor-3ZUTtB8Q.js.map +1 -0
- package/dist/core/web/public/next/assets/sheet-DP8ByDWU.js +2 -0
- package/dist/core/web/public/next/assets/sheet-DP8ByDWU.js.map +1 -0
- package/dist/core/web/public/next/assets/slots-DWlj_c7i.js +3 -0
- package/dist/core/web/public/next/assets/slots-DWlj_c7i.js.map +1 -0
- package/dist/core/web/public/next/assets/sources-queries-Cjk1rpDU.js +4 -0
- package/dist/core/web/public/next/assets/sources-queries-Cjk1rpDU.js.map +1 -0
- package/dist/core/web/public/next/assets/sse-Z3U8XhDI.js +2 -0
- package/dist/core/web/public/next/assets/sse-Z3U8XhDI.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-data-hufdOfpz.js +2 -0
- package/dist/core/web/public/next/assets/surface-data-hufdOfpz.js.map +1 -0
- package/dist/core/web/public/next/assets/surface-prefetch-CFtP8imB.js +2 -0
- package/dist/core/web/public/next/assets/surface-prefetch-CFtP8imB.js.map +1 -0
- package/dist/core/web/public/next/assets/terminal-client-CCSvMeEv.js +2 -0
- package/dist/core/web/public/next/assets/terminal-client-CCSvMeEv.js.map +1 -0
- package/dist/core/web/public/next/assets/terminal-icons-Dx6neM-J.js +2 -0
- package/dist/core/web/public/next/assets/terminal-icons-Dx6neM-J.js.map +1 -0
- package/dist/core/web/public/next/assets/terminal-view-BSieiQvi.js +6 -0
- package/dist/core/web/public/next/assets/terminal-view-BSieiQvi.js.map +1 -0
- package/dist/core/web/public/next/assets/thread-data-Cd2DZffn.js +2 -0
- package/dist/core/web/public/next/assets/thread-data-Cd2DZffn.js.map +1 -0
- package/dist/core/web/public/next/assets/ui-parts-wvov2ktB.js +2 -0
- package/dist/core/web/public/next/assets/ui-parts-wvov2ktB.js.map +1 -0
- package/dist/core/web/public/next/assets/usage-queries-nZjJ1aky.js +2 -0
- package/dist/core/web/public/next/assets/usage-queries-nZjJ1aky.js.map +1 -0
- package/dist/core/web/public/next/assets/use-chat-activity-_tBmEPPN.js +2 -0
- package/dist/core/web/public/next/assets/use-chat-activity-_tBmEPPN.js.map +1 -0
- package/dist/core/web/public/next/assets/use-guarded-action-DKKjhPKG.js +2 -0
- package/dist/core/web/public/next/assets/use-guarded-action-DKKjhPKG.js.map +1 -0
- package/dist/core/web/public/next/assets/use-ticker-w1c3SOqK.js +2 -0
- package/dist/core/web/public/next/assets/use-ticker-w1c3SOqK.js.map +1 -0
- package/dist/core/web/public/next/assets/use-token-gate-h5QAERLT.js +2 -0
- package/dist/core/web/public/next/assets/use-token-gate-h5QAERLT.js.map +1 -0
- package/dist/core/web/public/next/assets/useAutoSeat-Dpbn0XUv.js +2 -0
- package/dist/core/web/public/next/assets/useAutoSeat-Dpbn0XUv.js.map +1 -0
- package/dist/core/web/public/next/assets/useOnboarding-VoV1LcuJ.js +2 -0
- package/dist/core/web/public/next/assets/useOnboarding-VoV1LcuJ.js.map +1 -0
- package/dist/core/web/public/next/assets/useSeatHealth-DuSaKdIs.js +2 -0
- package/dist/core/web/public/next/assets/useSeatHealth-DuSaKdIs.js.map +1 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-DFaR1jSz.js +2 -0
- package/dist/core/web/public/next/assets/useSeatsRefresh-DFaR1jSz.js.map +1 -0
- package/dist/core/web/public/next/assets/useVerseSession-BOsgJzT5.js +2 -0
- package/dist/core/web/public/next/assets/useVerseSession-BOsgJzT5.js.map +1 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-BN_fMz6x.js +2 -0
- package/dist/core/web/public/next/assets/useVerseTranscript-BN_fMz6x.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-bootstrap-query-B3vFD9XK.js +2 -0
- package/dist/core/web/public/next/assets/verse-bootstrap-query-B3vFD9XK.js.map +1 -0
- package/dist/core/web/public/next/assets/verse-icons-vSkflmRB.js +2 -0
- package/dist/core/web/public/next/assets/verse-icons-vSkflmRB.js.map +1 -0
- package/dist/core/web/public/next/assets/warmup-D9MjYs5S.js +3 -0
- package/dist/core/web/public/next/assets/warmup-D9MjYs5S.js.map +1 -0
- package/dist/core/web/public/next/assets/wiki-focus-De8-E48Z.js +2 -0
- package/dist/core/web/public/next/assets/wiki-focus-De8-E48Z.js.map +1 -0
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/package.json +1 -1
- package/dist/core/web/public/next/assets/ActionMenu-CebJFKYy.js +0 -2
- package/dist/core/web/public/next/assets/ActionMenu-CebJFKYy.js.map +0 -1
- package/dist/core/web/public/next/assets/Advanced-Dr9aVbXV.js +0 -2
- package/dist/core/web/public/next/assets/Advanced-Dr9aVbXV.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentDetailScreen-DCVf81Vo.js +0 -2
- package/dist/core/web/public/next/assets/AgentDetailScreen-DCVf81Vo.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentToolsSheet-C3SbvEiV.js +0 -2
- package/dist/core/web/public/next/assets/AgentToolsSheet-C3SbvEiV.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentToolsStrip-CZNxj_Iv.js +0 -2
- package/dist/core/web/public/next/assets/AgentToolsStrip-CZNxj_Iv.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentsScreen-zLj4gzPR.js +0 -2
- package/dist/core/web/public/next/assets/AgentsScreen-zLj4gzPR.js.map +0 -1
- package/dist/core/web/public/next/assets/AgentsSection-CIo_nRmi.js +0 -3
- package/dist/core/web/public/next/assets/AgentsSection-CIo_nRmi.js.map +0 -1
- package/dist/core/web/public/next/assets/App-CPKNuUdC.js +0 -8
- package/dist/core/web/public/next/assets/App-CPKNuUdC.js.map +0 -1
- package/dist/core/web/public/next/assets/AppsSection-D2F2CM-E.js +0 -2
- package/dist/core/web/public/next/assets/AppsSection-D2F2CM-E.js.map +0 -1
- package/dist/core/web/public/next/assets/AreaTrend-DiZu8bjc.js +0 -2
- package/dist/core/web/public/next/assets/AreaTrend-DiZu8bjc.js.map +0 -1
- package/dist/core/web/public/next/assets/AutomationsSection-B4rBNUyo.js +0 -2
- package/dist/core/web/public/next/assets/AutomationsSection-B4rBNUyo.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomyOffState-DEznxI-Q.js +0 -3
- package/dist/core/web/public/next/assets/AutonomyOffState-DEznxI-Q.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-Dq5n3gs7.js +0 -2
- package/dist/core/web/public/next/assets/AutonomySection-Dq5n3gs7.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomyStatus-Uydy6-pZ.js +0 -2
- package/dist/core/web/public/next/assets/AutonomyStatus-Uydy6-pZ.js.map +0 -1
- package/dist/core/web/public/next/assets/BranchBar-BzUmUM_j.js +0 -2
- package/dist/core/web/public/next/assets/BranchBar-BzUmUM_j.js.map +0 -1
- package/dist/core/web/public/next/assets/BrowserPanel-C_VI6Awi.js +0 -7
- package/dist/core/web/public/next/assets/BrowserPanel-C_VI6Awi.js.map +0 -1
- package/dist/core/web/public/next/assets/BudgetControl-B23rNAuC.js +0 -2
- package/dist/core/web/public/next/assets/BudgetControl-B23rNAuC.js.map +0 -1
- package/dist/core/web/public/next/assets/Button-DJY_Pu5B.js +0 -2
- package/dist/core/web/public/next/assets/Button-DJY_Pu5B.js.map +0 -1
- package/dist/core/web/public/next/assets/CapacityStrip-B5Yj2PhZ.js +0 -2
- package/dist/core/web/public/next/assets/CapacityStrip-B5Yj2PhZ.js.map +0 -1
- package/dist/core/web/public/next/assets/ChangesPaneHost-LsUonc7P.js +0 -16
- package/dist/core/web/public/next/assets/ChangesPaneHost-LsUonc7P.js.map +0 -1
- package/dist/core/web/public/next/assets/ChartFrame-CakjKkPx.js +0 -2
- package/dist/core/web/public/next/assets/ChartFrame-CakjKkPx.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatPanes-DgKskpXb.js +0 -2
- package/dist/core/web/public/next/assets/ChatPanes-DgKskpXb.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatSection-DXpzV1NW.js +0 -3
- package/dist/core/web/public/next/assets/ChatSection-DXpzV1NW.js.map +0 -1
- package/dist/core/web/public/next/assets/ChecksPanel-BeCJVOJC.js +0 -5
- package/dist/core/web/public/next/assets/ChecksPanel-BeCJVOJC.js.map +0 -1
- package/dist/core/web/public/next/assets/CloudBudgetForm-4SWIGJLs.js +0 -2
- package/dist/core/web/public/next/assets/CloudBudgetForm-4SWIGJLs.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandPalette-B4QaFGY5.js +0 -3
- package/dist/core/web/public/next/assets/CommandPalette-B4QaFGY5.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandSection-8TFjYitt.js +0 -3
- package/dist/core/web/public/next/assets/CommandSection-8TFjYitt.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandWorkflowForm-B2ooVjof.js +0 -9
- package/dist/core/web/public/next/assets/CommandWorkflowForm-B2ooVjof.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-C09vJiUG.js +0 -3
- package/dist/core/web/public/next/assets/CommandWorkflowPicker-C09vJiUG.js.map +0 -1
- package/dist/core/web/public/next/assets/CompareDialog-CaopnGI0.js +0 -4
- package/dist/core/web/public/next/assets/CompareDialog-CaopnGI0.js.map +0 -1
- package/dist/core/web/public/next/assets/ComputerControl-BflC6wd1.js +0 -2
- package/dist/core/web/public/next/assets/ComputerControl-BflC6wd1.js.map +0 -1
- package/dist/core/web/public/next/assets/ConfirmDialog-CTeMFavv.js +0 -2
- package/dist/core/web/public/next/assets/ConfirmDialog-CTeMFavv.js.map +0 -1
- package/dist/core/web/public/next/assets/DeleteChatDialog-B2bUTuZ9.js +0 -2
- package/dist/core/web/public/next/assets/DeleteChatDialog-B2bUTuZ9.js.map +0 -1
- package/dist/core/web/public/next/assets/DevinStopDialog-DPP34cna.js +0 -2
- package/dist/core/web/public/next/assets/DevinStopDialog-DPP34cna.js.map +0 -1
- package/dist/core/web/public/next/assets/Dialog-r4j4R4b6.js +0 -2
- package/dist/core/web/public/next/assets/Dialog-r4j4R4b6.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffPane-CKnpzqaU.js +0 -2
- package/dist/core/web/public/next/assets/DiffPane-CKnpzqaU.js.map +0 -1
- package/dist/core/web/public/next/assets/DiffViewer-BzQ7245p.js +0 -2
- package/dist/core/web/public/next/assets/DiffViewer-BzQ7245p.js.map +0 -1
- package/dist/core/web/public/next/assets/DockHost-BCZtC_lm.js +0 -2
- package/dist/core/web/public/next/assets/DockHost-BCZtC_lm.js.map +0 -1
- package/dist/core/web/public/next/assets/EmptyState-Cwpga8L9.js +0 -2
- package/dist/core/web/public/next/assets/EmptyState-Cwpga8L9.js.map +0 -1
- package/dist/core/web/public/next/assets/Epistemic-BBwXv-C1.js +0 -2
- package/dist/core/web/public/next/assets/Epistemic-BBwXv-C1.js.map +0 -1
- package/dist/core/web/public/next/assets/EvidenceTimeline-hAENJQCa.js +0 -2
- package/dist/core/web/public/next/assets/EvidenceTimeline-hAENJQCa.js.map +0 -1
- package/dist/core/web/public/next/assets/FilesPane-CrPN5zlx.js +0 -2
- package/dist/core/web/public/next/assets/FilesPane-CrPN5zlx.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetScreen-Cz9HQ-st.js +0 -2
- package/dist/core/web/public/next/assets/FleetScreen-Cz9HQ-st.js.map +0 -1
- package/dist/core/web/public/next/assets/FleetSection-CmZKQ1rr.js +0 -5
- package/dist/core/web/public/next/assets/FleetSection-CmZKQ1rr.js.map +0 -1
- package/dist/core/web/public/next/assets/Funnel-Cfg55EZp.js +0 -2
- package/dist/core/web/public/next/assets/Funnel-Cfg55EZp.js.map +0 -1
- package/dist/core/web/public/next/assets/GearTray-D-Mhc8TJ.js +0 -2
- package/dist/core/web/public/next/assets/GearTray-D-Mhc8TJ.js.map +0 -1
- package/dist/core/web/public/next/assets/GitDialogs-e-7RQEGv.js +0 -2
- package/dist/core/web/public/next/assets/GitDialogs-e-7RQEGv.js.map +0 -1
- package/dist/core/web/public/next/assets/GrowthSection-DsIrdTDd.js +0 -3
- package/dist/core/web/public/next/assets/GrowthSection-DsIrdTDd.js.map +0 -1
- package/dist/core/web/public/next/assets/HandoffDialog-1MB2fmT1.js +0 -2
- package/dist/core/web/public/next/assets/HandoffDialog-1MB2fmT1.js.map +0 -1
- package/dist/core/web/public/next/assets/HomeBody-n_t3A58_.js +0 -3
- package/dist/core/web/public/next/assets/HomeBody-n_t3A58_.js.map +0 -1
- package/dist/core/web/public/next/assets/HomeSeats-DA66aOWC.js +0 -2
- package/dist/core/web/public/next/assets/HomeSeats-DA66aOWC.js.map +0 -1
- package/dist/core/web/public/next/assets/Input-Bt6fp051.js +0 -2
- package/dist/core/web/public/next/assets/Input-Bt6fp051.js.map +0 -1
- package/dist/core/web/public/next/assets/LaunchDialog-BCd7XqCv.js +0 -9
- package/dist/core/web/public/next/assets/LaunchDialog-BCd7XqCv.js.map +0 -1
- package/dist/core/web/public/next/assets/LeaderCard-DFAFcyfZ.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-DFAFcyfZ.js.map +0 -1
- package/dist/core/web/public/next/assets/LeaderConversation-LSenfZzT.js +0 -3
- package/dist/core/web/public/next/assets/LeaderConversation-LSenfZzT.js.map +0 -1
- package/dist/core/web/public/next/assets/LeaderScreen-B2UxRWUm.js +0 -2
- package/dist/core/web/public/next/assets/LeaderScreen-B2UxRWUm.js.map +0 -1
- package/dist/core/web/public/next/assets/LessonsPanel-D86ZT0we.js +0 -2
- package/dist/core/web/public/next/assets/LessonsPanel-D86ZT0we.js.map +0 -1
- package/dist/core/web/public/next/assets/LiveTimer-AtG5hPwV.js +0 -2
- package/dist/core/web/public/next/assets/LiveTimer-AtG5hPwV.js.map +0 -1
- package/dist/core/web/public/next/assets/LocalSeatBadge-XfGRZCA3.js +0 -2
- package/dist/core/web/public/next/assets/LocalSeatBadge-XfGRZCA3.js.map +0 -1
- package/dist/core/web/public/next/assets/MatrixHeatmap-PSnyMJ2h.js +0 -2
- package/dist/core/web/public/next/assets/MatrixHeatmap-PSnyMJ2h.js.map +0 -1
- package/dist/core/web/public/next/assets/McpSection-BG2FSkgH.js +0 -2
- package/dist/core/web/public/next/assets/McpSection-BG2FSkgH.js.map +0 -1
- package/dist/core/web/public/next/assets/MessageMarkdown-CQEqoMvf.js +0 -3
- package/dist/core/web/public/next/assets/MessageMarkdown-CQEqoMvf.js.map +0 -1
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-DU-VLDhb.js +0 -72
- package/dist/core/web/public/next/assets/MessageMarkdownRenderer-DU-VLDhb.js.map +0 -1
- package/dist/core/web/public/next/assets/Meter-BfaE-BjY.js +0 -2
- package/dist/core/web/public/next/assets/Meter-BfaE-BjY.js.map +0 -1
- package/dist/core/web/public/next/assets/MicButton-BbGB7y_9.js +0 -2
- package/dist/core/web/public/next/assets/MicButton-BbGB7y_9.js.map +0 -1
- package/dist/core/web/public/next/assets/MindSection-CX0VaHo1.js +0 -3
- package/dist/core/web/public/next/assets/MindSection-CX0VaHo1.js.map +0 -1
- package/dist/core/web/public/next/assets/MobileComposer-CFeLWUCz.js +0 -2
- package/dist/core/web/public/next/assets/MobileComposer-CFeLWUCz.js.map +0 -1
- package/dist/core/web/public/next/assets/MobileGuardSheet-cGW9RCTr.js +0 -2
- package/dist/core/web/public/next/assets/MobileGuardSheet-cGW9RCTr.js.map +0 -1
- package/dist/core/web/public/next/assets/MobileRuntime-BWTZ_QLr.js +0 -3
- package/dist/core/web/public/next/assets/MobileRuntime-BWTZ_QLr.js.map +0 -1
- package/dist/core/web/public/next/assets/MoreScreen-BcHZhVrR.js +0 -2
- package/dist/core/web/public/next/assets/MoreScreen-BcHZhVrR.js.map +0 -1
- package/dist/core/web/public/next/assets/MultiModelBar-COxIRv7m.js +0 -7
- package/dist/core/web/public/next/assets/MultiModelBar-COxIRv7m.js.map +0 -1
- package/dist/core/web/public/next/assets/MutationTokenDialog-Dnf_rcnc.js +0 -2
- package/dist/core/web/public/next/assets/MutationTokenDialog-Dnf_rcnc.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-COrUlnd0.js +0 -3
- package/dist/core/web/public/next/assets/NeedsYouDrawer-COrUlnd0.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouList-AXzOe4EL.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouList-AXzOe4EL.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouScreen-HSXybHgd.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouScreen-HSXybHgd.js.map +0 -1
- package/dist/core/web/public/next/assets/NewAgentScreen-BI849ZsG.js +0 -2
- package/dist/core/web/public/next/assets/NewAgentScreen-BI849ZsG.js.map +0 -1
- package/dist/core/web/public/next/assets/NewChatDialog-BHoCnP6Q.js +0 -4
- package/dist/core/web/public/next/assets/NewChatDialog-BHoCnP6Q.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-BVljU2uy.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingFlow-BVljU2uy.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingGate-DlI4L7Ki.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingGate-DlI4L7Ki.js.map +0 -1
- package/dist/core/web/public/next/assets/PlaybooksSection-hhNpXnsR.js +0 -9
- package/dist/core/web/public/next/assets/PlaybooksSection-hhNpXnsR.js.map +0 -1
- package/dist/core/web/public/next/assets/PreviewPane-BbXr63u2.js +0 -2
- package/dist/core/web/public/next/assets/PreviewPane-BbXr63u2.js.map +0 -1
- package/dist/core/web/public/next/assets/ProviderLogo-BliSWEMw.js +0 -2
- package/dist/core/web/public/next/assets/ProviderLogo-BliSWEMw.js.map +0 -1
- package/dist/core/web/public/next/assets/RailStatus-SnrVxLnp.js +0 -2
- package/dist/core/web/public/next/assets/RailStatus-SnrVxLnp.js.map +0 -1
- package/dist/core/web/public/next/assets/ReasoningPane-C04_bOAi.js +0 -2
- package/dist/core/web/public/next/assets/ReasoningPane-C04_bOAi.js.map +0 -1
- package/dist/core/web/public/next/assets/ReasoningSheet-BvNFwtuX.js +0 -2
- package/dist/core/web/public/next/assets/ReasoningSheet-BvNFwtuX.js.map +0 -1
- package/dist/core/web/public/next/assets/RefreshIndicator-BNptNJiV.js +0 -2
- package/dist/core/web/public/next/assets/RefreshIndicator-BNptNJiV.js.map +0 -1
- package/dist/core/web/public/next/assets/RemoteMobileApp-osaSEvnm.js +0 -2
- package/dist/core/web/public/next/assets/RemoteMobileApp-osaSEvnm.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-LO31zjUR.js +0 -7
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-LO31zjUR.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-ByZE532G.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesChrome-ByZE532G.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-p_VCkMZH.css +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-BH9uwNE8.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesDrawer-BH9uwNE8.js.map +0 -1
- package/dist/core/web/public/next/assets/ReviewMenu-B2A_YDPi.js +0 -2
- package/dist/core/web/public/next/assets/ReviewMenu-B2A_YDPi.js.map +0 -1
- package/dist/core/web/public/next/assets/RouteErrorBoundary-CVabFM97.js +0 -2
- package/dist/core/web/public/next/assets/RouteErrorBoundary-CVabFM97.js.map +0 -1
- package/dist/core/web/public/next/assets/RunInCloudAction-BpNHE7m8.js +0 -2
- package/dist/core/web/public/next/assets/RunInCloudAction-BpNHE7m8.js.map +0 -1
- package/dist/core/web/public/next/assets/RunInDevinAction-Bkf5Gb3a.js +0 -2
- package/dist/core/web/public/next/assets/RunInDevinAction-Bkf5Gb3a.js.map +0 -1
- package/dist/core/web/public/next/assets/SchedulingEvidence-B08-qhhm.js +0 -2
- package/dist/core/web/public/next/assets/SchedulingEvidence-B08-qhhm.js.map +0 -1
- package/dist/core/web/public/next/assets/ScreenHost-BGSxFyWK.js +0 -3
- package/dist/core/web/public/next/assets/ScreenHost-BGSxFyWK.js.map +0 -1
- package/dist/core/web/public/next/assets/SeatSelector-B4lRZl0K.js +0 -3
- package/dist/core/web/public/next/assets/SeatSelector-B4lRZl0K.js.map +0 -1
- package/dist/core/web/public/next/assets/Segmented-Dokzywy8.js +0 -2
- package/dist/core/web/public/next/assets/Segmented-Dokzywy8.js.map +0 -1
- package/dist/core/web/public/next/assets/Select-tf4lNvWD.js +0 -2
- package/dist/core/web/public/next/assets/Select-tf4lNvWD.js.map +0 -1
- package/dist/core/web/public/next/assets/SessionGate-Bab2qO29.js +0 -2
- package/dist/core/web/public/next/assets/SessionGate-Bab2qO29.js.map +0 -1
- package/dist/core/web/public/next/assets/SessionInsightChip-C-fj8h4A.js +0 -2
- package/dist/core/web/public/next/assets/SessionInsightChip-C-fj8h4A.js.map +0 -1
- package/dist/core/web/public/next/assets/SessionSearch-CqjjwOW2.js +0 -2
- package/dist/core/web/public/next/assets/SessionSearch-CqjjwOW2.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-DfOsHzl6.js +0 -2
- package/dist/core/web/public/next/assets/SettingsSection-DfOsHzl6.js.map +0 -1
- package/dist/core/web/public/next/assets/SetupChecklist-BsxCTcYY.js +0 -2
- package/dist/core/web/public/next/assets/SetupChecklist-BsxCTcYY.js.map +0 -1
- package/dist/core/web/public/next/assets/ShadowDecisions-B1ZPv7K-.js +0 -3
- package/dist/core/web/public/next/assets/ShadowDecisions-B1ZPv7K-.js.map +0 -1
- package/dist/core/web/public/next/assets/Sheet-DLlZ00Lu.js +0 -2
- package/dist/core/web/public/next/assets/Sheet-DLlZ00Lu.js.map +0 -1
- package/dist/core/web/public/next/assets/ShortcutsOverlay-CDwQdpGV.js +0 -2
- package/dist/core/web/public/next/assets/ShortcutsOverlay-CDwQdpGV.js.map +0 -1
- package/dist/core/web/public/next/assets/Sidebar-H5WNri2S.js +0 -3
- package/dist/core/web/public/next/assets/Sidebar-H5WNri2S.js.map +0 -1
- package/dist/core/web/public/next/assets/SkipToContent-BjJE6yOo.js +0 -2
- package/dist/core/web/public/next/assets/SkipToContent-BjJE6yOo.js.map +0 -1
- package/dist/core/web/public/next/assets/Slider-C68TumXj.js +0 -2
- package/dist/core/web/public/next/assets/Slider-C68TumXj.js.map +0 -1
- package/dist/core/web/public/next/assets/SourcesPane-DHYs4YIg.js +0 -2
- package/dist/core/web/public/next/assets/SourcesPane-DHYs4YIg.js.map +0 -1
- package/dist/core/web/public/next/assets/SourcesPanel-DFyLfYBO.js +0 -2
- package/dist/core/web/public/next/assets/SourcesPanel-DFyLfYBO.js.map +0 -1
- package/dist/core/web/public/next/assets/StatTile-CTUuhOLS.js +0 -2
- package/dist/core/web/public/next/assets/StatTile-CTUuhOLS.js.map +0 -1
- package/dist/core/web/public/next/assets/StatusBadge-DrVbi5dF.js +0 -2
- package/dist/core/web/public/next/assets/StatusBadge-DrVbi5dF.js.map +0 -1
- package/dist/core/web/public/next/assets/StepBand-CXDpnu2R.js +0 -2
- package/dist/core/web/public/next/assets/StepBand-CXDpnu2R.js.map +0 -1
- package/dist/core/web/public/next/assets/Surface-DCL7uORg.js +0 -2
- package/dist/core/web/public/next/assets/Surface-DCL7uORg.js.map +0 -1
- package/dist/core/web/public/next/assets/Swimlane-BAEjfoVU.js +0 -2
- package/dist/core/web/public/next/assets/Swimlane-BAEjfoVU.js.map +0 -1
- package/dist/core/web/public/next/assets/Switch-Z7RmRjWE.js +0 -2
- package/dist/core/web/public/next/assets/Switch-Z7RmRjWE.js.map +0 -1
- package/dist/core/web/public/next/assets/Tag-Ciht3C94.js +0 -2
- package/dist/core/web/public/next/assets/Tag-Ciht3C94.js.map +0 -1
- package/dist/core/web/public/next/assets/TerminalPane-BdIyhtzJ.js +0 -26
- package/dist/core/web/public/next/assets/TerminalPane-BdIyhtzJ.js.map +0 -1
- package/dist/core/web/public/next/assets/TerminalPane-DJKT600N.js +0 -3
- package/dist/core/web/public/next/assets/TerminalPane-DJKT600N.js.map +0 -1
- package/dist/core/web/public/next/assets/ThinkingBlock-CHRZX_fJ.js +0 -2
- package/dist/core/web/public/next/assets/ThinkingBlock-CHRZX_fJ.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-QSoaY_Fk.js +0 -2
- package/dist/core/web/public/next/assets/UniverseConsoleApp-QSoaY_Fk.js.map +0 -1
- package/dist/core/web/public/next/assets/UniverseView-ZXAOJ0Rq.js +0 -9
- package/dist/core/web/public/next/assets/UniverseView-ZXAOJ0Rq.js.map +0 -1
- package/dist/core/web/public/next/assets/UsageSection-BEAa-W_q.js +0 -3
- package/dist/core/web/public/next/assets/UsageSection-BEAa-W_q.js.map +0 -1
- package/dist/core/web/public/next/assets/UsePlaybookAction-S7Yky_M8.js +0 -2
- package/dist/core/web/public/next/assets/UsePlaybookAction-S7Yky_M8.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-Cj6yPJo3.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-Cj6yPJo3.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-n6qr3lCF.css +0 -1
- package/dist/core/web/public/next/assets/VerseMobileApp-BRayqF_2.js +0 -3
- package/dist/core/web/public/next/assets/VerseMobileApp-BRayqF_2.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseShared-CH8mV5ew.js +0 -2
- package/dist/core/web/public/next/assets/VerseShared-CH8mV5ew.js.map +0 -1
- package/dist/core/web/public/next/assets/VoiceHud-CO4yGRlr.js +0 -2
- package/dist/core/web/public/next/assets/VoiceHud-CO4yGRlr.js.map +0 -1
- package/dist/core/web/public/next/assets/VoiceInput-fSLnbGJ4.js +0 -2
- package/dist/core/web/public/next/assets/VoiceInput-fSLnbGJ4.js.map +0 -1
- package/dist/core/web/public/next/assets/WikiSection-CN-HansV.js +0 -2
- package/dist/core/web/public/next/assets/WikiSection-CN-HansV.js.map +0 -1
- package/dist/core/web/public/next/assets/Workspace-dufi6DmW.js +0 -6
- package/dist/core/web/public/next/assets/Workspace-dufi6DmW.js.map +0 -1
- package/dist/core/web/public/next/assets/actions-gBplqbpY.js +0 -2
- package/dist/core/web/public/next/assets/actions-gBplqbpY.js.map +0 -1
- package/dist/core/web/public/next/assets/agent-tools-client-ClFut2J1.js +0 -2
- package/dist/core/web/public/next/assets/agent-tools-client-ClFut2J1.js.map +0 -1
- package/dist/core/web/public/next/assets/agents-focus-DjBz83BQ.js +0 -2
- package/dist/core/web/public/next/assets/agents-focus-DjBz83BQ.js.map +0 -1
- package/dist/core/web/public/next/assets/app-version-B0FcXqqB.js +0 -2
- package/dist/core/web/public/next/assets/app-version-B0FcXqqB.js.map +0 -1
- package/dist/core/web/public/next/assets/apps-model-C-SdWY0N.js +0 -2
- package/dist/core/web/public/next/assets/apps-model-C-SdWY0N.js.map +0 -1
- package/dist/core/web/public/next/assets/ask-seat-DhGxiGSd.js +0 -2
- package/dist/core/web/public/next/assets/ask-seat-DhGxiGSd.js.map +0 -1
- package/dist/core/web/public/next/assets/authority-model-CoXAS-Z6.js +0 -2
- package/dist/core/web/public/next/assets/authority-model-CoXAS-Z6.js.map +0 -1
- package/dist/core/web/public/next/assets/automations-focus-CeneF7lP.js +0 -2
- package/dist/core/web/public/next/assets/automations-focus-CeneF7lP.js.map +0 -1
- package/dist/core/web/public/next/assets/budget-queries-DCZevH2S.js +0 -2
- package/dist/core/web/public/next/assets/budget-queries-DCZevH2S.js.map +0 -1
- package/dist/core/web/public/next/assets/capacity-strip-model-Wna9o0dS.js +0 -2
- package/dist/core/web/public/next/assets/capacity-strip-model-Wna9o0dS.js.map +0 -1
- package/dist/core/web/public/next/assets/charts-CzqC55eL.js +0 -2
- package/dist/core/web/public/next/assets/charts-CzqC55eL.js.map +0 -1
- package/dist/core/web/public/next/assets/chat-pane-data-BBA55Pw-.js +0 -2
- package/dist/core/web/public/next/assets/chat-pane-data-BBA55Pw-.js.map +0 -1
- package/dist/core/web/public/next/assets/checkpoint-queries-gP6Vh70H.js +0 -2
- package/dist/core/web/public/next/assets/checkpoint-queries-gP6Vh70H.js.map +0 -1
- package/dist/core/web/public/next/assets/cloud-queries-Bsqo7wye.js +0 -2
- package/dist/core/web/public/next/assets/cloud-queries-Bsqo7wye.js.map +0 -1
- package/dist/core/web/public/next/assets/command-catalog-Dnx-iMLX.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-Dnx-iMLX.js.map +0 -1
- package/dist/core/web/public/next/assets/composer-queries-DHGJlnFJ.js +0 -2
- package/dist/core/web/public/next/assets/composer-queries-DHGJlnFJ.js.map +0 -1
- package/dist/core/web/public/next/assets/connectivity-BViMMNcD.js +0 -2
- package/dist/core/web/public/next/assets/connectivity-BViMMNcD.js.map +0 -1
- package/dist/core/web/public/next/assets/context-queries-Bsl-w0q-.js +0 -2
- package/dist/core/web/public/next/assets/context-queries-Bsl-w0q-.js.map +0 -1
- package/dist/core/web/public/next/assets/control-queries-CUNa6TAx.js +0 -2
- package/dist/core/web/public/next/assets/control-queries-CUNa6TAx.js.map +0 -1
- package/dist/core/web/public/next/assets/copy-setup-C2goNcTZ.js +0 -2
- package/dist/core/web/public/next/assets/copy-setup-C2goNcTZ.js.map +0 -1
- package/dist/core/web/public/next/assets/deep-link-Dg_zaqAl.js +0 -2
- package/dist/core/web/public/next/assets/deep-link-Dg_zaqAl.js.map +0 -1
- package/dist/core/web/public/next/assets/device-permissions-CEXY0Vor.js +0 -2
- package/dist/core/web/public/next/assets/device-permissions-CEXY0Vor.js.map +0 -1
- package/dist/core/web/public/next/assets/devin-queries-Cu_YYhw2.js +0 -2
- package/dist/core/web/public/next/assets/devin-queries-Cu_YYhw2.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-icons-DGZoDN6N.js +0 -2
- package/dist/core/web/public/next/assets/dock-icons-DGZoDN6N.js.map +0 -1
- package/dist/core/web/public/next/assets/dock-panes-BgSO9q_f.js +0 -2
- package/dist/core/web/public/next/assets/dock-panes-BgSO9q_f.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-control-queries-clsJWanE.js +0 -2
- package/dist/core/web/public/next/assets/fleet-control-queries-clsJWanE.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-queries-DX1AwHEt.js +0 -2
- package/dist/core/web/public/next/assets/fleet-queries-DX1AwHEt.js.map +0 -1
- package/dist/core/web/public/next/assets/fleet-state-EgNiSDxu.js +0 -3
- package/dist/core/web/public/next/assets/fleet-state-EgNiSDxu.js.map +0 -1
- package/dist/core/web/public/next/assets/focus-trap-B1vuEhZX.js +0 -2
- package/dist/core/web/public/next/assets/focus-trap-B1vuEhZX.js.map +0 -1
- package/dist/core/web/public/next/assets/git-model-Bu59fz1m.js +0 -5
- package/dist/core/web/public/next/assets/git-model-Bu59fz1m.js.map +0 -1
- package/dist/core/web/public/next/assets/global-BJ_kVFpD.js +0 -3
- package/dist/core/web/public/next/assets/global-BJ_kVFpD.js.map +0 -1
- package/dist/core/web/public/next/assets/guarded-action-CzvG7Qgc.js +0 -3
- package/dist/core/web/public/next/assets/guarded-action-CzvG7Qgc.js.map +0 -1
- package/dist/core/web/public/next/assets/guarded-runners-BPM0KdoQ.js +0 -2
- package/dist/core/web/public/next/assets/guarded-runners-BPM0KdoQ.js.map +0 -1
- package/dist/core/web/public/next/assets/health-queries-CMxSsJKS.js +0 -2
- package/dist/core/web/public/next/assets/health-queries-CMxSsJKS.js.map +0 -1
- package/dist/core/web/public/next/assets/icons-MYfI6vZr.js +0 -2
- package/dist/core/web/public/next/assets/icons-MYfI6vZr.js.map +0 -1
- package/dist/core/web/public/next/assets/index-DOAOxiKl.js +0 -11
- package/dist/core/web/public/next/assets/index-DOAOxiKl.js.map +0 -1
- package/dist/core/web/public/next/assets/jev-queries-CS2A5uWe.js +0 -2
- package/dist/core/web/public/next/assets/jev-queries-CS2A5uWe.js.map +0 -1
- package/dist/core/web/public/next/assets/ladder-queries-CBoG3heV.js +0 -2
- package/dist/core/web/public/next/assets/ladder-queries-CBoG3heV.js.map +0 -1
- package/dist/core/web/public/next/assets/leader-focus-DDQlv0TB.js +0 -2
- package/dist/core/web/public/next/assets/leader-focus-DDQlv0TB.js.map +0 -1
- package/dist/core/web/public/next/assets/live-model-CCjYFk48.js +0 -2
- package/dist/core/web/public/next/assets/live-model-CCjYFk48.js.map +0 -1
- package/dist/core/web/public/next/assets/mobile-actions-XqB_h7a8.js +0 -2
- package/dist/core/web/public/next/assets/mobile-actions-XqB_h7a8.js.map +0 -1
- package/dist/core/web/public/next/assets/mobile-toast-eIrghd9o.js +0 -2
- package/dist/core/web/public/next/assets/mobile-toast-eIrghd9o.js.map +0 -1
- package/dist/core/web/public/next/assets/multimodel-flows-CzI-yHg5.js +0 -7
- package/dist/core/web/public/next/assets/multimodel-flows-CzI-yHg5.js.map +0 -1
- package/dist/core/web/public/next/assets/multimodel-queries-DxIT9AZY.js +0 -2
- package/dist/core/web/public/next/assets/multimodel-queries-DxIT9AZY.js.map +0 -1
- package/dist/core/web/public/next/assets/mutations-BlGALvmG.js +0 -2
- package/dist/core/web/public/next/assets/mutations-BlGALvmG.js.map +0 -1
- package/dist/core/web/public/next/assets/nav-ByibvQW1.js +0 -2
- package/dist/core/web/public/next/assets/nav-ByibvQW1.js.map +0 -1
- package/dist/core/web/public/next/assets/needs-you-actions-Dp5UxM3X.js +0 -2
- package/dist/core/web/public/next/assets/needs-you-actions-Dp5UxM3X.js.map +0 -1
- package/dist/core/web/public/next/assets/needs-you-model-DYsqHMqy.js +0 -2
- package/dist/core/web/public/next/assets/needs-you-model-DYsqHMqy.js.map +0 -1
- package/dist/core/web/public/next/assets/open-terminal-dOVyLFvn.js +0 -2
- package/dist/core/web/public/next/assets/open-terminal-dOVyLFvn.js.map +0 -1
- package/dist/core/web/public/next/assets/open-terminal-request-BIhvirIl.js +0 -2
- package/dist/core/web/public/next/assets/open-terminal-request-BIhvirIl.js.map +0 -1
- package/dist/core/web/public/next/assets/overnight-queries-KxqH6BRN.js +0 -2
- package/dist/core/web/public/next/assets/overnight-queries-KxqH6BRN.js.map +0 -1
- package/dist/core/web/public/next/assets/palette-handoff-69pw9oBv.js +0 -2
- package/dist/core/web/public/next/assets/palette-handoff-69pw9oBv.js.map +0 -1
- package/dist/core/web/public/next/assets/panes-CHt3427X.js +0 -3
- package/dist/core/web/public/next/assets/panes-CHt3427X.js.map +0 -1
- package/dist/core/web/public/next/assets/path-display-DuIZF5G3.js +0 -2
- package/dist/core/web/public/next/assets/path-display-DuIZF5G3.js.map +0 -1
- package/dist/core/web/public/next/assets/playbook-composer-DipWgX7t.js +0 -2
- package/dist/core/web/public/next/assets/playbook-composer-DipWgX7t.js.map +0 -1
- package/dist/core/web/public/next/assets/playbook-focus-EXJPMBBI.js +0 -2
- package/dist/core/web/public/next/assets/playbook-focus-EXJPMBBI.js.map +0 -1
- package/dist/core/web/public/next/assets/playbooks-queries-BlpGBpOV.js +0 -2
- package/dist/core/web/public/next/assets/playbooks-queries-BlpGBpOV.js.map +0 -1
- package/dist/core/web/public/next/assets/preloaded-TmpzuCEi.js +0 -2
- package/dist/core/web/public/next/assets/preloaded-TmpzuCEi.js.map +0 -1
- package/dist/core/web/public/next/assets/primitives-CDKCUR2v.js +0 -1
- package/dist/core/web/public/next/assets/pwa-CTGMm-wR.js +0 -2
- package/dist/core/web/public/next/assets/pwa-CTGMm-wR.js.map +0 -1
- package/dist/core/web/public/next/assets/queries--mGK10fL.js +0 -2
- package/dist/core/web/public/next/assets/queries--mGK10fL.js.map +0 -1
- package/dist/core/web/public/next/assets/reasoning-pref-CWGL9MD2.js +0 -2
- package/dist/core/web/public/next/assets/reasoning-pref-CWGL9MD2.js.map +0 -1
- package/dist/core/web/public/next/assets/remote-session-I4RXlsas.js +0 -3
- package/dist/core/web/public/next/assets/remote-session-I4RXlsas.js.map +0 -1
- package/dist/core/web/public/next/assets/resolved-store-DwGn9hb_.js +0 -2
- package/dist/core/web/public/next/assets/resolved-store-DwGn9hb_.js.map +0 -1
- package/dist/core/web/public/next/assets/resources-queries-T6ER_hPN.js +0 -2
- package/dist/core/web/public/next/assets/resources-queries-T6ER_hPN.js.map +0 -1
- package/dist/core/web/public/next/assets/reveal-anchor-CHtvhrYm.js +0 -2
- package/dist/core/web/public/next/assets/reveal-anchor-CHtvhrYm.js.map +0 -1
- package/dist/core/web/public/next/assets/sheet-BlzGO1wo.js +0 -2
- package/dist/core/web/public/next/assets/sheet-BlzGO1wo.js.map +0 -1
- package/dist/core/web/public/next/assets/slots-40edgV7X.js +0 -3
- package/dist/core/web/public/next/assets/slots-40edgV7X.js.map +0 -1
- package/dist/core/web/public/next/assets/sources-queries-BrM41X16.js +0 -4
- package/dist/core/web/public/next/assets/sources-queries-BrM41X16.js.map +0 -1
- package/dist/core/web/public/next/assets/sse-CAFwslNC.js +0 -2
- package/dist/core/web/public/next/assets/sse-CAFwslNC.js.map +0 -1
- package/dist/core/web/public/next/assets/surface-data-D_oFOgkh.js +0 -2
- package/dist/core/web/public/next/assets/surface-data-D_oFOgkh.js.map +0 -1
- package/dist/core/web/public/next/assets/surface-prefetch-wqfiATYQ.js +0 -2
- package/dist/core/web/public/next/assets/surface-prefetch-wqfiATYQ.js.map +0 -1
- package/dist/core/web/public/next/assets/terminal-client-iL4DagCN.js +0 -2
- package/dist/core/web/public/next/assets/terminal-client-iL4DagCN.js.map +0 -1
- package/dist/core/web/public/next/assets/terminal-icons-BakeOpKV.js +0 -2
- package/dist/core/web/public/next/assets/terminal-icons-BakeOpKV.js.map +0 -1
- package/dist/core/web/public/next/assets/terminal-view-D6AAh08q.js +0 -6
- package/dist/core/web/public/next/assets/terminal-view-D6AAh08q.js.map +0 -1
- package/dist/core/web/public/next/assets/thread-data-CSDZ514s.js +0 -2
- package/dist/core/web/public/next/assets/thread-data-CSDZ514s.js.map +0 -1
- package/dist/core/web/public/next/assets/ui-parts-DubQJIoq.js +0 -2
- package/dist/core/web/public/next/assets/ui-parts-DubQJIoq.js.map +0 -1
- package/dist/core/web/public/next/assets/usage-queries-BONqdout.js +0 -2
- package/dist/core/web/public/next/assets/usage-queries-BONqdout.js.map +0 -1
- package/dist/core/web/public/next/assets/use-chat-activity-BZjdPPNP.js +0 -2
- package/dist/core/web/public/next/assets/use-chat-activity-BZjdPPNP.js.map +0 -1
- package/dist/core/web/public/next/assets/use-guarded-action-xJ4rxyVo.js +0 -2
- package/dist/core/web/public/next/assets/use-guarded-action-xJ4rxyVo.js.map +0 -1
- package/dist/core/web/public/next/assets/use-ticker-Bsu0cMvl.js +0 -2
- package/dist/core/web/public/next/assets/use-ticker-Bsu0cMvl.js.map +0 -1
- package/dist/core/web/public/next/assets/use-token-gate-E-xzEAu6.js +0 -2
- package/dist/core/web/public/next/assets/use-token-gate-E-xzEAu6.js.map +0 -1
- package/dist/core/web/public/next/assets/useAutoSeat-CXC9e4vx.js +0 -2
- package/dist/core/web/public/next/assets/useAutoSeat-CXC9e4vx.js.map +0 -1
- package/dist/core/web/public/next/assets/useOnboarding-Csw_AXrj.js +0 -2
- package/dist/core/web/public/next/assets/useOnboarding-Csw_AXrj.js.map +0 -1
- package/dist/core/web/public/next/assets/useSeatHealth-B6AXxre9.js +0 -2
- package/dist/core/web/public/next/assets/useSeatHealth-B6AXxre9.js.map +0 -1
- package/dist/core/web/public/next/assets/useSeatsRefresh-BIAa7Exn.js +0 -2
- package/dist/core/web/public/next/assets/useSeatsRefresh-BIAa7Exn.js.map +0 -1
- package/dist/core/web/public/next/assets/useVerseSession-BOyvOEDi.js +0 -2
- package/dist/core/web/public/next/assets/useVerseSession-BOyvOEDi.js.map +0 -1
- package/dist/core/web/public/next/assets/useVerseTranscript-BOhcfdp7.js +0 -2
- package/dist/core/web/public/next/assets/useVerseTranscript-BOhcfdp7.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-bootstrap-query-D-fU89IT.js +0 -2
- package/dist/core/web/public/next/assets/verse-bootstrap-query-D-fU89IT.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-icons-UKbUG3gv.js +0 -2
- package/dist/core/web/public/next/assets/verse-icons-UKbUG3gv.js.map +0 -1
- package/dist/core/web/public/next/assets/warmup-CZ-IBU5L.js +0 -3
- package/dist/core/web/public/next/assets/warmup-CZ-IBU5L.js.map +0 -1
- package/dist/core/web/public/next/assets/wiki-focus-DhAvbMnX.js +0 -2
- package/dist/core/web/public/next/assets/wiki-focus-DhAvbMnX.js.map +0 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/HomeBody-Ce3HBIEb.js","assets/VerseShared-Bf-XTHCh.js","assets/control-queries-BG53otwz.js","assets/mutations-CdLi0erM.js","assets/surface-data-hufdOfpz.js","assets/ui-parts-wvov2ktB.js","assets/parts.module-CBkHcD6w.js","assets/fleet-state-DfKcuo4A.js","assets/mobile-toast-BqSzGmw1.js","assets/mobile-actions-avKNGddD.js","assets/global-1SED_aTT.css","assets/parts-bRLxuRh-.css","assets/MobileRuntime-kMob_MjB.js","assets/device-permissions-DpsJJcUW.js","assets/resolved-store-UYN2k9My.js","assets/connectivity-xQ0Nh0j3.js","assets/ScreenHost-Dv6z76Ta.js","assets/SessionGate-CnASHl7g.js","assets/SessionGate-DvMpXNpJ.css","assets/RemoteMobileApp-DfDjiBTR.js","assets/remote-session-Bu-dtRcS.js","assets/pwa-BzXJXtDt.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,r as n,s as r,t as i}from"./index-BC5Uslm5.js";import{B as a,E as o,G as s,N as c,_ as l,s as u,t as d}from"./global-w7KDTTi0.js";import{n as f,r as p}from"./verse-bootstrap-query-B3vFD9XK.js";import{t as m}from"./preloaded-6hKNGuRp.js";var h=e(r(),1),g=new Set([`agents`,`new`,`needs`,`leader`,`more`,`fleet`]);function _(e){let[t,n,r]=e.replace(/^#\/?/,``).split(`/`).filter(Boolean);if(!t)return{screen:`home`};if(t===`agents`&&n){let e;try{e=decodeURIComponent(n)}catch{return{screen:`agents`}}return{screen:`agent`,id:e,pane:r===`changes`?`changes`:`transcript`}}return g.has(t)?{screen:t}:{screen:`home`}}function v(e){switch(e.screen){case`home`:return`#/`;case`agent`:return`#/agents/${encodeURIComponent(e.id)}${e.pane===`changes`?`/changes`:``}`;default:return`#/${e.screen}`}}function y(e){switch(e.screen){case`home`:return`home`;case`agents`:case`agent`:case`new`:return`agents`;case`needs`:return`needs`;case`leader`:return`leader`;case`more`:case`fleet`:return`more`}}function b(e){return{screen:e}}function x(e){return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)}function S(){return window.location.hash}function C(e,t={}){let n=v(e);n===window.location.hash||n===`#/`&&window.location.hash===``||(t.replace?window.location.replace(n):window.location.hash=n)}function ee(){let e=(0,h.useSyncExternalStore)(x,S,()=>``),t=(0,h.useCallback)((e,t)=>C(e,t),[]);return[_(e),t]}var w={ready:!1,permissions:{read:!1,act:`unavailable`,actReason:null,source:`session`,deviceLabel:null},reachability:`connecting`,activity:{status:`idle`,data:null,updatedAt:null,error:null},navigate:C,needsCount:null,workingCount:null,refreshActivity:()=>Promise.resolve()};function T(e){return e.act!==`unavailable`}var E=(0,h.createContext)(w);function D(){return(0,h.useContext)(E)}var O=t();function te(e){return(0,O.jsx)(p,{...e,children:(0,O.jsx)(`path`,{d:`M2.5 7.2 8 2.8l5.5 4.4V13a.5.5 0 0 1-.5.5H9.6V10H6.4v3.5H3a.5.5 0 0 1-.5-.5Z`})})}function ne(e){return(0,O.jsxs)(p,{...e,children:[(0,O.jsx)(`rect`,{x:`2`,y:`2.5`,width:`12`,height:`4`,rx:`1.2`}),(0,O.jsx)(`rect`,{x:`2`,y:`9.5`,width:`12`,height:`4`,rx:`1.2`}),(0,O.jsx)(`path`,{d:`M4.5 4.5h.01M4.5 11.5h.01`})]})}function re(e){return(0,O.jsxs)(p,{...e,children:[(0,O.jsx)(`path`,{d:`M4 6.5a4 4 0 0 1 8 0c0 3 1.2 4.2 1.5 4.5h-11C2.8 10.7 4 9.5 4 6.5Z`}),(0,O.jsx)(`path`,{d:`M6.5 13.2a1.6 1.6 0 0 0 3 0`})]})}function ie(e){return(0,O.jsx)(p,{...e,children:(0,O.jsx)(`path`,{d:`M2.5 4a1.5 1.5 0 0 1 1.5-1.5h8A1.5 1.5 0 0 1 13.5 4v5.5A1.5 1.5 0 0 1 12 11H7l-3 2.5V11a1.5 1.5 0 0 1-1.5-1.5Z`})})}function ae(e){return(0,O.jsxs)(p,{...e,children:[(0,O.jsx)(`circle`,{cx:`3.5`,cy:`8`,r:`0.9`}),(0,O.jsx)(`circle`,{cx:`8`,cy:`8`,r:`0.9`}),(0,O.jsx)(`circle`,{cx:`12.5`,cy:`8`,r:`0.9`})]})}function k(e){return(0,O.jsx)(p,{...e,children:(0,O.jsx)(`path`,{d:`M8 3v10M3 8h10`})})}function oe(e){return(0,O.jsx)(p,{...e,children:(0,O.jsx)(`path`,{d:`M10 3 5 8l5 5`})})}function A(e){return(0,O.jsx)(p,{...e,children:(0,O.jsx)(`path`,{d:`m6 3.5 4.5 4.5L6 12.5`})})}function j(e){return(0,O.jsxs)(p,{...e,children:[(0,O.jsx)(`rect`,{x:`5.75`,y:`1.75`,width:`4.5`,height:`8`,rx:`2.25`}),(0,O.jsx)(`path`,{d:`M3.5 7.5a4.5 4.5 0 0 0 9 0M8 12v2.25`})]})}var M={app:`_app_1h0aa_17`,screen:`_screen_1h0aa_44`,scroller:`_scroller_1h0aa_51`,enter:`_enter_1h0aa_61`,"screen-in":`_screen-in_1h0aa_1`,topbar:`_topbar_1h0aa_72`,topbarTitle:`_topbarTitle_1h0aa_87`,topbarLead:`_topbarLead_1h0aa_98`,topbarTrail:`_topbarTrail_1h0aa_103`,largeTitle:`_largeTitle_1h0aa_110`,subtitle:`_subtitle_1h0aa_119`,pull:`_pull_1h0aa_127`,pullArmed:`_pullArmed_1h0aa_137`,spinner:`_spinner_1h0aa_141`,spin:`_spin_1h0aa_141`,btn:`_btn_1h0aa_158`,block:`_block_1h0aa_185`,primary:`_primary_1h0aa_189`,secondary:`_secondary_1h0aa_194`,tinted:`_tinted_1h0aa_200`,destructive:`_destructive_1h0aa_205`,destructiveTinted:`_destructiveTinted_1h0aa_210`,plain:`_plain_1h0aa_215`,iconBtn:`_iconBtn_1h0aa_221`,group:`_group_1h0aa_232`,card:`_card_1h0aa_239`,skeletonRow:`_skeletonRow_1h0aa_247`,skeletonLine:`_skeletonLine_1h0aa_253`,muted:`_muted_1h0aa_258`};function N(...e){return e.filter(Boolean).join(` `)}var se=96;function P({title:e,large:t=!1,subtitle:n,onBack:r,backLabel:i=`Back`,trailing:a,onRefresh:o,header:s,footer:c,children:l,label:u}){let d=(0,h.useId)(),f=(0,h.useRef)(null),p=(0,h.useRef)(null),[m,g]=(0,h.useState)(0),[_,v]=(0,h.useState)(!1),y=(0,h.useCallback)(e=>{o&&!_&&(p.current=(f.current?.scrollTop??0)<=0?e.touches[0]?.clientY??null:null)},[o,_]),b=(0,h.useCallback)(e=>{if(p.current===null)return;let t=(e.touches[0]?.clientY??p.current)-p.current;g(t>0?Math.min(se,t/2):0)},[]),x=(0,h.useCallback)(()=>{let e=m>=40;p.current=null,g(0),e&&o&&(v(!0),Promise.resolve().then(()=>o()).catch(()=>void 0).finally(()=>v(!1)))},[m,o]),S=m>=40;return(0,O.jsxs)(`section`,{className:N(M.screen,M.enter),"aria-labelledby":d,children:[(0,O.jsxs)(`header`,{className:M.topbar,children:[(0,O.jsx)(`div`,{className:M.topbarLead,children:r?(0,O.jsxs)(`button`,{type:`button`,className:N(M.btn,M.plain),onClick:r,children:[(0,O.jsx)(oe,{size:18}),(0,O.jsx)(`span`,{children:i})]}):null}),t?(0,O.jsx)(`span`,{className:M.topbarTitle,"aria-hidden":`true`,children:e}):(0,O.jsx)(`h1`,{id:d,className:M.topbarTitle,children:e}),(0,O.jsx)(`div`,{className:M.topbarTrail,children:a})]}),s,(0,O.jsxs)(`div`,{ref:f,className:M.scroller,"aria-label":u,onTouchStart:o?y:void 0,onTouchMove:o?b:void 0,onTouchEnd:o?x:void 0,onTouchCancel:o?x:void 0,children:[o?(0,O.jsx)(`div`,{className:N(M.pull,S&&M.pullArmed),style:{height:_?`2.5rem`:`${m}px`},"aria-hidden":!_,children:_?(0,O.jsx)(`span`,{className:M.spinner,role:`progressbar`,"aria-label":`Refreshing`}):m>8?S?`Release to refresh`:`Pull to refresh`:null}):null,t?(0,O.jsx)(`h1`,{id:d,className:M.largeTitle,children:e}):null,n?(0,O.jsx)(`p`,{className:M.subtitle,children:n}):null,l]}),c]})}function F({variant:e=`secondary`,block:t=!1,icon:n=!1,className:r,type:i=`button`,...a}){return(0,O.jsx)(`button`,{type:i,className:N(M.btn,M[e],t&&M.block,n&&M.iconBtn,r),...a})}function I({rows:e=3,label:t=`Loading`}){return(0,O.jsx)(`div`,{className:M.group,role:`status`,"aria-label":t,"aria-busy":`true`,children:Array.from({length:e},(e,t)=>(0,O.jsxs)(`div`,{className:M.skeletonRow,children:[(0,O.jsx)(`span`,{className:N(`skeleton`,M.skeletonLine),style:{width:`${70-t*12}%`}}),(0,O.jsx)(`span`,{className:N(`skeleton`,M.skeletonLine),style:{width:`${45-t*6}%`}})]},t))})}var L={fleet:`_fleet_1gspb_3`,fleetTitle:`_fleetTitle_1gspb_9`,fleetDetail:`_fleetDetail_1gspb_14`,badgeSkeleton:`_badgeSkeleton_1gspb_20`,stats:`_stats_1gspb_26`,stat:`_stat_1gspb_26`,statValue:`_statValue_1gspb_51`,statLabel:`_statLabel_1gspb_63`,statHint:`_statHint_1gspb_69`,seats:`_seats_1gspb_74`},R=()=>i(()=>import(`./HomeBody-Ce3HBIEb.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11])),z=m(()=>R().then(e=>e.HomeBody));function B(){return(0,O.jsxs)(`div`,{"aria-busy":`true`,"aria-label":`Loading Home`,children:[(0,O.jsxs)(`div`,{className:`${M.card} ${L.fleet}`,children:[(0,O.jsx)(`span`,{className:`skeleton ${L.badgeSkeleton}`,"aria-hidden":`true`}),(0,O.jsx)(`span`,{className:`skeleton ${M.skeletonLine}`,style:{width:`80%`},"aria-hidden":`true`})]}),(0,O.jsx)(`div`,{className:L.stats,"aria-hidden":`true`,children:[0,1,2].map(e=>(0,O.jsx)(`div`,{className:`${L.stat} skeleton`,style:{height:`4.5rem`}},e))}),(0,O.jsx)(I,{rows:2,label:`Loading running agents`})]})}function V(){let{permissions:e,navigate:t,refreshActivity:n}=D(),r=T(e);return(0,O.jsx)(P,{title:`Verse`,large:!0,subtitle:e.act===`unavailable`?`Read-only on this device`:void 0,onRefresh:()=>Promise.all([n(),R().then(e=>e.refreshHome())]),trailing:r?(0,O.jsx)(F,{variant:`plain`,icon:!0,"aria-label":`New agent`,onClick:()=>t({screen:`new`}),children:(0,O.jsx)(k,{size:22})}):null,children:(0,O.jsx)(h.Suspense,{fallback:(0,O.jsx)(B,{}),children:(0,O.jsx)(z.Slot,{})})})}var H={stage:`_stage_15krn_6`,tabbar:`_tabbar_15krn_13`,tab:`_tab_15krn_13`,tabLabel:`_tabLabel_15krn_46`,tabBadge:`_tabBadge_15krn_53`,reach:`_reach_15krn_74`,boot:`_boot_15krn_94`},U=m(()=>i(()=>import(`./MobileRuntime-kMob_MjB.js`).then(e=>e.MobileRuntime),__vite__mapDeps([12,1,13,14,15,8,6,10,11]))).Slot,W=()=>i(()=>import(`./ScreenHost-Dv6z76Ta.js`),__vite__mapDeps([16])),G=m(()=>W().then(e=>e.ScreenHost)).Slot;function K(){W().then(e=>e.prefetchMobileScreens(),()=>void 0)}var ce=[{id:`home`,label:`Home`,Glyph:te},{id:`agents`,label:`Agents`,Glyph:ne},{id:`needs`,label:`Needs you`,Glyph:re},{id:`leader`,label:`Leader`,Glyph:ie},{id:`more`,label:`More`,Glyph:ae}];function le(){return(0,O.jsx)(`div`,{className:M.screen,children:(0,O.jsx)(`div`,{className:M.scroller,children:(0,O.jsx)(`div`,{className:H.boot,children:(0,O.jsx)(I,{rows:4,label:`Loading screen`})})})})}var q=class extends h.Component{state={failed:!1};static getDerivedStateFromError(){return{failed:!0}}render(){return this.state.failed?this.props.fallback??(0,O.jsx)(`div`,{className:M.screen,children:(0,O.jsx)(`div`,{className:M.scroller,children:(0,O.jsxs)(`div`,{className:H.boot,role:`alert`,children:[(0,O.jsx)(`p`,{className:M.muted,children:`This screen could not load — this phone is offline or your Mac is out of reach.`}),(0,O.jsx)(`button`,{type:`button`,className:`${M.btn} ${M.tinted}`,onClick:()=>window.location.reload(),children:`Try again`})]})})}):this.props.children}};function J({route:e,context:t,overlays:n}){let r=y(e),{navigate:i,needsCount:a,workingCount:o}=t,s=(0,h.useCallback)(e=>{i(b(e),{replace:e===r})},[i,r]);return(0,O.jsxs)(`div`,{className:M.app,"data-mobile-app":``,children:[(0,O.jsx)(`main`,{id:`main`,className:H.stage,children:(0,O.jsx)(q,{children:(0,O.jsx)(h.Suspense,{fallback:(0,O.jsx)(le,{}),children:e.screen===`home`?(0,O.jsx)(V,{}):(0,O.jsx)(G,{route:e})})},e.screen)}),n,(0,O.jsx)(`nav`,{className:H.tabbar,"aria-label":`Verse`,children:ce.map(({id:e,label:t,Glyph:n})=>{let i=e===`needs`?a:e===`agents`?o:null,c=i?`${t}, ${i} ${e===`needs`?`waiting`:`working`}`:t;return(0,O.jsxs)(`button`,{type:`button`,className:H.tab,"aria-current":r===e?`page`:void 0,"aria-label":c,onClick:()=>s(e),children:[(0,O.jsx)(n,{size:24}),(0,O.jsx)(`span`,{className:H.tabLabel,"aria-hidden":`true`,children:t}),i?(0,O.jsx)(`span`,{className:H.tabBadge,"data-tone":e===`agents`?`running`:void 0,"aria-hidden":`true`,children:i>99?`99+`:i}):null]},e)})})]})}function Y(){let[e,t]=ee();(0,h.useEffect)(()=>{if(typeof window.requestIdleCallback==`function`){let e=window.requestIdleCallback(K,{timeout:4e3});return()=>window.cancelIdleCallback(e)}let e=window.setTimeout(K,1500);return()=>window.clearTimeout(e)},[]);let n={...w,navigate:t},r=(0,O.jsx)(E.Provider,{value:n,children:(0,O.jsx)(J,{route:e,context:n})});return(0,O.jsx)(q,{fallback:r,children:(0,O.jsx)(h.Suspense,{fallback:r,children:(0,O.jsx)(U,{navigate:t,children:(t,n)=>(0,O.jsx)(J,{route:e,context:t,overlays:n})})})})}var X=()=>i(()=>import(`./SessionGate-CnASHl7g.js`),__vite__mapDeps([17,10,18])),ue=(0,h.lazy)(()=>X().then(e=>({default:e.SessionGate}))),de=(0,h.lazy)(()=>i(()=>import(`./RemoteMobileApp-DfDjiBTR.js`).then(e=>({default:e.RemoteMobileApp})),__vite__mapDeps([19,20,13,10])));function Z(e=window){if(e.location.pathname!==`/verse/m/`)try{e.history.replaceState(e.history.state,``,`${n}${e.location.hash}`)}catch{}}function fe(e=typeof document>`u`?null:document){let t=e?.head?.querySelector(`meta[name="viewport"]`),n=t?.getAttribute(`content`)??``;t&&!n.includes(`viewport-fit`)&&t.setAttribute(`content`,`${n}, viewport-fit=cover`)}fe();function pe(e,t){return e===`success`?`authenticated`:t instanceof d?t.status>=500?`unreachable`:`unauthenticated`:`unreachable`}function Q({children:e}){return(0,O.jsx)(`div`,{className:M.app,children:(0,O.jsx)(`div`,{className:M.scroller,style:{paddingTop:`calc(env(safe-area-inset-top) + var(--space-6))`},children:e})})}var $=(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(`p`,{className:M.muted,role:`status`,children:`Connecting to your Mac…`}),(0,O.jsx)(I,{rows:3,label:`Connecting`})]});function me(){return(0,h.useEffect)(()=>{Z(),i(()=>import(`./pwa-BzXJXtDt.js`).then(e=>(e.installMobileHead(document),e.registerMobileServiceWorker())),__vite__mapDeps([21])).catch(()=>void 0)},[]),c()?(0,O.jsx)(h.Suspense,{fallback:(0,O.jsx)(Q,{children:$}),children:(0,O.jsx)(de,{shell:(0,O.jsx)(Y,{}),Button:F,ui:M})}):(0,O.jsx)(he,{})}function he(){let e=u(),[t,n]=(0,h.useState)(!1),[r,i]=(0,h.useState)(0);return(0,h.useEffect)(()=>{if(e!==`checking`)return;X().catch(()=>void 0);let t=!1;return n(!1),l().then(e=>{if(!(t||e))return s(f.key,f.fetch).then(()=>{if(t)return;let e=a(f.key),r=pe(e.status,e.error);r===`unreachable`?n(!0):o(r===`authenticated`)})}),()=>{t=!0}},[e,r]),e===`authenticated`?(0,O.jsx)(Y,{}):(0,O.jsx)(Q,{children:e===`unauthenticated`?(0,O.jsx)(h.Suspense,{fallback:$,children:(0,O.jsx)(ue,{heading:`Connect to your Mac`,command:`ashlr verse`,subject:`Ashlr Verse`,mutationField:!0})}):t?(0,O.jsxs)(`div`,{role:`alert`,children:[(0,O.jsx)(`h1`,{className:M.largeTitle,children:`Can’t reach your Mac`}),(0,O.jsx)(`p`,{className:M.muted,children:`Verse runs on your Mac. It may be asleep, offline, or the connection to it is down. Nothing was sent.`}),(0,O.jsx)(`button`,{type:`button`,className:`${M.btn} ${M.primary}`,onClick:()=>i(e=>e+1),children:`Try again`})]}):$})}export{me as VerseMobileApp,I as a,A as c,E as d,T as f,P as i,j as l,L as n,N as o,D as p,F as r,M as s,H as t,k as u};
|
|
3
|
+
//# sourceMappingURL=VerseMobileApp-ePNuVERe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../../../../../src/web-ui/routes/verse/mobile/mobile-router.ts","../../../../../../src/web-ui/routes/verse/mobile/mobile-context.ts","../../../../../../src/web-ui/routes/verse/mobile/mobile-icons.tsx","../../../../../../src/web-ui/routes/verse/mobile/ui.tsx","../../../../../../src/web-ui/routes/verse/mobile/screens/HomeScreen.tsx","../../../../../../src/web-ui/routes/verse/mobile/MobileShell.tsx","../../../../../../src/web-ui/app/VerseMobileApp.tsx"],"sourcesContent":["/**\n * routes/verse/mobile/mobile-router.ts — where the phone app is, as a hash.\n *\n * The path is fixed (`/verse/m/`, the service worker's scope), so every screen\n * lives in the hash: `#/agents/<id>/changes`. A hash change is a history\n * entry, which is what makes the iOS edge-swipe and Android's back button go\n * back a screen instead of leaving the app. Nothing secret ever goes in it —\n * only screen names and chat ids the read session can list anyway.\n */\nimport { useCallback, useSyncExternalStore } from 'react';\n\nexport type MobileTab = 'home' | 'agents' | 'needs' | 'leader' | 'more';\n\nexport type AgentPane = 'transcript' | 'changes';\n\nexport type MobileRoute =\n | { screen: 'home' }\n | { screen: 'agents' }\n | { screen: 'agent'; id: string; pane: AgentPane }\n | { screen: 'new' }\n | { screen: 'needs' }\n | { screen: 'leader' }\n | { screen: 'more' }\n | { screen: 'fleet' };\n\nconst SIMPLE = new Set(['agents', 'new', 'needs', 'leader', 'more', 'fleet']);\n\n/** `#/agents/abc/changes` → the route. Anything unrecognised is Home, never an error. */\nexport function parseMobileHash(hash: string): MobileRoute {\n const parts = hash.replace(/^#\\/?/, '').split('/').filter(Boolean);\n const [head, id, pane] = parts;\n if (!head) return { screen: 'home' };\n if (head === 'agents' && id) {\n let decoded: string;\n try {\n decoded = decodeURIComponent(id);\n } catch {\n return { screen: 'agents' };\n }\n return { screen: 'agent', id: decoded, pane: pane === 'changes' ? 'changes' : 'transcript' };\n }\n if (SIMPLE.has(head)) return { screen: head as Exclude<MobileRoute['screen'], 'home' | 'agent'> } as MobileRoute;\n return { screen: 'home' };\n}\n\nexport function formatMobileHash(route: MobileRoute): string {\n switch (route.screen) {\n case 'home':\n return '#/';\n case 'agent':\n return `#/agents/${encodeURIComponent(route.id)}${route.pane === 'changes' ? '/changes' : ''}`;\n default:\n return `#/${route.screen}`;\n }\n}\n\n/** Which bottom tab a screen belongs to. */\nexport function tabOf(route: MobileRoute): MobileTab {\n switch (route.screen) {\n case 'home':\n return 'home';\n case 'agents':\n case 'agent':\n case 'new':\n return 'agents';\n case 'needs':\n return 'needs';\n case 'leader':\n return 'leader';\n case 'more':\n case 'fleet':\n return 'more';\n }\n}\n\n/** The tab's root screen (tapping the active tab again pops back to it). */\nexport function tabRoot(tab: MobileTab): MobileRoute {\n return { screen: tab } as MobileRoute;\n}\n\nfunction subscribe(listener: () => void): () => void {\n window.addEventListener('hashchange', listener);\n return () => window.removeEventListener('hashchange', listener);\n}\n\nfunction currentHash(): string {\n return window.location.hash;\n}\n\nexport interface NavigateOptions {\n /** Replace the current entry (a redirect, a tab re-tap) instead of pushing one. */\n replace?: boolean;\n}\n\nexport function navigateMobile(route: MobileRoute, options: NavigateOptions = {}): void {\n const hash = formatMobileHash(route);\n if (hash === window.location.hash || (hash === '#/' && window.location.hash === '')) return;\n if (options.replace) window.location.replace(hash);\n else window.location.hash = hash;\n}\n\n/** The current route; re-renders on every hash change. */\nexport function useMobileRoute(): [MobileRoute, (route: MobileRoute, options?: NavigateOptions) => void] {\n const hash = useSyncExternalStore(subscribe, currentHash, () => '');\n const navigate = useCallback((route: MobileRoute, options?: NavigateOptions) => navigateMobile(route, options), []);\n return [parseMobileHash(hash), navigate];\n}\n","/**\n * routes/verse/mobile/mobile-context.ts — what every phone screen reads from\n * the shell: this device's permissions, whether the Mac is reachable, the\n * shell's one activity loop, and navigation. One provider (MobileRuntime), so\n * a screen never opens a second activity poll or recomputes permissions.\n *\n * Until the runtime's chunk lands (it downloads in parallel with the session\n * probe — MobileShell.tsx) the value is BOOT_CONTEXT: nothing known, nothing\n * actionable. Actions stay hidden until the device's permissions are known.\n */\nimport { createContext, useContext } from 'react';\nimport type { ActivityState } from '../shell/useActivity.js';\nimport type { Reachability } from './connectivity.js';\nimport type { DevicePermissions } from './device-permissions.js';\nimport { navigateMobile, type MobileRoute, type NavigateOptions } from './mobile-router.js';\n\nexport interface MobileContextValue {\n /** False until the runtime (activity loop, permissions) has loaded. */\n ready: boolean;\n permissions: DevicePermissions;\n reachability: Reachability;\n activity: ActivityState;\n navigate: (route: MobileRoute, options?: NavigateOptions) => void;\n /** Needs-you items still waiting (acted-on ones hidden at once); null = unknown. */\n needsCount: number | null;\n /** Agents running a turn now; null = unknown. */\n workingCount: number | null;\n /** Re-poll activity now (pull-to-refresh on any screen). */\n refreshActivity: () => Promise<void>;\n}\n\nexport const BOOT_CONTEXT: MobileContextValue = {\n ready: false,\n permissions: { read: false, act: 'unavailable', actReason: null, source: 'session', deviceLabel: null },\n reachability: 'connecting',\n activity: { status: 'idle', data: null, updatedAt: null, error: null },\n navigate: navigateMobile,\n needsCount: null,\n workingCount: null,\n refreshActivity: () => Promise.resolve(),\n};\n\n/**\n * Whether an action control should render at all: never when the device\n * cannot act (dispatch off, read-only pairing, not yet known). Here rather\n * than in device-permissions.ts so first-paint code can ask without loading it.\n */\nexport function canShowActions(permissions: Pick<DevicePermissions, 'act'>): boolean {\n return permissions.act !== 'unavailable';\n}\n\nexport const MobileContext = createContext<MobileContextValue>(BOOT_CONTEXT);\n\nexport function useMobile(): MobileContextValue {\n return useContext(MobileContext);\n}\n","/**\n * routes/verse/mobile/mobile-icons.tsx — the phone app's glyphs, on the\n * console's icon geometry (components/primitives/icon-base.tsx: 16 box,\n * 1.5 stroke, currentColor, decorative unless titled). Only what the tab bar\n * and first-paint screens draw lives here, so the first paint does not load\n * the console's whole icon set.\n */\nimport { Icon, type IconProps } from '../../../components/primitives/icon-base.js';\n\nexport function HomeGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M2.5 7.2 8 2.8l5.5 4.4V13a.5.5 0 0 1-.5.5H9.6V10H6.4v3.5H3a.5.5 0 0 1-.5-.5Z\" />\n </Icon>\n );\n}\n\nexport function AgentsGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <rect x=\"2\" y=\"2.5\" width=\"12\" height=\"4\" rx=\"1.2\" />\n <rect x=\"2\" y=\"9.5\" width=\"12\" height=\"4\" rx=\"1.2\" />\n <path d=\"M4.5 4.5h.01M4.5 11.5h.01\" />\n </Icon>\n );\n}\n\nexport function NeedsGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M4 6.5a4 4 0 0 1 8 0c0 3 1.2 4.2 1.5 4.5h-11C2.8 10.7 4 9.5 4 6.5Z\" />\n <path d=\"M6.5 13.2a1.6 1.6 0 0 0 3 0\" />\n </Icon>\n );\n}\n\nexport function LeaderGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M2.5 4a1.5 1.5 0 0 1 1.5-1.5h8A1.5 1.5 0 0 1 13.5 4v5.5A1.5 1.5 0 0 1 12 11H7l-3 2.5V11a1.5 1.5 0 0 1-1.5-1.5Z\" />\n </Icon>\n );\n}\n\nexport function MoreGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <circle cx=\"3.5\" cy=\"8\" r=\"0.9\" />\n <circle cx=\"8\" cy=\"8\" r=\"0.9\" />\n <circle cx=\"12.5\" cy=\"8\" r=\"0.9\" />\n </Icon>\n );\n}\n\nexport function PlusGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M8 3v10M3 8h10\" />\n </Icon>\n );\n}\n\nexport function BackGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M10 3 5 8l5 5\" />\n </Icon>\n );\n}\n\nexport function ChevronGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"m6 3.5 4.5 4.5L6 12.5\" />\n </Icon>\n );\n}\n\nexport function MicGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <rect x=\"5.75\" y=\"1.75\" width=\"4.5\" height=\"8\" rx=\"2.25\" />\n <path d=\"M3.5 7.5a4.5 4.5 0 0 0 9 0M8 12v2.25\" />\n </Icon>\n );\n}\n\nexport function LockGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <rect x=\"3\" y=\"7\" width=\"10\" height=\"7\" rx=\"1.5\" />\n <path d=\"M5.5 7V5a2.5 2.5 0 0 1 5 0v2\" />\n </Icon>\n );\n}\n\nexport function FleetGlyph(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M8 2.5v11M2.5 8h11\" />\n <circle cx=\"8\" cy=\"8\" r=\"5.5\" />\n </Icon>\n );\n}\n","/**\n * routes/verse/mobile/ui.tsx — the phone app's first-paint building blocks:\n * a screen (top bar, large title, pull-to-refresh), buttons and loading\n * skeletons. Lists, badges, meters, banners and empty / error states are in\n * ui-parts.tsx, the bottom sheet in sheet.tsx — both off the first paint.\n *\n * Every screen composes these, so a state reads the same everywhere:\n * loading is a skeleton in the shape of what is coming, an empty list says\n * what would appear there, and an error says why in the server's own words\n * with a way to retry. Styling is ui.module.css.\n */\nimport {\n useCallback,\n useId,\n useRef,\n useState,\n type ButtonHTMLAttributes,\n type ReactNode,\n type TouchEvent as ReactTouchEvent,\n} from 'react';\nimport { BackGlyph } from './mobile-icons.js';\nimport styles from './ui.module.css';\n\nexport { styles as ui };\n\nexport function cx(...names: Array<string | false | null | undefined>): string {\n return names.filter(Boolean).join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// Screen\n// ---------------------------------------------------------------------------\n\n/** How far a pull must travel before letting go refreshes. */\nexport const PULL_THRESHOLD_PX = 64;\nconst PULL_MAX_PX = 96;\n\nexport interface ScreenProps {\n /** Shown in the top bar (and as the large title on a tab's root screen). */\n title: string;\n /** Tab root: a large title in the content. Nested screens show only the bar. */\n large?: boolean;\n subtitle?: ReactNode;\n onBack?: () => void;\n backLabel?: string;\n trailing?: ReactNode;\n /** Pull-to-refresh. Resolve when the data is back; the spinner stays until then. */\n onRefresh?: () => Promise<unknown> | void;\n /** Rendered under the top bar, above the scroller (a banner, a segmented control). */\n header?: ReactNode;\n /** Rendered under the scroller (a composer). */\n footer?: ReactNode;\n children: ReactNode;\n /** Test/landmark label for the scroll region. */\n label?: string;\n}\n\nexport function Screen({ title, large = false, subtitle, onBack, backLabel = 'Back', trailing, onRefresh, header, footer, children, label }: ScreenProps) {\n const headingId = useId();\n const scroller = useRef<HTMLDivElement>(null);\n const start = useRef<number | null>(null);\n const [pull, setPull] = useState(0);\n const [refreshing, setRefreshing] = useState(false);\n\n const onTouchStart = useCallback((e: ReactTouchEvent) => {\n if (!onRefresh || refreshing) return;\n start.current = (scroller.current?.scrollTop ?? 0) <= 0 ? e.touches[0]?.clientY ?? null : null;\n }, [onRefresh, refreshing]);\n\n const onTouchMove = useCallback((e: ReactTouchEvent) => {\n if (start.current === null) return;\n const dy = (e.touches[0]?.clientY ?? start.current) - start.current;\n // Resistance: the indicator moves at half the finger's speed, capped.\n setPull(dy > 0 ? Math.min(PULL_MAX_PX, dy / 2) : 0);\n }, []);\n\n const finish = useCallback(() => {\n const armed = pull >= PULL_THRESHOLD_PX / 2 + 8;\n start.current = null;\n setPull(0);\n if (!armed || !onRefresh) return;\n setRefreshing(true);\n void Promise.resolve()\n .then(() => onRefresh())\n .catch(() => undefined)\n .finally(() => setRefreshing(false));\n }, [pull, onRefresh]);\n\n const armed = pull >= PULL_THRESHOLD_PX / 2 + 8;\n return (\n <section className={cx(styles.screen, styles.enter)} aria-labelledby={headingId}>\n <header className={styles.topbar}>\n <div className={styles.topbarLead}>\n {onBack ? (\n <button type=\"button\" className={cx(styles.btn, styles.plain)} onClick={onBack}>\n <BackGlyph size={18} />\n <span>{backLabel}</span>\n </button>\n ) : null}\n </div>\n {large ? <span className={styles.topbarTitle} aria-hidden=\"true\">{title}</span> : <h1 id={headingId} className={styles.topbarTitle}>{title}</h1>}\n <div className={styles.topbarTrail}>{trailing}</div>\n </header>\n {header}\n <div\n ref={scroller}\n className={styles.scroller}\n aria-label={label}\n onTouchStart={onRefresh ? onTouchStart : undefined}\n onTouchMove={onRefresh ? onTouchMove : undefined}\n onTouchEnd={onRefresh ? finish : undefined}\n onTouchCancel={onRefresh ? finish : undefined}\n >\n {onRefresh ? (\n <div className={cx(styles.pull, armed && styles.pullArmed)} style={{ height: refreshing ? '2.5rem' : `${pull}px` }} aria-hidden={!refreshing}>\n {refreshing ? <span className={styles.spinner} role=\"progressbar\" aria-label=\"Refreshing\" /> : pull > 8 ? (armed ? 'Release to refresh' : 'Pull to refresh') : null}\n </div>\n ) : null}\n {large ? <h1 id={headingId} className={styles.largeTitle}>{title}</h1> : null}\n {subtitle ? <p className={styles.subtitle}>{subtitle}</p> : null}\n {children}\n </div>\n {footer}\n </section>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Buttons\n// ---------------------------------------------------------------------------\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'tinted' | 'destructive' | 'destructiveTinted' | 'plain';\n\nexport interface MobileButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n block?: boolean;\n icon?: boolean;\n}\n\nexport function Button({ variant = 'secondary', block = false, icon = false, className, type = 'button', ...rest }: MobileButtonProps) {\n return <button type={type} className={cx(styles.btn, styles[variant], block && styles.block, icon && styles.iconBtn, className)} {...rest} />;\n}\n\n/** A loading list in the shape of the rows that will replace it. */\nexport function SkeletonList({ rows = 3, label = 'Loading' }: { rows?: number; label?: string }) {\n return (\n <div className={styles.group} role=\"status\" aria-label={label} aria-busy=\"true\">\n {Array.from({ length: rows }, (_, i) => (\n <div key={i} className={styles.skeletonRow}>\n <span className={cx('skeleton', styles.skeletonLine)} style={{ width: `${70 - i * 12}%` }} />\n <span className={cx('skeleton', styles.skeletonLine)} style={{ width: `${45 - i * 6}%` }} />\n </div>\n ))}\n </div>\n );\n}\n","/**\n * routes/verse/mobile/screens/HomeScreen.tsx — Home's frame: the title, the\n * New-agent button, pull-to-refresh, and skeletons in the shape of the cards.\n *\n * FIRST PAINT (SPEC-310A's arrangement, as the workbench's Chat section does\n * it): this frame is the phone app's first-paint root, measured by\n * scripts/check-first-paint-budget.mjs against 250 KB — React alone is\n * ~220 KB of that. The cards (HomeBody.tsx: fleet, needs-you, working, spend,\n * seats) are a preloaded chunk: its download starts when this module\n * evaluates, in parallel with the session probe, and it renders synchronously\n * once in. On a warm launch (service worker cache) that is the same frame.\n */\nimport { Suspense } from 'react';\nimport { preloadedLazy } from '../../shell/preloaded.js';\nimport { canShowActions, useMobile } from '../mobile-context.js';\nimport { PlusGlyph } from '../mobile-icons.js';\nimport { Button, Screen, SkeletonList, ui } from '../ui.js';\nimport styles from './HomeScreen.module.css';\n\nconst loadBody = () => import('./HomeBody.js');\nconst Body = preloadedLazy<object>(() => loadBody().then((m) => m.HomeBody));\n\n/** The cards' shape, drawn until they arrive. */\nexport function HomeSkeleton() {\n return (\n <div aria-busy=\"true\" aria-label=\"Loading Home\">\n <div className={`${ui.card} ${styles.fleet}`}>\n <span className={`skeleton ${styles.badgeSkeleton}`} aria-hidden=\"true\" />\n <span className={`skeleton ${ui.skeletonLine}`} style={{ width: '80%' }} aria-hidden=\"true\" />\n </div>\n <div className={styles.stats} aria-hidden=\"true\">\n {[0, 1, 2].map((i) => <div key={i} className={`${styles.stat} skeleton`} style={{ height: '4.5rem' }} />)}\n </div>\n <SkeletonList rows={2} label=\"Loading running agents\" />\n </div>\n );\n}\n\nexport function HomeScreen() {\n const { permissions, navigate, refreshActivity } = useMobile();\n const canAct = canShowActions(permissions);\n const onRefresh = () => Promise.all([refreshActivity(), loadBody().then((m) => m.refreshHome())]);\n return (\n <Screen\n title=\"Verse\"\n large\n subtitle={permissions.act === 'unavailable' ? 'Read-only on this device' : undefined}\n onRefresh={onRefresh}\n trailing={canAct ? (\n <Button variant=\"plain\" icon aria-label=\"New agent\" onClick={() => navigate({ screen: 'new' })}>\n <PlusGlyph size={22} />\n </Button>\n ) : null}\n >\n <Suspense fallback={<HomeSkeleton />}>\n <Body.Slot />\n </Suspense>\n </Screen>\n );\n}\n","/**\n * routes/verse/mobile/MobileShell.tsx — Verse on a phone: five tabs (Home,\n * Agents, Needs you, Leader, More), one screen at a time, one activity loop.\n *\n * FIRST PAINT: this shell and Home's frame are the whole first-paint bundle\n * (check-first-paint-budget.mjs measures them against 250 KB; React is ~220 KB\n * of it). Everything live is a chunk of its own that starts downloading when\n * this module evaluates (preloadedLazy), in parallel with the session probe\n * it would have to wait for anyway:\n *\n * MobileRuntime activity loop, permissions, reachability, sheet, toasts\n * HomeBody Home's cards (screens/HomeScreen.tsx)\n * ScreenHost every other screen, each its own chunk, prefetched idle\n *\n * Until the runtime lands the frame draws with BOOT_CONTEXT (mobile-context.ts):\n * no badges, no actions, skeletons where data goes.\n */\nimport { Component, Suspense, useCallback, useEffect, type ComponentType, type ReactNode } from 'react';\nimport { preloadedLazy } from '../shell/preloaded.js';\nimport { BOOT_CONTEXT, MobileContext, type MobileContextValue } from './mobile-context.js';\nimport { AgentsGlyph, HomeGlyph, LeaderGlyph, MoreGlyph, NeedsGlyph } from './mobile-icons.js';\nimport { tabOf, tabRoot, useMobileRoute, type MobileRoute, type MobileTab } from './mobile-router.js';\nimport type { MobileRuntimeProps } from './MobileRuntime.js';\nimport { HomeScreen } from './screens/HomeScreen.js';\nimport { SkeletonList, ui } from './ui.js';\nimport styles from './MobileShell.module.css';\n\nconst Runtime = preloadedLazy<MobileRuntimeProps>(() => import('./MobileRuntime.js').then((m) => m.MobileRuntime)).Slot;\n\n/** Every screen but Home (ScreenHost.tsx), preloaded the same way. */\nconst loadHost = () => import('./ScreenHost.js');\nconst Host = preloadedLazy<{ route: Exclude<MobileRoute, { screen: 'home' }> }>(() => loadHost().then((m) => m.ScreenHost)).Slot;\n\n/** Warm every screen chunk once the phone is idle. */\nexport function prefetchMobileScreens(): void {\n void loadHost().then((m) => m.prefetchMobileScreens(), () => undefined);\n}\n\nconst TABS: ReadonlyArray<{ id: MobileTab; label: string; Glyph: ComponentType<{ size?: number }> }> = [\n { id: 'home', label: 'Home', Glyph: HomeGlyph },\n { id: 'agents', label: 'Agents', Glyph: AgentsGlyph },\n { id: 'needs', label: 'Needs you', Glyph: NeedsGlyph },\n { id: 'leader', label: 'Leader', Glyph: LeaderGlyph },\n { id: 'more', label: 'More', Glyph: MoreGlyph },\n];\n\nfunction ScreenFallback() {\n return (\n <div className={ui.screen}>\n <div className={ui.scroller}>\n <div className={styles.boot}>\n <SkeletonList rows={4} label=\"Loading screen\" />\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * A chunk that cannot load (offline and not yet cached, or the Mac went away\n * mid-download) must not blank the app: the failed part says so and offers a\n * reload; everything around it keeps working.\n */\nexport class ChunkBoundary extends Component<{ children: ReactNode; fallback?: ReactNode }, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override render() {\n if (!this.state.failed) return this.props.children;\n return this.props.fallback ?? (\n <div className={ui.screen}>\n <div className={ui.scroller}>\n <div className={styles.boot} role=\"alert\">\n <p className={ui.muted}>This screen could not load — this phone is offline or your Mac is out of reach.</p>\n <button type=\"button\" className={`${ui.btn} ${ui.tinted}`} onClick={() => window.location.reload()}>Try again</button>\n </div>\n </div>\n </div>\n );\n }\n}\n\ninterface FrameProps {\n route: MobileRoute;\n context: MobileContextValue;\n overlays?: ReactNode;\n}\n\n/** The tab bar and the current screen; the context comes from the runtime (or BOOT_CONTEXT). */\nfunction Frame({ route, context, overlays }: FrameProps) {\n const current = tabOf(route);\n const { navigate, needsCount, workingCount } = context;\n const onTab = useCallback((tab: MobileTab) => {\n // Re-tapping the active tab pops back to its root, as on iOS.\n navigate(tabRoot(tab), { replace: tab === current });\n }, [navigate, current]);\n\n return (\n <div className={ui.app} data-mobile-app=\"\">\n <main id=\"main\" className={styles.stage}>\n <ChunkBoundary key={route.screen}>\n <Suspense fallback={<ScreenFallback />}>\n {route.screen === 'home' ? <HomeScreen /> : <Host route={route} />}\n </Suspense>\n </ChunkBoundary>\n </main>\n {overlays}\n <nav className={styles.tabbar} aria-label=\"Verse\">\n {TABS.map(({ id, label, Glyph }) => {\n const badge = id === 'needs' ? needsCount : id === 'agents' ? workingCount : null;\n const spoken = badge ? `${label}, ${badge} ${id === 'needs' ? 'waiting' : 'working'}` : label;\n return (\n <button\n key={id}\n type=\"button\"\n className={styles.tab}\n aria-current={current === id ? 'page' : undefined}\n aria-label={spoken}\n onClick={() => onTab(id)}\n >\n <Glyph size={24} />\n <span className={styles.tabLabel} aria-hidden=\"true\">{label}</span>\n {badge ? (\n <span className={styles.tabBadge} data-tone={id === 'agents' ? 'running' : undefined} aria-hidden=\"true\">\n {badge > 99 ? '99+' : badge}\n </span>\n ) : null}\n </button>\n );\n })}\n </nav>\n </div>\n );\n}\n\nexport function MobileShell() {\n const [route, navigate] = useMobileRoute();\n\n useEffect(() => {\n // Safari has no requestIdleCallback; a short timeout after first paint stands in.\n if (typeof window.requestIdleCallback === 'function') {\n const handle = window.requestIdleCallback(prefetchMobileScreens, { timeout: 4000 });\n return () => window.cancelIdleCallback(handle);\n }\n const handle = window.setTimeout(prefetchMobileScreens, 1500);\n return () => window.clearTimeout(handle);\n }, []);\n\n const boot = { ...BOOT_CONTEXT, navigate };\n const bootFrame = <MobileContext.Provider value={boot}><Frame route={route} context={boot} /></MobileContext.Provider>;\n // Without the runtime the frame still navigates and reads; it just knows nothing live.\n return (\n <ChunkBoundary fallback={bootFrame}>\n <Suspense fallback={bootFrame}>\n <Runtime navigate={navigate}>\n {(context, overlays) => <Frame route={route} context={context} overlays={overlays} />}\n </Runtime>\n </Suspense>\n </ChunkBoundary>\n );\n}\n","/**\n * app/VerseMobileApp.tsx — isolated bootstrap for /verse/m, Verse on a phone\n * (pattern: VerseConsoleApp). No workbench, no global dashboard shell, no\n * Hub observer stream: the read session is probed against\n * /api/verse/bootstrap, and the phone shell (routes/verse/mobile/) takes over\n * once authenticated.\n *\n * AUTH IS THE WEB UI'S, UNCHANGED: the SessionGate exchanges the read token\n * for the HttpOnly cookie and (optionally, same screen) puts the mutation\n * token in the memory-only hold. This page stores nothing else. The remote\n * transport (relay / tunnel pairing) plugs in through\n * routes/verse/mobile/device-permissions.ts, never by widening this.\n *\n * On mount it also: moves `/verse/m` to the canonical `/verse/m/` (the\n * service worker's scope), writes the PWA head tags, and registers the\n * service worker (routes/verse/mobile/pwa.ts).\n */\nimport { lazy, Suspense, useEffect, useState, type ReactNode } from 'react';\nimport { adoptInjectedTokens, markCheckComplete } from '../data/auth-store.js';\nimport { isRemoteMobileMode } from '../data/remote-mode.js';\nimport { getQuerySnapshot, runQuery } from '../data/cache.js';\nimport { ApiError } from '../data/client.js';\nimport { useAuthPhase } from '../data/hooks.js';\nimport { MobileShell } from '../routes/verse/mobile/MobileShell.js';\nimport { Button, SkeletonList, ui } from '../routes/verse/mobile/ui.js';\nimport { verseBootstrapQuery } from '../routes/verse/verse-bootstrap-query.js';\nimport { VERSE_MOBILE_PATH } from './console-mode.js';\nimport '../design/global.css';\n\nconst importSessionGate = () => import('../components/auth/SessionGate.js');\nconst SessionGate = lazy(() => importSessionGate().then((m) => ({ default: m.SessionGate })));\nconst RemoteMobileApp = lazy(() => import('../routes/verse/mobile/RemoteMobileApp.js').then((m) => ({ default: m.RemoteMobileApp })));\n\n/** `/verse/m` → `/verse/m/`, keeping the hash (the screen). */\nexport function canonicalizeMobilePath(win: Window = window): void {\n if (win.location.pathname === VERSE_MOBILE_PATH) return;\n try {\n win.history.replaceState(win.history.state, '', `${VERSE_MOBILE_PATH}${win.location.hash}`);\n } catch {\n /* the app works at either path; only offline launch needs the slash */\n }\n}\n\n/**\n * Safe-area insets are 0 until the viewport opts in, so this runs as the\n * module evaluates — before the first paint, not after pwa.ts's chunk — or a\n * home-screen launch would draw under the notch for a frame.\n */\nexport function coverViewport(doc: Document | null = typeof document === 'undefined' ? null : document): void {\n const meta = doc?.head?.querySelector('meta[name=\"viewport\"]');\n const content = meta?.getAttribute('content') ?? '';\n if (meta && !content.includes('viewport-fit')) meta.setAttribute('content', `${content}, viewport-fit=cover`);\n}\n\ncoverViewport();\n\n/**\n * The probe's answer. A probe that never reached the Mac (asleep, offline,\n * the tunnel down) or reached a failing one is not a reason to ask for a\n * token — it gets its own screen and a retry.\n */\nexport function probeOutcome(status: string, error: unknown): 'authenticated' | 'unauthenticated' | 'unreachable' {\n if (status === 'success') return 'authenticated';\n // A 4xx is the Mac answering (401: no session; 404: a build without Verse) — the gate explains it.\n if (error instanceof ApiError) return error.status >= 500 ? 'unreachable' : 'unauthenticated';\n return 'unreachable';\n}\n\n/** The page before the shell: connecting, out of reach, or the session gate. One frame for all three. */\nfunction Boot({ children }: { children: ReactNode }) {\n return (\n <div className={ui.app}>\n <div className={ui.scroller} style={{ paddingTop: 'calc(env(safe-area-inset-top) + var(--space-6))' }}>{children}</div>\n </div>\n );\n}\n\nconst CONNECTING = (\n <>\n <p className={ui.muted} role=\"status\">Connecting to your Mac…</p>\n <SkeletonList rows={3} label=\"Connecting\" />\n </>\n);\n\nexport function VerseMobileApp() {\n useEffect(() => {\n canonicalizeMobilePath();\n void import('../routes/verse/mobile/pwa.js')\n .then((pwa) => {\n pwa.installMobileHead(document);\n return pwa.registerMobileServiceWorker();\n })\n .catch(() => undefined);\n }, []);\n // The gateway marker is injected by the gateway into this HTML response.\n // Decide before mounting the local token gate or starting its read probe.\n return isRemoteMobileMode()\n ? <Suspense fallback={<Boot>{CONNECTING}</Boot>}><RemoteMobileApp shell={<MobileShell />} Button={Button} ui={ui} /></Suspense>\n : <LocalVerseMobileApp />;\n}\n\nfunction LocalVerseMobileApp() {\n const phase = useAuthPhase();\n const [unreachable, setUnreachable] = useState(false);\n const [attempt, setAttempt] = useState(0);\n\n useEffect(() => {\n if (phase !== 'checking') return;\n void importSessionGate().catch(() => undefined);\n let cancelled = false;\n setUnreachable(false);\n void adoptInjectedTokens().then((adopted) => {\n if (cancelled || adopted) return;\n return runQuery(verseBootstrapQuery.key, verseBootstrapQuery.fetch).then(() => {\n if (cancelled) return;\n const snap = getQuerySnapshot(verseBootstrapQuery.key);\n const outcome = probeOutcome(snap.status, snap.error);\n if (outcome === 'unreachable') setUnreachable(true);\n else markCheckComplete(outcome === 'authenticated');\n });\n });\n return () => {\n cancelled = true;\n };\n }, [phase, attempt]);\n\n if (phase === 'authenticated') return <MobileShell />;\n return (\n <Boot>\n {phase === 'unauthenticated' ? (\n <Suspense fallback={CONNECTING}>\n <SessionGate heading=\"Connect to your Mac\" command=\"ashlr verse\" subject=\"Ashlr Verse\" mutationField />\n </Suspense>\n ) : unreachable ? (\n <div role=\"alert\">\n <h1 className={ui.largeTitle}>Can’t reach your Mac</h1>\n <p className={ui.muted}>Verse runs on your Mac. It may be asleep, offline, or the connection to it is down. Nothing was sent.</p>\n <button type=\"button\" className={`${ui.btn} ${ui.primary}`} onClick={() => setAttempt((n) => n + 1)}>Try again</button>\n </div>\n ) : CONNECTING}\n </Boot>\n );\n}\n"],"file":"VerseMobileApp-ePNuVERe.js"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,s as n}from"./index-BC5Uslm5.js";import{C as r,M as i,T as a,V as o,a as s,i as c,n as l,o as u,t as d}from"./global-w7KDTTi0.js";import{t as f}from"./verse-bootstrap-query-B3vFD9XK.js";var p=e(n(),1),ee=[`command`,`fleet`,`growth`,`mind`,`chat`,`agents`],te=[`settings`,`apps`,`usage`,`wiki`,`playbooks`,`automations`],ne=[...ee,...te];function re(e){return typeof e==`string`&&ne.includes(e)}var m={chat:{section:`chat`,openNeedsYou:!1},autonomy:{section:`fleet`,openNeedsYou:!1},approvals:{section:`command`,openNeedsYou:!0},usage:{section:`usage`,openNeedsYou:!1},settings:{section:`settings`,openNeedsYou:!1},mcp:{section:`apps`,openNeedsYou:!1}};function ie(e){return typeof e==`string`?Object.prototype.hasOwnProperty.call(m,e)?m[e]:re(e)?{section:e,openNeedsYou:!1}:null:null}var ae={claude:`C`,codex:`X`,grok:`G`,local:`L`,devin:`D`},oe=[`approvals`,`fleet`,`chats`,`accounts`],se={approval:`approvals`,"owner-lane-pr":`approvals`,"class-c":`approvals`,"veto-window":`fleet`,"leader-question":`fleet`,"owner-hold":`fleet`,quarantine:`fleet`,revert:`fleet`,grant:`fleet`,kill:`fleet`,"chat-failed":`chats`,"queue-held":`chats`,"agent-plan":`chats`,"agent-spend":`chats`,"agent-ci":`chats`,"agent-setup":`chats`,"agent-waiting":`chats`,reconnect:`accounts`,repin:`accounts`},ce={approve:`A`,reject:`R`,veto:`V`,done:`E`};function le(e){return typeof e==`string`&&e.length<=512&&e.startsWith(`/api/`)&&!e.startsWith(`//`)&&!e.includes(`..`)&&!/[\s\\]/.test(e)}var h=`/api/verse/activity`,g=`/api/verse/activity/seen`,_=`/api/verse/session-meta`,ue=`/api/verse/session-controls`,de=`/api/verse/session-controls/defaults`,fe=`/api/verse/attachments`,pe=`/api/verse/queue`,me=`/api/verse/files`,he=8388608,ge=`/api/verse/terminal`,_e=16384,ve=`/api/verse/terminal/redact`,ye=`/api/verse/terminal/launch`,be=`/api/verse/terminal/stream`,v=`/api/verse/terminal/history`,xe=`/api/verse/terminal/history/clear`,Se=`/api/verse/terminal/settings`,Ce=`/api/verse/terminal/assist`,we=`/api/verse/preview/targets`,Te=`/api/verse/preview/raw`;function Ee(e){let t;try{t=new URL(e)}catch{return!1}return t.protocol===`http:`&&(t.hostname===`127.0.0.1`||t.hostname===`localhost`)&&t.username===``&&t.password===``}var De=`/api/verse/apps`,y={request:null,phase:`confirm`,error:null},b=y,x=new Set;function S(e){b=e;for(let e of[...x])e()}function Oe(e){return b.request?!1:e.skipConfirm?(e.token&&!a()?S({request:e,phase:`token`,error:null}):T(e),!0):(S({request:e,phase:`confirm`,error:null}),!0)}function ke(){return b.request!==null}function C(e){return b.request===e&&b.phase===`confirm`}function w(e){return e instanceof l?"This server was started without dispatch, so actions are unavailable. Run `ashlr verse` to act.":e instanceof d?e.status===401?"The mutation token was rejected. Unlock again with the token `ashlr verse` printed.":e.status===409?e.detail??`Something changed underneath this action. Refresh and try again.`:e.detail??`The server refused (HTTP ${e.status}).`:e instanceof Error&&e.message?e.message:`Something went wrong.`}async function T(e){S({request:e,phase:`running`,error:null});try{await e.run(),S(y),e.onDone?.()}catch(t){let n=w(t);S(e.skipConfirm?y:{request:e,phase:`confirm`,error:n}),e.onError?.(n)}}function Ae(e){let{request:t}=b;if(!(!t||b.phase!==`confirm`||e&&t!==e)){if(t.token&&!a()){S({request:t,phase:`token`,error:null});return}T(t)}}function je(){b.phase!==`running`&&S(y)}function Me(){let{request:e}=b;e&&(a()?T(e):S(y))}function Ne(e){return x.add(e),()=>x.delete(e)}function Pe(){return(0,p.useSyncExternalStore)(Ne,()=>b,()=>b)}var Fe=t(),E=(0,p.createContext)(!0);function Ie({visible:e,children:t}){let n=(0,p.useContext)(E);return(0,Fe.jsx)(E.Provider,{value:n&&e,children:t})}function D(){return(0,p.useContext)(E)}function Le(){return typeof document>`u`||document.visibilityState!==`hidden`}function Re(e){return typeof document>`u`?()=>{}:(document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e))}function ze(){return(0,p.useSyncExternalStore)(Re,Le,()=>!0)}var O=2e3;function Be(e,t,n={}){let r=D(),i=ze(),a=r&&i,o=(n.enabled??!0)&&a,s=n.refreshOnShow??!0,c=Math.max(O,Number.isFinite(t)?t:O),l=(0,p.useRef)(e);l.current=e;let u=(0,p.useRef)(null);(0,p.useEffect)(()=>{let e=u.current;if(u.current=a,!o)return;e===!1&&s&&l.current();let t=setInterval(()=>l.current(),c);return()=>clearInterval(t)},[o,a,c,s])}var Ve=5e3,He=3e4,Ue=(e,t)=>c(e,t),k={status:`idle`,data:null,updatedAt:null,error:null},A=null,j=null,M=null,N=0,P=new Set,F=new Set;function I(e){k=e;for(let e of[...P])e()}function L(){return typeof document<`u`&&document.visibilityState===`hidden`}function R(){if(j&&clearTimeout(j),j=null,N===0)return;let e=Math.max(O,L()?He:Ve);j=setTimeout(()=>{z()},e)}function z(){if(M)return M;k.status===`idle`&&I({...k,status:`loading`});let e=A?`${h}?since=${encodeURIComponent(A)}`:h;return M=(async()=>{try{let t=await Ue(e),n=A===null;if(A=typeof t.cursor==`string`?t.cursor:null,I({status:`ready`,data:t,updatedAt:Date.now(),error:null}),!n&&Array.isArray(t.completions)&&t.completions.length>0)for(let e of[...F])try{e(t.completions)}catch{}}catch(e){e instanceof d&&e.status===404?I({status:`unavailable`,data:null,updatedAt:k.updatedAt,error:null}):e instanceof d&&e.status===400&&A?(A=null,I({...k,status:k.data?`stale`:`loading`})):I({...k,status:k.data?`stale`:`unavailable`,error:u(e)})}finally{M=null,R()}})(),M}function B(){!L()&&N>0?z():R()}function We(){N+=1,N===1&&(typeof document<`u`&&document.addEventListener(`visibilitychange`,B),z())}function Ge(){N=Math.max(0,N-1),!(N>0)&&(j&&clearTimeout(j),j=null,typeof document<`u`&&document.removeEventListener(`visibilitychange`,B))}function Ke(e){return P.add(e),We(),()=>{P.delete(e),Ge()}}function V(){return k}function qe(){return(0,p.useSyncExternalStore)(Ke,V,V)}function Je(e){return F.add(e),()=>F.delete(e)}var H=`verse-sessions`,Ye={key:H,fetch:e=>c(`/api/verse/sessions`,e)};function U(e,t=``){return`/api/verse/sessions/${encodeURIComponent(e)}${t}`}function Xe(e,t){return c(U(e),t)}var W=class extends Error{constructor(){super(`Unlock actions with the mutation token before chatting.`),this.name=`VerseMutationLockedError`}};async function G(e,t){let n=r();if(!n)throw new W;let a=await s(e,t,n);return i(),a}function K(){o(H),o(f)}async function Ze(e){let t=await G(`/api/verse/sessions`,e);return K(),t}async function Qe(e,t){let n={text:t},r=await G(U(e,`/turns`),n);return o(H),r}async function $e(e){await G(U(e,`/cancel`),{}),o(H)}async function et(e){let t=await G(U(e,`/terminate`),{confirm:!0});return o(H),{cancelled:t.cancelled,terminated:t.terminated}}async function tt(e){await G(U(e,`/delete`),{}),K()}async function nt(e,t){let n=await G(U(e,`/rename`),{title:t});return o(H),n}var q=`verse-workspaces`,J=`verse-autonomy-scope`,rt={key:q,fetch:e=>c(`/api/verse/workspaces`,e)},it={key:J,fetch:e=>c(`/api/verse/autonomy-scope`,e)};function at(e,t){return c(U(e,`/roots`),t)}function Y(){o(q),o(J),o(f)}async function ot(e){let t=await G(`/api/verse/workspaces`,e);return Y(),t}async function X(e,t){let n=await G(`/api/verse/workspaces/${encodeURIComponent(e)}/update`,t);return Y(),n}async function st(e){await G(`/api/verse/workspaces/${encodeURIComponent(e)}/delete`,{}),Y()}async function ct(e,t){await G(`/api/verse/workspaces/priority`,{path:e,priority:t}),Y()}async function lt(e){await G(`/api/verse/workspaces/focus`,{sectionId:e}),Y()}var Z=`verse-activity`,Q=`verse-session-meta`;async function $(e,t){try{return await c(e,t)}catch(e){if(e instanceof d&&e.status===404)return null;throw e}}var ut={key:Z,fetch:e=>$(h,e)},dt={key:Q,fetch:e=>$(_,e)};async function ft(e,t){let n={};typeof t.pinned==`boolean`&&(n.pinned=t.pinned),typeof t.archived==`boolean`&&(n.archived=t.archived);let r=await G(`${_}/${encodeURIComponent(e)}`,n);return o(Q),r}async function pt(e,t){let n=r();if(!n)return!1;let i={sessionId:e,turnCount:t};try{return await s(g,i,n),!0}catch{return!1}}export{ue as $,Ie as A,Pe as B,U as C,Je as D,V as E,w as F,g as G,ce as H,Me as I,he as J,De as K,C as L,D as M,je as N,z as O,Ae as P,pe as Q,ke as R,dt as S,rt as T,oe as U,ae as V,se as W,Te as X,me as Y,we as Z,ft as _,Ze as a,ye as at,ut as b,st as c,Se as ct,K as d,le as dt,de as et,pt as f,ie as ft,ct as g,lt as h,$e as i,_e as it,Be as j,qe as k,Xe as l,be as lt,Qe as m,H as n,xe as nt,ot as o,ge as ot,nt as p,fe as q,W as r,v as rt,tt as s,ve as st,Z as t,Ce as tt,at as u,Ee as ut,et as v,Ye as w,it as x,X as y,Oe as z};
|
|
2
|
+
//# sourceMappingURL=VerseShared-Bf-XTHCh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerseShared-Bf-XTHCh.js","names":[],"sources":["../../../../../../src/core/verse/workbench-types.ts","../../../../../../src/web-ui/routes/verse/shell/guard-store.ts","../../../../../../src/web-ui/routes/verse/shell/section-visibility.tsx","../../../../../../src/web-ui/routes/verse/shell/useActivity.ts","../../../../../../src/web-ui/routes/verse/verse-queries.ts"],"sourcesContent":["/**\n * Verse 3.10 workbench — cross-unit contracts (unit C0, frozen once written).\n *\n * SPEC-310C builds the workbench in parallel: C1 shell/palette/activity, C2\n * chat + dock, C3 composer, C4 terminal + preview, C5 git, C6 apps, C7\n * surfaces, C8 native — and Track B's autonomy units feed it (R1). Every shape\n * two of those units exchange is declared HERE, once, so each can build\n * against fixtures on day 0 and the pieces fit when they land:\n *\n * §1 information architecture (surfaces, tray, the v2 → v3 migration)\n * §2 Needs you (R1: the item B-U1 / B-U5 / B-U8 export, and the drawer acts on)\n * §3 activity + session meta (C1; the engine signatures C3 implements)\n * §4 session controls, attachments, queue, files (C3)\n * §5 terminal (C4) §6 preview (C4) §7 git / review / PR (C5)\n * §8 apps & accounts (C6)\n * §9 the route families C0 mounts in verse-api.ts\n *\n * Honesty rule (docs/VERSE-TELEMETRY-V2.md): `null` means UNKNOWN, never\n * \"none\" or \"zero\". Copy is operator language with units; no file paths,\n * stack traces or secrets in any string field.\n *\n * BROWSER-SAFE: the web bundle imports this (type-only via data/api-types.ts,\n * plus the plain constants). Type-only imports and plain data — no node:\n * modules, ever.\n */\nimport type {\n VerseEffort,\n VerseEngine,\n VersePermissionMode,\n VerseProgressPhase,\n VerseSessionControls,\n} from './types.js';\n\nexport type { VerseEffort, VersePermissionMode, VerseSessionControls };\n\n// ===========================================================================\n// §1 Information architecture (SPEC-310C §0.1, SPEC-310B §6)\n// ===========================================================================\n\n/**\n * The rail, in ⌘1–⌘6 order. Chat moved from ⌘1 to ⌘5 in 3.10; 3.16 adds the\n * Agents board at ⌘6 (every chat and agent across repos, by attention).\n */\nexport const WORKBENCH_SURFACES = ['command', 'fleet', 'growth', 'mind', 'chat', 'agents'] as const;\nexport type WorkbenchSurfaceId = (typeof WORKBENCH_SURFACES)[number];\n\n/**\n * Sections reached from the gear tray, not the rail (Shortcuts is an overlay,\n * not a section). 3.15 adds the private repo wiki here — and to ⌘K — rather\n * than as a sixth rail slot: it is a reference you open, not a surface you watch.\n * Playbooks (3.15) join it for the same reason: a library you open and edit.\n * Automations (3.15) sit here too: standing instructions you set up and check\n * on, not a live surface.\n */\nexport const WORKBENCH_TRAY_SECTIONS = ['settings', 'apps', 'usage', 'wiki', 'playbooks', 'automations'] as const;\nexport type WorkbenchTraySectionId = (typeof WORKBENCH_TRAY_SECTIONS)[number];\n\nexport type WorkbenchSectionId = WorkbenchSurfaceId | WorkbenchTraySectionId;\n\nexport const WORKBENCH_SECTION_IDS: readonly WorkbenchSectionId[] = [...WORKBENCH_SURFACES, ...WORKBENCH_TRAY_SECTIONS];\n\nexport function isWorkbenchSectionId(value: unknown): value is WorkbenchSectionId {\n return typeof value === 'string' && (WORKBENCH_SECTION_IDS as readonly string[]).includes(value);\n}\n\n/** The `section` values `ashlr.verse.ui.v2` could hold. */\nexport type LegacyVerseSectionId = 'chat' | 'autonomy' | 'approvals' | 'usage' | 'settings' | 'mcp';\n\nexport interface SectionMigration {\n section: WorkbenchSectionId;\n /** Approvals became the Needs-you drawer: land on Command WITH the drawer open. */\n openNeedsYou: boolean;\n}\n\n/**\n * v2 → v3 (SPEC-310C §0.1): autonomy → fleet, approvals → command + drawer,\n * mcp → apps. Chat, Usage and Settings keep their ids.\n */\nexport const LEGACY_SECTION_MIGRATION: Readonly<Record<LegacyVerseSectionId, SectionMigration>> = {\n chat: { section: 'chat', openNeedsYou: false },\n autonomy: { section: 'fleet', openNeedsYou: false },\n approvals: { section: 'command', openNeedsYou: true },\n usage: { section: 'usage', openNeedsYou: false },\n settings: { section: 'settings', openNeedsYou: false },\n mcp: { section: 'apps', openNeedsYou: false },\n};\n\n/**\n * A stored `section` value → its v3 home. A v3 id passes through; a v2 id is\n * migrated; anything else (a hand-edited or future value) is null, and the\n * caller falls back to its own default rather than to a guess.\n */\nexport function migrateSectionId(value: unknown): SectionMigration | null {\n if (typeof value !== 'string') return null;\n if (Object.prototype.hasOwnProperty.call(LEGACY_SECTION_MIGRATION, value)) {\n return LEGACY_SECTION_MIGRATION[value as LegacyVerseSectionId];\n }\n return isWorkbenchSectionId(value) ? { section: value, openNeedsYou: false } : null;\n}\n\n/**\n * Engine identity is a 2px tick plus a one-letter monogram — never a vendor\n * logo (SPEC-310C §6). One table so the rail, sidebar, Apps and the native\n * notifications all print the same letter.\n */\nexport const ENGINE_MONOGRAM: Readonly<Record<VerseEngine, 'C' | 'X' | 'G' | 'L' | 'D'>> = {\n claude: 'C',\n codex: 'X',\n grok: 'G',\n local: 'L',\n devin: 'D',\n};\n\n// ===========================================================================\n// §2 Needs you (cross-track request R1)\n// ===========================================================================\n//\n// ONE inbox for everything waiting on Mason: approvals, fleet holds, Leader\n// questions and vetoes, grant renewal, failed chats, seats to reconnect.\n// Producers:\n// - C1 derives `approvals` (inbox), `chats` and `accounts` (A2 health);\n// - B-U1, B-U5 and B-U8 each EXPORT `needsYouItems(): NeedsYouItem[]` —\n// see NEEDS_YOU_PROVIDERS for where C1's activity route looks for them.\n// An item carries its own actions (route + confirmation), so the drawer is\n// generic: it never needs to know what a grant or an owner-lane PR is.\n\nexport const NEEDS_YOU_SOURCES = ['approvals', 'authority', 'fleet', 'leader', 'chats', 'accounts'] as const;\nexport type NeedsYouSource = (typeof NEEDS_YOU_SOURCES)[number];\n\n/**\n * What the item is. A new kind is a C0 contract change (send the request):\n * the drawer's split and the native notification copy both key off it.\n */\nexport const NEEDS_YOU_KINDS = [\n // approvals split\n 'approval', // an inbox proposal waiting for approve / reject\n 'owner-lane-pr', // G1: a fleet PR on the owner lane — never auto-merged\n 'class-c', // a Leader action outside the grant: Mason only, argument attached\n // fleet split\n 'veto-window', // a class-B Leader action that applies when its window closes\n 'leader-question', // the memo's questionsForMason\n 'owner-hold', // a repo on owner-hold (one-click resume)\n 'quarantine', // a repo quarantined after a post-merge red\n 'revert', // a fleet merge was reverted\n 'grant', // grant renewal / expiring / paused (\"authority code changed\")\n 'kill', // the fleet is stopped (KILL or a soft kill)\n // chats split\n 'chat-failed', // a turn failed and has not been looked at\n 'queue-held', // a queued follow-up is held after a failure or Stop\n 'agent-plan', // 3.16: an agent's plan waits for approval (Plan first)\n 'agent-spend', // 3.16: an agent is at 80% of its spend cap, or reached it\n 'agent-ci', // 3.16: an agent's PR is red with no auto-fix left, or cannot merge\n 'agent-setup', // 3.16: an agent workspace's setup script failed (its prompt is held)\n 'agent-waiting', // 3.15: a CLI agent in a terminal tab is waiting on the operator (Claude Code, Codex…)\n // accounts split\n 'reconnect', // a seat is signed out or its credential is expiring\n 'repin', // a seat is pinned to an older CLI than the newest installed\n] as const;\nexport type NeedsYouKind = (typeof NEEDS_YOU_KINDS)[number];\n\n/** The drawer's splits besides All (SPEC-310C §1: H / L switch between them). */\nexport const NEEDS_YOU_CATEGORIES = ['approvals', 'fleet', 'chats', 'accounts'] as const;\nexport type NeedsYouCategory = (typeof NEEDS_YOU_CATEGORIES)[number];\n\n/** Split is a pure function of kind, so a producer can never file an item in the wrong one. */\nexport const NEEDS_YOU_KIND_CATEGORY: Readonly<Record<NeedsYouKind, NeedsYouCategory>> = {\n approval: 'approvals',\n 'owner-lane-pr': 'approvals',\n 'class-c': 'approvals',\n 'veto-window': 'fleet',\n 'leader-question': 'fleet',\n 'owner-hold': 'fleet',\n quarantine: 'fleet',\n revert: 'fleet',\n grant: 'fleet',\n kill: 'fleet',\n 'chat-failed': 'chats',\n 'queue-held': 'chats',\n 'agent-plan': 'chats',\n 'agent-spend': 'chats',\n 'agent-ci': 'chats',\n 'agent-setup': 'chats',\n 'agent-waiting': 'chats',\n reconnect: 'accounts',\n repin: 'accounts',\n};\n\nexport function needsYouCategory(item: Pick<NeedsYouItem, 'kind'>): NeedsYouCategory {\n return NEEDS_YOU_KIND_CATEGORY[item.kind];\n}\n\n/** Same vocabulary as ReasoningInsight severity. */\nexport type NeedsYouSeverity = 'info' | 'warn' | 'high';\n\n/**\n * Drawer keys (SPEC-310C §1): A approves, R rejects, V vetoes, E marks done.\n * `resume`, `renew` and `fix` are buttons only.\n */\nexport const NEEDS_YOU_ACTION_KINDS = ['approve', 'reject', 'veto', 'done', 'resume', 'renew', 'fix'] as const;\nexport type NeedsYouActionKind = (typeof NEEDS_YOU_ACTION_KINDS)[number];\n\nexport const NEEDS_YOU_ACTION_KEYS: Readonly<Partial<Record<NeedsYouActionKind, 'A' | 'R' | 'V' | 'E'>>> = {\n approve: 'A',\n reject: 'R',\n veto: 'V',\n done: 'E',\n};\n\nexport interface NeedsYouConfirm {\n title: string;\n body: string;\n confirmLabel: string;\n}\n\nexport interface NeedsYouAction {\n kind: NeedsYouActionKind;\n /** Button text, operator language: \"Approve\", \"Veto\", \"Resume repo\". */\n label: string;\n /**\n * The same-origin route the drawer POSTs (JSON body, mutation token) — always\n * under `/api/` (isNeedsYouItem enforces it). Null when the action cannot be\n * taken from the page (it needs Touch ID or a terminal): the drawer opens the\n * item's `target` instead, where that flow lives.\n */\n request: { method: 'POST'; path: string; body: Record<string, unknown> } | null;\n /**\n * Dialog text. The drawer confirms approve / reject / veto ALWAYS\n * (SPEC-310C: keyboard triage goes through confirmation, then the token) —\n * a null here gets its generic copy; other kinds confirm only when set.\n */\n confirm: NeedsYouConfirm | null;\n /** Painted as a destructive action (reject, veto, close). */\n destructive: boolean;\n}\n\n/** Where Enter goes. */\nexport type NeedsYouTarget =\n | { kind: 'session'; sessionId: string }\n | { kind: 'approval'; proposalId: string }\n | { kind: 'section'; section: WorkbenchSectionId; anchor: string | null }\n | { kind: 'seat'; seatId: string }\n /** 3.15: a terminal tab (and the chat it belongs to): the Terminal pane opens on it. */\n | { kind: 'terminal'; sessionId: string | null; tabId: string }\n /** Opened outside the app (a GitHub PR). https only. */\n | { kind: 'url'; url: string };\n\n/** What the row is about, for its meta line. Every field null when not applicable. */\nexport interface NeedsYouSubject {\n repo: string | null;\n pr: number | null;\n seatId: string | null;\n sessionId: string | null;\n engine: VerseEngine | null;\n}\n\nexport interface NeedsYouItem {\n /**\n * Stable across polls AND restarts — `<source>:<kind>:<ref>` (e.g.\n * `fleet:owner-hold:ashlrai/binshield`). The drawer's selection, \"seen\" and\n * native \"N new\" counting all key on it.\n */\n id: string;\n source: NeedsYouSource;\n kind: NeedsYouKind;\n severity: NeedsYouSeverity;\n /** One line, ≤ 120 chars, operator language with units. Never a path or a trace. */\n title: string;\n /** Optional second line — the Leader's argument, the failing check. */\n detail: string | null;\n /** ISO time it became actionable. */\n since: string;\n /** ISO time it stops being actionable on its own (veto window close, grant expiry); null = never. */\n expiresAt: string | null;\n subject: NeedsYouSubject;\n target: NeedsYouTarget;\n actions: NeedsYouAction[];\n}\n\n/**\n * R1: `export function needsYouItems(): NeedsYouItem[]`. PURE and served from\n * the producer's own cache: activity calls it on every poll (Rust every 5 s),\n * so it must return in well under a millisecond and never do I/O on the\n * caller's stack. A producer that cannot answer throws — activity then reports\n * `sources.<source>: 'error'` rather than an all-clear it cannot vouch for.\n */\nexport type NeedsYouItemsProvider = () => NeedsYouItem[];\n\n/**\n * Where C1's activity route lazy-imports each Track B producer from: the\n * unit's own mounted API module (§9), which activity can import without a\n * load-time edge into core/{authority,fleet,vision}. A module that has not\n * landed makes activity report that source `unavailable` — never a false\n * all-clear. Moving a producer is a C0 contract change.\n */\nexport const NEEDS_YOU_PROVIDERS = [\n { source: 'authority', owner: 'B-U1', module: 'src/core/verse/authority-api.ts', exportName: 'needsYouItems' },\n { source: 'fleet', owner: 'B-U5', module: 'src/core/verse/fleet-live-api.ts', exportName: 'needsYouItems' },\n { source: 'leader', owner: 'B-U8', module: 'src/core/verse/leader-api.ts', exportName: 'needsYouItems' },\n] as const satisfies readonly { source: NeedsYouSource; owner: string; module: string; exportName: 'needsYouItems' }[];\n\nexport const NEEDS_YOU_TITLE_MAX = 120;\nexport const NEEDS_YOU_DETAIL_MAX = 400;\nconst NEEDS_YOU_ID_MAX = 200;\n\nconst ISO_RE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction isIso(value: unknown): value is string {\n return typeof value === 'string' && ISO_RE.test(value) && !Number.isNaN(Date.parse(value));\n}\n\nfunction isNullableString(value: unknown, max: number): boolean {\n return value === null || (typeof value === 'string' && value.length <= max);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * A same-origin API route: `/api/…`, no scheme, no host, no `..`, no\n * backslash, no whitespace. The drawer POSTs these WITH the mutation token, so\n * an item must never be able to aim that token anywhere else.\n */\nexport function isSafeApiRoute(path: unknown): path is string {\n return typeof path === 'string'\n && path.length <= 512\n && path.startsWith('/api/')\n && !path.startsWith('//')\n && !path.includes('..')\n && !/[\\s\\\\]/.test(path);\n}\n\nfunction isTarget(value: unknown): value is NeedsYouTarget {\n if (!isRecord(value)) return false;\n switch (value['kind']) {\n case 'session':\n return typeof value['sessionId'] === 'string' && value['sessionId'].length > 0;\n case 'approval':\n return typeof value['proposalId'] === 'string' && value['proposalId'].length > 0;\n case 'section':\n return isWorkbenchSectionId(value['section']) && isNullableString(value['anchor'], 200);\n case 'seat':\n return typeof value['seatId'] === 'string' && value['seatId'].length > 0;\n case 'url':\n return typeof value['url'] === 'string' && /^https:\\/\\/[^\\s]+$/.test(value['url']) && value['url'].length <= 2048;\n case 'terminal':\n return typeof value['tabId'] === 'string' && /^t-[a-z0-9]{1,32}$/.test(value['tabId'])\n && (value['sessionId'] === null || (typeof value['sessionId'] === 'string' && value['sessionId'].length > 0));\n default:\n return false;\n }\n}\n\nfunction isAction(value: unknown): value is NeedsYouAction {\n if (!isRecord(value)) return false;\n if (!(NEEDS_YOU_ACTION_KINDS as readonly unknown[]).includes(value['kind'])) return false;\n if (typeof value['label'] !== 'string' || value['label'].length === 0 || value['label'].length > 60) return false;\n if (typeof value['destructive'] !== 'boolean') return false;\n const request = value['request'];\n if (request !== null) {\n if (!isRecord(request) || request['method'] !== 'POST' || !isSafeApiRoute(request['path']) || !isRecord(request['body'])) {\n return false;\n }\n }\n const confirm = value['confirm'];\n if (confirm !== null) {\n if (!isRecord(confirm)) return false;\n for (const key of ['title', 'body', 'confirmLabel'] as const) {\n if (typeof confirm[key] !== 'string' || (confirm[key] as string).length === 0) return false;\n }\n }\n return true;\n}\n\n/**\n * Boundary check for items that come from ANOTHER unit's producer. Activity\n * drops (and counts) anything that fails, so one malformed producer degrades\n * to \"that source errored\" instead of breaking the drawer or smuggling a\n * foreign route into a token-bearing POST.\n */\nexport function isNeedsYouItem(value: unknown): value is NeedsYouItem {\n if (!isRecord(value)) return false;\n const id = value['id'];\n if (typeof id !== 'string' || id.length === 0 || id.length > NEEDS_YOU_ID_MAX) return false;\n if (!(NEEDS_YOU_SOURCES as readonly unknown[]).includes(value['source'])) return false;\n if (!(NEEDS_YOU_KINDS as readonly unknown[]).includes(value['kind'])) return false;\n if (!['info', 'warn', 'high'].includes(value['severity'] as string)) return false;\n const title = value['title'];\n if (typeof title !== 'string' || title.trim().length === 0 || title.length > NEEDS_YOU_TITLE_MAX) return false;\n if (!isNullableString(value['detail'], NEEDS_YOU_DETAIL_MAX)) return false;\n if (!isIso(value['since'])) return false;\n if (value['expiresAt'] !== null && !isIso(value['expiresAt'])) return false;\n const subject = value['subject'];\n if (!isRecord(subject)) return false;\n for (const key of ['repo', 'seatId', 'sessionId'] as const) {\n if (!isNullableString(subject[key], 300)) return false;\n }\n if (subject['pr'] !== null && !(Number.isInteger(subject['pr']) && (subject['pr'] as number) > 0)) return false;\n if (subject['engine'] !== null && !['claude', 'codex', 'grok', 'local', 'devin'].includes(subject['engine'] as string)) return false;\n if (!isTarget(value['target'])) return false;\n const actions = value['actions'];\n return Array.isArray(actions) && actions.length <= 6 && actions.every(isAction);\n}\n\n// ===========================================================================\n// §3 Activity + session meta (C1) and the engine signatures behind it (C3)\n// ===========================================================================\n\nexport const VERSE_ACTIVITY_PATH = '/api/verse/activity';\nexport const VERSE_ACTIVITY_SEEN_PATH = '/api/verse/activity/seen';\nexport const VERSE_SESSION_META_PATH = '/api/verse/session-meta';\n\n/** Activity must answer in < 5 ms (SPEC-310C budgets): everything it reads is already in memory. */\nexport const VERSE_ACTIVITY_BUDGET_MS = 5;\n\n/**\n * ENGINE SIGNATURE (C3 implements on the engine handle; C1's activity reads\n * it): what a running turn is doing right now, folded from the transient\n * `progress` / `thinking-delta` events the engine already fans out. Returns\n * null when the session has no running turn. O(1), no I/O.\n */\nexport interface VerseLiveStatus {\n sessionId: string;\n turnId: string;\n /** ISO start of the running turn. */\n startedAt: string;\n /** Last `progress.phase`; null before the first progress event. */\n phase: VerseProgressPhase | null;\n /** The running tool when `phase` is `tool` (\"npm test\"); null otherwise. */\n tool: string | null;\n /** Wall time since `startedAt`, computed at peek time. */\n elapsedMs: number;\n /** Last ≤ VERSE_LIVE_THINKING_TAIL_CHARS of streamed reasoning, scrubbed; null when none streamed. */\n thinkingTail: string | null;\n outTokens: number | null;\n tokPerSec: number | null;\n}\nexport type PeekLiveStatus = (sessionId: string) => VerseLiveStatus | null;\nexport const VERSE_LIVE_THINKING_TAIL_CHARS = 160;\n\nexport type VerseTurnOutcome = 'ok' | 'failed' | 'cancelled';\n\n/**\n * ENGINE SIGNATURE (C3): one finished turn. `seq` is an engine-wide counter,\n * PROCESS-LOCAL — it restarts at 0 with the server, which is why activity's\n * wire cursor (VerseActivityResponse.cursor) is opaque and carries a boot id.\n */\nexport interface VerseTurnEnd {\n seq: number;\n sessionId: string;\n turnId: string;\n outcome: VerseTurnOutcome;\n /** ISO end time. */\n at: string;\n durationMs: number | null;\n /** The session's turnCount after this turn — unread = turnCount > seenTurnCount. */\n turnCount: number;\n}\n\n/**\n * ENGINE SIGNATURE (C3): turn ends with `seq > cursor`, oldest first. The\n * engine keeps the last VERSE_TURN_END_BUFFER in memory; a cursor older than\n * that gets what is left (activity never replays a log from disk).\n */\nexport type TurnEndsSince = (cursor: number) => { cursor: number; ends: VerseTurnEnd[] };\nexport const VERSE_TURN_END_BUFFER = 200;\n\nexport interface VerseActivityLive {\n phase: VerseProgressPhase | null;\n tool: string | null;\n elapsedMs: number;\n thinkingTail: string | null;\n}\n\nexport interface VerseActivityRunning {\n sessionId: string;\n title: string;\n engine: VerseEngine;\n seatId: string;\n startedAt: string;\n /** Null when the engine could not be peeked (the row still shows \"running\"). */\n live: VerseActivityLive | null;\n}\n\nexport interface VerseActivityCompletion {\n sessionId: string;\n title: string;\n outcome: VerseTurnOutcome;\n at: string;\n durationMs: number | null;\n}\n\nexport interface VerseActivityCounts {\n running: number;\n needsYou: number;\n unread: number;\n}\n\n/**\n * Per producer: `ok` answered; `unavailable` its module has not landed or is\n * not mounted in this build; `error` it threw or returned items that failed\n * isNeedsYouItem. Anything but `ok` means the drawer must NOT say \"All clear\"\n * for that split.\n */\nexport type VerseActivitySourceState = 'ok' | 'unavailable' | 'error';\nexport type VerseActivitySources = Record<NeedsYouSource, VerseActivitySourceState>;\n\n/** The rail's Fleet badge (SPEC-310C §1). Null in the response = unknown. */\nexport interface VerseAutonomyBadge {\n /** The clamp switch (B-U1): Off | Propose | Autonomous. */\n mode: 'off' | 'propose' | 'autonomous';\n /** Grant paused (\"authority code changed — re-approve\") or expired. */\n paused: boolean;\n /** KILL / soft kill in force. */\n stopped: boolean;\n /** Operator-language one-liner for the tooltip: \"Autonomous · 5 building\". */\n label: string;\n}\n\n/** The rail foot's capacity ring: the scarcest seat. */\nexport interface VerseCapacityBadge {\n seatId: string;\n engine: VerseEngine;\n label: string;\n /** 0–100 of the binding window. */\n usedPercent: number;\n /** Window label as the seat names it (\"5h\", \"weekly\"). */\n window: string;\n resetsAt: string | null;\n}\n\n/** The rail's Mind dot. */\nexport interface VerseMindBadge {\n latestMemoAt: string | null;\n /** A memo newer than the operator last opened Mind. */\n unseen: boolean;\n}\n\n/** GET /api/verse/activity?since=<cursor> */\nexport interface VerseActivityResponse {\n /** Opaque; send back as `?since=`. A different boot id resets completions (never an error). */\n cursor: string;\n generatedAt: string;\n running: VerseActivityRunning[];\n needsYou: NeedsYouItem[];\n /** Turn ends after `since`, oldest first (empty on the first poll: history is not \"new\"). */\n completions: VerseActivityCompletion[];\n counts: VerseActivityCounts;\n sources: VerseActivitySources;\n autonomy: VerseAutonomyBadge | null;\n capacity: VerseCapacityBadge | null;\n mind: VerseMindBadge | null;\n /**\n * 3.15 — terminal events for the desktop notifier: long commands that\n * finished, CLI agents that went idle or need the operator. Absent from\n * servers without it; see VerseActivityTerminal.\n */\n terminal?: VerseActivityTerminal | null;\n}\n\n/**\n * 3.15 — the last few terminal events (newest last). NOT cursor-filtered: the\n * consumer remembers the highest `seq` it has seen for this `boot` and treats\n * the first response of a boot as history (never announced).\n */\nexport interface VerseActivityTerminal {\n /** Changes when the server restarts (seqs restart with it). */\n boot: string;\n /** The newest event's seq (0 = none yet). */\n seq: number;\n events: VerseTerminalActivityEvent[];\n}\nexport type VerseTerminalActivityKind = 'command-finished' | 'agent-idle' | 'agent-needs-you';\nexport interface VerseTerminalActivityEvent {\n seq: number;\n kind: VerseTerminalActivityKind;\n tabId: string;\n /** command-finished: the block. */\n blockId: string | null;\n sessionId: string | null;\n /** The tab's title (never the command line: it can hold a secret). */\n title: string;\n agent: VerseTerminalAgentKind | null;\n exitCode: number | null;\n durationMs: number | null;\n at: string;\n}\n\n/** POST /api/verse/activity/seen — the operator has looked at this chat up to `turnCount`. */\nexport interface VerseActivitySeenRequest {\n sessionId: string;\n turnCount: number;\n}\n\n/** Per-chat organisation + read state (NOT in the session record: the engine owns that). */\nexport interface VerseSessionMeta {\n sessionId: string;\n pinned: boolean;\n archived: boolean;\n /** Highest turnCount the operator has seen; 0 = never opened. */\n seenTurnCount: number;\n}\n\n/** GET /api/verse/session-meta → every chat with non-default meta. GET …/:id → VerseSessionMeta. */\nexport interface VerseSessionMetaResponse {\n sessions: Record<string, VerseSessionMeta>;\n}\n\n/** POST /api/verse/session-meta/:id — unknown keys are a 400. */\nexport interface VerseSessionMetaUpdate {\n pinned?: boolean;\n archived?: boolean;\n}\n\n// ===========================================================================\n// §4 Session controls, attachments, queue, files (C3)\n// ===========================================================================\n\nexport const VERSE_SESSION_CONTROLS_PATH = '/api/verse/session-controls';\nexport const VERSE_SESSION_CONTROL_DEFAULTS_PATH = '/api/verse/session-controls/defaults';\nexport const VERSE_ATTACHMENTS_PATH = '/api/verse/attachments';\nexport const VERSE_QUEUE_PATH = '/api/verse/queue';\nexport const VERSE_FILES_PATH = '/api/verse/files';\n\n/** One picker option. Unavailable options are shown DISABLED with `reason`, never hidden. */\nexport interface VerseControlOption<T extends string = string> {\n id: T;\n label: string;\n available: boolean;\n reason?: string;\n /** Painted red (bypass). */\n danger?: boolean;\n /**\n * 3.15. A heading this option sits under (\"SWE-2 · Free\"); consecutive\n * options with the same group share one heading. Absent = ungrouped.\n */\n group?: string;\n /** 3.15. A short line under an AVAILABLE option's label (a price that differs from its group's). */\n note?: string;\n}\n\n/** GET|POST /api/verse/session-controls/:id */\nexport interface VerseSessionControlsResponse {\n sessionId: string;\n /** Effective values: `model` is the session's model; `effort` null = the CLI's own default. */\n controls: { model: string; effort: VerseEffort | null; permissionMode: VersePermissionMode };\n /** True while a turn runs: the change is recorded now and applies from the next turn. */\n appliesNextTurn: boolean;\n options: {\n models: VerseControlOption[];\n efforts: VerseControlOption<VerseEffort>[];\n permissionModes: VerseControlOption<VersePermissionMode>[];\n };\n}\n\n/**\n * POST /api/verse/session-controls/:id — unknown keys are a 400. `effort: null`\n * resets to the CLI default. Setting `permissionMode: 'bypass'` REQUIRES\n * `confirmBypass: true` (400 otherwise): the palette and the picker both\n * reach this route, and neither may turn every check off with one keystroke.\n */\nexport interface VerseSessionControlsUpdate {\n model?: string;\n effort?: VerseEffort | null;\n permissionMode?: VersePermissionMode;\n confirmBypass?: true;\n}\n\n/**\n * GET|POST /api/verse/session-controls/defaults — what a NEW chat starts with.\n * `bypass` is refused here: it is confirmed per chat, never inherited.\n */\nexport interface VerseSessionControlDefaults {\n global: VerseSessionControls;\n seats: Record<string, VerseSessionControls>;\n}\nexport interface VerseSessionControlDefaultsUpdate {\n /** Absent = the global default. */\n seatId?: string;\n effort?: VerseEffort | null;\n permissionMode?: Exclude<VersePermissionMode, 'bypass'>;\n}\n\n/** POST /api/verse/attachments/:sessionId (body cap raised for this route only). */\nexport interface VerseAttachmentUpload {\n name: string;\n mime: string;\n dataBase64: string;\n}\nexport interface VerseAttachment {\n id: string;\n sessionId: string;\n /** Sanitised display name. */\n name: string;\n mime: string;\n bytes: number;\n /** The `@path` token the composer inserts (`~`-relative, as every response is sanitised). */\n ref: string;\n createdAt: string;\n}\n/** Per file. Stored 0600 under ~/.ashlr/verse/attachments/<sid>/ and granted with exactly that `--add-dir`. */\nexport const VERSE_ATTACHMENT_MAX_BYTES = 8 * 1024 * 1024;\n\n/** GET /api/verse/queue/:sessionId; POST …/:sessionId {text}; POST …/:sessionId/:qid/delete */\nexport interface VerseQueuedTurn {\n id: string;\n sessionId: string;\n text: string;\n createdAt: string;\n}\nexport interface VerseQueueResponse {\n sessionId: string;\n items: VerseQueuedTurn[];\n /** After a failed or stopped turn the queue HOLDS and asks, instead of draining. */\n held: boolean;\n heldReason: string | null;\n}\n/**\n * POST /api/verse/queue/:sessionId. `sendNow` (⇧⌘↩ / \"Send now\") stops the\n * running turn and makes this text the next turn instead of queueing it last.\n */\nexport interface VerseQueueRequest {\n text: string;\n sendNow?: boolean;\n}\n/**\n * POST /api/verse/queue/:sessionId (and POST …/:sessionId/:qid/send) answer\n * with the queue PLUS the turn they started, if any — null when the text was\n * only queued behind a running turn.\n */\nexport interface VerseQueueSendResponse extends VerseQueueResponse {\n sentTurnId: string | null;\n}\n/** Additional queue route (C3): send one queued item now. */\nexport const VERSE_QUEUE_SEND_SUFFIX = '/send';\n/** Enter during a running turn queues server-side, at most this many. */\nexport const VERSE_QUEUE_MAX = 3;\n\n/** GET /api/verse/files?sessionId=&q= — the `@` fuzzy finder over the chat's roots. */\nexport interface VerseFileMatch {\n /** Path relative to `root`. */\n path: string;\n root: string;\n}\nexport interface VerseFilesResponse {\n sessionId: string;\n query: string;\n files: VerseFileMatch[];\n truncated: boolean;\n /**\n * The chat's primary root (C3 addition): matches in it are inserted as bare\n * relative `@path`s, matches in other roots keep their root. Optional — an\n * older server omits it and every match is shown with its root.\n */\n primaryRoot?: string | null;\n}\n/*\n * Attachment routes beyond the upload (C3 additions; same family):\n * GET /api/verse/attachments/:sessionId → { attachments: VerseAttachment[] }\n * POST /api/verse/attachments/:sessionId/:aid/delete → { ok: true }\n */\nexport interface VerseAttachmentListResponse {\n attachments: VerseAttachment[];\n}\n\n// ===========================================================================\n// §5 Terminal (C4)\n// ===========================================================================\n\nexport const VERSE_TERMINAL_PATH = '/api/verse/terminal';\nexport const VERSE_TERMINAL_MAX_TABS = 8;\n/** Per request, before base64. */\nexport const VERSE_TERMINAL_INPUT_MAX_BYTES = 16 * 1024;\n/** Per tab, in memory only — never written to disk. */\nexport const VERSE_TERMINAL_SCROLLBACK_BYTES = 256 * 1024;\nexport const VERSE_TERMINAL_IDLE_KILL_MS = 12 * 60 * 60 * 1000;\n/** SSE frames are coalesced to at most this rate. */\nexport const VERSE_TERMINAL_MAX_FRAME_HZ = 60;\n\nexport interface VerseTerminalTab {\n id: string;\n sessionId: string | null;\n /** The session root (or discovered project) the shell started in. */\n root: string;\n /** From the shell's OSC title; falls back to the root's name. */\n title: string;\n cols: number;\n rows: number;\n createdAt: string;\n lastActivityAt: string;\n /** Set when the shell exited; the tab stays until closed so its output can be read. */\n exited: { code: number | null; signal: string | null; at: string } | null;\n /** Opened from Apps' [Launch ▸] or Preview's dev-server Start, when it was. */\n appId: string | null;\n devServerId: string | null;\n /**\n * 3.15: the shell's current directory, as its shell integration last\n * reported it (OSC 7 / OSC 633 P;Cwd). Null until reported, or when the\n * shell runs without integration.\n */\n cwd?: string | null;\n /**\n * 3.15: whether command blocks come from this shell. `active` once the\n * injected integration has drawn its first prompt marker; `injected` while\n * it is loading; `off` for a shell it does not support (sh, ksh…) or when\n * it was turned off.\n */\n shellIntegration?: VerseTerminalShellIntegration;\n /** 3.15: the tab runs an agent (Apps [Launch ▸]) — hung up when the kill switch is engaged. */\n agent?: boolean;\n /**\n * 3.15: what the CLI agent in this tab is doing (running / idle / needs you),\n * for a tab launched as one of VERSE_TERMINAL_AGENT_KINDS. Null for a plain\n * shell, and until the agent's first signal.\n */\n agentState?: VerseTerminalAgentState | null;\n}\n\n/** 3.15 — the CLI agents whose terminal tabs report a live status. */\nexport const VERSE_TERMINAL_AGENT_KINDS = ['claude-code', 'codex', 'devin', 'grok'] as const;\nexport type VerseTerminalAgentKind = (typeof VERSE_TERMINAL_AGENT_KINDS)[number];\nexport type VerseTerminalAgentStateName = 'running' | 'idle' | 'needs-you';\n\n/**\n * 3.15 — a terminal agent tab's status. `channel` says how the tab learns it:\n * `hooks` — per-launch hooks were installed (Claude Code's Stop / Notification\n * hooks through a temporary `--settings` file, Codex's `notify` through `-c`),\n * which POST to `/api/verse/terminal/:id/agent-state` with the tab's own\n * token; `heuristic` — read from the tab's output only (Devin, Grok, or a\n * launch through Ollama). The operator's global CLI configs are never touched.\n */\nexport interface VerseTerminalAgentState {\n agent: VerseTerminalAgentKind;\n state: VerseTerminalAgentStateName;\n /** ISO time the state began. */\n since: string;\n /** Who said so this time: the CLI's hook, or the output heuristic. */\n source: 'hook' | 'output';\n channel: 'hooks' | 'heuristic';\n /** Why it needs you, when the CLI said (one line, ≤ 200 chars); null otherwise. */\n message: string | null;\n}\n\n/** POST /api/verse/terminal/:id/agent-state?state=… — the hook callback (token-bound, NOT the mutation token). */\nexport const VERSE_TERMINAL_AGENT_STATE_PATH_RE = /^\\/api\\/verse\\/terminal\\/(t-[a-z0-9]{1,32})\\/agent-state$/;\n/** The header the per-launch hook scripts carry their tab's token in. */\nexport const VERSE_TERMINAL_AGENT_TOKEN_HEADER = 'x-ashlr-agent-token';\n/** A command at least this long that ends while the app is not in front is announced (desktop notification). */\nexport const VERSE_TERMINAL_LONG_COMMAND_MS = 30_000;\n\nexport type VerseTerminalShellIntegration = 'active' | 'injected' | 'off';\n\n/** Per tab: how many finished blocks keep their metadata (their OUTPUT has a byte budget of its own). */\nexport const VERSE_TERMINAL_MAX_BLOCKS = 500;\n/** Per block, the output kept (the LAST bytes: an error is at the end). */\nexport const VERSE_TERMINAL_BLOCK_OUTPUT_BYTES = 256 * 1024;\n/** Per tab, all blocks' output together; the oldest blocks' output goes first. */\nexport const VERSE_TERMINAL_BLOCKS_TOTAL_BYTES = 4 * 1024 * 1024;\n\n/**\n * 3.15 — one command the operator ran in a terminal tab, cut from the byte\n * stream by the shell integration's OSC 133 markers (A prompt, B input,\n * C executed, D;<exit> finished) and OSC 633 E (the command line, nonce-checked\n * so program output cannot forge one).\n *\n * `startSeq`/`ordinal` place the block's C marker in the output stream: the\n * `ordinal`-th C marker inside output frame `startSeq`. The page uses that to\n * pin an xterm marker to the exact line the command started on.\n */\nexport interface VerseTerminalBlock {\n /** `b-<n>`, unique within its tab. */\n id: string;\n tabId: string;\n /** The command line as typed; '' when the shell did not say and nothing could be read back. */\n command: string;\n /** Where it ran, when the integration reported it. */\n cwd: string | null;\n startedAt: string;\n finishedAt: string | null;\n durationMs: number | null;\n /** Null while running, or when the shell never reported one (a prompt redrawn without D). */\n exitCode: number | null;\n state: 'running' | 'done';\n startSeq: number;\n ordinal: number;\n /** Bytes of output captured (before truncation). */\n outputBytes: number;\n /** The kept output is the tail only. */\n truncated: boolean;\n /** Output dropped to stay inside the tab's budget (metadata kept). */\n evicted: boolean;\n /** The command switched to the alternate screen (vim, less, htop): its output is not a transcript. */\n fullscreen: boolean;\n /**\n * 3.15: loopback URLs the command printed (`http://localhost:5173/` …), first\n * seen first, at most 3 — \"Open in Browser pane\". Absent on older servers.\n */\n localUrls?: string[];\n}\n\n/** GET /api/verse/terminal/:id/blocks */\nexport interface VerseTerminalBlocksResponse {\n blocks: VerseTerminalBlock[];\n}\n\n/**\n * GET /api/verse/terminal/:id/blocks/:blockId?format=ansi|text|chat\n * ansi — the bytes as the shell wrote them (UTF-8), for the block view;\n * text — escape sequences and carriage-return redraws removed (\"Copy output\");\n * chat — `text`, then every recognised secret replaced by [REDACTED] (scrubSecrets),\n * the command line too. The ONLY form that may be sent to a chat seat.\n */\nexport type VerseTerminalBlockOutputFormat = 'ansi' | 'text' | 'chat';\nexport interface VerseTerminalBlockOutputResponse {\n block: VerseTerminalBlock;\n /** The command, scrubbed when format=chat. */\n command: string;\n output: string;\n truncated: boolean;\n}\n\n/** POST /api/verse/terminal/redact { text } → { text } — \"Send selection to chat\" goes through the same scrub. */\nexport const VERSE_TERMINAL_REDACT_PATH = '/api/verse/terminal/redact';\nexport const VERSE_TERMINAL_REDACT_MAX_BYTES = 256 * 1024;\n\n/**\n * POST /api/verse/terminal/:id/open-file { path, line?, column? } → { ok: true }\n * A `file:line[:col]` link clicked in the terminal. Relative paths resolve\n * against `cwd` (the block's or the tab's); the file must resolve INSIDE one\n * of the tab's chat roots, and opens in the operator's configured editor.\n */\nexport interface VerseTerminalOpenFileRequest {\n path: string;\n line?: number;\n column?: number;\n cwd?: string;\n}\n\n/** GET /api/verse/terminal. `available: false` under Node (no Bun PTY) — `reason` says \"needs the desktop app\". */\nexport interface VerseTerminalListResponse {\n available: boolean;\n reason: string | null;\n tabs: VerseTerminalTab[];\n}\n\n/** How an Apps [Launch ▸] runs an agent: its own command, or `ollama launch <id>` (C6). */\nexport type VerseTerminalLaunchVia = 'native' | 'ollama';\n\n/**\n * POST /api/verse/terminal. With `appId`, the server resolves the command from\n * the apps catalog and the installed binaries (`resolveAppLaunch`) — the page\n * never supplies a command. `via` / `model` choose HOW that app launches:\n * `model` is an installed Ollama tag and implies `via: 'ollama'` (a local\n * model only launches through Ollama). Both are refused without `appId`.\n */\nexport interface VerseTerminalCreateRequest {\n sessionId: string;\n root?: string;\n appId?: string;\n via?: VerseTerminalLaunchVia;\n model?: string;\n devServerId?: string;\n /**\n * 3.15: start in this directory instead of the root — a split opening where\n * its neighbour is. Must resolve inside `root` (or the chat's primary root).\n */\n cwd?: string;\n /** 3.15: false = no shell integration for this tab (no command blocks). Default true. */\n shellIntegration?: boolean;\n cols: number;\n rows: number;\n}\n\n/**\n * POST /api/verse/terminal/open-external { sessionId, root? } → 202 — opens\n * Terminal.app at the root (C4 addition: the pane header's \"Open in\n * Terminal.app\", and the pane's fallback where no Bun PTY exists).\n */\nexport const VERSE_TERMINAL_OPEN_EXTERNAL_PATH = '/api/verse/terminal/open-external';\nexport interface VerseTerminalOpenExternalRequest {\n sessionId: string;\n root?: string;\n}\n\n/** POST /api/verse/terminal/:id/input */\nexport interface VerseTerminalInputRequest {\n dataBase64: string;\n}\n\n/** POST /api/verse/terminal/:id/resize */\nexport interface VerseTerminalResizeRequest {\n cols: number;\n rows: number;\n}\n\n/**\n * GET /api/verse/terminal/:id/stream?after=<seq> — SSE. Scrollback is sent\n * first (as `output` frames), so a reload re-attaches. `seq` counts output\n * frames per tab; `after` resumes past what the client already has.\n */\nexport type VerseTerminalFrame =\n | { type: 'output'; seq: number; dataBase64: string }\n | { type: 'title'; title: string }\n | { type: 'exit'; code: number | null; signal: string | null };\n\n/**\n * 3.15 — everything the stream may carry: the 3.10 frames plus the shell\n * integration's. A 3.10 client ignores the new event types (its parser\n * returns null for them), so the stream stays compatible.\n */\nexport type VerseTerminalStreamFrame =\n | VerseTerminalFrame\n /** A block started or finished (the whole record each time). Replayed on subscribe. */\n | { type: 'block'; block: VerseTerminalBlock }\n /** The shell's directory changed. */\n | { type: 'cwd'; cwd: string }\n /** Shell integration came up. */\n | { type: 'integration'; state: VerseTerminalShellIntegration }\n /** 3.15: the tab's CLI agent changed state (null: the agent exited; the tab is a plain shell again). */\n | { type: 'agent-state'; agentState: VerseTerminalAgentState | null };\n\n/**\n * 3.15 — POST /api/verse/terminal/:id/blocks/:blockId/fix {} → the LOCAL\n * model's candidate commands for a block that exited non-zero (terminal-assist.ts).\n * Never run: the page shows them as chips ([Paste] types one at a prompt).\n * 503 TERMINAL_ASSIST_UNAVAILABLE when no local model answers.\n */\nexport interface VerseTerminalFixSuggestion {\n command: string;\n why: string;\n}\nexport interface VerseTerminalFixResponse {\n suggestions: VerseTerminalFixSuggestion[];\n /** The local model tag that answered. */\n model: string;\n}\n\n/**\n * 3.15 — launch configurations: `.ashlr/verse/launch.json` in a chat's root.\n *\n * { \"version\": 1, \"configurations\": [ { \"name\": \"Dev\", \"tabs\": [\n * { \"split\": \"right\", \"panes\": [ { \"cwd\": \"web\", \"command\": \"npm run dev\" }, { \"command\": \"npm test -- --watch\" } ] },\n * { \"panes\": [ { \"agent\": \"claude-code\" } ] } ] } ] }\n *\n * GET /api/verse/terminal/launch?sessionId=… → VerseTerminalLaunchListResponse\n * POST /api/verse/terminal/launch { sessionId, root, name, digest, cols, rows } → VerseTerminalLaunchResponse\n *\n * Nothing is typed on load: the configurations are listed (their commands\n * shown), and a named one's commands are typed only when the operator clicks\n * it. The POST names a configuration and presents the digest of exactly what\n * the operator reviewed; a changed file is refused before any shell starts.\n * Commands still come from the file on the server, never from the request.\n */\nexport const VERSE_TERMINAL_LAUNCH_PATH = '/api/verse/terminal/launch';\nexport const VERSE_TERMINAL_LAUNCH_FILE = '.ashlr/verse/launch.json';\nexport const VERSE_TERMINAL_LAUNCH_MAX_CONFIGS = 20;\nexport const VERSE_TERMINAL_LAUNCH_MAX_TABS = 4;\nexport interface VerseTerminalLaunchPane {\n /** Relative to the root (default: the root). */\n cwd: string | null;\n /** Typed (with Enter) when the configuration is launched; null = just a shell. */\n command: string | null;\n /** A catalog agent to start instead of a command (its hooks installed like Apps [Launch ▸]). */\n agent: string | null;\n}\nexport interface VerseTerminalLaunchTab {\n split: 'right' | 'down';\n /** One or two panes (a tab holds two terminals at most). */\n panes: VerseTerminalLaunchPane[];\n}\nexport interface VerseTerminalLaunchConfig {\n name: string;\n /** The chat root whose launch.json declared it. */\n root: string;\n tabs: VerseTerminalLaunchTab[];\n /** Server digest binding the displayed commands, agent IDs, and cwds. */\n digest: string;\n}\nexport interface VerseTerminalLaunchListResponse {\n configs: VerseTerminalLaunchConfig[];\n /** A launch.json that exists but could not be used: which root, and why (one line). */\n errors: Array<{ root: string; error: string }>;\n}\nexport interface VerseTerminalLaunchRequest {\n sessionId: string;\n root: string;\n name: string;\n digest: string;\n cols: number;\n rows: number;\n}\nexport interface VerseTerminalLaunchResponse {\n /** Per launched tab, its shells in pane order. A pane that failed to open is left out. */\n groups: Array<{ split: 'right' | 'down'; tabs: VerseTerminalTab[] }>;\n /** Panes that could not be opened (one line each). */\n errors: string[];\n}\n\n/**\n * 3.15 — ONE stream for many shells.\n *\n * GET /api/verse/terminal/stream?tabs=<id>:<after>,<id>:<after>,… → SSE\n *\n * Every frame of every listed tab, each tagged with its tab (`tab`), in one\n * connection — so six visible panes cost one of the browser's ~6 connections\n * per origin instead of six. Each tab resumes past its own `after` (a bare\n * `<id>` is `<id>:0`: the whole scrollback). A tab that does not exist, or\n * goes away while streamed, gets one `gone` frame; the stream ends when none\n * is left. The per-tab `/:id/stream` route stays for older pages.\n */\nexport const VERSE_TERMINAL_STREAM_PATH = '/api/verse/terminal/stream';\n/** At most this many tabs on one multiplexed stream (every tab the server can hold). */\nexport const VERSE_TERMINAL_STREAM_MAX_TABS = VERSE_TERMINAL_MAX_TABS;\nexport type VerseTerminalMuxFrame = { tab: string } & (VerseTerminalStreamFrame | { type: 'gone' });\n\n// ---------------------------------------------------------------------------\n// 3.15 — command history (terminal-history.ts)\n// ---------------------------------------------------------------------------\n\n/**\n * GET /api/verse/terminal/history?q=&cwd=&repo=&limit= → VerseTerminalHistoryResponse\n * POST /api/verse/terminal/history/clear {} → { ok: true }\n * GET /api/verse/terminal/settings → VerseTerminalSettings\n * POST /api/verse/terminal/settings { history?, assist? } → VerseTerminalSettings\n *\n * Every command a shell finished (a closed block) — command, where, exit,\n * duration, when — kept in ~/.ashlr/verse/terminal-history.jsonl (0600),\n * secrets scrubbed BEFORE it is written. Ranked: prefix match → same cwd →\n * same repo → succeeded → most recent; one row per distinct command.\n */\nexport const VERSE_TERMINAL_HISTORY_PATH = '/api/verse/terminal/history';\nexport const VERSE_TERMINAL_HISTORY_CLEAR_PATH = '/api/verse/terminal/history/clear';\nexport const VERSE_TERMINAL_SETTINGS_PATH = '/api/verse/terminal/settings';\nexport const VERSE_TERMINAL_HISTORY_MAX_LIMIT = 500;\n\n/** One distinct command, aggregated over every time it ran. */\nexport interface VerseTerminalHistoryEntry {\n cmd: string;\n /** Where it last ran. */\n cwd: string | null;\n repo: string | null;\n /** The last run's exit code (null: the shell did not say). */\n exit: number | null;\n durMs: number | null;\n /** ISO time of the last run. */\n ts: string;\n /** How many times it ran, and how many of those exited 0. */\n count: number;\n okCount: number;\n /** Ran in the queried cwd / repo (ranking signals, shown as a hint). */\n here: boolean;\n sameRepo: boolean;\n}\n\nexport interface VerseTerminalHistoryResponse {\n enabled: boolean;\n entries: VerseTerminalHistoryEntry[];\n}\n\n/** Server-side terminal settings (~/.ashlr/verse/terminal-settings.json). */\nexport interface VerseTerminalSettings {\n /** Record finished commands to disk (default true). Off also stops reading them back. */\n history: boolean;\n /**\n * Plain language → command (terminal-assist.ts): `local` = the local model\n * only; `auto` = the local model, then Grok when it is configured; `off` =\n * never. Default `local`; cloud fallback requires an explicit mode selection\n * and an explicit `cloudAllowed` flag on each request.\n */\n assist: VerseTerminalAssistMode;\n}\nexport type VerseTerminalAssistMode = 'auto' | 'local' | 'off';\n\n// ---------------------------------------------------------------------------\n// 3.15 — plain language → command (terminal-assist.ts)\n// ---------------------------------------------------------------------------\n\n/**\n * POST /api/verse/terminal/assist { tabId?, sessionId?, request, cwd?, blockIds?, cloudAllowed? }\n * → VerseTerminalAssistResponse\n *\n * The operator's request plus the tab's cwd, OS, shell and its last few\n * blocks (scrubbed text, capped) go to the LOCAL model by default. The reply\n * is text for the operator to edit — the server never types or runs it.\n */\nexport const VERSE_TERMINAL_ASSIST_PATH = '/api/verse/terminal/assist';\nexport const VERSE_TERMINAL_ASSIST_MAX_REQUEST_CHARS = 2_000;\nexport interface VerseTerminalAssistRequest {\n request: string;\n tabId?: string;\n cwd?: string;\n /** Blocks to include as context (default: the tab's last few). */\n blockIds?: string[];\n /** May use Grok if the operator also selected auto mode. Omitted means local only. */\n cloudAllowed?: boolean;\n}\nexport interface VerseTerminalAssistResponse {\n /** The suggested command line(s), ready to edit. Never run by the server. */\n command: string;\n /** One short sentence on what it does, when the model gave one. */\n explanation: string | null;\n /** Which model answered: `local:<model>` or `grok:<model>`. */\n provider: string;\n /** The model flagged it as destructive (rm -rf, force-push, DROP …) or the server's own check did. */\n risky: boolean;\n}\n\n// ===========================================================================\n// §6 Preview (C4)\n// ===========================================================================\n\nexport const VERSE_PREVIEW_TARGETS_PATH = '/api/verse/preview/targets';\nexport const VERSE_PREVIEW_RAW_PATH = '/api/verse/preview/raw';\n/** preview/raw serves at most this much (nosniff, `CSP: sandbox allow-scripts`). */\nexport const VERSE_PREVIEW_RAW_MAX_BYTES = 5 * 1024 * 1024;\n\nexport type VersePreviewDevServerSource = 'launch-json' | 'package-json' | 'listening';\n\nexport interface VersePreviewDevServer {\n id: string;\n label: string;\n /** Loopback http only (127.0.0.1 / localhost). */\n url: string;\n port: number;\n source: VersePreviewDevServerSource;\n running: boolean;\n root: string;\n /**\n * Exactly what Start types into a terminal tab (`npm run dev`, a launch.json\n * `runtimeExecutable` + args), so the row can show it BEFORE the click\n * (C4 addition). Null for a server only observed listening — there is\n * nothing to start. Optional: an older server omits it.\n */\n command?: string | null;\n}\n\nexport type VersePreviewArtifactKind = 'html' | 'md' | 'svg' | 'image' | 'pdf';\n\nexport interface VersePreviewArtifact {\n /** Relative to the session root it lives in; served only through preview/raw. */\n path: string;\n kind: VersePreviewArtifactKind;\n bytes: number;\n}\n\n/** GET /api/verse/preview/targets?sessionId= */\nexport interface VersePreviewTargetsResponse {\n devServers: VersePreviewDevServer[];\n artifacts: VersePreviewArtifact[];\n}\n\n/*\n * Preview frame tickets (C4 addition). An `<iframe src>` cannot send the\n * read-client header, and a srcdoc/blob frame would inherit the page's\n * script-src, so an artifact frame is loaded through a one-file ticket:\n * GET /api/verse/preview/ticket?sessionId=&path= (read session) → { url, expiresAt, kind }\n * GET /api/verse/preview/frame/<43-char ticket> (NO read-session check; the\n * ticket expires in 5 min and redeems only with the minting session's cookie)\n * That frame path is the ONE route in the workbench exempt from the read-session\n * gate (core/web/server.ts), and it serves under `CSP: sandbox allow-scripts`.\n */\nexport const VERSE_PREVIEW_TICKET_PATH = '/api/verse/preview/ticket';\nexport const VERSE_PREVIEW_FRAME_PATH = '/api/verse/preview/frame';\n/** The frame path's exact shape — the one server.ts lets past the read boundary. */\nexport const VERSE_PREVIEW_FRAME_PATH_RE = /^\\/api\\/verse\\/preview\\/frame\\/([A-Za-z0-9_-]{43})$/;\nexport interface VersePreviewTicketResponse {\n /** The frame URL carrying the ticket (`/api/verse/preview/frame/<ticket>`). */\n url: string;\n expiresAt: string;\n kind: VersePreviewArtifactKind;\n}\n\n/**\n * Loopback http only — the one rule the Preview URL bar, the iframe and the\n * server's `frame-src` all share. Anything else gets \"Open in browser ↗\".\n */\nexport function isLoopbackPreviewUrl(value: string): boolean {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return false;\n }\n return url.protocol === 'http:'\n && (url.hostname === '127.0.0.1' || url.hostname === 'localhost')\n && url.username === ''\n && url.password === '';\n}\n\n// ===========================================================================\n// §7 Git, review, PR (C5)\n// ===========================================================================\n\nexport const VERSE_GIT_PATH = '/api/verse/git';\nexport const VERSE_GIT_STATUS_PATH = '/api/verse/git/status';\nexport const VERSE_GIT_DIFF_PATH = '/api/verse/git/diff';\n/** Patches load lazily per file, each capped here. */\nexport const VERSE_GIT_PATCH_MAX_BYTES = 256 * 1024;\n/** git/status answers < 300 ms and is cached this long. */\nexport const VERSE_GIT_STATUS_CACHE_MS = 5_000;\n/** Every git/gh subprocess: async execFile, this timeout. */\nexport const VERSE_GIT_TIMEOUT_MS = 60_000;\n/** \"Isolate in worktree\": ~/.ashlr-worktrees/<repo>/<name> on branch verse/<name>. */\nexport const VERSE_WORKTREE_DIR = '~/.ashlr-worktrees';\nexport const VERSE_WORKTREE_BRANCH_PREFIX = 'verse/';\n\n/** The branch bar's primary button (SPEC-310C §2). `merge` only with green checks and a mergeable branch. */\nexport type VerseGitSuggestedAction = 'commit' | 'push' | 'create-pr' | 'merge' | 'view-pr' | 'none';\nexport type VersePrState = 'open' | 'draft' | 'merged' | 'closed';\nexport type VersePrChecks = 'passing' | 'failing' | 'pending' | 'none' | 'unknown';\n\nexport interface VerseGitPr {\n number: number;\n title: string;\n url: string;\n state: VersePrState;\n checks: VersePrChecks;\n /** GitHub's mergeability; null while GitHub is still computing it. */\n mergeable: boolean | null;\n headSha: string | null;\n baseRef: string;\n headRef: string;\n}\n\nexport interface VerseGitDiffstat {\n files: number;\n additions: number;\n deletions: number;\n}\n\n/** GET /api/verse/git/status?root= */\nexport interface VerseGitStatus {\n root: string;\n name: string;\n /** Null on a detached HEAD. */\n branch: string | null;\n upstream: string | null;\n /** The branch the PR would target; null when unknown. */\n base: string | null;\n ahead: number;\n behind: number;\n /** Changed paths in the working tree (staged + unstaged + untracked). */\n dirty: number;\n /** Everything this branch would ship against `base`, uncommitted work included (the bar's ± counts). */\n diffstat: VerseGitDiffstat;\n pr: VerseGitPr | null;\n suggested: VerseGitSuggestedAction;\n checkedAt: string;\n}\n\n/**\n * `pr` is only as good as GitHub's answer (C5 addition):\n * ok GitHub answered — `pr: null` really means \"no PR\";\n * pending the answer is being fetched in the background (the bar says\n * \"Checking GitHub…\" and re-reads shortly);\n * unavailable gh missing, signed out, offline, or not a GitHub remote —\n * `pr: null` means \"could not look\", never \"no PR\".\n */\nexport type VerseGitPrLookup = 'ok' | 'pending' | 'unavailable';\n\n/** The counts behind `pr.checks`, for \"3 of 9 checks failing\". */\nexport interface VerseGitCheckCounts {\n total: number;\n passed: number;\n failed: number;\n pending: number;\n}\n\n/**\n * What GET /api/verse/git/status actually serves: the frozen VerseGitStatus\n * plus C5's additive fields. Kept a separate interface (not new required\n * fields on VerseGitStatus) so a fixture written against §7 still compiles.\n */\nexport interface VerseGitStatusDetail extends VerseGitStatus {\n /** The repository's top level. Several chat roots inside one repo share one bar row. */\n gitRoot: string;\n prLookup: VerseGitPrLookup;\n prCheckCounts: VerseGitCheckCounts | null;\n /** Conflicted paths (merge/rebase in progress). Commit is refused while > 0. */\n conflicts: number;\n /** HEAD's commit subject — the Create PR dialog's default title. Null on an unborn branch. */\n headSubject: string | null;\n /** HEAD's SHA; null on an unborn branch. */\n headSha: string | null;\n}\n\n/** Server scopes. The UI adds `turn` (from the chat's own events). */\nexport type VerseGitDiffScope = 'working' | 'branch';\nexport type VerseReviewScope = 'turn' | VerseGitDiffScope;\nexport type VerseGitFileStatus = 'M' | 'A' | 'D' | 'R' | 'U';\n\nexport interface VerseGitDiffFile {\n path: string;\n /** Previous path for a rename. */\n oldPath: string | null;\n status: VerseGitFileStatus;\n additions: number;\n deletions: number;\n binary: boolean;\n}\n\nexport interface VerseGitPatch {\n path: string;\n /** Unified diff text, possibly cut at VERSE_GIT_PATCH_MAX_BYTES. */\n text: string;\n truncated: boolean;\n}\n\n/** GET /api/verse/git/diff?root=&scope=working|branch[&file=] — `patch` only when `file` was asked. */\nexport interface VerseGitDiffResponse {\n root: string;\n scope: VerseGitDiffScope;\n base: string | null;\n files: VerseGitDiffFile[];\n patch: VerseGitPatch | null;\n}\n\n/** POST /api/verse/git/commit — no `paths` = every change. */\nexport interface VerseGitCommitRequest {\n root: string;\n message: string;\n paths?: string[];\n}\n/** POST /api/verse/git/push */\nexport interface VerseGitPushRequest {\n root: string;\n}\n/** POST /api/verse/git/pr — pushes first (gh refuses an unpushed branch), then opens the PR. */\nexport interface VerseGitPrRequest {\n root: string;\n title: string;\n body?: string;\n draft?: boolean;\n base?: string;\n}\n/**\n * POST /api/verse/git/pr/merge — refused unless every check passes AND GitHub's\n * head SHA still equals `headSha` (no merging a commit the operator never\n * saw). Never `--admin`.\n */\nexport interface VerseGitMergeRequest {\n root: string;\n number: number;\n headSha: string;\n}\n/** POST /api/verse/git/worktree */\nexport interface VerseGitWorktreeRequest {\n root: string;\n name: string;\n}\nexport interface VerseGitWorktreeResponse {\n path: string;\n branch: string;\n}\n/** Every git POST answers with the fresh status (and the PR when one was opened or merged). A busy root is a 409. */\nexport interface VerseGitActionResponse {\n ok: true;\n status: VerseGitStatus;\n pr: VerseGitPr | null;\n}\n\n// ===========================================================================\n// §8 Apps & accounts (C6; the static catalog is apps-catalog.ts)\n// ===========================================================================\n\nexport const VERSE_APPS_PATH = '/api/verse/apps';\n\nexport const VERSE_APP_GROUPS = ['accounts', 'desktop', 'terminal-agents', 'local-models', 'mcp-servers'] as const;\nexport type VerseAppGroupId = (typeof VERSE_APP_GROUPS)[number];\n\nexport type VerseAppHealthState = 'ok' | 'warn' | 'error' | 'off' | 'unknown';\n\n/** A dot WITH a word — never colour alone. */\nexport interface VerseAppHealth {\n state: VerseAppHealthState;\n /** \"connected\", \"not installed\", \"8.5 tok/s\", \"signed out\". */\n label: string;\n}\n\nexport type VerseAppActionKind = 'launch' | 'reconnect' | 'fix' | 'edit-budget' | 'restore' | 'add-mcp';\n\nexport interface VerseAppAction {\n kind: VerseAppActionKind;\n label: string;\n /** The command it runs or shows (argv, never a shell string; never a secret). */\n command: string[] | null;\n /** Disabled WITH a reason, never hidden. */\n disabledReason: string | null;\n}\n\n/**\n * A toggle that changes ANOTHER app's settings (Claude Desktop \"Use Ollama\n * models\", Hermes Desktop). Turning it either way needs `confirm: true` and the\n * confirmation shows `command` and `restoreCommand` verbatim.\n */\nexport interface VerseAppToggle {\n enabled: boolean;\n command: string[];\n restoreCommand: string[];\n}\n\nexport interface VerseAppRow {\n id: string;\n name: string;\n /** 32px tile letter(s). */\n monogram: string;\n /** Tints the tile for seats and engine-backed agents; null = neutral tile. */\n engine: VerseEngine | null;\n description: string;\n health: VerseAppHealth;\n /** Null = not checked (e.g. a seat row). */\n installed: boolean | null;\n version: string | null;\n /** The copy pill (⧉ → ✓ for 1.2 s). */\n copy: { label: string; text: string } | null;\n /** `ollama launch <id>`, only when the INSTALLED ollama's `launch --help` lists it. */\n ollamaLaunch: string[] | null;\n toggle: VerseAppToggle | null;\n actions: VerseAppAction[];\n /** For seat rows: the Verse seat it represents. */\n seatId: string | null;\n /** Second line: \"5h 62% · weekly 40% · resets Thu · reserved for you 40%\". */\n detail: string | null;\n}\n\nexport interface VerseAppGroup {\n id: VerseAppGroupId;\n title: string;\n /** A standing caveat shown under the header (MCP: claude and local seats load none). */\n caveat: string | null;\n apps: VerseAppRow[];\n}\n\n/** GET /api/verse/apps (POST /api/verse/apps/refresh re-probes and answers the same). */\nexport interface VerseAppsResponse {\n checkedAt: string;\n /** Where binary detection looked: the login shell's PATH, or the fallback dirs (see login-path.ts). */\n pathSource: 'login-shell' | 'fallback';\n groups: VerseAppGroup[];\n}\n\n/** POST /api/verse/apps/:id/toggle — `confirm: true` is required; anything else is a 400. */\nexport interface VerseAppToggleRequest {\n enabled: boolean;\n confirm: true;\n}\n\n/**\n * POST /api/verse/apps/:id/launch (C6 addition) — opens the agent in a\n * visible Terminal.app window at `root` (a chat folder or discovered\n * project). The command is resolved server-side from the catalog and the\n * installed binaries; `model` is an installed Ollama tag and implies Ollama.\n */\nexport interface VerseAppLaunchRequest {\n root: string;\n via?: VerseTerminalLaunchVia;\n model?: string;\n}\nexport interface VerseAppLaunchResponse {\n ok: true;\n opened: 'terminal-app';\n /** The command as the operator would type it (bare argv[0]). */\n command: string[];\n}\n\n// ===========================================================================\n// §9 Route families C0 mounts (verse-api.ts WORKBENCH mount table)\n// ===========================================================================\n\n/**\n * Every Track B / C route family, its owner, the module and export the specs\n * name, and the path prefixes it — and ONLY it — answers. The mount in\n * verse-api.ts routes by these prefixes (segment boundary: `/api/verse/git`\n * owns `/api/verse/git/status`, never `/api/verse/github`), so a module can\n * neither shadow another family nor a V1 route, and a family whose module has\n * not landed is a plain 404 that touches nothing else.\n *\n * `/api/verse/fleet/history` is A8's (Track A) and `/api/verse/fleet` is the\n * V2.2 control route: Track B's live fleet is `/api/verse/fleet/live` ONLY.\n */\nexport const WORKBENCH_ROUTE_FAMILIES = [\n {\n id: 'activity',\n owner: 'C1',\n module: 'src/core/verse/activity-api.ts',\n handler: 'handleActivityApi',\n prefixes: ['/api/verse/activity', '/api/verse/session-meta'],\n },\n {\n id: 'session-controls',\n owner: 'C3',\n module: 'src/core/verse/session-controls-api.ts',\n handler: 'handleSessionControlsApi',\n prefixes: ['/api/verse/session-controls', '/api/verse/attachments', '/api/verse/queue', '/api/verse/files'],\n },\n {\n id: 'terminal',\n owner: 'C4',\n module: 'src/core/verse/terminal-api.ts',\n handler: 'handleTerminalApi',\n prefixes: ['/api/verse/terminal'],\n },\n {\n id: 'preview',\n owner: 'C4',\n module: 'src/core/verse/preview-api.ts',\n handler: 'handlePreviewApi',\n prefixes: ['/api/verse/preview'],\n },\n { id: 'git', owner: 'C5', module: 'src/core/verse/git-api.ts', handler: 'handleGitApi', prefixes: ['/api/verse/git'] },\n { id: 'apps', owner: 'C6', module: 'src/core/verse/apps-api.ts', handler: 'handleAppsApi', prefixes: ['/api/verse/apps'] },\n {\n id: 'authority',\n owner: 'B-U1',\n module: 'src/core/verse/authority-api.ts',\n handler: 'handleAuthorityApi',\n prefixes: ['/api/verse/authority'],\n },\n {\n id: 'overnight',\n owner: 'B-U5',\n module: 'src/core/verse/overnight-api.ts',\n handler: 'handleOvernightApi',\n prefixes: ['/api/verse/overnight'],\n },\n {\n id: 'fleet-live',\n owner: 'B-U5',\n module: 'src/core/verse/fleet-live-api.ts',\n handler: 'handleFleetLiveApi',\n prefixes: ['/api/verse/fleet/live'],\n },\n {\n // 3.15: the Fleet tab's control surface (Start / Pause / Resume / Stop,\n // per-run stop and interject, task and goal edits). Its own prefix, so it\n // never shadows /api/verse/fleet (V2.2) or /api/verse/fleet/live.\n id: 'fleet-control',\n owner: 'fleet-control',\n module: 'src/core/verse/fleet-control-api.ts',\n handler: 'handleFleetControlApi',\n prefixes: ['/api/verse/fleet/control'],\n },\n {\n id: 'leader',\n owner: 'B-U8',\n module: 'src/core/verse/leader-api.ts',\n handler: 'handleLeaderApi',\n prefixes: ['/api/verse/leader'],\n },\n {\n id: 'learning',\n owner: 'B-U9',\n module: 'src/core/verse/learning-api.ts',\n handler: 'handleLearningApi',\n prefixes: ['/api/verse/learning'],\n },\n {\n id: 'wiki',\n owner: '3.15-wiki',\n module: 'src/core/verse/wiki-api.ts',\n handler: 'handleWikiApi',\n prefixes: ['/api/verse/wiki'],\n },\n {\n id: 'playbooks',\n owner: '3.15-playbooks',\n module: 'src/core/verse/playbooks-api.ts',\n handler: 'handlePlaybooksApi',\n prefixes: ['/api/verse/playbooks'],\n },\n {\n id: 'automations',\n owner: '3.15-automations',\n module: 'src/core/verse/automations-api.ts',\n handler: 'handleAutomationsApi',\n prefixes: ['/api/verse/automations'],\n },\n {\n // The integrated Browser pane (3.15): the pane's policy / command relay,\n // and the per-chat MCP endpoint seats reach it through (browser-types.ts).\n id: 'browser',\n owner: '3.15-browser',\n module: 'src/core/verse/browser-api.ts',\n handler: 'handleBrowserApi',\n prefixes: ['/api/verse/browser'],\n },\n {\n // 3.15 agent tools: Verse's one MCP server for every seat (bearer per\n // turn) and the chat's Agent tools sheet (verse-mcp-types.ts).\n id: 'agent-tools',\n owner: '3.15-agent-tools',\n module: 'src/core/verse/verse-mcp-api.ts',\n handler: 'handleVerseMcpApi',\n prefixes: ['/api/verse/agent-tools'],\n },\n {\n // Desktop control for agents (3.15, agent-tools P4): the Verse window's\n // relay, grants and KILL (computer-api.ts). No seat-facing endpoint:\n // seats reach the tools through verse-mcp.ts in-process.\n id: 'computer',\n owner: '3.15-computer',\n module: 'src/core/verse/computer-api.ts',\n handler: 'handleComputerApi',\n prefixes: ['/api/verse/computer'],\n },\n {\n id: 'multimodel',\n owner: '3.16-multimodel',\n module: 'src/core/verse/multimodel-api.ts',\n handler: 'handleMultimodelApi',\n prefixes: ['/api/verse/multimodel'],\n },\n {\n id: 'checkpoints',\n owner: '3.15-checkpoints',\n module: 'src/core/verse/checkpoints-api.ts',\n handler: 'handleCheckpointsApi',\n prefixes: ['/api/verse/checkpoints'],\n },\n {\n id: 'sources',\n owner: 'R1',\n module: 'src/core/verse/sources-api.ts',\n handler: 'handleSourcesApi',\n prefixes: ['/api/verse/sources'],\n },\n {\n // 3.16 \"run many agents\": the Agents board, agent workspaces, Checks,\n // Plan first and spend caps (core/verse/agents/types.ts).\n id: 'agents',\n owner: '3.16-agents',\n module: 'src/core/verse/agents-api.ts',\n handler: 'handleAgentsApi',\n prefixes: ['/api/verse/agents'],\n },\n] as const satisfies readonly {\n id: string;\n owner: string;\n module: string;\n handler: string;\n prefixes: readonly string[];\n}[];\n\nexport type WorkbenchRouteFamily = (typeof WORKBENCH_ROUTE_FAMILIES)[number];\nexport type WorkbenchRouteFamilyId = WorkbenchRouteFamily['id'];\n\n/** Exact path or path + '/…' — the only prefix rule the mount uses. */\nexport function routePrefixOwns(prefix: string, path: string): boolean {\n return path === prefix || path.startsWith(`${prefix}/`);\n}\n\n/** The family that owns `path`, or null. Prefixes never overlap (tested), so at most one matches. */\nexport function workbenchFamilyFor(path: string): WorkbenchRouteFamily | null {\n for (const family of WORKBENCH_ROUTE_FAMILIES) {\n if (family.prefixes.some((prefix) => routePrefixOwns(prefix, path))) return family;\n }\n return null;\n}\n","/**\n * routes/verse/shell/guard-store.ts — the guarded-action STATE MACHINE\n * (confirm → token → run), without any dialog.\n *\n * Split out of guarded-action.tsx so a surface that draws its own\n * confirmation (the phone app, routes/verse/mobile/MobileGuardSheet.tsx) runs\n * exactly the same order as the desktop GuardHost — one machine, two\n * renderers — without evaluating guarded-action.tsx, whose preloaded desktop\n * dialogs would start downloading the moment it loads. guarded-action.tsx\n * re-exports everything here, so every existing import is unchanged.\n */\nimport { useSyncExternalStore, type ReactNode } from 'react';\nimport { hasMutationHold } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\n\nexport interface GuardedRequest {\n title: string;\n body: ReactNode;\n confirmLabel: string;\n destructive: boolean;\n /** Ask for the mutation token before running (every server write does). */\n token: boolean;\n /** Why the token is needed, in the token dialog's own words. */\n tokenReason?: string;\n run: () => Promise<void>;\n /**\n * For actions the regular UI does not confirm either (Mark read, Reconnect\n * with no item copy): straight to the token (if needed), then run; a\n * failure goes to `onError` only, since there is no dialog to show it in.\n */\n skipConfirm?: boolean;\n onDone?: () => void;\n /** Called with the sentence when the run fails (after the dialog shows it). */\n onError?: (message: string) => void;\n}\n\nexport type GuardPhase = 'confirm' | 'token' | 'running';\n\nexport interface GuardState {\n request: GuardedRequest | null;\n phase: GuardPhase;\n error: string | null;\n}\n\nconst IDLE: GuardState = { request: null, phase: 'confirm', error: null };\nlet state: GuardState = IDLE;\nconst listeners = new Set<() => void>();\n\nfunction set(next: GuardState): void {\n state = next;\n for (const l of [...listeners]) l();\n}\n\n/** Start a guarded action. A second request while one is open replaces nothing: it is ignored. */\nexport function requestGuarded(request: GuardedRequest): boolean {\n if (state.request) return false;\n if (request.skipConfirm) {\n if (request.token && !hasMutationHold()) set({ request, phase: 'token', error: null });\n else void execute(request);\n return true;\n }\n set({ request, phase: 'confirm', error: null });\n return true;\n}\n\nexport function isGuardOpen(): boolean {\n return state.request !== null;\n}\n\n/** Bind an asynchronous device check to the confirmation it displayed. */\nexport function isCurrentGuardRequest(request: GuardedRequest): boolean {\n return state.request === request && state.phase === 'confirm';\n}\n\n/** Test hygiene. */\nexport function resetGuard(): void {\n set(IDLE);\n}\n\n/** Operator language for a failed write — never a stack, never a path. */\nexport function describeActionError(err: unknown): string {\n if (err instanceof DispatchDisabledError) return 'This server was started without dispatch, so actions are unavailable. Run `ashlr verse` to act.';\n if (err instanceof ApiError) {\n if (err.status === 401) return 'The mutation token was rejected. Unlock again with the token `ashlr verse` printed.';\n if (err.status === 409) return err.detail ?? 'Something changed underneath this action. Refresh and try again.';\n return err.detail ?? `The server refused (HTTP ${err.status}).`;\n }\n return err instanceof Error && err.message ? err.message : 'Something went wrong.';\n}\n\nasync function execute(request: GuardedRequest): Promise<void> {\n set({ request, phase: 'running', error: null });\n try {\n await request.run();\n set(IDLE);\n request.onDone?.();\n } catch (err) {\n const message = describeActionError(err);\n set(request.skipConfirm ? IDLE : { request, phase: 'confirm', error: message });\n request.onError?.(message);\n }\n}\n\n/** The confirm step's primary button. */\nexport function confirmGuard(expectedRequest?: GuardedRequest): void {\n const { request } = state;\n // A phone's optional device check is asynchronous. A cancelled check must\n // never confirm a different request opened while that promise was pending.\n if (!request || state.phase !== 'confirm' || (expectedRequest && request !== expectedRequest)) return;\n if (request.token && !hasMutationHold()) {\n set({ request, phase: 'token', error: null });\n return;\n }\n void execute(request);\n}\n\n/** Cancel / Escape / backdrop — ignored while the action runs. */\nexport function cancelGuard(): void {\n if (state.phase === 'running') return;\n set(IDLE);\n}\n\n/** The token prompt closed: unlocked → run, otherwise → nothing happened. */\nexport function guardTokenClosed(): void {\n const { request } = state;\n if (!request) return;\n // MutationTokenDialog closes synchronously after storing the token, so a\n // live read says whether this close was \"unlocked\" or \"cancelled\".\n if (hasMutationHold()) void execute(request);\n else set(IDLE);\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function useGuardState(): GuardState {\n return useSyncExternalStore(subscribe, () => state, () => state);\n}\n","/**\n * routes/verse/shell/section-visibility.tsx — \"is this surface on screen?\"\n * for the keep-alive shell (unit C0; SPEC-310C §1).\n *\n * 3.10 keeps the last three surfaces MOUNTED (hidden with `hidden` + `inert`)\n * so switching back is instant and keeps scroll, selection and filters. The\n * price is that a hidden surface's polls keep running: Fleet's live swimlane\n * polling every few seconds behind a chat the operator is reading. The shell\n * (C1) wraps each mounted surface in <SectionVisibilityProvider visible>, and\n * every surface polls through usePollWhileVisible — so a hidden surface, or a\n * hidden window, costs nothing.\n *\n * Outside any provider a section counts as visible: components rendered on\n * their own (tests, the legacy sections before C1 lands) behave as today.\n */\nimport { createContext, useContext, useEffect, useRef, useSyncExternalStore, type ReactNode } from 'react';\n\nconst SectionVisibleContext = createContext<boolean>(true);\n\nexport function SectionVisibilityProvider({ visible, children }: { visible: boolean; children: ReactNode }) {\n // A hidden surface nested in a visible one is hidden; a visible one nested\n // in a hidden one is hidden too.\n const parent = useContext(SectionVisibleContext);\n return <SectionVisibleContext.Provider value={parent && visible}>{children}</SectionVisibleContext.Provider>;\n}\n\n/** True while the surface this component lives in is the one on screen. */\nexport function useSectionVisible(): boolean {\n return useContext(SectionVisibleContext);\n}\n\nfunction documentVisible(): boolean {\n return typeof document === 'undefined' || document.visibilityState !== 'hidden';\n}\n\nfunction subscribeDocument(onChange: () => void): () => void {\n if (typeof document === 'undefined') return () => {};\n document.addEventListener('visibilitychange', onChange);\n return () => document.removeEventListener('visibilitychange', onChange);\n}\n\n/** True while the window itself is visible (not minimised, not a background tab). */\nexport function useDocumentVisible(): boolean {\n return useSyncExternalStore(subscribeDocument, documentVisible, () => true);\n}\n\n/**\n * The performance budget's floor (SPEC-310A §0: \"no new polling faster than\n * 2 s\"). Enforced here, in the one place surfaces poll from, rather than by\n * review.\n */\nexport const MIN_POLL_INTERVAL_MS = 2_000;\n\nexport interface PollOptions {\n /** Poll at all (e.g. only while a panel is expanded). Default true. */\n enabled?: boolean;\n /**\n * Tick once as soon as the surface becomes visible again, so data that went\n * stale while it was hidden is refreshed on sight instead of one interval\n * later. Default true. (The first mount is the caller's own fetch.)\n */\n refreshOnShow?: boolean;\n}\n\n/**\n * Run `tick` every `intervalMs` (at least MIN_POLL_INTERVAL_MS) while the\n * section AND the document are visible. The latest `tick` is always the one\n * called, so passing an inline closure does not restart the interval.\n */\nexport function usePollWhileVisible(tick: () => void, intervalMs: number, options: PollOptions = {}): void {\n const sectionVisible = useSectionVisible();\n const docVisible = useDocumentVisible();\n const visible = sectionVisible && docVisible;\n const active = (options.enabled ?? true) && visible;\n const refreshOnShow = options.refreshOnShow ?? true;\n const every = Math.max(MIN_POLL_INTERVAL_MS, Number.isFinite(intervalMs) ? intervalMs : MIN_POLL_INTERVAL_MS);\n\n const tickRef = useRef(tick);\n tickRef.current = tick;\n // VISIBILITY history, not activity: turning `enabled` on is the caller's\n // own decision (and it fetches for itself); coming back into view is not.\n const wasVisible = useRef<boolean | null>(null);\n\n useEffect(() => {\n const previouslyVisible = wasVisible.current;\n wasVisible.current = visible;\n if (!active) return;\n // Back in view after being hidden: catch up now rather than one interval late.\n if (previouslyVisible === false && refreshOnShow) tickRef.current();\n const id = setInterval(() => tickRef.current(), every);\n return () => clearInterval(id);\n }, [active, visible, every, refreshOnShow]);\n}\n","/**\n * routes/verse/shell/useActivity.ts — the shell's one CURSOR loop over\n * GET /api/verse/activity (unit C1; route: core/verse/activity-api.ts).\n *\n * The rail badges, the palette's \"Needs you\" and running chats, the Needs-you\n * drawer and the in-app \"Finished / Failed\" toasts all read this ONE store,\n * so the whole shell costs one request per tick however many things show a\n * count. (The chat list polls the same route WITHOUT a cursor for its\n * present-tense view — chat/use-chat-activity.ts, C2.)\n *\n * CADENCE. Every 5 s while the window is visible, every 30 s while it is\n * hidden (the badges still need to be right when it comes back, and the tab\n * title count; C8's Rust owns native notifications). Never under the 2 s\n * floor (section-visibility MIN_POLL_INTERVAL_MS). Polls only while\n * something is subscribed.\n *\n * HONESTY. A 404 means the activity module is not in this build →\n * `unavailable`, and every badge renders \"unknown\" (no dot), never zero. A\n * failed poll keeps the last good data and says `stale` — a badge that\n * flashes to 0 on one dropped request would read as a false all-clear.\n * Any other failure carries the server's own reason in `error` (the route\n * answers `{ code, error }` when it could not read, e.g. a 503), so a\n * surface can say \"could not read the inbox: …\" instead of calling a broken\n * server \"not in this build\".\n *\n * COMPLETIONS arrive once per cursor; `onActivityCompletions` listeners get\n * each batch exactly once. The first poll of a page carries none (history is\n * not news).\n */\nimport { useSyncExternalStore } from 'react';\nimport type { VerseActivityCompletion, VerseActivityResponse } from '../../../../core/verse/workbench-types.js';\nimport { VERSE_ACTIVITY_PATH } from '../../../../core/verse/workbench-types.js';\nimport { ApiError, apiGet, readFailureReason } from '../../../data/client.js';\nimport { MIN_POLL_INTERVAL_MS } from './section-visibility.js';\n\nexport const ACTIVITY_POLL_VISIBLE_MS = 5_000;\nexport const ACTIVITY_POLL_HIDDEN_MS = 30_000;\n\nexport type ActivityStatus = 'idle' | 'loading' | 'ready' | 'stale' | 'unavailable';\n\nexport interface ActivityState {\n status: ActivityStatus;\n data: VerseActivityResponse | null;\n /** ms epoch of the last successful poll. */\n updatedAt: number | null;\n /** Why the last poll failed (null after a success, and for a 404 — that is `unavailable`, not a failure). */\n error?: string | null;\n}\n\ntype Fetcher = (path: string, signal?: AbortSignal) => Promise<VerseActivityResponse>;\n\nlet fetcher: Fetcher = (path, signal) => apiGet<VerseActivityResponse>(path, signal);\nlet snapshot: ActivityState = { status: 'idle', data: null, updatedAt: null, error: null };\nlet cursor: string | null = null;\nlet timer: ReturnType<typeof setTimeout> | null = null;\nlet inFlight: Promise<void> | null = null;\nlet subscribers = 0;\nconst listeners = new Set<() => void>();\nconst completionListeners = new Set<(batch: VerseActivityCompletion[]) => void>();\n\nfunction emit(next: ActivityState): void {\n snapshot = next;\n for (const l of [...listeners]) l();\n}\n\nfunction hidden(): boolean {\n return typeof document !== 'undefined' && document.visibilityState === 'hidden';\n}\n\nfunction schedule(): void {\n if (timer) clearTimeout(timer);\n timer = null;\n if (subscribers === 0) return;\n const every = Math.max(MIN_POLL_INTERVAL_MS, hidden() ? ACTIVITY_POLL_HIDDEN_MS : ACTIVITY_POLL_VISIBLE_MS);\n timer = setTimeout(() => {\n void refreshActivity();\n }, every);\n}\n\n/** Poll now (joins one already running). Resolves when it has settled; never rejects. */\nexport function refreshActivity(): Promise<void> {\n if (inFlight) return inFlight;\n if (snapshot.status === 'idle') emit({ ...snapshot, status: 'loading' });\n const path = cursor ? `${VERSE_ACTIVITY_PATH}?since=${encodeURIComponent(cursor)}` : VERSE_ACTIVITY_PATH;\n inFlight = (async () => {\n try {\n const data = await fetcher(path);\n const firstPoll = cursor === null;\n cursor = typeof data.cursor === 'string' ? data.cursor : null;\n emit({ status: 'ready', data, updatedAt: Date.now(), error: null });\n if (!firstPoll && Array.isArray(data.completions) && data.completions.length > 0) {\n for (const l of [...completionListeners]) {\n try { l(data.completions); } catch { /* a listener must not stop the loop */ }\n }\n }\n } catch (err) {\n if (err instanceof ApiError && err.status === 404) {\n emit({ status: 'unavailable', data: null, updatedAt: snapshot.updatedAt, error: null });\n } else if (err instanceof ApiError && err.status === 400 && cursor) {\n // A cursor the server no longer accepts: start over rather than stall.\n cursor = null;\n emit({ ...snapshot, status: snapshot.data ? 'stale' : 'loading' });\n } else {\n emit({ ...snapshot, status: snapshot.data ? 'stale' : 'unavailable', error: readFailureReason(err) });\n }\n } finally {\n inFlight = null;\n schedule();\n }\n })();\n return inFlight;\n}\n\nfunction onVisibility(): void {\n // Back in view: catch up now rather than up to 30 s late.\n if (!hidden() && subscribers > 0) void refreshActivity();\n else schedule();\n}\n\nfunction start(): void {\n subscribers += 1;\n if (subscribers === 1) {\n if (typeof document !== 'undefined') document.addEventListener('visibilitychange', onVisibility);\n void refreshActivity();\n }\n}\n\nfunction stop(): void {\n subscribers = Math.max(0, subscribers - 1);\n if (subscribers > 0) return;\n if (timer) clearTimeout(timer);\n timer = null;\n if (typeof document !== 'undefined') document.removeEventListener('visibilitychange', onVisibility);\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n start();\n return () => {\n listeners.delete(listener);\n stop();\n };\n}\n\nexport function getActivityState(): ActivityState {\n return snapshot;\n}\n\n/** The shell's activity. Subscribing starts the poll; the last unsubscribe stops it. */\nexport function useActivity(): ActivityState {\n return useSyncExternalStore(subscribe, getActivityState, getActivityState);\n}\n\n/** Each batch of newly finished turns, exactly once. Returns the unsubscribe. */\nexport function onActivityCompletions(listener: (batch: VerseActivityCompletion[]) => void): () => void {\n completionListeners.add(listener);\n return () => completionListeners.delete(listener);\n}\n\n/** Test seam: inject the fetch, clear state (and any timer). */\nexport function resetActivityForTest(next?: Fetcher): void {\n if (timer) clearTimeout(timer);\n timer = null;\n inFlight = null;\n cursor = null;\n subscribers = 0;\n listeners.clear();\n completionListeners.clear();\n fetcher = next ?? ((path, signal) => apiGet<VerseActivityResponse>(path, signal));\n snapshot = { status: 'idle', data: null, updatedAt: null, error: null };\n}\n","/**\n * routes/verse/verse-queries.ts — every /api/verse/* call the Verse console\n * makes. Reads are QueryDefs consumed through useQuery (cache-backed, so a\n * sidebar refresh never blanks the list); writes are wrapped like\n * data/mutations.ts's helpers — they pull the held mutation token from\n * auth-store, touch the hold on success, and invalidate the cache keys they\n * obviously affect. Nothing here ever sees launcher commands or env: the\n * server strips those before any payload leaves it (docs/VERSE-CONTRACT-V1).\n */\nimport type {\n VerseAutonomyScopeView,\n VerseCreateSessionRequest,\n VerseRootPriority,\n VerseSession,\n VerseSessionDetail,\n VerseSessionRootsResponse,\n VerseTurnRequest,\n VerseTurnResponse,\n VerseWorkspace,\n VerseWorkspaceCreateRequest,\n VerseWorkspacesResponse,\n VerseWorkspaceUpdateRequest,\n} from '../../data/api-types.js';\nimport type {\n VerseActivityResponse,\n VerseActivitySeenRequest,\n VerseSessionMeta,\n VerseSessionMetaResponse,\n VerseSessionMetaUpdate,\n} from '../../../core/verse/workbench-types.js';\nimport { VERSE_ACTIVITY_PATH, VERSE_ACTIVITY_SEEN_PATH, VERSE_SESSION_META_PATH } from '../../../core/verse/workbench-types.js';\nimport { getMutationToken, touchMutationHold } from '../../data/auth-store.js';\nimport { ApiError, apiGet, apiPost } from '../../data/client.js';\nimport { invalidate } from '../../data/cache.js';\nimport type { QueryDef } from '../../data/queries.js';\n\n// The bootstrap read has a module of its own (the phone app's first paint\n// needs it without the rest of this file); re-exported here unchanged.\nimport { VERSE_BOOTSTRAP_KEY } from './verse-bootstrap-query.js';\nexport { VERSE_BOOTSTRAP_KEY, verseBootstrapQuery } from './verse-bootstrap-query.js';\nexport const VERSE_SESSIONS_KEY = 'verse-sessions';\n\nexport const verseSessionsQuery: QueryDef<VerseSession[]> = {\n key: VERSE_SESSIONS_KEY,\n fetch: (signal) => apiGet<VerseSession[]>('/api/verse/sessions', signal),\n};\n\nexport function verseSessionPath(sessionId: string, suffix = ''): string {\n return `/api/verse/sessions/${encodeURIComponent(sessionId)}${suffix}`;\n}\n\nexport function fetchVerseSessionDetail(sessionId: string, signal?: AbortSignal): Promise<VerseSessionDetail> {\n return apiGet<VerseSessionDetail>(verseSessionPath(sessionId), signal);\n}\n\nexport class VerseMutationLockedError extends Error {\n constructor() {\n super('Unlock actions with the mutation token before chatting.');\n this.name = 'VerseMutationLockedError';\n }\n}\n\nasync function post<T>(path: string, body: unknown): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseMutationLockedError();\n const result = await apiPost<T>(path, body, token);\n touchMutationHold();\n return result;\n}\n\n/** Sidebar + resources panel both read these; refresh them after any write. */\nexport function invalidateVerseLists(): void {\n invalidate(VERSE_SESSIONS_KEY);\n invalidate(VERSE_BOOTSTRAP_KEY);\n}\n\nexport async function createVerseSession(req: VerseCreateSessionRequest): Promise<VerseSession> {\n const session = await post<VerseSession>('/api/verse/sessions', req);\n invalidateVerseLists();\n return session;\n}\n\nexport async function sendVerseTurn(sessionId: string, text: string): Promise<VerseTurnResponse> {\n const body: VerseTurnRequest = { text };\n const response = await post<VerseTurnResponse>(verseSessionPath(sessionId, '/turns'), body);\n invalidate(VERSE_SESSIONS_KEY);\n return response;\n}\n\nexport async function cancelVerseTurn(sessionId: string): Promise<void> {\n await post<{ ok: true }>(verseSessionPath(sessionId, '/cancel'), {});\n invalidate(VERSE_SESSIONS_KEY);\n}\n\n/**\n * 3.15: Stop in a Devin chat, confirmed — end the Devin session for good\n * (the server also stops watching a running turn). Irreversible, so the body\n * must carry `confirm: true`.\n */\nexport async function terminateVerseDevinSession(sessionId: string): Promise<{ cancelled: boolean; terminated: boolean }> {\n const response = await post<{ ok: true; cancelled: boolean; terminated: boolean }>(verseSessionPath(sessionId, '/terminate'), { confirm: true });\n invalidate(VERSE_SESSIONS_KEY);\n return { cancelled: response.cancelled, terminated: response.terminated };\n}\n\nexport async function deleteVerseSession(sessionId: string): Promise<void> {\n await post<{ ok: true }>(verseSessionPath(sessionId, '/delete'), {});\n invalidateVerseLists();\n}\n\nexport async function renameVerseSession(sessionId: string, title: string): Promise<VerseSession> {\n const session = await post<VerseSession>(verseSessionPath(sessionId, '/rename'), { title });\n invalidate(VERSE_SESSIONS_KEY);\n return session;\n}\n\n// ---------------------------------------------------------------------------\n// Workspaces (V2.2)\n// ---------------------------------------------------------------------------\n\nexport const VERSE_WORKSPACES_KEY = 'verse-workspaces';\nexport const VERSE_AUTONOMY_SCOPE_KEY = 'verse-autonomy-scope';\n\nexport const verseWorkspacesQuery: QueryDef<VerseWorkspacesResponse> = {\n key: VERSE_WORKSPACES_KEY,\n fetch: (signal) => apiGet<VerseWorkspacesResponse>('/api/verse/workspaces', signal),\n};\n\n/**\n * Enrolled repos, ordered by section focus and priority. Kept on its own key\n * from `verseScopeQuery` (which is the raw registry) so a re-rank refreshes\n * the ORDER without re-reading enrollment — and so it is obvious in the cache\n * that these are two different facts.\n */\nexport const verseAutonomyScopeQuery: QueryDef<VerseAutonomyScopeView> = {\n key: VERSE_AUTONOMY_SCOPE_KEY,\n fetch: (signal) => apiGet<VerseAutonomyScopeView>('/api/verse/autonomy-scope', signal),\n};\n\n/**\n * Per-root identity for one session: branch, dirty state, remote, whether the\n * engine can reach each root and whether the autonomous lane would.\n *\n * Deliberately NOT cached by session id alone at module scope — a branch goes\n * stale the moment a turn commits, so the panel refetches it per open.\n */\nexport function fetchVerseSessionRoots(sessionId: string, signal?: AbortSignal): Promise<VerseSessionRootsResponse> {\n return apiGet<VerseSessionRootsResponse>(verseSessionPath(sessionId, '/roots'), signal);\n}\n\nfunction invalidateWorkspaces(): void {\n invalidate(VERSE_WORKSPACES_KEY);\n invalidate(VERSE_AUTONOMY_SCOPE_KEY);\n invalidate(VERSE_BOOTSTRAP_KEY);\n}\n\nexport async function createVerseWorkspace(req: VerseWorkspaceCreateRequest): Promise<VerseWorkspace> {\n const workspace = await post<VerseWorkspace>('/api/verse/workspaces', req);\n invalidateWorkspaces();\n return workspace;\n}\n\nexport async function updateVerseWorkspace(id: string, patch: VerseWorkspaceUpdateRequest): Promise<VerseWorkspace> {\n const workspace = await post<VerseWorkspace>(`/api/verse/workspaces/${encodeURIComponent(id)}/update`, patch);\n invalidateWorkspaces();\n return workspace;\n}\n\nexport async function deleteVerseWorkspace(id: string): Promise<void> {\n await post<{ ok: true }>(`/api/verse/workspaces/${encodeURIComponent(id)}/delete`, {});\n invalidateWorkspaces();\n}\n\nexport async function setVerseRootPriority(path: string, priority: VerseRootPriority): Promise<void> {\n await post<unknown>('/api/verse/workspaces/priority', { path, priority });\n invalidateWorkspaces();\n}\n\nexport async function setVerseFocusSection(sectionId: string | null): Promise<void> {\n await post<unknown>('/api/verse/workspaces/focus', { sectionId });\n invalidateWorkspaces();\n}\n\n// ---------------------------------------------------------------------------\n// 3.10 — activity + per-chat meta (C1's routes; C2's sidebar reads them)\n// ---------------------------------------------------------------------------\n//\n// Both route families are mounted lazily (C0's mount table): on a build where\n// C1's module has not landed they answer a plain 404. That is \"this server\n// has no activity yet\", not an error the sidebar should paint red — so a 404\n// reads as `null` and every consumer falls back to what the session list\n// alone can say (running dot from `status`, no pins, no unread).\n\nexport const VERSE_ACTIVITY_KEY = 'verse-activity';\nexport const VERSE_SESSION_META_KEY = 'verse-session-meta';\n\nasync function getOrNull<T>(path: string, signal?: AbortSignal): Promise<T | null> {\n try {\n return await apiGet<T>(path, signal);\n } catch (err) {\n if (err instanceof ApiError && err.status === 404) return null;\n throw err;\n }\n}\n\n/**\n * The poll-shaped read (no `since`): running chats with their live line and\n * the Needs-you items. Completions are C1's concern (its cursor loop feeds\n * the rail and the native notifications); the sidebar needs only the present.\n */\nexport const verseActivityQuery: QueryDef<VerseActivityResponse | null> = {\n key: VERSE_ACTIVITY_KEY,\n fetch: (signal) => getOrNull<VerseActivityResponse>(VERSE_ACTIVITY_PATH, signal),\n};\n\nexport const verseSessionMetaQuery: QueryDef<VerseSessionMetaResponse | null> = {\n key: VERSE_SESSION_META_KEY,\n fetch: (signal) => getOrNull<VerseSessionMetaResponse>(VERSE_SESSION_META_PATH, signal),\n};\n\n/** Pin / archive one chat. Unknown keys are a 400 on the server, so only the two known ones are ever sent. */\nexport async function setVerseSessionMeta(sessionId: string, update: VerseSessionMetaUpdate): Promise<VerseSessionMeta> {\n const body: VerseSessionMetaUpdate = {};\n if (typeof update.pinned === 'boolean') body.pinned = update.pinned;\n if (typeof update.archived === 'boolean') body.archived = update.archived;\n const meta = await post<VerseSessionMeta>(`${VERSE_SESSION_META_PATH}/${encodeURIComponent(sessionId)}`, body);\n invalidate(VERSE_SESSION_META_KEY);\n return meta;\n}\n\n/**\n * \"The operator has read this chat up to `turnCount`.\" Best-effort and SILENT:\n * it runs only when a token is already held (opening a chat must never raise\n * the token dialog), and a failure is swallowed — the sidebar keeps its own\n * optimistic read state, so the unread dot clears either way.\n */\nexport async function markVerseSessionSeen(sessionId: string, turnCount: number): Promise<boolean> {\n const token = getMutationToken();\n if (!token) return false;\n const body: VerseActivitySeenRequest = { sessionId, turnCount };\n try {\n // apiPost, not post(): reading a chat is not operator ACTIVITY, so it\n // must not extend the mutation hold the way a real write does.\n await apiPost<unknown>(VERSE_ACTIVITY_SEEN_PATH, body, token);\n return true;\n } catch {\n return false;\n }\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-BC5Uslm5.js";import{a as r,c as i,d as a,f as o,i as s,l as c,o as l,s as u,t as d,u as f}from"./VoiceInput-k3vB_FxV.js";var p=e(n(),1),m=t(),h=24;function g(){try{let e=document.documentElement.getAttribute(`data-motion`);return e===`reduce`||e!==`full`&&window.matchMedia(`(prefers-reduced-motion: reduce)`).matches}catch{return!1}}function _({active:e}){let[t]=(0,p.useState)(g),n=(0,p.useRef)(null),i=(0,p.useRef)(null);return(0,p.useEffect)(()=>{let e=Array(h).fill(0);return a(r=>{if(t){i.current&&(i.current.style.transform=`scaleX(${Math.max(.02,r)})`);return}e.shift(),e.push(r);let a=n.current?.children;if(a)for(let t=0;t<a.length;t+=1){let n=a[t];n.style.transform=`scaleY(${Math.max(.08,e[t]??0)})`}})},[t]),t?(0,m.jsx)(`span`,{className:r.meter,"data-active":e?`true`:void 0,"aria-hidden":`true`,children:(0,m.jsx)(`span`,{ref:i,className:r.meterFill})}):(0,m.jsx)(`span`,{ref:n,className:r.wave,"data-active":e?`true`:void 0,"aria-hidden":`true`,children:Array.from({length:h},(e,t)=>(0,m.jsx)(`span`,{className:r.waveBar},t))})}var v=`npm run ship:local -- --native`;function y(e){switch(e.code){case`mic-undetermined`:return{label:`Allow microphone`,action:`request-mic`};case`mic-denied`:case`mic-restricted`:return{label:`Open Microphone privacy settings`,action:`open-mic-settings`};case`no-usage-description`:return{label:`Copy reinstall command`,action:`copy-reinstall`};case`no-input-device`:case`capture-failed`:return{label:`Open Sound settings`,action:`open-sound-settings`};case`model-download-failed`:case`model-load-failed`:return{label:`Download again`,action:`download-model`};case`engine-failed`:case`unsupported`:return{label:`Dismiss`,action:`dismiss`};default:return null}}function b(e){return e>=1e9?`${(e/1e9).toFixed(1)} GB`:`${Math.round(e/1e6)} MB`}async function x(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}function S(e){let t=e.native?.engine;if(!t)return null;let n=t.id===`whisper`?`Whisper`:`Parakeet`;switch(t.model){case`downloading`:return{text:`Downloading ${n} · ${Math.round((t.progress??0)*100)}% of ${b(t.totalBytes)} (once)`,progress:t.progress??0,cancellable:!0};case`verifying`:return{text:`Verifying ${n}…`,progress:t.progress,cancellable:!1};case`loading`:return{text:`Loading ${n}…`,progress:null,cancellable:!1};default:return null}}function C(e,t=140){return e.length>t?`…${e.slice(e.length-t+1)}`:e}function w(){let e=o(),[t,n]=(0,p.useState)(!1),a=(0,p.useCallback)(e=>{if(e.action===`dismiss`)return u();if(e.action===`copy-reinstall`){x(v).then(e=>n(e));return}c(e.action)},[]),{session:h,error:g,notice:b}=e,w=S(e),E=e.backend===`native`?e.native?.engine.label??`local Parakeet`:`browser speech`;if(h){let t=h.phase!==`finalizing`,n=s(e.native?.hotkey.accelerator??`Ctrl+Option+V`),i=h.origin===`hotkey`&&!h.latched?`Release ${n} to insert`:e.backend===`native`?`${n} or Stop inserts · Esc cancels`:`Stop inserts · Esc cancels`,a=h.mode===`command`?` · command`:h.mode===`verbatim`?` · terminal, verbatim`:``;return(0,m.jsxs)(`div`,{className:r.hud,"data-state":t?`listening`:`finalizing`,role:`group`,"aria-label":`Dictation`,children:[(0,m.jsxs)(`div`,{className:r.hudRow,children:[(0,m.jsx)(`span`,{className:r.hudDot,"aria-hidden":`true`,children:(0,m.jsx)(d,{})}),(0,m.jsx)(_,{active:t}),(0,m.jsxs)(`span`,{className:r.hudLabel,role:`status`,children:[t?h.phase===`starting`?`Starting…`:`Listening · ${E}`:`Transcribing…`,(0,m.jsx)(`span`,{className:r.hudWhere,children:a})]}),t?(0,m.jsx)(`span`,{className:r.hudHint,children:i}):null,t?(0,m.jsx)(`button`,{type:`button`,className:r.hudButton,"data-primary":`true`,onClick:f,children:`Stop`}):null,(0,m.jsx)(`button`,{type:`button`,className:r.hudIcon,"aria-label":`Cancel dictation`,onClick:l,children:`×`})]}),w?(0,m.jsx)(T,{text:w.text,progress:w.progress,cancellable:w.cancellable}):null,h.partial?(0,m.jsx)(`p`,{className:r.hudPartial,"aria-hidden":`true`,children:C(h.partial)}):null]})}if(g?.code===`model-missing`&&w)return(0,m.jsxs)(`div`,{className:r.hud,"data-state":`model`,role:`status`,children:[(0,m.jsxs)(`div`,{className:r.hudRow,children:[(0,m.jsx)(`span`,{className:r.hudDot,"aria-hidden":`true`,children:(0,m.jsx)(d,{})}),(0,m.jsx)(`span`,{className:r.hudMessage,children:g.message}),(0,m.jsx)(`button`,{type:`button`,className:r.hudIcon,"aria-label":`Dismiss`,onClick:u,children:`×`})]}),(0,m.jsx)(T,{text:w.text,progress:w.progress,cancellable:w.cancellable})]});if(g){let e=y(g);return(0,m.jsxs)(`div`,{className:r.hud,"data-state":`error`,role:`alert`,children:[(0,m.jsxs)(`div`,{className:r.hudRow,children:[(0,m.jsx)(`span`,{className:r.hudDot,"data-tone":`danger`,"aria-hidden":`true`,children:(0,m.jsx)(d,{})}),(0,m.jsx)(`span`,{className:r.hudMessage,children:g.message}),e&&e.action!==`dismiss`?(0,m.jsx)(`button`,{type:`button`,className:r.hudButton,"data-primary":`true`,onClick:()=>a(e),children:e.action===`copy-reinstall`&&t?`Copied`:e.label}):null,(0,m.jsx)(`button`,{type:`button`,className:r.hudIcon,"aria-label":`Dismiss`,onClick:u,children:`×`})]}),w?(0,m.jsx)(T,{text:w.text,progress:w.progress,cancellable:w.cancellable}):null]})}if(w)return(0,m.jsx)(`div`,{className:r.hud,"data-state":`model`,role:`status`,children:(0,m.jsx)(T,{text:w.text,progress:w.progress,cancellable:w.cancellable})});if(b){let e=b.mode!==`verbatim`&&b.lexicon!==null&&b.lexicon!==`live`,t=b.latencyMs===null?``:` · ${Math.round(b.latencyMs)} ms`;return b.kind===`orphan`?(0,m.jsxs)(`div`,{className:r.hud,"data-state":`notice`,role:`status`,children:[(0,m.jsxs)(`div`,{className:r.hudRow,children:[(0,m.jsx)(`span`,{className:r.hudMessage,children:`No input to put this in — click one, then paste:`}),(0,m.jsx)(`button`,{type:`button`,className:r.hudButton,"data-primary":`true`,onClick:()=>{x(b.text).then(e=>{e&&i()})},children:`Copy`}),(0,m.jsx)(`button`,{type:`button`,className:r.hudIcon,"aria-label":`Dismiss`,onClick:i,children:`×`})]}),(0,m.jsx)(`p`,{className:r.hudPartial,"data-solid":`true`,children:C(b.text,280)})]}):(0,m.jsx)(`div`,{className:r.hud,"data-state":`notice`,role:`status`,children:(0,m.jsxs)(`div`,{className:r.hudRow,children:[(0,m.jsxs)(`span`,{className:r.hudLabel,children:[b.kind===`palette`?`Sent to ⌘K`:`Inserted`,t]}),e?(0,m.jsx)(`button`,{type:`button`,className:r.rawBadge,title:b.lexicon===`cached`?`lexicon serve was offline — spellings came from the cached term map. Click to retry.`:`lexicon serve was offline and no term map is cached — words are as heard. Click to retry.`,onClick:()=>c(`retry-lexicon`),children:`raw`}):null]})})}return null}function T({text:e,progress:t,cancellable:n}){return(0,m.jsxs)(`div`,{className:r.hudModel,children:[(0,m.jsx)(`span`,{className:r.hudModelText,children:e}),t===null?null:(0,m.jsx)(`span`,{className:r.progress,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(t*100),"aria-label":`Model download`,children:(0,m.jsx)(`span`,{className:r.progressFill,style:{transform:`scaleX(${t})`}})}),n?(0,m.jsx)(`button`,{type:`button`,className:r.hudButton,onClick:()=>c(`cancel-download`),children:`Cancel`}):null]})}export{v as REINSTALL_COMMAND,w as VoiceHud,w as default,y as fixFor};
|
|
2
|
+
//# sourceMappingURL=VoiceHud-BG5FV2h0.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceHud-BG5FV2h0.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/voice/Waveform.tsx","../../../../../../src/web-ui/routes/verse/voice/VoiceHud.tsx"],"sourcesContent":["/**\n * routes/verse/voice/Waveform.tsx — the live mic meter in the dictation pill.\n *\n * Full motion: a scrolling bar waveform of the last ~1.2 s of levels.\n * Reduced motion (OS preference unless Settings says full, or Settings says\n * reduce — the same two triggers as tokens.css): a static level meter, no\n * scrolling and no transitions.\n *\n * Levels arrive at ~20 Hz from `subscribeVoiceLevel`; bars are painted by\n * writing transforms directly, so the meter never re-renders React.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { subscribeVoiceLevel } from './voice-store.js';\nimport styles from './VoiceInput.module.css';\n\nconst BARS = 24;\n\nexport function prefersReducedMotion(): boolean {\n try {\n const setting = document.documentElement.getAttribute('data-motion');\n if (setting === 'reduce') return true;\n if (setting === 'full') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n } catch {\n return false;\n }\n}\n\nexport function Waveform({ active }: { active: boolean }) {\n const [reduced] = useState(prefersReducedMotion);\n const barsRef = useRef<HTMLSpanElement>(null);\n const meterRef = useRef<HTMLSpanElement>(null);\n\n useEffect(() => {\n const history = new Array<number>(BARS).fill(0);\n return subscribeVoiceLevel((level) => {\n if (reduced) {\n if (meterRef.current) meterRef.current.style.transform = `scaleX(${Math.max(0.02, level)})`;\n return;\n }\n history.shift();\n history.push(level);\n const bars = barsRef.current?.children;\n if (!bars) return;\n for (let i = 0; i < bars.length; i += 1) {\n const el = bars[i] as HTMLElement;\n el.style.transform = `scaleY(${Math.max(0.08, history[i] ?? 0)})`;\n }\n });\n }, [reduced]);\n\n if (reduced) {\n return (\n <span className={styles.meter} data-active={active ? 'true' : undefined} aria-hidden=\"true\">\n <span ref={meterRef} className={styles.meterFill} />\n </span>\n );\n }\n return (\n <span ref={barsRef} className={styles.wave} data-active={active ? 'true' : undefined} aria-hidden=\"true\">\n {Array.from({ length: BARS }, (_, i) => (\n <span key={i} className={styles.waveBar} />\n ))}\n </span>\n );\n}\n","/**\n * routes/verse/voice/VoiceHud.tsx — the floating dictation pill, one for the\n * whole app (mounted lazily by VerseApp).\n *\n * listening waveform · \"Listening · local Parakeet\" · how to finish ·\n * Stop / Cancel, and the partial transcript DIMMED underneath\n * finalizing \"Transcribing…\"\n * done \"Inserted · 180 ms\" (+ a quiet \"raw\" badge when the lexicon\n * was offline), \"Sent to ⌘K\", or — nowhere to put it — the text\n * with Copy\n * model download / verify / load progress, with Cancel\n * error what happened and ONE button that fixes it\n *\n * Renders nothing when idle.\n */\nimport { useCallback, useState } from 'react';\nimport {\n cancelVoice,\n dismissVoiceError,\n dismissVoiceNotice,\n fixVoice,\n stopVoice,\n useVoiceSnapshot,\n type VoiceErrorView,\n type VoiceSnapshot,\n} from './voice-store.js';\nimport type { FixAction } from './voice-bridge.js';\nimport { MicIcon, readableVoiceAccelerator } from './VoiceInput.js';\nimport { Waveform } from './Waveform.js';\nimport styles from './VoiceInput.module.css';\n\nexport const REINSTALL_COMMAND = 'npm run ship:local -- --native';\n\ninterface Fix {\n label: string;\n action: FixAction | 'copy-reinstall' | 'dismiss';\n}\n\n/** The one-click fix for an error, or null when there is nothing to do. */\nexport function fixFor(error: VoiceErrorView): Fix | null {\n switch (error.code) {\n case 'mic-undetermined':\n return { label: 'Allow microphone', action: 'request-mic' };\n case 'mic-denied':\n case 'mic-restricted':\n return { label: 'Open Microphone privacy settings', action: 'open-mic-settings' };\n case 'no-usage-description':\n return { label: 'Copy reinstall command', action: 'copy-reinstall' };\n case 'no-input-device':\n case 'capture-failed':\n return { label: 'Open Sound settings', action: 'open-sound-settings' };\n case 'model-download-failed':\n case 'model-load-failed':\n return { label: 'Download again', action: 'download-model' };\n case 'engine-failed':\n case 'unsupported':\n return { label: 'Dismiss', action: 'dismiss' };\n default:\n return null;\n }\n}\n\nfunction formatBytes(bytes: number): string {\n return bytes >= 1e9 ? `${(bytes / 1e9).toFixed(1)} GB` : `${Math.round(bytes / 1e6)} MB`;\n}\n\nasync function copy(text: string): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction modelLine(voice: VoiceSnapshot): { text: string; progress: number | null; cancellable: boolean } | null {\n const engine = voice.native?.engine;\n if (!engine) return null;\n const name = engine.id === 'whisper' ? 'Whisper' : 'Parakeet';\n switch (engine.model) {\n case 'downloading': {\n const pct = Math.round((engine.progress ?? 0) * 100);\n return { text: `Downloading ${name} · ${pct}% of ${formatBytes(engine.totalBytes)} (once)`, progress: engine.progress ?? 0, cancellable: true };\n }\n case 'verifying':\n return { text: `Verifying ${name}…`, progress: engine.progress, cancellable: false };\n case 'loading':\n return { text: `Loading ${name}…`, progress: null, cancellable: false };\n default:\n return null;\n }\n}\n\nfunction tail(text: string, max = 140): string {\n return text.length > max ? `…${text.slice(text.length - max + 1)}` : text;\n}\n\nexport function VoiceHud() {\n const voice = useVoiceSnapshot();\n const [copied, setCopied] = useState(false);\n const runFix = useCallback((fix: Fix) => {\n if (fix.action === 'dismiss') return dismissVoiceError();\n if (fix.action === 'copy-reinstall') {\n void copy(REINSTALL_COMMAND).then((ok) => setCopied(ok));\n return;\n }\n fixVoice(fix.action);\n }, []);\n\n const { session, error, notice } = voice;\n const model = modelLine(voice);\n const engineLabel = voice.backend === 'native' ? (voice.native?.engine.label ?? 'local Parakeet') : 'browser speech';\n\n if (session) {\n const listening = session.phase !== 'finalizing';\n const accel = readableVoiceAccelerator(voice.native?.hotkey.accelerator ?? 'Ctrl+Option+V');\n const how = session.origin === 'hotkey' && !session.latched\n ? `Release ${accel} to insert`\n : voice.backend === 'native'\n ? `${accel} or Stop inserts · Esc cancels`\n : 'Stop inserts · Esc cancels';\n const where = session.mode === 'command' ? ' · command' : session.mode === 'verbatim' ? ' · terminal, verbatim' : '';\n return (\n <div className={styles.hud} data-state={listening ? 'listening' : 'finalizing'} role=\"group\" aria-label=\"Dictation\">\n <div className={styles.hudRow}>\n <span className={styles.hudDot} aria-hidden=\"true\"><MicIcon /></span>\n <Waveform active={listening} />\n <span className={styles.hudLabel} role=\"status\">\n {listening ? (session.phase === 'starting' ? 'Starting…' : `Listening · ${engineLabel}`) : 'Transcribing…'}\n <span className={styles.hudWhere}>{where}</span>\n </span>\n {listening ? <span className={styles.hudHint}>{how}</span> : null}\n {listening ? (\n <button type=\"button\" className={styles.hudButton} data-primary=\"true\" onClick={stopVoice}>Stop</button>\n ) : null}\n <button type=\"button\" className={styles.hudIcon} aria-label=\"Cancel dictation\" onClick={cancelVoice}>×</button>\n </div>\n {model ? <ModelRow text={model.text} progress={model.progress} cancellable={model.cancellable} /> : null}\n {session.partial ? (\n // Partials change every ~400 ms: hidden from screen readers (the\n // final is announced instead).\n <p className={styles.hudPartial} aria-hidden=\"true\">{tail(session.partial)}</p>\n ) : null}\n </div>\n );\n }\n\n // The first dictation on a new Mac starts the one-time model download:\n // that is progress, not a failure — no red.\n if (error?.code === 'model-missing' && model) {\n return (\n <div className={styles.hud} data-state=\"model\" role=\"status\">\n <div className={styles.hudRow}>\n <span className={styles.hudDot} aria-hidden=\"true\"><MicIcon /></span>\n <span className={styles.hudMessage}>{error.message}</span>\n <button type=\"button\" className={styles.hudIcon} aria-label=\"Dismiss\" onClick={dismissVoiceError}>×</button>\n </div>\n <ModelRow text={model.text} progress={model.progress} cancellable={model.cancellable} />\n </div>\n );\n }\n\n if (error) {\n const fix = fixFor(error);\n return (\n <div className={styles.hud} data-state=\"error\" role=\"alert\">\n <div className={styles.hudRow}>\n <span className={styles.hudDot} data-tone=\"danger\" aria-hidden=\"true\"><MicIcon /></span>\n <span className={styles.hudMessage}>{error.message}</span>\n {fix && fix.action !== 'dismiss' ? (\n <button type=\"button\" className={styles.hudButton} data-primary=\"true\" onClick={() => runFix(fix)}>\n {fix.action === 'copy-reinstall' && copied ? 'Copied' : fix.label}\n </button>\n ) : null}\n <button type=\"button\" className={styles.hudIcon} aria-label=\"Dismiss\" onClick={dismissVoiceError}>×</button>\n </div>\n {model ? <ModelRow text={model.text} progress={model.progress} cancellable={model.cancellable} /> : null}\n </div>\n );\n }\n\n if (model) {\n return (\n <div className={styles.hud} data-state=\"model\" role=\"status\">\n <ModelRow text={model.text} progress={model.progress} cancellable={model.cancellable} />\n </div>\n );\n }\n\n if (notice) {\n const raw = notice.mode !== 'verbatim' && notice.lexicon !== null && notice.lexicon !== 'live';\n const timing = notice.latencyMs !== null ? ` · ${Math.round(notice.latencyMs)} ms` : '';\n if (notice.kind === 'orphan') {\n return (\n <div className={styles.hud} data-state=\"notice\" role=\"status\">\n <div className={styles.hudRow}>\n <span className={styles.hudMessage}>No input to put this in — click one, then paste:</span>\n <button type=\"button\" className={styles.hudButton} data-primary=\"true\"\n onClick={() => { void copy(notice.text).then((ok) => { if (ok) dismissVoiceNotice(); }); }}>Copy</button>\n <button type=\"button\" className={styles.hudIcon} aria-label=\"Dismiss\" onClick={dismissVoiceNotice}>×</button>\n </div>\n <p className={styles.hudPartial} data-solid=\"true\">{tail(notice.text, 280)}</p>\n </div>\n );\n }\n return (\n <div className={styles.hud} data-state=\"notice\" role=\"status\">\n <div className={styles.hudRow}>\n <span className={styles.hudLabel}>{notice.kind === 'palette' ? 'Sent to ⌘K' : 'Inserted'}{timing}</span>\n {raw ? (\n <button type=\"button\" className={styles.rawBadge}\n title={notice.lexicon === 'cached'\n ? 'lexicon serve was offline — spellings came from the cached term map. Click to retry.'\n : 'lexicon serve was offline and no term map is cached — words are as heard. Click to retry.'}\n onClick={() => fixVoice('retry-lexicon')}>raw</button>\n ) : null}\n </div>\n </div>\n );\n }\n return null;\n}\n\nfunction ModelRow({ text, progress, cancellable }: { text: string; progress: number | null; cancellable: boolean }) {\n return (\n <div className={styles.hudModel}>\n <span className={styles.hudModelText}>{text}</span>\n {progress !== null ? (\n <span className={styles.progress} role=\"progressbar\" aria-valuemin={0} aria-valuemax={100} aria-valuenow={Math.round(progress * 100)} aria-label=\"Model download\">\n <span className={styles.progressFill} style={{ transform: `scaleX(${progress})` }} />\n </span>\n ) : null}\n {cancellable ? <button type=\"button\" className={styles.hudButton} onClick={() => fixVoice('cancel-download')}>Cancel</button> : null}\n </div>\n );\n}\n\nexport default VoiceHud;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{n as e,r as t}from"./rolldown-runtime-hePW80VL.js";import{n,s as r}from"./index-BC5Uslm5.js";import{wt as i}from"./VerseConsoleApp-DjPpZLo1.js";import{n as a,t as o}from"./web-speech-q3gDv2ax.js";import{n as s}from"./palette-handoff-XL2WWc9I.js";var c=t(r(),1),l=`ashlr:voice`,u=[`prose`,`verbatim`,`command`],d=[`granted`,`denied`,`restricted`,`undetermined`,`no-usage-description`,`unsupported`],f=[`missing`,`downloading`,`verifying`,`ready`,`loading`,`loaded`,`failed`],p=[`live`,`cached`,`none`],m=[`mic-denied`,`mic-restricted`,`mic-undetermined`,`no-usage-description`,`no-input-device`,`capture-failed`,`model-missing`,`model-download-failed`,`model-load-failed`,`engine-failed`,`no-speech`,`busy`,`unsupported`],h=65536,g=400,_=/^[A-Za-z0-9_-]{1,64}$/;function v(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function y(e,t){return typeof e==`string`&&e.length<=t}function b(e){return typeof e==`string`&&_.test(e)}function x(e){return typeof e==`number`&&Number.isFinite(e)}function S(e,t){return typeof e==`string`&&t.includes(e)}function ee(e){if(!v(e)||!v(e.engine)||!v(e.hotkey))return null;let t=e.engine,n=e.hotkey,r=e.session;if(!x(e.version)||!S(e.mic,d)||!S(e.lexicon,p)||!S(t.id,[`parakeet`,`whisper`,`none`])||!y(t.label,60)||!S(t.model,f)||!(t.progress===null||x(t.progress)&&t.progress>=0&&t.progress<=1)||!x(t.totalBytes)||!(t.error===null||y(t.error,g))||!y(n.accelerator,16)||!y(n.commandAccelerator,16)||typeof n.registered!=`boolean`||!(n.error===null||y(n.error,g)))return null;let i=null;if(r!==null){if(!v(r)||!b(r.id)||!S(r.origin,[`button`,`hotkey`])||!S(r.mode,u)||!S(r.phase,[`listening`,`finalizing`])||typeof r.latched!=`boolean`)return null;i={id:r.id,origin:r.origin,mode:r.mode,phase:r.phase,latched:r.latched}}return{version:e.version,mic:e.mic,engine:{id:t.id,label:t.label,model:t.model,progress:t.progress,totalBytes:t.totalBytes,error:t.error},hotkey:{accelerator:n.accelerator,commandAccelerator:n.commandAccelerator,registered:n.registered,error:n.error},lexicon:e.lexicon,session:i}}function te(e){if(!v(e))return null;switch(e.event){case`voice://state`:{let t=ee(e.state);return t?{event:`voice://state`,state:t}:null}case`voice://level`:{let t=e.level;return!b(e.session)||!x(t)?null:{event:`voice://level`,session:e.session,level:Math.min(1,Math.max(0,t))}}case`voice://partial`:return!b(e.session)||!y(e.text,h)?null:{event:`voice://partial`,session:e.session,text:e.text};case`voice://final`:{let t=e;return!b(t.session)||!y(t.text,h)||!S(t.mode,u)||!y(t.engine,32)||!S(t.lexicon,p)||!x(t.latencyMs)||!x(t.audioMs)?null:{event:`voice://final`,session:t.session,text:t.text,mode:t.mode,engine:t.engine,lexicon:t.lexicon,latencyMs:t.latencyMs,audioMs:t.audioMs}}case`voice://error`:{let t=e.session;return!(t===null||b(t))||!S(e.code,m)||!y(e.message,g)?null:{event:`voice://error`,session:t,code:e.code,message:e.message}}default:return null}}function C(){try{let e=window.__ASHLR_DESKTOP__?.voice;if(!e||e.version!==1||typeof e.send!=`function`)return null;let t=e.send;return{send:e=>{try{return t(e)===!0}catch{return!1}}}}catch{return null}}function ne(e){function t(t){let n=te(t.detail);n&&e(n)}return window.addEventListener(l,t),()=>window.removeEventListener(l,t)}var w=new Set(`ts.tsx.js.jsx.mjs.cjs.rs.md.json.css.scss.html.toml.yaml.yml.py.go.swift.kt.java.rb.sh.sql.txt.lock.plist`.split(`.`)),re=new Set([`file`,`component`,`function`,`hook`,`module`,`struct`,`class`,`type`,`test`,`script`,`crate`,`enum`,`trait`]),ie=new Set([`dot`,`period`]);function T(e){return e.toLowerCase().replace(/[^a-z0-9]/g,``)}function E(e){let t=e.lastIndexOf(`.`);return t<=0||t===e.length-1?{stem:e,ext:null}:{stem:e.slice(0,t),ext:e.slice(t+1).toLowerCase()}}function ae(e){let t=[],n=/[A-Za-z0-9_]+(?:[.-][A-Za-z0-9_]+)*/g;for(let r=n.exec(e);r;r=n.exec(e))t.push({text:r[0],start:r.index,end:r.index+r[0].length});return t}function D(e,t,n){return/^[ \t]+$/.test(e.slice(t.end,n.start))}function oe(e,t){let n=0;for(let r=0;r<t;r+=1)e[r]==="`"&&(n+=1);return n%2==1}function se(e){return/[a-z][A-Z]/.test(e)||/[A-Za-z0-9]_[A-Za-z0-9]/.test(e)||/^[A-Za-z0-9_-]+\.[A-Za-z0-9]+$/.test(e)}function ce(e){let t=ae(e),n=[],r=(n,r)=>{for(let i=n;i<r;i+=1)if(!D(e,t[i],t[i+1]))return!1;return!0};for(let i=0;i<t.length;i+=1){let a=t[i],o=a.text.toLowerCase();if(ie.has(o)&&i+1<t.length&&w.has(t[i+1].text.toLowerCase())&&D(e,a,t[i+1])){let e=t[i+1].text.toLowerCase();for(let a=Math.min(4,i);a>=1;--a){if(!r(i-a,i))continue;let o=t.slice(i-a,i);n.push({start:o[0].start,end:t[i+1].end,compact:T(o.map(e=>e.text).join(``)),ext:e,kind:`extension`,words:a})}}let{stem:s,ext:c}=E(a.text);if(c&&w.has(c))for(let e=Math.min(3,i);e>=0;--e){if(e>0&&!r(i-e,i))continue;let o=t.slice(i-e,i),l=`${o.map(e=>e.text).join(``)}${s}`;n.push({start:(o[0]??a).start,end:a.end,compact:T(l),ext:c,kind:`extension`,words:e+1})}if(re.has(o))for(let e=Math.min(4,i);e>=2;--e){if(!r(i-e,i))continue;let a=t.slice(i-e,i);n.push({start:a[0].start,end:a[a.length-1].end,compact:T(a.map(e=>e.text).join(``)),ext:null,kind:`cue`,words:e})}if(se(a.text)){let e=E(a.text);n.push({start:a.start,end:a.end,compact:T(e.ext&&w.has(e.ext)?e.stem:a.text),ext:e.ext&&w.has(e.ext)?e.ext:null,kind:`token`,words:1})}}return n.filter(t=>t.compact.length>=3&&!oe(e,t.start))}function le(e,t=6){let n=[],r=[...e].sort((e,t)=>t.words-e.words);for(let e of r)if(n.includes(e.compact)||n.push(e.compact),n.length>=t)break;return n}function ue(e){let t=e.split(/[\\/]/);return t[t.length-1]??e}function de(e,t){let n=new Set;for(let r of t){let t=ue(r),{stem:i,ext:a}=E(t);e.ext===null?e.kind===`token`?(T(i)===e.compact||T(t)===e.compact)&&n.add(a?t:i):T(i)===e.compact&&T(i).length>=6&&n.add(t):a===e.ext&&T(i)===e.compact&&n.add(t)}return n.size===1?[...n][0]:null}function fe(e,t,n){if(n.length===0||t.length===0)return e;let r=t.map(e=>({c:e,name:de(e,n)})).filter(e=>e.name!==null).sort((e,t)=>t.c.end-t.c.start-(e.c.end-e.c.start)),i=[],a=[];for(let{c:e,name:t}of r)i.some(([t,n])=>e.start<n&&t<e.end)||(i.push([e.start,e.end]),a.push({start:e.start,end:e.end,name:t}));a.sort((e,t)=>t.start-e.start);let o=e;for(let{start:e,end:t,name:n}of a)o=`${o.slice(0,e)}\`${n}\`${o.slice(t)}`;return o}async function pe(e,t,n=400){let r=ce(e);if(r.length===0)return e;try{return fe(e,r,await Promise.race([t(le(r)),new Promise(e=>setTimeout(()=>e([]),n))]))}catch{return e}}var me=new Set([`mic-denied`,`mic-restricted`,`mic-undetermined`,`no-usage-description`,`no-input-device`,`model-download-failed`,`model-load-failed`]),he=6e3,ge=2600,_e=6e3,O=new Map,k=null,A={backend:`none`,native:null,session:null,error:null,notice:null,targets:[]},j=new Set,M=new Set,N=!1,P=null,F=0,I=null,L=null,R=null;function z(e){A={...A,...e};for(let e of[...j])e()}function ve(){return C()?`native`:o()?`web-speech`:`none`}function ye(e){let t=e.target instanceof Node?e.target:null;if(t){for(let e of O.values())if(e.element()?.contains(t)){k=e.id;return}}}function be(e){e.key===`Escape`&&A.session&&(e.preventDefault(),Ee())}function B(){if(N)return;N=!0;let e=ve();z({backend:e});try{document.addEventListener(`focusin`,ye,!0),document.addEventListener(`keydown`,be,!0)}catch{}e===`native`&&(ne(ke),C()?.send({op:`status`}))}function xe(e){return B(),O.set(e.id,e),z({targets:[...O.keys()]}),()=>{O.get(e.id)===e&&O.delete(e.id),k===e.id&&(k=null),z({targets:[...O.keys()]})}}function Se(e=Ce()){let t=[...O.values()].filter(e=>e.element()?.isConnected!==!1);if(e){let n=t.find(t=>t.element()?.contains(e));if(n)return n}return(k?t.find(e=>e.id===k):void 0)||(t.find(e=>e.surface===`composer`)??t.find(e=>e.surface===`leader`)??t[0]??null)}function Ce(){try{return document.activeElement}catch{return null}}function V(){return F+=1,`v-${Date.now().toString(36)}-${F}`}function H(e,t,n){I&&clearTimeout(I),I=null,z({error:{code:e,message:t,targetId:n}}),me.has(e)||(I=setTimeout(()=>{I=null,z({error:null})},he))}function U(){I&&clearTimeout(I),I=null,z({error:null})}function W(e,t=!1){L&&clearTimeout(L),L=null,z({notice:e}),e&&!t&&(L=setTimeout(()=>{L=null,z({notice:null})},ge))}function we(){W(null)}function G(){let e=A.session;R&&clearTimeout(R),R=null,e?.targetId&&O.get(e.targetId)?.onListening?.(!1),z({session:null});for(let e of[...M])e(0)}function K(e){z({session:e,error:null}),e.targetId&&O.get(e.targetId)?.onListening?.(!0)}function Te(e){B();let t=O.get(e);if(!t||A.session)return;let n=t.mode;if(A.backend===`native`){let r=V(),i=t.cwd?.()??null;if(K({id:r,targetId:e,origin:`button`,mode:n,phase:`starting`,partial:``,latched:!0}),!(C()?.send({op:`start`,session:r,mode:n,...i?{cwd:i}:{}})??!1)){G(),H(`unsupported`,`The desktop app did not accept the request — restart Ashlr.`,e);return}R=setTimeout(()=>{R=null,A.session?.id===r&&A.session.phase===`starting`&&(G(),H(`capture-failed`,`The microphone did not start — try again.`,e))},_e);return}if(A.backend===`web-speech`){let t=V();K({id:t,targetId:e,origin:`button`,mode:n,phase:`listening`,partial:``,latched:!0}),P=a({onPartial:e=>{A.session?.id===t&&z({session:{...A.session,partial:e}})},onFinal:t=>{je(e,t,n,null,null)},onError:(t,n)=>H(t,n,e),onEnd:()=>{P=null,A.session?.id===t&&G()}}),P||G();return}H(`unsupported`,`Dictation is not available in this browser.`,e)}function q(){let e=A.session;if(e){if(A.backend===`native`){z({session:{...e,phase:`finalizing`}}),C()?.send({op:`stop`,session:e.id});return}P&&(z({session:{...e,phase:`finalizing`}}),P.stop())}}function Ee(){let e=A.session;e&&(A.backend===`native`&&C()?.send({op:`cancel`,session:e.id}),P?.cancel(),P=null,G())}function De(e){let t=A.session;if(!t)Te(e);else if(t.phase===`finalizing`)return;else q()}function Oe(e){A.backend===`native`&&(C()?.send({op:`fix`,action:e}),e!==`cancel-download`&&U())}function ke(e){switch(e.event){case`voice://state`:return Ae(e.state);case`voice://level`:if(A.session?.id===e.session)for(let t of[...M])t(e.level);return;case`voice://partial`:A.session?.id===e.session&&z({session:{...A.session,partial:e.text}});return;case`voice://final`:{let t=A.session?.id===e.session,n=t?A.session?.targetId??null:null;t&&G(),je(n,e.text,e.mode,e.lexicon,e.latencyMs);return}case`voice://error`:{let t=A.session?.targetId??null;e.session!==null&&e.session===A.session?.id&&G(),H(e.code,e.message,t);return}}}function Ae(e){z({native:e});let t=A.session,n=e.session;if(!n){t&&t.phase!==`starting`&&G();return}if(t&&t.id===n.id){R&&n.phase===`listening`&&(clearTimeout(R),R=null);let e=t.phase===`finalizing`?`finalizing`:n.phase;z({session:{...t,phase:e,latched:n.origin===`button`||n.latched,mode:n.mode}});return}if(n.origin===`hotkey`){let e=Se(),r=n.mode===`command`?`command`:e?.mode??`prose`,i=r===`prose`?e?.cwd?.()??null:null;t&&G(),K({id:n.id,targetId:r===`command`?null:e?.id??null,origin:`hotkey`,mode:r,phase:n.phase,partial:``,latched:n.latched}),C()?.send({op:`context`,session:n.id,mode:r,...i?{cwd:i}:{}});return}t?.phase!==`starting`&&(t&&G(),K({id:n.id,targetId:null,origin:`button`,mode:n.mode,phase:n.phase,partial:``,latched:!0}))}async function je(e,t,n,r,i){let a=t.trim();if(!a)return;if(n===`command`){s(a),W({kind:`palette`,text:a,lexicon:r,latencyMs:i,mode:n});return}let o=e?O.get(e):void 0;if(!o){W({kind:`orphan`,text:a,lexicon:r,latencyMs:i,mode:n},!0);return}let c=a;n===`prose`&&o.lookupIdentifiers&&(c=await pe(a,o.lookupIdentifiers)),o.insert(c);try{o.element()?.focus({preventScroll:!0})}catch{}W({kind:`inserted`,text:c,lexicon:r,latencyMs:i,mode:n})}function Me(){return A}function Ne(e){return B(),j.add(e),()=>{j.delete(e)}}function Pe(e){return M.add(e),()=>{M.delete(e)}}function J(){return(0,c.useSyncExternalStore)(Ne,Me,Me)}var Y={mic:`_mic_1sqe6_5`,micLive:`_micLive_1sqe6_35`,micPulse:`_micPulse_1sqe6_36`,"voice-ring":`_voice-ring_1sqe6_1`,hud:`_hud_1sqe6_50`,hudRow:`_hudRow_1sqe6_73`,hudDot:`_hudDot_1sqe6_74`,hudLabel:`_hudLabel_1sqe6_86`,hudWhere:`_hudWhere_1sqe6_87`,hudHint:`_hudHint_1sqe6_88`,hudMessage:`_hudMessage_1sqe6_89`,hudButton:`_hudButton_1sqe6_90`,hudIcon:`_hudIcon_1sqe6_106`,rawBadge:`_rawBadge_1sqe6_106`,hudPartial:`_hudPartial_1sqe6_121`,hudModel:`_hudModel_1sqe6_129`,hudModelText:`_hudModelText_1sqe6_130`,progress:`_progress_1sqe6_131`,progressFill:`_progressFill_1sqe6_132`,wave:`_wave_1sqe6_148`,waveBar:`_waveBar_1sqe6_149`,meter:`_meter_1sqe6_160`,meterFill:`_meterFill_1sqe6_161`},Fe=e({MicIcon:()=>$,VoiceInput:()=>Q,default:()=>Q,readableVoiceAccelerator:()=>Z}),X=n();function Z(e){return e.replaceAll(`⌃`,`Ctrl+`).replaceAll(`⌥`,`Option+`).replaceAll(`⇧`,`Shift+`).replaceAll(`⌘`,`Command+`)}function Q({surface:e,mode:t=`prose`,targetRef:n,onInsert:r,cwd:a,lookupIdentifiers:o,onListeningChange:s,disabled:l=!1,className:u}){let d=`${e}-${(0,c.useId)()}`,f=J(),p=(0,c.useRef)({onInsert:r,cwd:a,lookupIdentifiers:o,onListeningChange:s});p.current={onInsert:r,cwd:a,lookupIdentifiers:o,onListeningChange:s},(0,c.useEffect)(()=>xe({id:d,surface:e,mode:t,element:()=>n.current,cwd:()=>p.current.cwd?.()??null,insert:e=>p.current.onInsert(e),...o?{lookupIdentifiers:e=>p.current.lookupIdentifiers?.(e)??Promise.resolve([])}:{},onListening:e=>p.current.onListeningChange?.(e)}),[d,e,t,n,!!o]);let m=f.session,h=m?.targetId===d,g=h&&m?.phase!==`finalizing`,_=h&&m?.phase===`finalizing`,v=f.error?.targetId===d,y=f.backend===`native`?f.native?.hotkey:null;if(f.backend===`none`)return(0,X.jsx)(i,{label:`Dictation needs the Ashlr desktop app, or a browser with speech recognition`,placement:`top`,children:(0,X.jsxs)(`button`,{type:`button`,className:`${Y.mic} ${u??``}`,disabled:!0,"aria-disabled":`true`,"data-surface":e,children:[(0,X.jsx)($,{}),(0,X.jsx)(`span`,{className:`visually-hidden`,children:`Dictation unavailable`})]})});let b=g?`Stop and insert`:_?`Transcribing…`:`Dictate`,x=g?`Esc cancels`:y?.registered?Z(y.accelerator):void 0;return(0,X.jsx)(i,{label:b,shortcut:x,placement:`top`,children:(0,X.jsxs)(`button`,{type:`button`,className:`${Y.mic} ${g?Y.micLive:``} ${u??``}`,"data-surface":e,"data-error":v?`true`:void 0,disabled:l&&!h||!!m&&!h,"aria-pressed":g,"aria-busy":_||void 0,"aria-label":g?`Stop dictation and insert`:`Start dictation`,onMouseDown:e=>e.preventDefault(),onClick:()=>De(d),children:[(0,X.jsx)($,{}),g?(0,X.jsx)(`span`,{className:Y.micPulse,"aria-hidden":`true`}):null]})})}function $(){return(0,X.jsxs)(`svg`,{viewBox:`0 0 20 20`,width:`16`,height:`16`,"aria-hidden":`true`,focusable:`false`,children:[(0,X.jsx)(`rect`,{x:`7`,y:`2`,width:`6`,height:`10`,rx:`3`,fill:`currentColor`}),(0,X.jsx)(`path`,{d:`M4.5 9.5a5.5 5.5 0 0 0 11 0M10 15v3M7 18h6`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.6`,strokeLinecap:`round`})]})}export{Y as a,we as c,Pe as d,J as f,Z as i,Oe as l,Q as n,Ee as o,Fe as r,U as s,$ as t,q as u};
|
|
2
|
+
//# sourceMappingURL=VoiceInput-k3vB_FxV.js.map
|