@ashlr/hub 3.11.5 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +70 -0
- package/dist/authority-surface.json +3 -3
- package/dist/build-identity.json +2 -2
- package/dist/core/authority/trust-roots.js +7 -1
- package/dist/core/authority/trust-roots.js.map +1 -1
- package/dist/core/universe/builtins/preparation/manifest.json +1 -1
- package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +8 -2
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +7 -1
- package/dist/core/web/public/next/assets/{ActionMenu-DffwPklw.js → ActionMenu-B4-39f2S.js} +2 -2
- package/dist/core/web/public/next/assets/{ActionMenu-DffwPklw.js.map → ActionMenu-B4-39f2S.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Advanced-CxzE6ekM.js → Advanced-B-LqYXvd.js} +2 -2
- package/dist/core/web/public/next/assets/{Advanced-CxzE6ekM.js.map → Advanced-B-LqYXvd.js.map} +1 -1
- package/dist/core/web/public/next/assets/{App-DFlp-vdv.js → App-E2zCDRxm.js} +2 -2
- package/dist/core/web/public/next/assets/{App-DFlp-vdv.js.map → App-E2zCDRxm.js.map} +1 -1
- package/dist/core/web/public/next/assets/{AppsSection-Ct2O605-.js → AppsSection-8wXPPhZb.js} +2 -2
- package/dist/core/web/public/next/assets/{AppsSection-Ct2O605-.js.map → AppsSection-8wXPPhZb.js.map} +1 -1
- package/dist/core/web/public/next/assets/{AreaTrend-o-GLl2Is.js → AreaTrend-BFimExYn.js} +2 -2
- package/dist/core/web/public/next/assets/{AreaTrend-o-GLl2Is.js.map → AreaTrend-BFimExYn.js.map} +1 -1
- package/dist/core/web/public/next/assets/{AutonomyOffState-CXhXpsim.js → AutonomyOffState-B5eEkmiz.js} +2 -2
- package/dist/core/web/public/next/assets/{AutonomyOffState-CXhXpsim.js.map → AutonomyOffState-B5eEkmiz.js.map} +1 -1
- package/dist/core/web/public/next/assets/AutonomySection-B46igJKR.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-BTg7yVa1.js.map → AutonomySection-B46igJKR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{BranchBar-BjPFtGsj.js → BranchBar-BRkrEQGs.js} +2 -2
- package/dist/core/web/public/next/assets/{BranchBar-BjPFtGsj.js.map → BranchBar-BRkrEQGs.js.map} +1 -1
- package/dist/core/web/public/next/assets/{BudgetControl-ng6swoZp.js → BudgetControl-T_RjPrw9.js} +2 -2
- package/dist/core/web/public/next/assets/{BudgetControl-ng6swoZp.js.map → BudgetControl-T_RjPrw9.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Button-OjVJSrFq.js → Button-BhO-WKPp.js} +2 -2
- package/dist/core/web/public/next/assets/{Button-OjVJSrFq.js.map → Button-BhO-WKPp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{CapacityStrip-Bx4c3dxD.js → CapacityStrip-CkFz5vq2.js} +2 -2
- package/dist/core/web/public/next/assets/{CapacityStrip-Bx4c3dxD.js.map → CapacityStrip-CkFz5vq2.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ChartFrame-B_w2Siqg.js → ChartFrame-SygZ7B3x.js} +2 -2
- package/dist/core/web/public/next/assets/{ChartFrame-B_w2Siqg.js.map → ChartFrame-SygZ7B3x.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ChatSection-Bisj9R6E.js → ChatSection-D6WybBpB.js} +3 -3
- package/dist/core/web/public/next/assets/{ChatSection-Bisj9R6E.js.map → ChatSection-D6WybBpB.js.map} +1 -1
- package/dist/core/web/public/next/assets/{CloudBudgetForm-5Gf4iAok.js → CloudBudgetForm-Bd91iStN.js} +2 -2
- package/dist/core/web/public/next/assets/{CloudBudgetForm-5Gf4iAok.js.map → CloudBudgetForm-Bd91iStN.js.map} +1 -1
- package/dist/core/web/public/next/assets/{CommandPalette-iTpk6I8r.js → CommandPalette-B6SgDJH-.js} +2 -2
- package/dist/core/web/public/next/assets/{CommandPalette-iTpk6I8r.js.map → CommandPalette-B6SgDJH-.js.map} +1 -1
- package/dist/core/web/public/next/assets/{CommandSection-D8ZihzvE.js → CommandSection-DgMGoepd.js} +2 -2
- package/dist/core/web/public/next/assets/{CommandSection-D8ZihzvE.js.map → CommandSection-DgMGoepd.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ConfirmDialog-_S9iE-cJ.js → ConfirmDialog-Bv4hdK2T.js} +2 -2
- package/dist/core/web/public/next/assets/{ConfirmDialog-_S9iE-cJ.js.map → ConfirmDialog-Bv4hdK2T.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DeleteChatDialog-KUYUygiA.js → DeleteChatDialog-CH1Ix8Eh.js} +2 -2
- package/dist/core/web/public/next/assets/{DeleteChatDialog-KUYUygiA.js.map → DeleteChatDialog-CH1Ix8Eh.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Dialog-BuIaG6HF.js → Dialog-BSsIFNqD.js} +2 -2
- package/dist/core/web/public/next/assets/{Dialog-BuIaG6HF.js.map → Dialog-BSsIFNqD.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DiffPane-De4IQt82.js → DiffPane-BpNuJmth.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffPane-De4IQt82.js.map → DiffPane-BpNuJmth.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DiffViewer-B75t6Ile.js → DiffViewer-CJarUvs0.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffViewer-B75t6Ile.js.map → DiffViewer-CJarUvs0.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DockHost-BPqyhtCP.js → DockHost-DW9q0NdR.js} +2 -2
- package/dist/core/web/public/next/assets/{DockHost-BPqyhtCP.js.map → DockHost-DW9q0NdR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{EmptyState-DXkT4vhW.js → EmptyState-DPrd2aak.js} +2 -2
- package/dist/core/web/public/next/assets/{EmptyState-DXkT4vhW.js.map → EmptyState-DPrd2aak.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Epistemic-CfqFe_aP.js → Epistemic-D7MxSmED.js} +2 -2
- package/dist/core/web/public/next/assets/{Epistemic-CfqFe_aP.js.map → Epistemic-D7MxSmED.js.map} +1 -1
- package/dist/core/web/public/next/assets/{FleetSection-B7f-XBiX.js → FleetSection-BdZN6rGS.js} +3 -3
- package/dist/core/web/public/next/assets/{FleetSection-B7f-XBiX.js.map → FleetSection-BdZN6rGS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Funnel-pXYySwXQ.js → Funnel-BeNQZWv2.js} +2 -2
- package/dist/core/web/public/next/assets/{Funnel-pXYySwXQ.js.map → Funnel-BeNQZWv2.js.map} +1 -1
- package/dist/core/web/public/next/assets/{GearTray-gj6lT7ba.js → GearTray-CIPtzeIx.js} +2 -2
- package/dist/core/web/public/next/assets/{GearTray-gj6lT7ba.js.map → GearTray-CIPtzeIx.js.map} +1 -1
- package/dist/core/web/public/next/assets/{GrowthSection-D8e9m9Wy.js → GrowthSection-iiQg6wvK.js} +2 -2
- package/dist/core/web/public/next/assets/{GrowthSection-D8e9m9Wy.js.map → GrowthSection-iiQg6wvK.js.map} +1 -1
- package/dist/core/web/public/next/assets/{HandoffDialog-VfKxKhxF.js → HandoffDialog-DrQ6ofuy.js} +2 -2
- package/dist/core/web/public/next/assets/{HandoffDialog-VfKxKhxF.js.map → HandoffDialog-DrQ6ofuy.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Input-u1YR_Ogl.js → Input-C0MQxEM6.js} +2 -2
- package/dist/core/web/public/next/assets/{Input-u1YR_Ogl.js.map → Input-C0MQxEM6.js.map} +1 -1
- package/dist/core/web/public/next/assets/{LeaderCard-BDELBrnx.js → LeaderCard-BRr3_yE-.js} +2 -2
- package/dist/core/web/public/next/assets/{LeaderCard-BDELBrnx.js.map → LeaderCard-BRr3_yE-.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MatrixHeatmap-NKLF2srR.js → MatrixHeatmap-DZvZeWXL.js} +2 -2
- package/dist/core/web/public/next/assets/{MatrixHeatmap-NKLF2srR.js.map → MatrixHeatmap-DZvZeWXL.js.map} +1 -1
- package/dist/core/web/public/next/assets/McpSection-BRuCcTjT.js +2 -0
- package/dist/core/web/public/next/assets/{McpSection-D1tDvlRa.js.map → McpSection-BRuCcTjT.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdown-DlfLEJxu.js → MessageMarkdown-bRvD5nSc.js} +3 -3
- package/dist/core/web/public/next/assets/{MessageMarkdown-DlfLEJxu.js.map → MessageMarkdown-bRvD5nSc.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-BYZzI115.js → MessageMarkdownRenderer-FjjkPKA2.js} +2 -2
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-BYZzI115.js.map → MessageMarkdownRenderer-FjjkPKA2.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-BSVhU43Q.js → Meter-CFNLpwA-.js} +2 -2
- package/dist/core/web/public/next/assets/{Meter-BSVhU43Q.js.map → Meter-CFNLpwA-.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MindSection-lqV2e_Sq.js → MindSection-BTIiQS8P.js} +2 -2
- package/dist/core/web/public/next/assets/{MindSection-lqV2e_Sq.js.map → MindSection-BTIiQS8P.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MutationTokenDialog-CLGP72g6.js → MutationTokenDialog-T7gv3a9r.js} +2 -2
- package/dist/core/web/public/next/assets/{MutationTokenDialog-CLGP72g6.js.map → MutationTokenDialog-T7gv3a9r.js.map} +1 -1
- package/dist/core/web/public/next/assets/{NeedsYouDrawer-D992XTOn.js → NeedsYouDrawer-lYN4G_aM.js} +2 -2
- package/dist/core/web/public/next/assets/{NeedsYouDrawer-D992XTOn.js.map → NeedsYouDrawer-lYN4G_aM.js.map} +1 -1
- package/dist/core/web/public/next/assets/{NeedsYouList-eBOlJr0b.js → NeedsYouList-BgH8ezqf.js} +2 -2
- package/dist/core/web/public/next/assets/{NeedsYouList-eBOlJr0b.js.map → NeedsYouList-BgH8ezqf.js.map} +1 -1
- package/dist/core/web/public/next/assets/{NewChatDialog-DoYTH26M.js → NewChatDialog-Db5Xjrk8.js} +2 -2
- package/dist/core/web/public/next/assets/{NewChatDialog-DoYTH26M.js.map → NewChatDialog-Db5Xjrk8.js.map} +1 -1
- package/dist/core/web/public/next/assets/{OnboardingFlow-D3yfITK1.js → OnboardingFlow-LoY-zuSe.js} +2 -2
- package/dist/core/web/public/next/assets/{OnboardingFlow-D3yfITK1.js.map → OnboardingFlow-LoY-zuSe.js.map} +1 -1
- package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js +3 -0
- package/dist/core/web/public/next/assets/{OnboardingGate-DrDEVBqw.js.map → OnboardingGate-C4VXn7BJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{PreviewPane-ULN673zm.js → PreviewPane-BPBbcROb.js} +2 -2
- package/dist/core/web/public/next/assets/{PreviewPane-ULN673zm.js.map → PreviewPane-BPBbcROb.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ProviderLogo-8WaUjTlN.js → ProviderLogo-CT2cSfkg.js} +2 -2
- package/dist/core/web/public/next/assets/{ProviderLogo-8WaUjTlN.js.map → ProviderLogo-CT2cSfkg.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RailStatus-Ckw9nvYU.js → RailStatus-Vgl0GYtd.js} +2 -2
- package/dist/core/web/public/next/assets/{RailStatus-Ckw9nvYU.js.map → RailStatus-Vgl0GYtd.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RefreshIndicator-DGubF4vR.js → RefreshIndicator-CSyqpY_q.js} +2 -2
- package/dist/core/web/public/next/assets/{RefreshIndicator-DGubF4vR.js.map → RefreshIndicator-CSyqpY_q.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BahEaY4d.js → ResourcePoolConsoleApp-BX2nkdmZ.js} +2 -2
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BahEaY4d.js.map → ResourcePoolConsoleApp-BX2nkdmZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcesChrome-C2ZrA7la.js → ResourcesChrome-B2U2lO1H.js} +3 -3
- package/dist/core/web/public/next/assets/{ResourcesChrome-C2ZrA7la.js.map → ResourcesChrome-B2U2lO1H.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ResourcesDrawer-BC93fzwQ.js → ResourcesDrawer-DlUKOjl9.js} +2 -2
- package/dist/core/web/public/next/assets/{ResourcesDrawer-BC93fzwQ.js.map → ResourcesDrawer-DlUKOjl9.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-BvhHNpE_.js → RouteErrorBoundary-BaC7YVzR.js} +2 -2
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-BvhHNpE_.js.map → RouteErrorBoundary-BaC7YVzR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RunInCloudAction-Dywfnw0C.js → RunInCloudAction-D5PDHJPE.js} +2 -2
- package/dist/core/web/public/next/assets/{RunInCloudAction-Dywfnw0C.js.map → RunInCloudAction-D5PDHJPE.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SeatSelector-CH7hTgwy.js → SeatSelector-Cg75LInq.js} +2 -2
- package/dist/core/web/public/next/assets/{SeatSelector-CH7hTgwy.js.map → SeatSelector-Cg75LInq.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Segmented-Wynbg0F5.js → Segmented-CametjLt.js} +2 -2
- package/dist/core/web/public/next/assets/{Segmented-Wynbg0F5.js.map → Segmented-CametjLt.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Select-DMyLCkId.js → Select-De52fghU.js} +2 -2
- package/dist/core/web/public/next/assets/{Select-DMyLCkId.js.map → Select-De52fghU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionGate-8RtQFWeZ.js → SessionGate-CzlcNq3O.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionGate-8RtQFWeZ.js.map → SessionGate-CzlcNq3O.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionInsightChip-zBJbKv2L.js → SessionInsightChip-Bk_Owa7u.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionInsightChip-zBJbKv2L.js.map → SessionInsightChip-Bk_Owa7u.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionSearch-DfJIcxxM.js → SessionSearch-C6C8DHN8.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionSearch-DfJIcxxM.js.map → SessionSearch-C6C8DHN8.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SettingsSection-Da9RYyH5.js → SettingsSection-mI9wQYZg.js} +2 -2
- package/dist/core/web/public/next/assets/{SettingsSection-Da9RYyH5.js.map → SettingsSection-mI9wQYZg.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Sheet-DhXyIDmq.js → Sheet-CJhK9Dqv.js} +2 -2
- package/dist/core/web/public/next/assets/{Sheet-DhXyIDmq.js.map → Sheet-CJhK9Dqv.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-Bi5f-wUw.js → ShortcutsOverlay-DDW-i9Fc.js} +2 -2
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-Bi5f-wUw.js.map → ShortcutsOverlay-DDW-i9Fc.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Sidebar-BuO3sViG.js → Sidebar-DT7ykaqS.js} +3 -3
- package/dist/core/web/public/next/assets/{Sidebar-BuO3sViG.js.map → Sidebar-DT7ykaqS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Slider-Bd9YFWEV.js → Slider-Bwd9HfXl.js} +2 -2
- package/dist/core/web/public/next/assets/{Slider-Bd9YFWEV.js.map → Slider-Bwd9HfXl.js.map} +1 -1
- package/dist/core/web/public/next/assets/{StatTile-DScTd3c-.js → StatTile-DPZ5yyaU.js} +2 -2
- package/dist/core/web/public/next/assets/{StatTile-DScTd3c-.js.map → StatTile-DPZ5yyaU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{StatusBadge-DQ1UtQAJ.js → StatusBadge-DHKRtttH.js} +2 -2
- package/dist/core/web/public/next/assets/{StatusBadge-DQ1UtQAJ.js.map → StatusBadge-DHKRtttH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{StepBand-BB3IJxhr.js → StepBand-DQykLkk_.js} +2 -2
- package/dist/core/web/public/next/assets/{StepBand-BB3IJxhr.js.map → StepBand-DQykLkk_.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Surface-DWMtQe3Q.js → Surface-D--LXgQm.js} +2 -2
- package/dist/core/web/public/next/assets/{Surface-DWMtQe3Q.js.map → Surface-D--LXgQm.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Swimlane-DcENqtdp.js → Swimlane-BzH6OCee.js} +2 -2
- package/dist/core/web/public/next/assets/{Swimlane-DcENqtdp.js.map → Swimlane-BzH6OCee.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Switch-CenChEYf.js → Switch-PMixU6b0.js} +2 -2
- package/dist/core/web/public/next/assets/{Switch-CenChEYf.js.map → Switch-PMixU6b0.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Tag-D4k5E3u0.js → Tag-fordBsrJ.js} +2 -2
- package/dist/core/web/public/next/assets/{Tag-D4k5E3u0.js.map → Tag-fordBsrJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{TerminalPane-DCQTukcE.js → TerminalPane-BSnGdUuF.js} +2 -2
- package/dist/core/web/public/next/assets/{TerminalPane-DCQTukcE.js.map → TerminalPane-BSnGdUuF.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-DsuWT0pi.js → UniverseConsoleApp-DtXFhAhw.js} +2 -2
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-DsuWT0pi.js.map → UniverseConsoleApp-DtXFhAhw.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-DyI5ApsA.js → UniverseView-sWm3pnTW.js} +2 -2
- package/dist/core/web/public/next/assets/{UniverseView-DyI5ApsA.js.map → UniverseView-sWm3pnTW.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UsageSection-Imr28nwK.js → UsageSection-CiD1DbuF.js} +2 -2
- package/dist/core/web/public/next/assets/{UsageSection-Imr28nwK.js.map → UsageSection-CiD1DbuF.js.map} +1 -1
- package/dist/core/web/public/next/assets/{VerseConsoleApp-DeuBEvAO.js → VerseConsoleApp-BCY5uSok.js} +3 -3
- package/dist/core/web/public/next/assets/{VerseConsoleApp-DeuBEvAO.js.map → VerseConsoleApp-BCY5uSok.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Workspace-CpxBO98E.js → Workspace-BQSZFSeO.js} +5 -5
- package/dist/core/web/public/next/assets/{Workspace-CpxBO98E.js.map → Workspace-BQSZFSeO.js.map} +1 -1
- package/dist/core/web/public/next/assets/{actions-DE8NoWV_.js → actions-Ci6I4C0l.js} +2 -2
- package/dist/core/web/public/next/assets/{actions-DE8NoWV_.js.map → actions-Ci6I4C0l.js.map} +1 -1
- package/dist/core/web/public/next/assets/{apps-model-CFGCUu9p.js → apps-model-DlwnfqwJ.js} +2 -2
- package/dist/core/web/public/next/assets/{apps-model-CFGCUu9p.js.map → apps-model-DlwnfqwJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{authority-model-CmnfJzmM.js → authority-model-BFuPezSo.js} +2 -2
- package/dist/core/web/public/next/assets/{authority-model-CmnfJzmM.js.map → authority-model-BFuPezSo.js.map} +1 -1
- package/dist/core/web/public/next/assets/{budget-queries-DjrPRFwl.js → budget-queries-DsAjH8ac.js} +2 -2
- package/dist/core/web/public/next/assets/{budget-queries-DjrPRFwl.js.map → budget-queries-DsAjH8ac.js.map} +1 -1
- package/dist/core/web/public/next/assets/{capacity-strip-model-C7cdQnuK.js → capacity-strip-model-Dn1cNOhz.js} +2 -2
- package/dist/core/web/public/next/assets/{capacity-strip-model-C7cdQnuK.js.map → capacity-strip-model-Dn1cNOhz.js.map} +1 -1
- package/dist/core/web/public/next/assets/{charts-DUD_jprE.js → charts-C_xJbJiw.js} +2 -2
- package/dist/core/web/public/next/assets/{charts-DUD_jprE.js.map → charts-C_xJbJiw.js.map} +1 -1
- package/dist/core/web/public/next/assets/{cloud-model-DoxBMDvx.js → cloud-model-CX407gPY.js} +2 -2
- package/dist/core/web/public/next/assets/{cloud-model-DoxBMDvx.js.map → cloud-model-CX407gPY.js.map} +1 -1
- package/dist/core/web/public/next/assets/{cloud-queries-CTGvO-k-.js → cloud-queries-QAhpExlz.js} +2 -2
- package/dist/core/web/public/next/assets/{cloud-queries-CTGvO-k-.js.map → cloud-queries-QAhpExlz.js.map} +1 -1
- package/dist/core/web/public/next/assets/{command-catalog-CmrHNFzh.js → command-catalog-CF0cQQac.js} +2 -2
- package/dist/core/web/public/next/assets/{command-catalog-CmrHNFzh.js.map → command-catalog-CF0cQQac.js.map} +1 -1
- package/dist/core/web/public/next/assets/{context-model-9xywbXxX.js → context-model-Co4wh3SM.js} +2 -2
- package/dist/core/web/public/next/assets/{context-model-9xywbXxX.js.map → context-model-Co4wh3SM.js.map} +1 -1
- package/dist/core/web/public/next/assets/{context-model-2Owp2jYF.js → context-model-DV1zCfAm.js} +2 -2
- package/dist/core/web/public/next/assets/{context-model-2Owp2jYF.js.map → context-model-DV1zCfAm.js.map} +1 -1
- package/dist/core/web/public/next/assets/{context-queries-wvcRnV-I.js → context-queries-CktFQqSS.js} +2 -2
- package/dist/core/web/public/next/assets/{context-queries-wvcRnV-I.js.map → context-queries-CktFQqSS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{control-queries-DB6Kh7UN.js → control-queries-DAvlh_YM.js} +2 -2
- package/dist/core/web/public/next/assets/{control-queries-DB6Kh7UN.js.map → control-queries-DAvlh_YM.js.map} +1 -1
- package/dist/core/web/public/next/assets/{copy-setup-CJQhFl-4.js → copy-setup-CqRSfELB.js} +2 -2
- package/dist/core/web/public/next/assets/{copy-setup-CJQhFl-4.js.map → copy-setup-CqRSfELB.js.map} +1 -1
- package/dist/core/web/public/next/assets/{dock-icons-BBUGl4tE.js → dock-icons-BFuBbqJl.js} +2 -2
- package/dist/core/web/public/next/assets/{dock-icons-BBUGl4tE.js.map → dock-icons-BFuBbqJl.js.map} +1 -1
- package/dist/core/web/public/next/assets/{fleet-model-BRfRWkZl.js → fleet-model-Dfd5JyLR.js} +2 -2
- package/dist/core/web/public/next/assets/{fleet-model-BRfRWkZl.js.map → fleet-model-Dfd5JyLR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{fleet-queries-tU6UEXN2.js → fleet-queries-RtMTd5rR.js} +2 -2
- package/dist/core/web/public/next/assets/{fleet-queries-tU6UEXN2.js.map → fleet-queries-RtMTd5rR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{focus-trap-BGOceFvj.js → focus-trap-BdrbWfC4.js} +2 -2
- package/dist/core/web/public/next/assets/{focus-trap-BGOceFvj.js.map → focus-trap-BdrbWfC4.js.map} +1 -1
- package/dist/core/web/public/next/assets/{format-DEAaVF6X.js → format-Dk4Fmxax.js} +2 -2
- package/dist/core/web/public/next/assets/{format-DEAaVF6X.js.map → format-Dk4Fmxax.js.map} +1 -1
- package/dist/core/web/public/next/assets/{git-model-53iRLInY.js → git-model-_BnI_Ogh.js} +2 -2
- package/dist/core/web/public/next/assets/{git-model-53iRLInY.js.map → git-model-_BnI_Ogh.js.map} +1 -1
- package/dist/core/web/public/next/assets/{global-CXHHMz9o.js → global-CNNGMril.js} +2 -2
- package/dist/core/web/public/next/assets/{global-CXHHMz9o.js.map → global-CNNGMril.js.map} +1 -1
- package/dist/core/web/public/next/assets/{guarded-runners-B8zFVBVZ.js → guarded-runners-DPh2d32e.js} +2 -2
- package/dist/core/web/public/next/assets/{guarded-runners-B8zFVBVZ.js.map → guarded-runners-DPh2d32e.js.map} +1 -1
- package/dist/core/web/public/next/assets/{icons-D4s-jlxX.js → icons-0haWy6nh.js} +2 -2
- package/dist/core/web/public/next/assets/{icons-D4s-jlxX.js.map → icons-0haWy6nh.js.map} +1 -1
- package/dist/core/web/public/next/assets/{index-BG177cPN.js → index-QesfXBsb.js} +3 -3
- package/dist/core/web/public/next/assets/{index-BG177cPN.js.map → index-QesfXBsb.js.map} +1 -1
- package/dist/core/web/public/next/assets/{live-model-CEf01wrW.js → live-model-De-q0ZFK.js} +2 -2
- package/dist/core/web/public/next/assets/{live-model-CEf01wrW.js.map → live-model-De-q0ZFK.js.map} +1 -1
- package/dist/core/web/public/next/assets/{mind.module-D_xk6HIQ.js → mind.module-BrK2nFOL.js} +2 -2
- package/dist/core/web/public/next/assets/{mind.module-D_xk6HIQ.js.map → mind.module-BrK2nFOL.js.map} +1 -1
- package/dist/core/web/public/next/assets/{mutations-CbTSofVH.js → mutations-DTCtKCn_.js} +2 -2
- package/dist/core/web/public/next/assets/{mutations-CbTSofVH.js.map → mutations-DTCtKCn_.js.map} +1 -1
- package/dist/core/web/public/next/assets/{nav-CmZcbPFJ.js → nav-KmGX0CVz.js} +2 -2
- package/dist/core/web/public/next/assets/{nav-CmZcbPFJ.js.map → nav-KmGX0CVz.js.map} +1 -1
- package/dist/core/web/public/next/assets/{overnight-queries-CR0b_j-V.js → overnight-queries-mlO0xzsr.js} +2 -2
- package/dist/core/web/public/next/assets/{overnight-queries-CR0b_j-V.js.map → overnight-queries-mlO0xzsr.js.map} +1 -1
- package/dist/core/web/public/next/assets/primitives-D0Fb3TtS.js +1 -0
- package/dist/core/web/public/next/assets/{queries-rvRsAGW2.js → queries-CyBE8nsW.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-rvRsAGW2.js.map → queries-CyBE8nsW.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reasoning-pref-DMPQkujg.js → reasoning-pref-CaoA4_Vl.js} +2 -2
- package/dist/core/web/public/next/assets/{reasoning-pref-DMPQkujg.js.map → reasoning-pref-CaoA4_Vl.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reveal-anchor-BKk2wZZZ.js → reveal-anchor-BP1VqnPU.js} +2 -2
- package/dist/core/web/public/next/assets/{reveal-anchor-BKk2wZZZ.js.map → reveal-anchor-BP1VqnPU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{seat-subscription-CLn2ReSZ.js → seat-subscription-C5Tvr0WQ.js} +2 -2
- package/dist/core/web/public/next/assets/{seat-subscription-CLn2ReSZ.js.map → seat-subscription-C5Tvr0WQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{sidebar-model-CjQLvdag.js → sidebar-model-B5Qk95k_.js} +2 -2
- package/dist/core/web/public/next/assets/{sidebar-model-CjQLvdag.js.map → sidebar-model-B5Qk95k_.js.map} +1 -1
- package/dist/core/web/public/next/assets/{slots-DRxNosZg.js → slots-DHKQDoE6.js} +3 -3
- package/dist/core/web/public/next/assets/{slots-DRxNosZg.js.map → slots-DHKQDoE6.js.map} +1 -1
- package/dist/core/web/public/next/assets/{surface-data-DshUC_TU.js → surface-data-CchClvHo.js} +2 -2
- package/dist/core/web/public/next/assets/{surface-data-DshUC_TU.js.map → surface-data-CchClvHo.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js +2 -0
- package/dist/core/web/public/next/assets/{surface-prefetch-DO8r4ttQ.js.map → surface-prefetch-BWr0LBQn.js.map} +1 -1
- package/dist/core/web/public/next/assets/{tasks-model-BKPFZAmZ.js → tasks-model-D6WFVULI.js} +2 -2
- package/dist/core/web/public/next/assets/{tasks-model-BKPFZAmZ.js.map → tasks-model-D6WFVULI.js.map} +1 -1
- package/dist/core/web/public/next/assets/{terminal-icons-DoeQkP3y.js → terminal-icons-BvCvuXk2.js} +2 -2
- package/dist/core/web/public/next/assets/{terminal-icons-DoeQkP3y.js.map → terminal-icons-BvCvuXk2.js.map} +1 -1
- package/dist/core/web/public/next/assets/{usage-queries-MnUeYzwp.js → usage-queries-D1SU1t7r.js} +2 -2
- package/dist/core/web/public/next/assets/{usage-queries-MnUeYzwp.js.map → usage-queries-D1SU1t7r.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-guarded-action-P12MfNwU.js → use-guarded-action-BZmBv7CJ.js} +2 -2
- package/dist/core/web/public/next/assets/{use-guarded-action-P12MfNwU.js.map → use-guarded-action-BZmBv7CJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-ticker-DIvAZ4Ey.js → use-ticker-CkJ4-0wU.js} +2 -2
- package/dist/core/web/public/next/assets/{use-ticker-DIvAZ4Ey.js.map → use-ticker-CkJ4-0wU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-token-gate-DfEja7Wr.js → use-token-gate-CYcfk_GS.js} +2 -2
- package/dist/core/web/public/next/assets/{use-token-gate-DfEja7Wr.js.map → use-token-gate-CYcfk_GS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useOnboarding-CkOHadqC.js → useOnboarding-CujRS6PK.js} +2 -2
- package/dist/core/web/public/next/assets/{useOnboarding-CkOHadqC.js.map → useOnboarding-CujRS6PK.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useSeatsRefresh-BDlbDlIU.js → useSeatsRefresh-BEaQdkZs.js} +2 -2
- package/dist/core/web/public/next/assets/{useSeatsRefresh-BDlbDlIU.js.map → useSeatsRefresh-BEaQdkZs.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useVerseTranscript-BGtA55k2.js → useVerseTranscript-BQ0J6Xhx.js} +2 -2
- package/dist/core/web/public/next/assets/{useVerseTranscript-BGtA55k2.js.map → useVerseTranscript-BQ0J6Xhx.js.map} +1 -1
- package/dist/core/web/public/next/assets/{verse-icons-wOet9JZy.js → verse-icons-DndgEgKS.js} +2 -2
- package/dist/core/web/public/next/assets/{verse-icons-wOet9JZy.js.map → verse-icons-DndgEgKS.js.map} +1 -1
- package/dist/core/web/public/next/assets/{verse-model-CSzzdyu2.js → verse-model-MMySehjj.js} +2 -2
- package/dist/core/web/public/next/assets/{verse-model-CSzzdyu2.js.map → verse-model-MMySehjj.js.map} +1 -1
- package/dist/core/web/public/next/assets/{warmup-CecO_Nk0.js → warmup-CNEH_-be.js} +3 -3
- package/dist/core/web/public/next/assets/{warmup-CecO_Nk0.js.map → warmup-CNEH_-be.js.map} +1 -1
- package/dist/core/web/public/next/assets/{why-seat-model-D68ZA7G8.js → why-seat-model-jlDTwYSc.js} +2 -2
- package/dist/core/web/public/next/assets/{why-seat-model-D68ZA7G8.js.map → why-seat-model-jlDTwYSc.js.map} +1 -1
- package/dist/core/web/public/next/assets/{workspace-model-BdIVybKr.js → workspace-model-Dukb2wwv.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-BdIVybKr.js.map → workspace-model-Dukb2wwv.js.map} +1 -1
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/package.json +1 -1
- package/dist/core/web/public/next/assets/AutonomySection-BTg7yVa1.js +0 -2
- package/dist/core/web/public/next/assets/McpSection-D1tDvlRa.js +0 -2
- package/dist/core/web/public/next/assets/OnboardingGate-DrDEVBqw.js +0 -3
- package/dist/core/web/public/next/assets/primitives-DNI-uJBd.js +0 -1
- package/dist/core/web/public/next/assets/surface-prefetch-DO8r4ttQ.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-guarded-action-
|
|
1
|
+
{"version":3,"file":"use-guarded-action-BZmBv7CJ.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/use-guarded-action.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/use-guarded-action.ts — the one place a Verse control\n * surface turns \"the operator clicked something destructive\" into an actual\n * request. Shared by the Autonomy cockpit and the Approvals surface.\n *\n * It folds together the three things every mutating click in this app has to\n * do, which were previously re-implemented per call site:\n *\n * - **Token hand-off.** No mutation hold yet → remember the action, open\n * MutationTokenDialog, and run it once the token lands. The hold is read\n * LIVE on dialog close, never from a render-time snapshot, because\n * MutationTokenDialog's onClose fires before this component re-renders.\n * - **Read-only sessions.** Every POST 404s when the server was started\n * without dispatch. That is a session mode, not a failure, so it flips a\n * `readOnly` flag the surface renders as an explanation — never as an error\n * toast and never as a crash.\n * - **Busy + error state** for exactly one in-flight action at a time.\n */\nimport { useCallback, useRef, useState } from 'react';\nimport { hasMutationHold } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\nimport { VerseControlLockedError } from './control-queries.js';\nimport { tidyProse } from './format.js';\n\nexport function describeControlError(err: unknown): string {\n if (err instanceof DispatchDisabledError) return 'This server runs without dispatch, so that action is unavailable.';\n if (err instanceof VerseControlLockedError) return err.message;\n if (err instanceof ApiError) {\n if (err.status === 401) return 'The mutation token was rejected. Unlock again with the token `ashlr verse` printed.';\n // The control plane writes a careful refusal ladder — \"no repositories are\n // enrolled, so the loop would do nothing. Add scope first.\" — and returns\n // it as `note` on the 409 body. A blanket \"something else is already\n // running\" replaced every one of those with a sentence that was usually\n // false and never actionable. Show the server's own words whenever it\n // sent any; the generic line is now only the last resort. `tidyProse`\n // reads any ISO instant in those words as local time.\n if (err.detail) return tidyProse(err.detail);\n if (err.status === 400) return tidyProse(err.message);\n if (err.status === 409) return 'The server refused the action, and sent no reason.';\n return tidyProse(err.message);\n }\n return err instanceof Error ? tidyProse(err.message) : 'That action failed. Try again.';\n}\n\nexport interface GuardedAction {\n /**\n * Run `fn`, prompting for the mutation token first when none is held.\n *\n * `onResult` receives `fn`'s resolved value when it succeeds. It exists\n * because the value was previously dropped on the floor, and for the daemon\n * routes that value carries the server's own account of what just happened\n * (`VerseDaemonActionResult.note` — e.g. that an ordinary stop also engaged\n * the global kill switch). It is not called when `fn` throws.\n */\n request: <T>(fn: () => Promise<T>, reason: string, onResult?: (result: T) => void) => void;\n busy: boolean;\n error: string | null;\n clearError: () => void;\n /** True once a POST 404'd — the server has no dispatch enabled. */\n readOnly: boolean;\n /** Bind these three to <MutationTokenDialog/>. */\n tokenOpen: boolean;\n tokenReason: string;\n closeToken: () => void;\n}\n\nexport function useGuardedAction(): GuardedAction {\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [readOnly, setReadOnly] = useState(false);\n const [tokenOpen, setTokenOpen] = useState(false);\n const [tokenReason, setTokenReason] = useState('');\n // The deferred action and the callback that wants its result travel together\n // — the token dialog may run it a render later, long after `request` returned.\n const pending = useRef<{ fn: () => Promise<unknown>; onResult?: (result: never) => void } | null>(null);\n\n const perform = useCallback(\n async (fn: () => Promise<unknown>, onResult?: (result: never) => void) => {\n setBusy(true);\n setError(null);\n try {\n const result = await fn();\n onResult?.(result as never);\n } catch (err) {\n if (err instanceof DispatchDisabledError) setReadOnly(true);\n else setError(describeControlError(err));\n } finally {\n setBusy(false);\n }\n },\n [],\n );\n\n const request = useCallback(\n <T,>(fn: () => Promise<T>, reason: string, onResult?: (result: T) => void) => {\n setError(null);\n const handler = onResult as ((result: never) => void) | undefined;\n if (hasMutationHold()) {\n void perform(fn, handler);\n return;\n }\n pending.current = { fn, onResult: handler };\n setTokenReason(reason);\n setTokenOpen(true);\n },\n [perform],\n );\n\n const closeToken = useCallback(() => {\n setTokenOpen(false);\n const next = pending.current;\n pending.current = null;\n // Live read: the dialog closes synchronously after setToken().\n if (next && hasMutationHold()) void perform(next.fn, next.onResult);\n }, [perform]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return { request, busy, error, clearError, readOnly, tokenOpen, tokenReason, closeToken };\n}\n"],"mappings":"gNAwBA,SAAgB,EAAqB,EAAsB,CAiBzD,OAhBI,aAAe,EAA8B,oEAC7C,aAAe,EAAgC,EAAI,QACnD,aAAe,EACb,EAAI,SAAW,IAAY,sFAQ3B,EAAI,OAAe,EAAU,EAAI,MAAM,EACvC,EAAI,SAAW,IAAY,EAAU,EAAI,OAAO,EAChD,EAAI,SAAW,IAAY,qDACxB,EAAU,EAAI,OAAO,EAEvB,aAAe,MAAQ,EAAU,EAAI,OAAO,EAAI,gCACzD,CAwBA,SAAgB,GAAkC,CAChD,GAAM,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,CAAS,EAAK,EAChC,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAwB,IAAI,EAChD,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAS,EAAK,EACxC,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,EAAK,EAC1C,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAS,EAAE,EAG3C,GAAA,EAAU,EAAA,OAAA,CAAkF,IAAI,EAEhG,GAAA,EAAU,EAAA,YAAA,CACd,MAAO,EAA4B,IAAuC,CACxE,EAAQ,EAAI,EACZ,EAAS,IAAI,EACb,GAAI,CACF,IAAM,EAAS,MAAM,EAAG,EACxB,IAAW,CAAe,CAC5B,OAAS,EAAK,CACR,aAAe,EAAuB,EAAY,EAAI,EACrD,EAAS,EAAqB,CAAG,CAAC,CACzC,QAAU,CACR,EAAQ,EAAK,CACf,CACF,EACA,CAAC,CACH,EAEM,GAAA,EAAU,EAAA,YAAA,EACT,EAAsB,EAAgB,IAAmC,CAC5E,EAAS,IAAI,EACb,IAAM,EAAU,EAChB,GAAI,EAAgB,EAAG,CACrB,EAAa,EAAI,CAAO,EACxB,MACF,CACA,EAAQ,QAAU,CAAE,KAAI,SAAU,CAAQ,EAC1C,EAAe,CAAM,EACrB,EAAa,EAAI,CACnB,EACA,CAAC,CAAO,CACV,EAEM,GAAA,EAAa,EAAA,YAAA,KAAkB,CACnC,EAAa,EAAK,EAClB,IAAM,EAAO,EAAQ,QACrB,EAAQ,QAAU,KAEd,GAAQ,EAAgB,GAAG,EAAa,EAAK,GAAI,EAAK,QAAQ,CACpE,EAAG,CAAC,CAAO,CAAC,EAIZ,MAAO,CAAE,UAAS,OAAM,QAAO,YAAA,EAFZ,EAAA,YAAA,KAAkB,EAAS,IAAI,EAAG,CAAC,CAEvB,EAAY,WAAU,YAAW,cAAa,YAAW,CAC1F"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=use-ticker-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";var n=t(e(),1);function r(e=1e3){let[t,r]=(0,n.useState)(()=>Date.now());return(0,n.useEffect)(()=>{let t=setInterval(()=>r(Date.now()),e);return()=>clearInterval(t)},[e]),t}export{r as t};
|
|
2
|
+
//# sourceMappingURL=use-ticker-CkJ4-0wU.js.map
|
package/dist/core/web/public/next/assets/{use-ticker-DIvAZ4Ey.js.map → use-ticker-CkJ4-0wU.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-ticker-
|
|
1
|
+
{"version":3,"file":"use-ticker-CkJ4-0wU.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/autonomy/use-ticker.ts"],"sourcesContent":["/**\n * routes/verse/autonomy/use-ticker.ts — a shared 1Hz clock for the countdown\n * and the relative ages in the status header — one interval per consumer\n * rather than a bespoke timer inside each panel.\n *\n * It deliberately keeps ticking under `prefers-reduced-motion`: a countdown is\n * information, not decoration. The design language's quiet-motion rule governs\n * transitions and animation, not numbers that have to stay true.\n */\nimport { useEffect, useState } from 'react';\n\nexport function useNow(intervalMs = 1000): number {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), intervalMs);\n return () => clearInterval(id);\n }, [intervalMs]);\n return now;\n}\n"],"mappings":"8DAWA,SAAgB,EAAO,EAAa,IAAc,CAChD,GAAM,CAAC,EAAK,IAAA,EAAU,EAAA,SAAA,KAAe,KAAK,IAAI,CAAC,EAK/C,OAJA,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAK,gBAAkB,EAAO,KAAK,IAAI,CAAC,EAAG,CAAU,EAC3D,UAAa,cAAc,CAAE,CAC/B,EAAG,CAAC,CAAU,CAAC,EACR,CACT"}
|
package/dist/core/web/public/next/assets/{use-token-gate-DfEja7Wr.js → use-token-gate-CYcfk_GS.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=use-token-gate-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";import{O as n,o as r,s as i}from"./global-CNNGMril.js";import{i as a}from"./VerseConsoleApp-BCY5uSok.js";import{y as o}from"./format-Dk4Fmxax.js";var s=t(e(),1);function c(){let[e,t]=(0,s.useState)({open:!1,reason:``}),r=(0,s.useRef)(null),i=(0,s.useCallback)((e,i)=>n()?i():(r.current?.cancel(),new Promise((n,a)=>{r.current={run:()=>{i().then(n,a)},cancel:()=>n(null)},t({open:!0,reason:e})})),[]),a=(0,s.useCallback)(()=>{t({open:!1,reason:``});let e=r.current;e&&setTimeout(()=>{r.current===e&&(r.current=null,e.cancel())},0)},[]),o=(0,s.useCallback)(()=>{let e=r.current;r.current=null,e?.run()},[]);return{run:i,dialog:{open:e.open,reason:e.reason,onClose:a,onUnlocked:o}}}function l(e){return e instanceof i?"This server is read-only (started without dispatch — run `ashlr verse`), or older than this console.":e instanceof a?`Unlock actions with the mutation token first.`:e instanceof r?e.status===401?"The mutation token was rejected. Unlock again with the token `ashlr verse` printed.":e.code===`VERSE_SESSION_NOT_FOUND`?`This chat no longer exists on the server — it may have been deleted. Refresh the chat list.`:e.detail?o(e.detail):e.status===404?"This server does not have that route yet — update Ashlr and restart `ashlr verse`.":e.status===409?`A turn is already running in this chat. Wait for it or stop it first.`:o(e.message):e instanceof Error&&e.message?o(e.message):`Something went wrong.`}export{c as n,l as t};
|
|
2
|
+
//# sourceMappingURL=use-token-gate-CYcfk_GS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-token-gate-
|
|
1
|
+
{"version":3,"file":"use-token-gate-CYcfk_GS.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/context/use-token-gate.ts"],"sourcesContent":["/**\n * routes/verse/context/use-token-gate.ts — the mutation-token hand-off for\n * the self-contained context surfaces (handoff dialog, memory panel).\n *\n * Same contract as ChatSection's `withToken`, extracted because these\n * components are mounted by OTHER owners (the workspace header, the resources\n * panel) that cannot thread a guard down to them:\n *\n * - a held token → the action runs now;\n * - no token → the action is parked, MutationTokenDialog opens with a reason\n * saying what the click will do, and the action runs once unlocked;\n * - the dialog dismissed → the promise resolves `null`, so the caller can\n * tell \"not done\" from \"done\" without an exception.\n *\n * The hold is read LIVE (`hasMutationHold()`), never from a render snapshot:\n * MutationTokenDialog calls `onClose` before `onUnlocked` in the same tick,\n * so a snapshot taken at render time is always one step behind.\n */\nimport { useCallback, useRef, useState } from 'react';\nimport { hasMutationHold } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\nimport { VerseMutationLockedError } from '../verse-queries.js';\nimport { tidyProse } from '../autonomy/format.js';\n\nexport interface TokenGateDialogProps {\n open: boolean;\n reason: string;\n onClose: () => void;\n onUnlocked: () => void;\n}\n\nexport interface TokenGate {\n run<T>(reason: string, action: () => Promise<T>): Promise<T | null>;\n /** Spread onto <MutationTokenDialog />. */\n dialog: TokenGateDialogProps;\n}\n\nexport function useTokenGate(): TokenGate {\n const [prompt, setPrompt] = useState<{ open: boolean; reason: string }>({ open: false, reason: '' });\n const pending = useRef<{ run: () => void; cancel: () => void } | null>(null);\n\n const run = useCallback(<T,>(reason: string, action: () => Promise<T>): Promise<T | null> => {\n if (hasMutationHold()) return action();\n // A second click while the prompt is up supersedes the first: the earlier\n // caller is told \"not done\" rather than left waiting forever.\n pending.current?.cancel();\n return new Promise<T | null>((resolve, reject) => {\n pending.current = {\n run: () => { action().then(resolve, reject); },\n cancel: () => resolve(null),\n };\n setPrompt({ open: true, reason });\n });\n }, []);\n\n const onClose = useCallback(() => {\n setPrompt({ open: false, reason: '' });\n // onClose fires BEFORE onUnlocked on a successful submit, so only treat\n // this as a dismissal if nothing claimed the parked action by next tick.\n const parked = pending.current;\n if (!parked) return;\n setTimeout(() => {\n if (pending.current === parked) {\n pending.current = null;\n parked.cancel();\n }\n }, 0);\n }, []);\n\n const onUnlocked = useCallback(() => {\n const parked = pending.current;\n pending.current = null;\n parked?.run();\n }, []);\n\n return { run, dialog: { open: prompt.open, reason: prompt.reason, onClose, onUnlocked } };\n}\n\n/**\n * One sentence for a failed context action. Prefers the server's own words\n * (`ApiError.detail`), which the context routes write for a person.\n */\nexport function describeContextError(err: unknown): string {\n if (err instanceof DispatchDisabledError) {\n // A CODELESS 404 on a write: the dispatch gate, or a server that predates\n // this route — the two answer the same bare body by design (client.ts).\n // A missing chat is NOT this: it carries VERSE_SESSION_NOT_FOUND below.\n return 'This server is read-only (started without dispatch — run `ashlr verse`), or older than this console.';\n }\n if (err instanceof VerseMutationLockedError) return 'Unlock actions with the mutation token first.';\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.code === 'VERSE_SESSION_NOT_FOUND') return 'This chat no longer exists on the server — it may have been deleted. Refresh the chat list.';\n // The server's own words, with any ISO instant in them read as local time.\n if (err.detail) return tidyProse(err.detail);\n if (err.status === 404) return 'This server does not have that route yet — update Ashlr and restart `ashlr verse`.';\n if (err.status === 409) return 'A turn is already running in this chat. Wait for it or stop it first.';\n return tidyProse(err.message);\n }\n return err instanceof Error && err.message ? tidyProse(err.message) : 'Something went wrong.';\n}\n"],"mappings":"gNAqCA,SAAgB,GAA0B,CACxC,GAAM,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAA4C,CAAE,KAAM,GAAO,OAAQ,EAAG,CAAC,EAC7F,GAAA,EAAU,EAAA,OAAA,CAAuD,IAAI,EAErE,GAAA,EAAM,EAAA,YAAA,EAAiB,EAAgB,IACvC,EAAgB,EAAU,EAAO,GAGrC,EAAQ,SAAS,OAAO,EACjB,IAAI,SAAmB,EAAS,IAAW,CAChD,EAAQ,QAAU,CAChB,QAAW,CAAE,EAAO,CAAC,CAAC,KAAK,EAAS,CAAM,CAAG,EAC7C,WAAc,EAAQ,IAAI,CAC5B,EACA,EAAU,CAAE,KAAM,GAAM,QAAO,CAAC,CAClC,CAAC,GACA,CAAC,CAAC,EAEC,GAAA,EAAU,EAAA,YAAA,KAAkB,CAChC,EAAU,CAAE,KAAM,GAAO,OAAQ,EAAG,CAAC,EAGrC,IAAM,EAAS,EAAQ,QAClB,GACL,eAAiB,CACX,EAAQ,UAAY,IACtB,EAAQ,QAAU,KAClB,EAAO,OAAO,EAElB,EAAG,CAAC,CACN,EAAG,CAAC,CAAC,EAEC,GAAA,EAAa,EAAA,YAAA,KAAkB,CACnC,IAAM,EAAS,EAAQ,QACvB,EAAQ,QAAU,KAClB,GAAQ,IAAI,CACd,EAAG,CAAC,CAAC,EAEL,MAAO,CAAE,MAAK,OAAQ,CAAE,KAAM,EAAO,KAAM,OAAQ,EAAO,OAAQ,UAAS,YAAW,CAAE,CAC1F,CAMA,SAAgB,EAAqB,EAAsB,CAiBzD,OAhBI,aAAe,EAIV,uGAEL,aAAe,EAAiC,gDAChD,aAAe,EACb,EAAI,SAAW,IAAY,sFAC3B,EAAI,OAAS,0BAAkC,8FAE/C,EAAI,OAAe,EAAU,EAAI,MAAM,EACvC,EAAI,SAAW,IAAY,qFAC3B,EAAI,SAAW,IAAY,wEACxB,EAAU,EAAI,OAAO,EAEvB,aAAe,OAAS,EAAI,QAAU,EAAU,EAAI,OAAO,EAAI,uBACxE"}
|
package/dist/core/web/public/next/assets/{useOnboarding-CkOHadqC.js → useOnboarding-CujRS6PK.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=useOnboarding-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";var n=t(e(),1),r=`ashlr.verse.onboarding.v1`,i={completedAt:null,dismissedAt:null,expanded:!1,step:0};function a(){try{let e=localStorage.getItem(r);if(!e)return i;let t=JSON.parse(e);return!t||typeof t!=`object`?i:{completedAt:typeof t.completedAt==`string`?t.completedAt:null,dismissedAt:typeof t.dismissedAt==`string`?t.dismissedAt:null,expanded:t.expanded===!0,step:typeof t.step==`number`&&Number.isFinite(t.step)?Math.max(0,Math.trunc(t.step)):0}}catch{return{...i,dismissedAt:new Date(0).toISOString()}}}function o(){let e={completedAt:l.completedAt,dismissedAt:l.dismissedAt,expanded:l.expanded,step:l.step};try{localStorage.setItem(r,JSON.stringify(e))}catch{}}function s(e){return e.completedAt===null&&e.dismissedAt===null}var c=a(),l={completedAt:c.completedAt,dismissedAt:c.dismissedAt,open:s(c),expanded:c.expanded,step:c.step},u=new Set;function d(e,t=!1){let n={...l,...e};if(!Object.keys(e).every(e=>Object.is(l[e],n[e]))){l=n,t&&o();for(let e of u)e()}}function f(e){return u.add(e),()=>u.delete(e)}function p(){return l}function m(e){d({step:Math.max(0,Math.trunc(e))},!0)}function h(){d({expanded:!0},!0)}function g(){d({expanded:!1},!0)}function _(){d({dismissedAt:new Date().toISOString(),open:!1},!0)}function v(){d({completedAt:new Date().toISOString(),open:!1},!0)}function y(){d({open:!0,expanded:!0,step:0})}function b(){return(0,n.useSyncExternalStore)(f,p,p)}export{h as a,_ as i,g as n,y as o,v as r,m as s,b as t};
|
|
2
|
+
//# sourceMappingURL=useOnboarding-CujRS6PK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOnboarding-
|
|
1
|
+
{"version":3,"file":"useOnboarding-CujRS6PK.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/onboarding/onboarding-store.ts","../../../../../../src/web-ui/routes/verse/onboarding/useOnboarding.ts"],"sourcesContent":["/**\n * routes/verse/onboarding/onboarding-store.ts — whether the first-run tour\n * is showing, and whether it has already been answered.\n *\n * Framework-free, same shape as verse-ui-store.ts: a module-level snapshot,\n * a listener set, and one `useSyncExternalStore` hook in ./useOnboarding.ts.\n *\n * Persisted under `ashlr.verse.onboarding.v1`. Two facts are stored and they\n * are deliberately different:\n *\n * - `completedAt` — the operator walked to the end.\n * - `dismissedAt` — the operator skipped, or closed it part-way.\n *\n * Either one silences the tour for good; storing which happened means a\n * later build can tell \"has seen it\" from \"chose not to\", and it makes the\n * Settings replay affordance honest about what it is replaying.\n *\n * Two UI prefs ride along in the same record:\n *\n * - `expanded` — the tour starts as a one-line chip (\"Getting started\n * 1/6 →\") and only becomes the full card when the operator opens it. A\n * 420×640 card over every surface on first launch covered half a 900px\n * window; the chip asks for nothing. Whichever the operator last chose\n * is kept across launches.\n * - `step` — where they were, so the chip's \"2/6\" survives a relaunch.\n *\n * SHOWING IT IS FAIL-SAFE IN THE QUIET DIRECTION. A storage read that throws\n * (private window, storage disabled) or returns something malformed resolves\n * to NOT showing the tour. A first-run flow that reappears on every launch\n * because storage is unavailable would be worse than one that never appears:\n * the app is fully usable without it, and it is reachable from Settings.\n */\n\nexport interface OnboardingRecord {\n /** ISO timestamp of the run that reached the last step. */\n completedAt: string | null;\n /** ISO timestamp of a skip or an early close. */\n dismissedAt: string | null;\n}\n\n/** What is stored: the answer plus the two UI prefs. */\ninterface StoredOnboarding extends OnboardingRecord {\n expanded: boolean;\n step: number;\n}\n\nexport interface OnboardingState extends OnboardingRecord {\n /** Is the flow on screen right now (as the chip or the card)? */\n open: boolean;\n /** The full card (true) or the one-line chip (false). */\n expanded: boolean;\n /** 0-based index into the step list (./onboarding-model.ts ONBOARDING_STEPS). */\n step: number;\n}\n\nexport const VERSE_ONBOARDING_STORAGE_KEY = 'ashlr.verse.onboarding.v1';\n\nconst EMPTY: StoredOnboarding = { completedAt: null, dismissedAt: null, expanded: false, step: 0 };\n\nfunction readStored(): StoredOnboarding {\n try {\n const raw = localStorage.getItem(VERSE_ONBOARDING_STORAGE_KEY);\n if (!raw) return EMPTY;\n const parsed = JSON.parse(raw) as Partial<StoredOnboarding> | null;\n if (!parsed || typeof parsed !== 'object') return EMPTY;\n return {\n completedAt: typeof parsed.completedAt === 'string' ? parsed.completedAt : null,\n dismissedAt: typeof parsed.dismissedAt === 'string' ? parsed.dismissedAt : null,\n expanded: parsed.expanded === true,\n step: typeof parsed.step === 'number' && Number.isFinite(parsed.step) ? Math.max(0, Math.trunc(parsed.step)) : 0,\n };\n } catch {\n // Unreadable storage means \"answered\" — see the fail-safe note above.\n return { ...EMPTY, dismissedAt: new Date(0).toISOString() };\n }\n}\n\nfunction persist(): void {\n const stored: StoredOnboarding = {\n completedAt: state.completedAt,\n dismissedAt: state.dismissedAt,\n expanded: state.expanded,\n step: state.step,\n };\n try {\n localStorage.setItem(VERSE_ONBOARDING_STORAGE_KEY, JSON.stringify(stored));\n } catch {\n /* best-effort: a private window without storage still runs the app */\n }\n}\n\n/** True when neither answer has been recorded yet. */\nexport function isFirstRun(record: OnboardingRecord): boolean {\n return record.completedAt === null && record.dismissedAt === null;\n}\n\nconst initialStored = readStored();\n\nlet state: OnboardingState = {\n completedAt: initialStored.completedAt,\n dismissedAt: initialStored.dismissedAt,\n open: isFirstRun(initialStored),\n expanded: initialStored.expanded,\n step: initialStored.step,\n};\n\nconst listeners = new Set<() => void>();\n\n/** Apply `delta`; notify (and, with `save`, persist) only when something changed. */\nfunction patch(delta: Partial<OnboardingState>, save = false): void {\n const next = { ...state, ...delta };\n if ((Object.keys(delta) as (keyof OnboardingState)[]).every((k) => Object.is(state[k], next[k]))) return;\n state = next;\n if (save) persist();\n for (const l of listeners) l();\n}\n\nexport function subscribeOnboarding(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nexport function getOnboardingState(): OnboardingState {\n return state;\n}\n\nexport function setOnboardingStep(step: number): void {\n patch({ step: Math.max(0, Math.trunc(step)) }, true);\n}\n\n/** The chip was clicked: show the full card. */\nexport function expandOnboarding(): void {\n patch({ expanded: true }, true);\n}\n\n/** Back to the one-line chip — the tour is NOT answered, just out of the way. */\nexport function collapseOnboarding(): void {\n patch({ expanded: false }, true);\n}\n\n/** Skip, or the chip's × — the same answer. */\nexport function dismissOnboarding(): void {\n patch({ dismissedAt: new Date().toISOString(), open: false }, true);\n}\n\n/** Walked to the end. */\nexport function completeOnboarding(): void {\n patch({ completedAt: new Date().toISOString(), open: false }, true);\n}\n\n/** Settings → \"Replay onboarding\". Reopens at the first step, as the full\n * card (the operator asked for it); the stored answer is kept, so closing\n * the replay does not re-arm the first run. */\nexport function replayOnboarding(): void {\n patch({ open: true, expanded: true, step: 0 });\n}\n\n/** Test hygiene — forgets the stored answer and re-arms the first run (as the chip). */\nexport function resetOnboarding(): void {\n try {\n localStorage.removeItem(VERSE_ONBOARDING_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n state = { completedAt: null, dismissedAt: null, open: true, expanded: false, step: 0 };\n for (const l of listeners) l();\n}\n","/**\n * routes/verse/onboarding/useOnboarding.ts — the single React binding over\n * onboarding-store.ts, kept in its own file for the same reason\n * useVerseUi.ts is: the store stays framework-free and unit-testable\n * without a DOM.\n */\nimport { useSyncExternalStore } from 'react';\nimport { getOnboardingState, subscribeOnboarding, type OnboardingState } from './onboarding-store.js';\n\nexport function useOnboarding(): OnboardingState {\n return useSyncExternalStore(subscribeOnboarding, getOnboardingState, getOnboardingState);\n}\n"],"mappings":"8DAuDa,EAA+B,4BAEtC,EAA0B,CAAE,YAAa,KAAM,YAAa,KAAM,SAAU,GAAO,KAAM,CAAE,EAEjG,SAAS,GAA+B,CACtC,GAAI,CACF,IAAM,EAAM,aAAa,QAAQ,CAA4B,EAC7D,GAAI,CAAC,EAAK,OAAO,EACjB,IAAM,EAAS,KAAK,MAAM,CAAG,EAE7B,MADI,CAAC,GAAU,OAAO,GAAW,SAAiB,EAC3C,CACL,YAAa,OAAO,EAAO,aAAgB,SAAW,EAAO,YAAc,KAC3E,YAAa,OAAO,EAAO,aAAgB,SAAW,EAAO,YAAc,KAC3E,SAAU,EAAO,WAAa,GAC9B,KAAM,OAAO,EAAO,MAAS,UAAY,OAAO,SAAS,EAAO,IAAI,EAAI,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,IAAI,CAAC,EAAI,CACjH,CACF,MAAQ,CAEN,MAAO,CAAE,GAAG,EAAO,YAAa,IAAI,KAAK,CAAC,CAAA,CAAE,YAAY,CAAE,CAC5D,CACF,CAEA,SAAS,GAAgB,CACvB,IAAM,EAA2B,CAC/B,YAAa,EAAM,YACnB,YAAa,EAAM,YACnB,SAAU,EAAM,SAChB,KAAM,EAAM,IACd,EACA,GAAI,CACF,aAAa,QAAQ,EAA8B,KAAK,UAAU,CAAM,CAAC,CAC3E,MAAQ,CAER,CACF,CAGA,SAAgB,EAAW,EAAmC,CAC5D,OAAO,EAAO,cAAgB,MAAQ,EAAO,cAAgB,IAC/D,CAEA,IAAM,EAAgB,EAAW,EAE7B,EAAyB,CAC3B,YAAa,EAAc,YAC3B,YAAa,EAAc,YAC3B,KAAM,EAAW,CAAa,EAC9B,SAAU,EAAc,SACxB,KAAM,EAAc,IACtB,EAEM,EAAY,IAAI,IAGtB,SAAS,EAAM,EAAiC,EAAO,GAAa,CAClE,IAAM,EAAO,CAAE,GAAG,EAAO,GAAG,CAAM,EAC7B,WAAO,KAAK,CAAK,CAAC,CAA+B,MAAO,GAAM,OAAO,GAAG,EAAM,GAAI,EAAK,EAAE,CAAC,EAE/F,CADA,EAAQ,EACJ,GAAM,EAAQ,EAClB,IAAK,IAAM,KAAK,EAAW,EAAE,CADX,CAEpB,CAEA,SAAgB,EAAoB,EAAkC,CAEpE,OADA,EAAU,IAAI,CAAQ,MACT,EAAU,OAAO,CAAQ,CACxC,CAEA,SAAgB,GAAsC,CACpD,OAAO,CACT,CAEA,SAAgB,EAAkB,EAAoB,CACpD,EAAM,CAAE,KAAM,KAAK,IAAI,EAAG,KAAK,MAAM,CAAI,CAAC,CAAE,EAAG,EAAI,CACrD,CAGA,SAAgB,GAAyB,CACvC,EAAM,CAAE,SAAU,EAAK,EAAG,EAAI,CAChC,CAGA,SAAgB,GAA2B,CACzC,EAAM,CAAE,SAAU,EAAM,EAAG,EAAI,CACjC,CAGA,SAAgB,GAA0B,CACxC,EAAM,CAAE,YAAa,IAAI,KAAK,CAAA,CAAE,YAAY,EAAG,KAAM,EAAM,EAAG,EAAI,CACpE,CAGA,SAAgB,GAA2B,CACzC,EAAM,CAAE,YAAa,IAAI,KAAK,CAAA,CAAE,YAAY,EAAG,KAAM,EAAM,EAAG,EAAI,CACpE,CAKA,SAAgB,GAAyB,CACvC,EAAM,CAAE,KAAM,GAAM,SAAU,GAAM,KAAM,CAAE,CAAC,CAC/C,CClJA,SAAgB,GAAiC,CAC/C,OAAA,EAAO,EAAA,qBAAA,CAAqB,EAAqB,EAAoB,CAAkB,CACzF"}
|
package/dist/core/web/public/next/assets/{useSeatsRefresh-BDlbDlIU.js → useSeatsRefresh-BEaQdkZs.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=useSeatsRefresh-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";import{G as n,V as r,c as i,m as a,p as o}from"./global-CNNGMril.js";import{S as s,n as c}from"./VerseConsoleApp-BCY5uSok.js";import{C as l,E as u}from"./capacity-strip-model-Dn1cNOhz.js";var d=t(e(),1),f=3e4;function p(e=!0){let t=o(u),n=a(u);return(0,d.useEffect)(()=>{if(!e)return;let t=()=>{(typeof document>`u`||document.visibilityState!==`hidden`)&&n()},r=window.setInterval(t,f);return document.addEventListener(`visibilitychange`,t),()=>{window.clearInterval(r),document.removeEventListener(`visibilitychange`,t)}},[e,n]),t}var m=3e4,h=`/api/verse/seats`;function g(e,t){return{...e,seats:t.seats,localRuntime:t.localRuntime}}function _(){let e=r(c).data,t=()=>s.fetch();return e===void 0?n(c,t):n(c,l(async()=>{let t=await i(h);return g(r(`verse-bootstrap`).data??e,t)},t))}function v(e=!0){let t=(0,d.useCallback)(()=>{_()},[]);(0,d.useEffect)(()=>{if(!e)return;let n=()=>{(typeof document>`u`||document.visibilityState!==`hidden`)&&t()},r=window.setInterval(n,m);return document.addEventListener(`visibilitychange`,n),()=>{window.clearInterval(r),document.removeEventListener(`visibilitychange`,n)}},[e,t])}export{p as n,v as t};
|
|
2
|
+
//# sourceMappingURL=useSeatsRefresh-BEaQdkZs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSeatsRefresh-
|
|
1
|
+
{"version":3,"file":"useSeatsRefresh-BEaQdkZs.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/health/useSeatHealth.ts","../../../../../../src/web-ui/routes/verse/useSeatsRefresh.ts"],"sourcesContent":["/**\n * routes/verse/health/useSeatHealth.ts — the seat health reports, kept live\n * while the app is on screen.\n *\n * The SERVER sweeps every ten minutes whether or not anyone looks\n * (core/verse/account-health.ts) — that is what catches a sign-out while the\n * app is hidden, and it is what the desktop shell's notifications read. This\n * hook only has to keep a VISIBLE page current, so it polls a cheap cached\n * read every 30 s (no probe runs per request), skips ticks while hidden, and\n * re-reads the moment the page is looked at again.\n */\nimport { useEffect } from 'react';\nimport type { VerseHealthResponse } from '../../../../core/verse/health-types.js';\nimport type { QueryEntry } from '../../../data/cache.js';\nimport { useQuery, useRefetch } from '../../../data/hooks.js';\nimport { verseHealthQuery } from './health-queries.js';\n\n/** The fastest poll the performance budget allows is 2 s; 30 s is plenty for a status line. */\nexport const HEALTH_POLL_MS = 30_000;\n\nexport function useSeatHealth(active = true): QueryEntry<VerseHealthResponse> {\n const entry = useQuery(verseHealthQuery);\n const refetch = useRefetch(verseHealthQuery);\n useEffect(() => {\n if (!active) return;\n const tick = (): void => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;\n refetch();\n };\n const timer = window.setInterval(tick, HEALTH_POLL_MS);\n document.addEventListener('visibilitychange', tick);\n return () => {\n window.clearInterval(timer);\n document.removeEventListener('visibilitychange', tick);\n };\n }, [active, refetch]);\n return entry;\n}\n","/**\n * routes/verse/useSeatsRefresh.ts — keep the seat roster live.\n *\n * THE BUG THIS CLOSES. `GET /api/verse/bootstrap` carries the seats, and it\n * has NO entry in sse.ts's `EVENT_TO_CACHE_KEYS`: nothing on the server can\n * push a new reading into it. It is re-read only on mount and after a write\n * (`invalidateVerseLists`). The account collector, meanwhile, needs roughly a\n * cycle and a half — about 75 seconds measured — before its first readings\n * exist. Open the app cold, as Mason does, and the one read that ever happens\n * lands BEFORE any reading exists. Every seat then shows \"unknown\" for the\n * rest of the session, on the surface he looks at all day, and no amount of\n * correct rendering downstream can fix that.\n *\n * So the chat surfaces poll. The cost is a cached JSON read, not a probe: the\n * collector spawns its processes on its own 30s cycle regardless of whether\n * anyone asks, and this only picks up what it already published. Owner S's\n * V2.1 bootstrap handler recomputes seat telemetry on every read\n * (`liveSeats` in core/verse/verse-api.ts), so a poll of this key genuinely\n * returns the collector's CURRENT state rather than a warm cache.\n *\n * V3.10 — POLL `GET /api/verse/seats`, NOT BOOTSTRAP. Bootstrap also\n * re-reads projects, preferences and the workspace registry; measured, it\n * blocked the server's event loop ~384 ms per poll (research r2/perf-server).\n * `/seats` is the same live seat list and nothing else. The seats still have\n * to land in the `verse-bootstrap` cache key, because that is what ChatSection\n * hands to the sidebar, workspace, seat selector and new-chat dialog — so the\n * poll MERGES `/seats` into the cached bootstrap (`mergeSeatsIntoBootstrap`)\n * instead of re-reading all of it.\n *\n * The cache remembers the last fetcher it ran for a key and re-runs it on\n * every later `invalidate` (after a write). A plain \"/seats and merge\" fetcher\n * would therefore turn every later full refresh into a seats-only one; the\n * poll registers a ONE-SHOT fetcher (health/health-queries.ts\n * `oneShotFetcher`) that merges once and falls back to the real bootstrap read.\n * With no bootstrap cached yet there is nothing to merge into, so the poll\n * reads bootstrap itself.\n *\n * Two deliberate choices:\n *\n * - Refetch semantics, not refresh. A refetch collapses a burst of ticks (and\n * a tick landing on a read that just started) into ONE request, which is\n * what a poll wants. A forced refresh never joins, which is what a person\n * pressing a button wants; the panel's own Refresh control uses that.\n * - Nothing is requested while the document is hidden, and a read is issued\n * the moment it becomes visible again. A backgrounded app polls zero times\n * and is nonetheless correct the instant it is looked at.\n */\nimport { useCallback, useEffect } from 'react';\nimport type { VerseBootstrap } from '../../data/api-types.js';\nimport type { VerseSeatsResponse } from '../../../core/verse/types.js';\nimport { getQuerySnapshot, refetchQuery } from '../../data/cache.js';\nimport { apiGet } from '../../data/client.js';\nimport { oneShotFetcher } from './health/health-queries.js';\nimport { VERSE_BOOTSTRAP_KEY, verseBootstrapQuery } from './verse-queries.js';\n\n/** Matches the collector's own publish cadence; there is nothing to gain from faster. */\nexport const SEATS_POLL_MS = 30_000;\n\nexport const VERSE_SEATS_URL = '/api/verse/seats';\n\n/** The cached bootstrap with its seat list (and local runtime) replaced by a live `/seats` read. */\nexport function mergeSeatsIntoBootstrap(bootstrap: VerseBootstrap, live: VerseSeatsResponse): VerseBootstrap {\n return { ...bootstrap, seats: live.seats, localRuntime: live.localRuntime };\n}\n\n/** One poll tick: `/seats` merged into the cached bootstrap, or a full bootstrap when none is cached. */\nexport function pollSeats(): Promise<void> {\n const cached = getQuerySnapshot<VerseBootstrap>(VERSE_BOOTSTRAP_KEY).data;\n const full = (): Promise<VerseBootstrap> => verseBootstrapQuery.fetch();\n if (cached === undefined) return refetchQuery(VERSE_BOOTSTRAP_KEY, full);\n const merged = async (): Promise<VerseBootstrap> => {\n const live = await apiGet<VerseSeatsResponse>(VERSE_SEATS_URL);\n // Merge into whatever is cached NOW, not at tick time: a write may have\n // refreshed the rest of the bootstrap while this read was in flight.\n const current = getQuerySnapshot<VerseBootstrap>(VERSE_BOOTSTRAP_KEY).data ?? cached;\n return mergeSeatsIntoBootstrap(current, live);\n };\n return refetchQuery(VERSE_BOOTSTRAP_KEY, oneShotFetcher(merged, full));\n}\n\nexport function useSeatsRefresh(active = true): void {\n const refetch = useCallback(() => { void pollSeats(); }, []);\n useEffect(() => {\n if (!active) return;\n const tick = (): void => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;\n refetch();\n };\n const timer = window.setInterval(tick, SEATS_POLL_MS);\n document.addEventListener('visibilitychange', tick);\n return () => {\n window.clearInterval(timer);\n document.removeEventListener('visibilitychange', tick);\n };\n }, [active, refetch]);\n}\n"],"mappings":"0PAkBa,EAAiB,IAE9B,SAAgB,EAAc,EAAS,GAAuC,CAC5E,IAAM,EAAQ,EAAS,CAAgB,EACjC,EAAU,EAAW,CAAgB,EAc3C,OAbA,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAQ,OACb,IAAM,MAAmB,EACnB,OAAO,SAAa,KAAe,SAAS,kBAAoB,WACpE,EAAQ,CACV,EACM,EAAQ,OAAO,YAAY,EAAM,CAAc,EAErD,OADA,SAAS,iBAAiB,mBAAoB,CAAI,MACrC,CACX,OAAO,cAAc,CAAK,EAC1B,SAAS,oBAAoB,mBAAoB,CAAI,CACvD,CACF,EAAG,CAAC,EAAQ,CAAO,CAAC,EACb,CACT,CCmBA,IAAa,EAAgB,IAEhB,EAAkB,mBAG/B,SAAgB,EAAwB,EAA2B,EAA0C,CAC3G,MAAO,CAAE,GAAG,EAAW,MAAO,EAAK,MAAO,aAAc,EAAK,YAAa,CAC5E,CAGA,SAAgB,GAA2B,CACzC,IAAM,EAAS,EAAiC,CAAmB,CAAC,CAAC,KAC/D,MAAsC,EAAoB,MAAM,EAStE,OARI,IAAW,IAAA,GAAkB,EAAa,EAAqB,CAAI,EAQhE,EAAa,EAAqB,EAAe,SAPJ,CAClD,IAAM,EAAO,MAAM,EAA2B,CAAe,EAI7D,OAAO,EADS,EAAA,iBAAoD,CAAC,CAAC,MAAQ,EACtC,CAAI,CAC9C,EACgE,CAAI,CAAC,CACvE,CAEA,SAAgB,EAAgB,EAAS,GAAY,CACnD,IAAM,GAAA,EAAU,EAAA,YAAA,KAAkB,CAAE,EAAe,CAAG,EAAG,CAAC,CAAC,GAC3D,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAQ,OACb,IAAM,MAAmB,EACnB,OAAO,SAAa,KAAe,SAAS,kBAAoB,WACpE,EAAQ,CACV,EACM,EAAQ,OAAO,YAAY,EAAM,CAAa,EAEpD,OADA,SAAS,iBAAiB,mBAAoB,CAAI,MACrC,CACX,OAAO,cAAc,CAAK,EAC1B,SAAS,oBAAoB,mBAAoB,CAAI,CACvD,CACF,EAAG,CAAC,EAAQ,CAAO,CAAC,CACtB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=useVerseTranscript-
|
|
1
|
+
import{a as e,c as t}from"./index-QesfXBsb.js";import{Et as n}from"./VerseConsoleApp-BCY5uSok.js";import{a as r,m as i,o as a}from"./verse-store-DNVRuiJL.js";import{o}from"./slots-DHKQDoE6.js";import{n as s}from"./ChatSection-D6WybBpB.js";var c=Object.fromEntries(n.filter(e=>e.slot!==null).map(e=>[e.id,e.slot]));function l(e){let t=c[e];return t===void 0||o(t)}var u=Object.fromEntries(n.map(e=>[e.id,e.label])),d=t(e(),1),f=new Map;i(e=>{e.kind===`reset`?f.clear():f.delete(e.sessionId)});var p={items:[],live:!1,usage:null,segments:[]};function m(e){if(!e)return p;let t=r(e),n=f.get(e);if(n&&n.events===t.events)return n.transcript;let i=n?.cache??g(),o=y(t.events,{cache:i,thinkingStats:a(e)});return f.set(e,{events:t.events,transcript:o,cache:i}),o}function h(e,t){let n=Date.parse(e),r=Date.parse(t);return Number.isFinite(n)&&Number.isFinite(r)?Math.max(0,r-n):null}function g(){return{segments:new Map}}function _(e,t,n,r){let i=[],a=new Map,o=[],s=[],c=null,l=null,u=null,d=()=>{c&&=(i.push({kind:`assistant`,key:c.key,turnId:c.turnId,at:c.at,text:c.text,streaming:!1}),null)};for(let f=t;f<n;f+=1){let t=e[f];switch(t.type){case`user-message`:d(),i.push({kind:`user`,key:`u-${t.seq}`,turnId:t.turnId,at:t.at,text:t.text});break;case`turn-started`:l=!0;break;case`text-delta`:c&&c.turnId!==t.turnId&&d(),c||={turnId:t.turnId,at:t.at,text:``,key:`d-${t.seq}`},c.text+=t.text;break;case`assistant-message`:c=null,i.push({kind:`assistant`,key:`a-${t.seq}`,turnId:t.turnId,at:t.at,text:t.text,streaming:!1});break;case`thinking`:{d();let e=r?.get(t.seq);i.push({kind:`thinking`,key:`t-${t.seq}`,turnId:t.turnId,at:t.at,text:t.text,redacted:t.redacted===!0,durationMs:typeof t.durationMs==`number`&&Number.isFinite(t.durationMs)&&t.durationMs>=0?t.durationMs:e?.durationMs??null,estimatedTokens:e?.estimatedTokens??null,thinkingKind:t.kind??null});break}case`tool-use`:d(),a.set(t.toolUseId,i.length),s.push(t.toolUseId),i.push({kind:`tool`,key:`tu-${t.seq}`,turnId:t.turnId,at:t.at,toolUseId:t.toolUseId,name:t.name,input:t.input,result:null,durationMs:null});break;case`tool-result`:{let e=a.get(t.toolUseId),n=e===void 0?void 0:i[e];n&&n.kind===`tool`?i[e]={...n,result:{output:t.output,isError:t.isError},durationMs:h(n.at,t.at)}:(o.push(t.toolUseId),i.push({kind:`tool`,key:`tr-${t.seq}`,turnId:t.turnId,at:t.at,toolUseId:t.toolUseId,name:`tool`,input:null,result:{output:t.output,isError:t.isError},durationMs:null}));break}case`usage`:u=t.usage;break;case`compaction`:i.push({kind:`compaction`,key:`k-${t.seq}`,turnId:t.turnId,at:t.at,trigger:t.trigger,preTokens:t.preTokens,postTokens:t.postTokens,durationMs:t.durationMs});break;case`error`:d(),i.push({kind:`error`,key:`e-${t.seq}`,turnId:t.turnId,at:t.at,message:t.message,code:typeof t.code==`string`&&t.code?t.code:null});break;case`cancelled`:d(),l=!1,i.push({kind:`cancelled`,key:`c-${t.seq}`,turnId:t.turnId,at:t.at});break;case`turn-done`:d(),l=!1,i.push({kind:`turn-done`,key:`td-${t.seq}`,turnId:t.turnId,at:t.at,ok:t.ok,durationMs:t.durationMs});break;case`recovered`:i.push({kind:`recovered`,key:`r-${t.seq}`,turnId:t.turnId,at:t.at,how:t.how,message:t.message});break;case`history-truncated`:i.push({kind:`truncated`,key:`h-${t.seq}`,turnId:null,at:t.at,droppedBefore:t.droppedBefore})}}return{items:i,pending:c,liveEffect:l,usage:u,orphanResults:o,toolUseIds:s}}function v(e,t,n){let r=t.pending;return r?{key:e,items:[...t.items,{kind:`assistant`,key:r.key,turnId:r.turnId,at:r.at,text:r.text,streaming:n}]}:{key:e,items:t.items}}function y(e,t={}){let{cache:n,thinkingStats:r}=t;if(e.length===0)return{items:[],live:!1,usage:null,segments:[]};let i=[0];for(let t=1;t<e.length;t+=1)e[t].type===`user-message`&&i.push(t);let a=[],o=new Set;for(let t=0;t<i.length;t+=1){let s=i[t],c=t+1<i.length?i[t+1]:e.length,l=e[s].seq,u=e[c-1].seq,d=c-s,f=`s-${l}`;o.add(f);let p=n?.segments.get(f);if(p&&p.firstSeq===l&&p.lastSeq===u&&p.count===d){a.push({key:f,build:p.build,cached:p});continue}let m=_(e,s,c,r),h={firstSeq:l,lastSeq:u,count:d,build:m,finalized:null};n?.segments.set(f,h),a.push({key:f,build:m,cached:h})}if(n)for(let e of[...n.segments.keys()])o.has(e)||n.segments.delete(e);if(a.length>1){let t=new Set;for(let n of a){if(n.build.orphanResults.some(e=>t.has(e)))return b(e,r);for(let e of n.build.toolUseIds)t.add(e)}}let s=!1,c=null;for(let e of a)e.build.liveEffect!==null&&(s=e.build.liveEffect),e.build.usage!==null&&(c=e.build.usage);let l=[],u=[];for(let e=0;e<a.length;e+=1){let t=a[e],n=e===a.length-1&&s,r;t.cached?.finalized&&t.cached.finalized.streaming===n?r=t.cached.finalized.segment:(r=v(t.key,t.build,n),t.cached&&(t.cached.finalized={streaming:n,segment:r})),l.push(r);for(let e of r.items)u.push(e)}return{items:u,live:s,usage:c,segments:l}}function b(e,t){let n=_(e,0,e.length,t),r=n.liveEffect??!1,i=v(`s-${e[0].seq}`,n,r);return{items:i.items,live:r,usage:n.usage,segments:[i]}}function x(e){let t=[],n=[],r=()=>{if(n.length===0)return;let e=n.length;for(;e>0&&n[e-1].kind===`thinking`;)--e;let r=n.slice(0,e),i=n.slice(e);if(r.filter(e=>e.kind===`tool`).length>=2)t.push(S(r));else for(let e of r)t.push(e);for(let e of i)t.push(e);n=[]};for(let i of e){if((i.kind===`tool`||i.kind===`thinking`)&&(n.length===0||n[0].turnId===i.turnId)){n.push(i);continue}r(),i.kind===`tool`||i.kind===`thinking`?n.push(i):t.push(i)}return r(),t}function S(e){let t=new Map,n=0,r=!1;for(let i of e)i.kind===`tool`&&(t.set(i.name,(t.get(i.name)??0)+1),i.result===null?r=!0:i.result.isError&&(n+=1));let i=[...t.values()].reduce((e,t)=>e+t,0),a=[...t.entries()].map(([e,t])=>t>1?`${e} ×${t}`:e).join(`, `),o=h(e[0].at,e[e.length-1].at);return{kind:`toolGroup`,key:`g-${e[0].key}`,turnId:e[0].turnId,at:e[0].at,items:e,toolCount:i,summary:a,errorCount:n,pending:r,spanMs:o}}function C(e){let t=s(e);return(0,d.useSyncExternalStore)(t,()=>m(e),()=>m(e))}export{l as i,x as n,u as r,C as t};
|
|
2
|
+
//# sourceMappingURL=useVerseTranscript-BQ0J6Xhx.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVerseTranscript-BGtA55k2.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/dock/dock-panes.ts","../../../../../../src/web-ui/routes/verse/verse-transcript.ts","../../../../../../src/web-ui/routes/verse/useVerseTranscript.ts"],"sourcesContent":["/**\n * routes/verse/dock/dock-panes.ts — which dock panes exist in this build,\n * and their names (unit C2).\n *\n * Split out of Dock.tsx so the header's pane toggles can ask without pulling\n * the dock itself into the chat's first-paint chunk: the dock is lazy (it\n * starts closed), the toggles are not.\n */\nimport { DOCK_PANES, type DockPaneId } from '../shell/dock-catalog.js';\nimport { isSlotAvailable, type SlotId } from '../shell/slots.js';\n\nconst SLOT_FOR: Readonly<Partial<Record<DockPaneId, SlotId>>> = Object.fromEntries(\n DOCK_PANES.filter((p) => p.slot !== null).map((p) => [p.id, p.slot]),\n);\n\n/** A pane exists in this build: C2's always, a slot pane once its unit's file landed. */\nexport function isPaneAvailable(pane: DockPaneId): boolean {\n const slot = SLOT_FOR[pane];\n return slot === undefined || isSlotAvailable(slot);\n}\n\nexport const DOCK_PANE_LABEL: Readonly<Record<DockPaneId, string>> = Object.fromEntries(\n DOCK_PANES.map((p) => [p.id, p.label]),\n) as Record<DockPaneId, string>;\n","/**\n * routes/verse/verse-transcript.ts — what the transcript renders, derived\n * from a session's raw event log (moved out of verse-store.ts).\n *\n * WHY A SEPARATE MODULE: verse-store is on the chat first-paint path (the\n * Chat section opens the selected chat's stream as it mounts), but nothing\n * reads a DERIVED transcript until the workspace or the dock — both lazy\n * chunks — renders one. Keeping the derivation here keeps ~5 KB of it out of\n * the chat first-paint critical JS (SPEC-310A §1, scripts/check-first-paint-\n * budget.mjs). verse-store must never import this module back as a value.\n *\n * `buildTranscript()` derives what the transcript renders from the raw\n * events: streamed `text-delta`s accumulate into a provisional assistant\n * bubble until the matching `assistant-message` arrives and replaces it;\n * `tool-use` and `tool-result` pair up by toolUseId into one card.\n * `getVerseTranscript()` memoizes it per session against the store's event\n * log, rebuilding only the turn segments that changed.\n */\nimport type { VerseEvent, VerseUsage } from '../../data/api-types.js';\nimport type { VerseRecoveryHow, VerseThinkingKind } from '../../../core/verse/types.js';\nimport { getVerseSessionState, getVerseThinkingStats, subscribeVerseStoreLifecycle, type VerseThinkingStat } from './verse-store.js';\n\n// ---------------------------------------------------------------------------\n// Per-session memo over the store\n// ---------------------------------------------------------------------------\n\nconst transcriptMemo = new Map<string, { events: readonly VerseEvent[]; transcript: Transcript; cache: TranscriptCache }>();\n\n// The store tells us when a chat is forgotten or everything is reset\n// (logout, tests), exactly when it used to clear this memo itself.\nsubscribeVerseStoreLifecycle((event) => {\n if (event.kind === 'reset') transcriptMemo.clear();\n else transcriptMemo.delete(event.sessionId);\n});\n\nconst EMPTY_TRANSCRIPT: Transcript = { items: [], live: false, usage: null, segments: [] };\n\n/**\n * The derived transcript, rebuilt only when the event log changed and then\n * only for the turn segments that changed (see buildTranscript's cache).\n */\nexport function getVerseTranscript(sessionId: string | null): Transcript {\n if (!sessionId) return EMPTY_TRANSCRIPT;\n const entry = getVerseSessionState(sessionId);\n const memo = transcriptMemo.get(sessionId);\n if (memo && memo.events === entry.events) return memo.transcript;\n const cache = memo?.cache ?? createTranscriptCache();\n const transcript = buildTranscript(entry.events, { cache, thinkingStats: getVerseThinkingStats(sessionId) });\n transcriptMemo.set(sessionId, { events: entry.events, transcript, cache });\n return transcript;\n}\n\n// ---------------------------------------------------------------------------\n// Transcript derivation\n// ---------------------------------------------------------------------------\n\nexport type TranscriptItem =\n | { kind: 'user'; key: string; turnId: string; at: string; text: string }\n | { kind: 'assistant'; key: string; turnId: string; at: string; text: string; streaming: boolean }\n | {\n kind: 'thinking';\n key: string;\n turnId: string;\n at: string;\n text: string;\n /** V3.10: the CLI sent a signature-only / redacted block — the model thought, the text is withheld. */\n redacted: boolean;\n /** Streaming wall time: the event's own figure, else what this tab measured; null = unknown. */\n durationMs: number | null;\n /** The CLI's reasoning-token estimate this tab saw while it streamed; null = unknown. */\n estimatedTokens: number | null;\n thinkingKind: VerseThinkingKind | null;\n }\n | {\n kind: 'tool';\n key: string;\n turnId: string;\n at: string;\n toolUseId: string;\n name: string;\n input: unknown;\n result: { output: string; isError: boolean } | null;\n /** tool-use → tool-result wall time; null while pending or unstamped. */\n durationMs: number | null;\n }\n | { kind: 'error'; key: string; turnId: string | null; at: string; message: string; code: string | null }\n | {\n /** V3.9: the CLI compacted its own context. Counts are null when the CLI does not report them (codex). */\n kind: 'compaction';\n key: string;\n turnId: string | null;\n at: string;\n trigger: 'auto' | 'manual';\n preTokens: number | null;\n postTokens: number | null;\n durationMs: number | null;\n }\n | { kind: 'cancelled'; key: string; turnId: string; at: string }\n | { kind: 'turn-done'; key: string; turnId: string; at: string; ok: boolean; durationMs: number }\n /** V3.10: the engine restored a lost native conversation. */\n | { kind: 'recovered'; key: string; turnId: string | null; at: string; how: VerseRecoveryHow; message: string }\n /** V3.10: the log hit its cap and dropped everything before `droppedBefore` (at a turn boundary). */\n | { kind: 'truncated'; key: string; turnId: null; at: string; droppedBefore: number };\n\n/**\n * One turn's worth of items — the log cut at each `user-message`. Unchanged\n * segments come back as the SAME object from a cached build, which is what\n * lets the renderer skip every finished turn while one is streaming.\n */\nexport interface TranscriptSegment {\n key: string;\n items: TranscriptItem[];\n}\n\nexport interface Transcript {\n items: TranscriptItem[];\n /** True while a turn is open (started and not yet done/cancelled). */\n live: boolean;\n /** Most recent usage frame seen in the log, if any. */\n usage: VerseUsage | null;\n /** `items`, cut into turn segments. Absent on a hand-built transcript (treated as one segment). */\n segments?: TranscriptSegment[];\n}\n\n/** Wall time between two ISO stamps; null when either is unparseable. */\nfunction spanMs(from: string, to: string): number | null {\n const a = Date.parse(from);\n const b = Date.parse(to);\n return Number.isFinite(a) && Number.isFinite(b) ? Math.max(0, b - a) : null;\n}\n\ninterface PendingText {\n turnId: string;\n at: string;\n text: string;\n key: string;\n}\n\ninterface SegmentBuild {\n /** Items without the trailing streamed text, which depends on whether the WHOLE log is live. */\n items: TranscriptItem[];\n pending: PendingText | null;\n /** The last live-flag change in this segment: true (started), false (ended) or null (none). */\n liveEffect: boolean | null;\n usage: VerseUsage | null;\n /** tool-results in this segment whose tool-use is not in it. */\n orphanResults: string[];\n toolUseIds: string[];\n}\n\ninterface CachedSegment {\n firstSeq: number;\n lastSeq: number;\n count: number;\n build: SegmentBuild;\n /** The finished segment per trailing-streaming flag it was finalized with. */\n finalized: { streaming: boolean; segment: TranscriptSegment } | null;\n}\n\nexport interface TranscriptCache {\n segments: Map<string, CachedSegment>;\n}\n\nexport function createTranscriptCache(): TranscriptCache {\n return { segments: new Map() };\n}\n\nexport interface BuildTranscriptOptions {\n /** Reuse segments from a previous build of the same session's log. */\n cache?: TranscriptCache;\n /** Measured figures for reasoning blocks this tab watched stream, by the persisted event's seq. */\n thinkingStats?: ReadonlyMap<number, VerseThinkingStat>;\n}\n\n/**\n * The original single-pass derivation over `events[from, to)`. A whole log\n * run through it in one range is exactly the pre-3.10 buildTranscript; cut\n * at `user-message` boundaries (where it flushes anyway) the pieces\n * concatenate to the same items.\n */\nfunction buildSegment(\n events: readonly VerseEvent[],\n from: number,\n to: number,\n stats: ReadonlyMap<number, VerseThinkingStat> | undefined,\n): SegmentBuild {\n const items: TranscriptItem[] = [];\n const toolIndex = new Map<string, number>();\n const orphanResults: string[] = [];\n const toolUseIds: string[] = [];\n let pending: PendingText | null = null;\n let liveEffect: boolean | null = null;\n let usage: VerseUsage | null = null;\n\n const flushPending = () => {\n if (!pending) return;\n items.push({ kind: 'assistant', key: pending.key, turnId: pending.turnId, at: pending.at, text: pending.text, streaming: false });\n pending = null;\n };\n\n for (let i = from; i < to; i += 1) {\n const e = events[i]!;\n switch (e.type) {\n case 'user-message':\n flushPending();\n items.push({ kind: 'user', key: `u-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text });\n break;\n case 'turn-started':\n liveEffect = true;\n break;\n case 'text-delta':\n if (pending && pending.turnId !== e.turnId) flushPending();\n if (!pending) pending = { turnId: e.turnId, at: e.at, text: '', key: `d-${e.seq}` };\n pending.text += e.text;\n break;\n case 'assistant-message':\n // The complete message supersedes whatever deltas streamed before it.\n pending = null;\n items.push({ kind: 'assistant', key: `a-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text, streaming: false });\n break;\n case 'thinking': {\n flushPending();\n const measured = stats?.get(e.seq);\n items.push({\n kind: 'thinking',\n key: `t-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n text: e.text,\n redacted: e.redacted === true,\n durationMs: typeof e.durationMs === 'number' && Number.isFinite(e.durationMs) && e.durationMs >= 0\n ? e.durationMs\n : measured?.durationMs ?? null,\n estimatedTokens: measured?.estimatedTokens ?? null,\n thinkingKind: e.kind ?? null,\n });\n break;\n }\n case 'tool-use':\n flushPending();\n toolIndex.set(e.toolUseId, items.length);\n toolUseIds.push(e.toolUseId);\n items.push({\n kind: 'tool',\n key: `tu-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n toolUseId: e.toolUseId,\n name: e.name,\n input: e.input,\n result: null,\n durationMs: null,\n });\n break;\n case 'tool-result': {\n const idx = toolIndex.get(e.toolUseId);\n const existing = idx === undefined ? undefined : items[idx];\n if (existing && existing.kind === 'tool') {\n items[idx!] = { ...existing, result: { output: e.output, isError: e.isError }, durationMs: spanMs(existing.at, e.at) };\n } else {\n orphanResults.push(e.toolUseId);\n items.push({\n kind: 'tool',\n key: `tr-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n toolUseId: e.toolUseId,\n name: 'tool',\n input: null,\n result: { output: e.output, isError: e.isError },\n durationMs: null,\n });\n }\n break;\n }\n case 'usage':\n usage = e.usage;\n break;\n case 'compaction':\n // Deliberately NO flushPending: CLIs compact between model calls, and\n // flushing a streamed bubble here would leave it in the list when the\n // complete `assistant-message` arrives — the same reply twice.\n items.push({\n kind: 'compaction',\n key: `k-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n trigger: e.trigger,\n preTokens: e.preTokens,\n postTokens: e.postTokens,\n durationMs: e.durationMs,\n });\n break;\n case 'error':\n flushPending();\n items.push({ kind: 'error', key: `e-${e.seq}`, turnId: e.turnId, at: e.at, message: e.message, code: typeof e.code === 'string' && e.code ? e.code : null });\n break;\n case 'cancelled':\n flushPending();\n liveEffect = false;\n items.push({ kind: 'cancelled', key: `c-${e.seq}`, turnId: e.turnId, at: e.at });\n break;\n case 'turn-done':\n flushPending();\n liveEffect = false;\n items.push({ kind: 'turn-done', key: `td-${e.seq}`, turnId: e.turnId, at: e.at, ok: e.ok, durationMs: e.durationMs });\n break;\n case 'recovered':\n // Like compaction, no flush: recovery happens before the new native\n // session produces anything, never in the middle of a reply.\n items.push({ kind: 'recovered', key: `r-${e.seq}`, turnId: e.turnId, at: e.at, how: e.how, message: e.message });\n break;\n case 'history-truncated':\n items.push({ kind: 'truncated', key: `h-${e.seq}`, turnId: null, at: e.at, droppedBefore: e.droppedBefore });\n break;\n default:\n break;\n }\n }\n return { items, pending, liveEffect, usage, orphanResults, toolUseIds };\n}\n\nfunction finalizeSegment(key: string, build: SegmentBuild, streaming: boolean): TranscriptSegment {\n const p = build.pending;\n if (!p) return { key, items: build.items };\n return {\n key,\n items: [...build.items, { kind: 'assistant', key: p.key, turnId: p.turnId, at: p.at, text: p.text, streaming }],\n };\n}\n\n// `VerseEvent[]` (not readonly) is the published signature: callers type\n// their fixture arrays as `Parameters<typeof buildTranscript>[0]` and push.\nexport function buildTranscript(events: VerseEvent[], options: BuildTranscriptOptions = {}): Transcript {\n const { cache, thinkingStats: stats } = options;\n if (events.length === 0) return { items: [], live: false, usage: null, segments: [] };\n\n // Cut at every user-message: a new ask always opens a new turn, and the\n // derivation flushes its streamed text there, so nothing spans the cut.\n const starts: number[] = [0];\n for (let i = 1; i < events.length; i += 1) if (events[i]!.type === 'user-message') starts.push(i);\n\n const builds: Array<{ key: string; build: SegmentBuild; cached: CachedSegment | null }> = [];\n const seenKeys = new Set<string>();\n for (let s = 0; s < starts.length; s += 1) {\n const from = starts[s]!;\n const to = s + 1 < starts.length ? starts[s + 1]! : events.length;\n const firstSeq = events[from]!.seq;\n const lastSeq = events[to - 1]!.seq;\n const count = to - from;\n const key = `s-${firstSeq}`;\n seenKeys.add(key);\n const hit = cache?.segments.get(key);\n if (hit && hit.firstSeq === firstSeq && hit.lastSeq === lastSeq && hit.count === count) {\n builds.push({ key, build: hit.build, cached: hit });\n continue;\n }\n const build = buildSegment(events, from, to, stats);\n const entry: CachedSegment = { firstSeq, lastSeq, count, build, finalized: null };\n cache?.segments.set(key, entry);\n builds.push({ key, build, cached: entry });\n }\n if (cache) for (const key of [...cache.segments.keys()]) if (!seenKeys.has(key)) cache.segments.delete(key);\n\n // A tool-result whose tool-use sits in an EARLIER segment would have\n // updated that earlier card in the single-pass derivation. It never\n // happens in a real log (a result follows its call inside one turn); if it\n // does, derive the whole log in one pass rather than render it differently.\n if (builds.length > 1) {\n const earlier = new Set<string>();\n for (const b of builds) {\n if (b.build.orphanResults.some((id) => earlier.has(id))) return singlePass(events, stats);\n for (const id of b.build.toolUseIds) earlier.add(id);\n }\n }\n\n let live = false;\n let usage: VerseUsage | null = null;\n for (const b of builds) {\n if (b.build.liveEffect !== null) live = b.build.liveEffect;\n if (b.build.usage !== null) usage = b.build.usage;\n }\n\n const segments: TranscriptSegment[] = [];\n const items: TranscriptItem[] = [];\n for (let s = 0; s < builds.length; s += 1) {\n const b = builds[s]!;\n // Deltas still arriving for an open turn render as a streaming bubble;\n // every earlier segment's trailing text was flushed by the next ask.\n const streaming = s === builds.length - 1 ? live : false;\n let segment: TranscriptSegment;\n if (b.cached?.finalized && b.cached.finalized.streaming === streaming) {\n segment = b.cached.finalized.segment;\n } else {\n segment = finalizeSegment(b.key, b.build, streaming);\n if (b.cached) b.cached.finalized = { streaming, segment };\n }\n segments.push(segment);\n for (const item of segment.items) items.push(item);\n }\n return { items, live, usage, segments };\n}\n\nfunction singlePass(events: readonly VerseEvent[], stats: ReadonlyMap<number, VerseThinkingStat> | undefined): Transcript {\n const build = buildSegment(events, 0, events.length, stats);\n const live = build.liveEffect ?? false;\n const segment = finalizeSegment(`s-${events[0]!.seq}`, build, live);\n return { items: segment.items, live, usage: build.usage, segments: [segment] };\n}\n\n// ---------------------------------------------------------------------------\n// Render-time grouping\n// ---------------------------------------------------------------------------\n\nexport type ToolGroupMember = Extract<TranscriptItem, { kind: 'tool' | 'thinking' }>;\n\nexport interface ToolGroupItem {\n kind: 'toolGroup';\n key: string;\n turnId: string;\n at: string;\n items: ToolGroupMember[];\n /** Tool calls only (thinking blocks are not counted). */\n toolCount: number;\n /** \"Read ×6, Edit ×4\" — names in first-seen order. */\n summary: string;\n errorCount: number;\n /** A member is still waiting for its result. */\n pending: boolean;\n /** Wall time between the first and last member, when both have parseable timestamps. */\n spanMs: number | null;\n}\n\nexport type TranscriptRenderItem = TranscriptItem | ToolGroupItem;\n\n/**\n * Fold runs of consecutive tool calls from the same turn that hold two or\n * more calls into one `toolGroup`, so an agentic turn reads as \"N tool calls\"\n * with a single disclosure instead of a wall of cards. A single call (with\n * whatever reasoning surrounds it) stays as it is.\n * Pure over buildTranscript()'s output (the index-based tool-result pairing\n * there is untouched).\n *\n * Reasoning INTERLEAVED between tool calls folds with them (it explains the\n * next call). Reasoning that ENDS a run — the model's last thought before it\n * answers or before the next ask — is lifted out and rendered on its own, so\n * the part worth reading is never two disclosures deep. A run of reasoning\n * alone never folds.\n */\nexport function groupTranscriptItems(items: readonly TranscriptItem[]): TranscriptRenderItem[] {\n const out: TranscriptRenderItem[] = [];\n let run: ToolGroupMember[] = [];\n\n const flush = () => {\n if (run.length === 0) return;\n let end = run.length;\n while (end > 0 && run[end - 1]!.kind === 'thinking') end -= 1;\n const folded = run.slice(0, end);\n const trailing = run.slice(end);\n // Only a run with two or more CALLS is worth a disclosure: \"1 tool\" hiding\n // a single call plus the reasoning before it is a click for nothing.\n if (folded.filter((m) => m.kind === 'tool').length >= 2) out.push(makeToolGroup(folded));\n else for (const member of folded) out.push(member);\n for (const thought of trailing) out.push(thought);\n run = [];\n };\n\n for (const item of items) {\n if ((item.kind === 'tool' || item.kind === 'thinking') && (run.length === 0 || run[0]!.turnId === item.turnId)) {\n run.push(item);\n continue;\n }\n flush();\n if (item.kind === 'tool' || item.kind === 'thinking') run.push(item);\n else out.push(item);\n }\n flush();\n return out;\n}\n\nfunction makeToolGroup(members: ToolGroupMember[]): ToolGroupItem {\n const counts = new Map<string, number>();\n let errorCount = 0;\n let pending = false;\n for (const m of members) {\n if (m.kind !== 'tool') continue;\n counts.set(m.name, (counts.get(m.name) ?? 0) + 1);\n if (m.result === null) pending = true;\n else if (m.result.isError) errorCount += 1;\n }\n const toolCount = [...counts.values()].reduce((a, b) => a + b, 0);\n const summary = [...counts.entries()].map(([name, n]) => (n > 1 ? `${name} ×${n}` : name)).join(', ');\n const span = spanMs(members[0]!.at, members[members.length - 1]!.at);\n return {\n kind: 'toolGroup',\n key: `g-${members[0]!.key}`,\n turnId: members[0]!.turnId,\n at: members[0]!.at,\n items: members,\n toolCount,\n summary,\n errorCount,\n pending,\n spanMs: span,\n };\n}\n","/**\n * routes/verse/useVerseTranscript.ts — the React glue over the derived\n * transcript (verse-transcript.ts).\n *\n * Not in useVerseSession.ts because that module is on the chat first-paint\n * path (the Chat section opens the chat through it) while the transcript is\n * rendered only by lazy chunks (the workspace, the dock). Importing the\n * derivation from there would put it back in the first-paint critical JS.\n */\nimport { useSyncExternalStore } from 'react';\nimport { useSessionSubscription } from './useVerseSession.js';\nimport { getVerseTranscript, type Transcript } from './verse-transcript.js';\n\n/** The transcript of one chat, rebuilt only for the turn that changed. */\nexport function useVerseTranscript(sessionId: string | null): Transcript {\n const subscribe = useSessionSubscription(sessionId);\n return useSyncExternalStore(\n subscribe,\n () => getVerseTranscript(sessionId),\n () => getVerseTranscript(sessionId),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useVerseTranscript-BQ0J6Xhx.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/dock/dock-panes.ts","../../../../../../src/web-ui/routes/verse/verse-transcript.ts","../../../../../../src/web-ui/routes/verse/useVerseTranscript.ts"],"sourcesContent":["/**\n * routes/verse/dock/dock-panes.ts — which dock panes exist in this build,\n * and their names (unit C2).\n *\n * Split out of Dock.tsx so the header's pane toggles can ask without pulling\n * the dock itself into the chat's first-paint chunk: the dock is lazy (it\n * starts closed), the toggles are not.\n */\nimport { DOCK_PANES, type DockPaneId } from '../shell/dock-catalog.js';\nimport { isSlotAvailable, type SlotId } from '../shell/slots.js';\n\nconst SLOT_FOR: Readonly<Partial<Record<DockPaneId, SlotId>>> = Object.fromEntries(\n DOCK_PANES.filter((p) => p.slot !== null).map((p) => [p.id, p.slot]),\n);\n\n/** A pane exists in this build: C2's always, a slot pane once its unit's file landed. */\nexport function isPaneAvailable(pane: DockPaneId): boolean {\n const slot = SLOT_FOR[pane];\n return slot === undefined || isSlotAvailable(slot);\n}\n\nexport const DOCK_PANE_LABEL: Readonly<Record<DockPaneId, string>> = Object.fromEntries(\n DOCK_PANES.map((p) => [p.id, p.label]),\n) as Record<DockPaneId, string>;\n","/**\n * routes/verse/verse-transcript.ts — what the transcript renders, derived\n * from a session's raw event log (moved out of verse-store.ts).\n *\n * WHY A SEPARATE MODULE: verse-store is on the chat first-paint path (the\n * Chat section opens the selected chat's stream as it mounts), but nothing\n * reads a DERIVED transcript until the workspace or the dock — both lazy\n * chunks — renders one. Keeping the derivation here keeps ~5 KB of it out of\n * the chat first-paint critical JS (SPEC-310A §1, scripts/check-first-paint-\n * budget.mjs). verse-store must never import this module back as a value.\n *\n * `buildTranscript()` derives what the transcript renders from the raw\n * events: streamed `text-delta`s accumulate into a provisional assistant\n * bubble until the matching `assistant-message` arrives and replaces it;\n * `tool-use` and `tool-result` pair up by toolUseId into one card.\n * `getVerseTranscript()` memoizes it per session against the store's event\n * log, rebuilding only the turn segments that changed.\n */\nimport type { VerseEvent, VerseUsage } from '../../data/api-types.js';\nimport type { VerseRecoveryHow, VerseThinkingKind } from '../../../core/verse/types.js';\nimport { getVerseSessionState, getVerseThinkingStats, subscribeVerseStoreLifecycle, type VerseThinkingStat } from './verse-store.js';\n\n// ---------------------------------------------------------------------------\n// Per-session memo over the store\n// ---------------------------------------------------------------------------\n\nconst transcriptMemo = new Map<string, { events: readonly VerseEvent[]; transcript: Transcript; cache: TranscriptCache }>();\n\n// The store tells us when a chat is forgotten or everything is reset\n// (logout, tests), exactly when it used to clear this memo itself.\nsubscribeVerseStoreLifecycle((event) => {\n if (event.kind === 'reset') transcriptMemo.clear();\n else transcriptMemo.delete(event.sessionId);\n});\n\nconst EMPTY_TRANSCRIPT: Transcript = { items: [], live: false, usage: null, segments: [] };\n\n/**\n * The derived transcript, rebuilt only when the event log changed and then\n * only for the turn segments that changed (see buildTranscript's cache).\n */\nexport function getVerseTranscript(sessionId: string | null): Transcript {\n if (!sessionId) return EMPTY_TRANSCRIPT;\n const entry = getVerseSessionState(sessionId);\n const memo = transcriptMemo.get(sessionId);\n if (memo && memo.events === entry.events) return memo.transcript;\n const cache = memo?.cache ?? createTranscriptCache();\n const transcript = buildTranscript(entry.events, { cache, thinkingStats: getVerseThinkingStats(sessionId) });\n transcriptMemo.set(sessionId, { events: entry.events, transcript, cache });\n return transcript;\n}\n\n// ---------------------------------------------------------------------------\n// Transcript derivation\n// ---------------------------------------------------------------------------\n\nexport type TranscriptItem =\n | { kind: 'user'; key: string; turnId: string; at: string; text: string }\n | { kind: 'assistant'; key: string; turnId: string; at: string; text: string; streaming: boolean }\n | {\n kind: 'thinking';\n key: string;\n turnId: string;\n at: string;\n text: string;\n /** V3.10: the CLI sent a signature-only / redacted block — the model thought, the text is withheld. */\n redacted: boolean;\n /** Streaming wall time: the event's own figure, else what this tab measured; null = unknown. */\n durationMs: number | null;\n /** The CLI's reasoning-token estimate this tab saw while it streamed; null = unknown. */\n estimatedTokens: number | null;\n thinkingKind: VerseThinkingKind | null;\n }\n | {\n kind: 'tool';\n key: string;\n turnId: string;\n at: string;\n toolUseId: string;\n name: string;\n input: unknown;\n result: { output: string; isError: boolean } | null;\n /** tool-use → tool-result wall time; null while pending or unstamped. */\n durationMs: number | null;\n }\n | { kind: 'error'; key: string; turnId: string | null; at: string; message: string; code: string | null }\n | {\n /** V3.9: the CLI compacted its own context. Counts are null when the CLI does not report them (codex). */\n kind: 'compaction';\n key: string;\n turnId: string | null;\n at: string;\n trigger: 'auto' | 'manual';\n preTokens: number | null;\n postTokens: number | null;\n durationMs: number | null;\n }\n | { kind: 'cancelled'; key: string; turnId: string; at: string }\n | { kind: 'turn-done'; key: string; turnId: string; at: string; ok: boolean; durationMs: number }\n /** V3.10: the engine restored a lost native conversation. */\n | { kind: 'recovered'; key: string; turnId: string | null; at: string; how: VerseRecoveryHow; message: string }\n /** V3.10: the log hit its cap and dropped everything before `droppedBefore` (at a turn boundary). */\n | { kind: 'truncated'; key: string; turnId: null; at: string; droppedBefore: number };\n\n/**\n * One turn's worth of items — the log cut at each `user-message`. Unchanged\n * segments come back as the SAME object from a cached build, which is what\n * lets the renderer skip every finished turn while one is streaming.\n */\nexport interface TranscriptSegment {\n key: string;\n items: TranscriptItem[];\n}\n\nexport interface Transcript {\n items: TranscriptItem[];\n /** True while a turn is open (started and not yet done/cancelled). */\n live: boolean;\n /** Most recent usage frame seen in the log, if any. */\n usage: VerseUsage | null;\n /** `items`, cut into turn segments. Absent on a hand-built transcript (treated as one segment). */\n segments?: TranscriptSegment[];\n}\n\n/** Wall time between two ISO stamps; null when either is unparseable. */\nfunction spanMs(from: string, to: string): number | null {\n const a = Date.parse(from);\n const b = Date.parse(to);\n return Number.isFinite(a) && Number.isFinite(b) ? Math.max(0, b - a) : null;\n}\n\ninterface PendingText {\n turnId: string;\n at: string;\n text: string;\n key: string;\n}\n\ninterface SegmentBuild {\n /** Items without the trailing streamed text, which depends on whether the WHOLE log is live. */\n items: TranscriptItem[];\n pending: PendingText | null;\n /** The last live-flag change in this segment: true (started), false (ended) or null (none). */\n liveEffect: boolean | null;\n usage: VerseUsage | null;\n /** tool-results in this segment whose tool-use is not in it. */\n orphanResults: string[];\n toolUseIds: string[];\n}\n\ninterface CachedSegment {\n firstSeq: number;\n lastSeq: number;\n count: number;\n build: SegmentBuild;\n /** The finished segment per trailing-streaming flag it was finalized with. */\n finalized: { streaming: boolean; segment: TranscriptSegment } | null;\n}\n\nexport interface TranscriptCache {\n segments: Map<string, CachedSegment>;\n}\n\nexport function createTranscriptCache(): TranscriptCache {\n return { segments: new Map() };\n}\n\nexport interface BuildTranscriptOptions {\n /** Reuse segments from a previous build of the same session's log. */\n cache?: TranscriptCache;\n /** Measured figures for reasoning blocks this tab watched stream, by the persisted event's seq. */\n thinkingStats?: ReadonlyMap<number, VerseThinkingStat>;\n}\n\n/**\n * The original single-pass derivation over `events[from, to)`. A whole log\n * run through it in one range is exactly the pre-3.10 buildTranscript; cut\n * at `user-message` boundaries (where it flushes anyway) the pieces\n * concatenate to the same items.\n */\nfunction buildSegment(\n events: readonly VerseEvent[],\n from: number,\n to: number,\n stats: ReadonlyMap<number, VerseThinkingStat> | undefined,\n): SegmentBuild {\n const items: TranscriptItem[] = [];\n const toolIndex = new Map<string, number>();\n const orphanResults: string[] = [];\n const toolUseIds: string[] = [];\n let pending: PendingText | null = null;\n let liveEffect: boolean | null = null;\n let usage: VerseUsage | null = null;\n\n const flushPending = () => {\n if (!pending) return;\n items.push({ kind: 'assistant', key: pending.key, turnId: pending.turnId, at: pending.at, text: pending.text, streaming: false });\n pending = null;\n };\n\n for (let i = from; i < to; i += 1) {\n const e = events[i]!;\n switch (e.type) {\n case 'user-message':\n flushPending();\n items.push({ kind: 'user', key: `u-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text });\n break;\n case 'turn-started':\n liveEffect = true;\n break;\n case 'text-delta':\n if (pending && pending.turnId !== e.turnId) flushPending();\n if (!pending) pending = { turnId: e.turnId, at: e.at, text: '', key: `d-${e.seq}` };\n pending.text += e.text;\n break;\n case 'assistant-message':\n // The complete message supersedes whatever deltas streamed before it.\n pending = null;\n items.push({ kind: 'assistant', key: `a-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text, streaming: false });\n break;\n case 'thinking': {\n flushPending();\n const measured = stats?.get(e.seq);\n items.push({\n kind: 'thinking',\n key: `t-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n text: e.text,\n redacted: e.redacted === true,\n durationMs: typeof e.durationMs === 'number' && Number.isFinite(e.durationMs) && e.durationMs >= 0\n ? e.durationMs\n : measured?.durationMs ?? null,\n estimatedTokens: measured?.estimatedTokens ?? null,\n thinkingKind: e.kind ?? null,\n });\n break;\n }\n case 'tool-use':\n flushPending();\n toolIndex.set(e.toolUseId, items.length);\n toolUseIds.push(e.toolUseId);\n items.push({\n kind: 'tool',\n key: `tu-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n toolUseId: e.toolUseId,\n name: e.name,\n input: e.input,\n result: null,\n durationMs: null,\n });\n break;\n case 'tool-result': {\n const idx = toolIndex.get(e.toolUseId);\n const existing = idx === undefined ? undefined : items[idx];\n if (existing && existing.kind === 'tool') {\n items[idx!] = { ...existing, result: { output: e.output, isError: e.isError }, durationMs: spanMs(existing.at, e.at) };\n } else {\n orphanResults.push(e.toolUseId);\n items.push({\n kind: 'tool',\n key: `tr-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n toolUseId: e.toolUseId,\n name: 'tool',\n input: null,\n result: { output: e.output, isError: e.isError },\n durationMs: null,\n });\n }\n break;\n }\n case 'usage':\n usage = e.usage;\n break;\n case 'compaction':\n // Deliberately NO flushPending: CLIs compact between model calls, and\n // flushing a streamed bubble here would leave it in the list when the\n // complete `assistant-message` arrives — the same reply twice.\n items.push({\n kind: 'compaction',\n key: `k-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n trigger: e.trigger,\n preTokens: e.preTokens,\n postTokens: e.postTokens,\n durationMs: e.durationMs,\n });\n break;\n case 'error':\n flushPending();\n items.push({ kind: 'error', key: `e-${e.seq}`, turnId: e.turnId, at: e.at, message: e.message, code: typeof e.code === 'string' && e.code ? e.code : null });\n break;\n case 'cancelled':\n flushPending();\n liveEffect = false;\n items.push({ kind: 'cancelled', key: `c-${e.seq}`, turnId: e.turnId, at: e.at });\n break;\n case 'turn-done':\n flushPending();\n liveEffect = false;\n items.push({ kind: 'turn-done', key: `td-${e.seq}`, turnId: e.turnId, at: e.at, ok: e.ok, durationMs: e.durationMs });\n break;\n case 'recovered':\n // Like compaction, no flush: recovery happens before the new native\n // session produces anything, never in the middle of a reply.\n items.push({ kind: 'recovered', key: `r-${e.seq}`, turnId: e.turnId, at: e.at, how: e.how, message: e.message });\n break;\n case 'history-truncated':\n items.push({ kind: 'truncated', key: `h-${e.seq}`, turnId: null, at: e.at, droppedBefore: e.droppedBefore });\n break;\n default:\n break;\n }\n }\n return { items, pending, liveEffect, usage, orphanResults, toolUseIds };\n}\n\nfunction finalizeSegment(key: string, build: SegmentBuild, streaming: boolean): TranscriptSegment {\n const p = build.pending;\n if (!p) return { key, items: build.items };\n return {\n key,\n items: [...build.items, { kind: 'assistant', key: p.key, turnId: p.turnId, at: p.at, text: p.text, streaming }],\n };\n}\n\n// `VerseEvent[]` (not readonly) is the published signature: callers type\n// their fixture arrays as `Parameters<typeof buildTranscript>[0]` and push.\nexport function buildTranscript(events: VerseEvent[], options: BuildTranscriptOptions = {}): Transcript {\n const { cache, thinkingStats: stats } = options;\n if (events.length === 0) return { items: [], live: false, usage: null, segments: [] };\n\n // Cut at every user-message: a new ask always opens a new turn, and the\n // derivation flushes its streamed text there, so nothing spans the cut.\n const starts: number[] = [0];\n for (let i = 1; i < events.length; i += 1) if (events[i]!.type === 'user-message') starts.push(i);\n\n const builds: Array<{ key: string; build: SegmentBuild; cached: CachedSegment | null }> = [];\n const seenKeys = new Set<string>();\n for (let s = 0; s < starts.length; s += 1) {\n const from = starts[s]!;\n const to = s + 1 < starts.length ? starts[s + 1]! : events.length;\n const firstSeq = events[from]!.seq;\n const lastSeq = events[to - 1]!.seq;\n const count = to - from;\n const key = `s-${firstSeq}`;\n seenKeys.add(key);\n const hit = cache?.segments.get(key);\n if (hit && hit.firstSeq === firstSeq && hit.lastSeq === lastSeq && hit.count === count) {\n builds.push({ key, build: hit.build, cached: hit });\n continue;\n }\n const build = buildSegment(events, from, to, stats);\n const entry: CachedSegment = { firstSeq, lastSeq, count, build, finalized: null };\n cache?.segments.set(key, entry);\n builds.push({ key, build, cached: entry });\n }\n if (cache) for (const key of [...cache.segments.keys()]) if (!seenKeys.has(key)) cache.segments.delete(key);\n\n // A tool-result whose tool-use sits in an EARLIER segment would have\n // updated that earlier card in the single-pass derivation. It never\n // happens in a real log (a result follows its call inside one turn); if it\n // does, derive the whole log in one pass rather than render it differently.\n if (builds.length > 1) {\n const earlier = new Set<string>();\n for (const b of builds) {\n if (b.build.orphanResults.some((id) => earlier.has(id))) return singlePass(events, stats);\n for (const id of b.build.toolUseIds) earlier.add(id);\n }\n }\n\n let live = false;\n let usage: VerseUsage | null = null;\n for (const b of builds) {\n if (b.build.liveEffect !== null) live = b.build.liveEffect;\n if (b.build.usage !== null) usage = b.build.usage;\n }\n\n const segments: TranscriptSegment[] = [];\n const items: TranscriptItem[] = [];\n for (let s = 0; s < builds.length; s += 1) {\n const b = builds[s]!;\n // Deltas still arriving for an open turn render as a streaming bubble;\n // every earlier segment's trailing text was flushed by the next ask.\n const streaming = s === builds.length - 1 ? live : false;\n let segment: TranscriptSegment;\n if (b.cached?.finalized && b.cached.finalized.streaming === streaming) {\n segment = b.cached.finalized.segment;\n } else {\n segment = finalizeSegment(b.key, b.build, streaming);\n if (b.cached) b.cached.finalized = { streaming, segment };\n }\n segments.push(segment);\n for (const item of segment.items) items.push(item);\n }\n return { items, live, usage, segments };\n}\n\nfunction singlePass(events: readonly VerseEvent[], stats: ReadonlyMap<number, VerseThinkingStat> | undefined): Transcript {\n const build = buildSegment(events, 0, events.length, stats);\n const live = build.liveEffect ?? false;\n const segment = finalizeSegment(`s-${events[0]!.seq}`, build, live);\n return { items: segment.items, live, usage: build.usage, segments: [segment] };\n}\n\n// ---------------------------------------------------------------------------\n// Render-time grouping\n// ---------------------------------------------------------------------------\n\nexport type ToolGroupMember = Extract<TranscriptItem, { kind: 'tool' | 'thinking' }>;\n\nexport interface ToolGroupItem {\n kind: 'toolGroup';\n key: string;\n turnId: string;\n at: string;\n items: ToolGroupMember[];\n /** Tool calls only (thinking blocks are not counted). */\n toolCount: number;\n /** \"Read ×6, Edit ×4\" — names in first-seen order. */\n summary: string;\n errorCount: number;\n /** A member is still waiting for its result. */\n pending: boolean;\n /** Wall time between the first and last member, when both have parseable timestamps. */\n spanMs: number | null;\n}\n\nexport type TranscriptRenderItem = TranscriptItem | ToolGroupItem;\n\n/**\n * Fold runs of consecutive tool calls from the same turn that hold two or\n * more calls into one `toolGroup`, so an agentic turn reads as \"N tool calls\"\n * with a single disclosure instead of a wall of cards. A single call (with\n * whatever reasoning surrounds it) stays as it is.\n * Pure over buildTranscript()'s output (the index-based tool-result pairing\n * there is untouched).\n *\n * Reasoning INTERLEAVED between tool calls folds with them (it explains the\n * next call). Reasoning that ENDS a run — the model's last thought before it\n * answers or before the next ask — is lifted out and rendered on its own, so\n * the part worth reading is never two disclosures deep. A run of reasoning\n * alone never folds.\n */\nexport function groupTranscriptItems(items: readonly TranscriptItem[]): TranscriptRenderItem[] {\n const out: TranscriptRenderItem[] = [];\n let run: ToolGroupMember[] = [];\n\n const flush = () => {\n if (run.length === 0) return;\n let end = run.length;\n while (end > 0 && run[end - 1]!.kind === 'thinking') end -= 1;\n const folded = run.slice(0, end);\n const trailing = run.slice(end);\n // Only a run with two or more CALLS is worth a disclosure: \"1 tool\" hiding\n // a single call plus the reasoning before it is a click for nothing.\n if (folded.filter((m) => m.kind === 'tool').length >= 2) out.push(makeToolGroup(folded));\n else for (const member of folded) out.push(member);\n for (const thought of trailing) out.push(thought);\n run = [];\n };\n\n for (const item of items) {\n if ((item.kind === 'tool' || item.kind === 'thinking') && (run.length === 0 || run[0]!.turnId === item.turnId)) {\n run.push(item);\n continue;\n }\n flush();\n if (item.kind === 'tool' || item.kind === 'thinking') run.push(item);\n else out.push(item);\n }\n flush();\n return out;\n}\n\nfunction makeToolGroup(members: ToolGroupMember[]): ToolGroupItem {\n const counts = new Map<string, number>();\n let errorCount = 0;\n let pending = false;\n for (const m of members) {\n if (m.kind !== 'tool') continue;\n counts.set(m.name, (counts.get(m.name) ?? 0) + 1);\n if (m.result === null) pending = true;\n else if (m.result.isError) errorCount += 1;\n }\n const toolCount = [...counts.values()].reduce((a, b) => a + b, 0);\n const summary = [...counts.entries()].map(([name, n]) => (n > 1 ? `${name} ×${n}` : name)).join(', ');\n const span = spanMs(members[0]!.at, members[members.length - 1]!.at);\n return {\n kind: 'toolGroup',\n key: `g-${members[0]!.key}`,\n turnId: members[0]!.turnId,\n at: members[0]!.at,\n items: members,\n toolCount,\n summary,\n errorCount,\n pending,\n spanMs: span,\n };\n}\n","/**\n * routes/verse/useVerseTranscript.ts — the React glue over the derived\n * transcript (verse-transcript.ts).\n *\n * Not in useVerseSession.ts because that module is on the chat first-paint\n * path (the Chat section opens the chat through it) while the transcript is\n * rendered only by lazy chunks (the workspace, the dock). Importing the\n * derivation from there would put it back in the first-paint critical JS.\n */\nimport { useSyncExternalStore } from 'react';\nimport { useSessionSubscription } from './useVerseSession.js';\nimport { getVerseTranscript, type Transcript } from './verse-transcript.js';\n\n/** The transcript of one chat, rebuilt only for the turn that changed. */\nexport function useVerseTranscript(sessionId: string | null): Transcript {\n const subscribe = useSessionSubscription(sessionId);\n return useSyncExternalStore(\n subscribe,\n () => getVerseTranscript(sessionId),\n () => getVerseTranscript(sessionId),\n );\n}\n"],"mappings":"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"}
|
package/dist/core/web/public/next/assets/{verse-icons-wOet9JZy.js → verse-icons-DndgEgKS.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e}from"./index-
|
|
2
|
-
//# sourceMappingURL=verse-icons-
|
|
1
|
+
import{n as e}from"./index-QesfXBsb.js";import{O as t,k as n}from"./VerseConsoleApp-BCY5uSok.js";import{a as r,b as i,g as a,i as o,l as s,v as c}from"./icons-0haWy6nh.js";var l=e(),u=s,d=i;function f(e){return(0,l.jsxs)(t,{...e,children:[(0,l.jsx)(`rect`,{x:`2.5`,y:`2.5`,width:`4.5`,height:`4.5`,rx:`1`}),(0,l.jsx)(`rect`,{x:`9`,y:`2.5`,width:`4.5`,height:`4.5`,rx:`1`}),(0,l.jsx)(`rect`,{x:`2.5`,y:`9`,width:`4.5`,height:`4.5`,rx:`1`}),(0,l.jsx)(`rect`,{x:`9`,y:`9`,width:`4.5`,height:`4.5`,rx:`1`})]})}var p={command:n.command,fleet:n.fleet,growth:n.growth,mind:n.mind,chat:n.chat,settings:d,apps:f,usage:u},m=c,h=a,g=o,_=r;function v(e){return(0,l.jsxs)(t,{...e,children:[(0,l.jsx)(`rect`,{x:`2.5`,y:`3`,width:`11`,height:`10`,rx:`1.5`}),(0,l.jsx)(`path`,{d:`M10 3v10`})]})}function y(e){return(0,l.jsxs)(t,{...e,children:[(0,l.jsx)(`rect`,{x:`2.5`,y:`3`,width:`11`,height:`10`,rx:`1.5`}),(0,l.jsx)(`path`,{d:`M6 3v10`})]})}function b(e){return(0,l.jsxs)(t,{width:`1em`,height:`1em`,style:{display:`inline-block`,verticalAlign:`-0.125em`},...e,children:[(0,l.jsx)(`path`,{d:`M13 3.5v5a2 2 0 0 1-2 2H3.5`}),(0,l.jsx)(`path`,{d:`M6 8 3.5 10.5 6 13`})]})}export{h as a,m as c,u as d,v as i,d as l,g as n,b as o,_ as r,p as s,f as t,y as u};
|
|
2
|
+
//# sourceMappingURL=verse-icons-DndgEgKS.js.map
|
package/dist/core/web/public/next/assets/{verse-icons-wOet9JZy.js.map → verse-icons-DndgEgKS.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verse-icons-
|
|
1
|
+
{"version":3,"file":"verse-icons-DndgEgKS.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/verse-icons.tsx"],"sourcesContent":["/**\n * routes/verse/verse-icons.tsx — the icons the shell rail and the chat chrome\n * use, under the names the Verse surfaces already import.\n *\n * Owner A's `components/primitives/icons.tsx` is now the drawing authority:\n * one geometry (16px box, 1.5px stroke, round caps/joins, currentColor), one\n * stroke weight, one accessibility convention. Everything below that has an\n * equivalent there is an ALIAS of it, so the rail and the inbox cannot drift\n * to two different chat glyphs.\n *\n * 3.10 adds the workbench surfaces (Command, Fleet, Growth, Mind), the gear\n * tray and Apps. They are drawn here, not in the shared set, because they\n * name Verse surfaces — a console page borrowing \"Fleet\" would be a lie.\n *\n * Five icons stay drawn here because the shared set has no equivalent and\n * they are Verse-specific chrome, not general console vocabulary:\n * `PanelIcon` / `SidebarIcon` (the two pane toggles, which must read as\n * mirror images of each other), `RailToggleIcon` (the rail's own expand /\n * collapse control, which has to read as the same family as those two),\n * `VerseMark` (the brand mark in the rail head, which is 32px and never takes\n * a color state; drawn in rail-icons.tsx with the other rail glyphs) and `McpIcon` (a plug — the shared set has no connector\n * glyph, and every candidate in it already means another rail section).\n */\nimport {\n IconChevronDown,\n IconChevronRight,\n IconCpu,\n IconGauge,\n IconInbox,\n IconMoon,\n IconPlus,\n IconSearch,\n IconSliders,\n IconTrash,\n type IconProps,\n} from '../../components/primitives/icons.js';\nimport { Icon, RAIL_ICON } from './rail-icons.js';\nimport type { ComponentType } from 'react';\nimport type { VerseSectionId } from './verse-ui-store.js';\n\nexport type { IconProps };\n// The rail's icons (the section glyphs, the gear, the mark) live in\n// rail-icons.tsx so the shell's first paint does not pull this module and the\n// shared icon set in with them; re-exported so the names stay importable here.\nexport {\n ChatIcon,\n CommandIcon,\n FleetIcon,\n GearIcon,\n GrowthIcon,\n MindIcon,\n NeedsYouIcon,\n RAIL_ICON,\n VerseMark,\n} from './rail-icons.js';\n\n// The gear tray's pages: drawn when the tray (or onboarding's tour) opens,\n// never by the rail itself, so not in rail-icons.tsx.\nexport const UsageIcon = IconGauge;\nexport const SettingsIcon = IconSliders;\n\n/** Apps & Accounts — a grid of tiles. */\nexport function AppsIcon(props: IconProps) {\n return (\n <Icon {...props}>\n <rect x=\"2.5\" y=\"2.5\" width=\"4.5\" height=\"4.5\" rx=\"1\" />\n <rect x=\"9\" y=\"2.5\" width=\"4.5\" height=\"4.5\" rx=\"1\" />\n <rect x=\"2.5\" y=\"9\" width=\"4.5\" height=\"4.5\" rx=\"1\" />\n <rect x=\"9\" y=\"9\" width=\"4.5\" height=\"4.5\" rx=\"1\" />\n </Icon>\n );\n}\n\n/** Every section's glyph: the rail's, plus the tray's. */\nexport const SECTION_ICON: Readonly<Record<VerseSectionId, ComponentType<IconProps>>> = {\n command: RAIL_ICON.command!,\n fleet: RAIL_ICON.fleet!,\n growth: RAIL_ICON.growth!,\n mind: RAIL_ICON.mind!,\n chat: RAIL_ICON.chat!,\n settings: SettingsIcon,\n apps: AppsIcon,\n usage: UsageIcon,\n};\n\n/**\n * Aliases onto the shared set. The names are the ones the Verse rail, sidebar\n * and composer already import — keeping them means this reconciliation\n * touched no call site.\n */\nexport const AutonomyIcon = IconCpu;\nexport const ApprovalsIcon = IconInbox;\nexport const SearchIcon = IconSearch;\nexport const PlusIcon = IconPlus;\nexport const TrashIcon = IconTrash;\nexport const ArrowDownIcon = IconChevronDown;\nexport const ChevronIcon = IconChevronRight;\n/** The rail's theme quick-toggle. One glyph for the control, not per-theme. */\nexport const ThemeIcon = IconMoon;\n\nexport function PanelIcon(props: IconProps) {\n return <Icon {...props}><rect x=\"2.5\" y=\"3\" width=\"11\" height=\"10\" rx=\"1.5\" /><path d=\"M10 3v10\" /></Icon>;\n}\n\nexport function SidebarIcon(props: IconProps) {\n return <Icon {...props}><rect x=\"2.5\" y=\"3\" width=\"11\" height=\"10\" rx=\"1.5\" /><path d=\"M6 3v10\" /></Icon>;\n}\n\n/**\n * The Return key (↩) as a key-legend glyph, 1em and inline so it sits in a\n * <kbd> like the letters around it. WHY drawn: of the fonts the console\n * serves, only the 230 KB full Plex face has U+21A9, so typing it into the\n * palette's or the drawer's key legend fetched that face each time one opened\n * (3.10 first-paint review; global.css scopes the full faces).\n */\nexport function ReturnKeyIcon(props: IconProps) {\n return (\n <Icon width=\"1em\" height=\"1em\" style={{ display: 'inline-block', verticalAlign: '-0.125em' }} {...props}>\n <path d=\"M13 3.5v5a2 2 0 0 1-2 2H3.5\" /><path d=\"M6 8 3.5 10.5 6 13\" />\n </Icon>\n );\n}\n\n/**\n * The rail's own expand/collapse control: the same framed panel as the two\n * pane toggles above, plus a chevron saying which way it is about to move.\n * ONE glyph that rotates rather than two drawings, so the control reads as a\n * single thing in two states — and so the state is carried by direction, the\n * one property a user can read without having memorised the other icon.\n */\nexport function RailToggleIcon({ expanded = false, ...props }: IconProps & { expanded?: boolean }) {\n return (\n <Icon {...props}>\n <rect x=\"2.5\" y=\"3\" width=\"11\" height=\"10\" rx=\"1.5\" />\n <path d=\"M6 3v10\" />\n {expanded ? <path d=\"M11.2 6.4 9.6 8l1.6 1.6\" /> : <path d=\"M9.4 6.4 11 8l-1.6 1.6\" />}\n </Icon>\n );\n}\n\n/**\n * MCP — a plug in a socket. Drawn here rather than aliased: the shared set's\n * nearest candidates (`IconCpu`, `IconSliders`, `IconKey`) are already the\n * Autonomy, Settings and credential glyphs, and two rail items that read as\n * the same picture is worse than one more 16px drawing.\n */\nexport function McpIcon(props: IconProps) {\n return (\n <Icon {...props}>\n <path d=\"M6 1.8v3.2M10 1.8v3.2\" />\n <path d=\"M3.8 5h8.4v2.6a4.2 4.2 0 0 1-4.2 4.2 4.2 4.2 0 0 1-4.2-4.2V5Z\" />\n <path d=\"M8 11.8v2.4\" />\n </Icon>\n );\n}\n"],"mappings":"sLA0Da,EAAY,EACZ,EAAe,EAG5B,SAAgB,EAAS,EAAkB,CACzC,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAM,GAAI,EAAV,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,MAAM,EAAE,MAAM,MAAM,MAAM,OAAO,MAAM,GAAG,GAAK,CAAA,GACvD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,IAAI,EAAE,MAAM,MAAM,MAAM,OAAO,MAAM,GAAG,GAAK,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,MAAM,EAAE,IAAI,MAAM,MAAM,OAAO,MAAM,GAAG,GAAK,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,IAAI,EAAE,IAAI,MAAM,MAAM,OAAO,MAAM,GAAG,GAAK,CAAA,CAC/C,GAEV,CAGA,IAAa,EAA2E,CACtF,QAAS,EAAU,QACnB,MAAO,EAAU,MACjB,OAAQ,EAAU,OAClB,KAAM,EAAU,KAChB,KAAM,EAAU,KAChB,SAAU,EACV,KAAM,EACN,MAAO,CACT,EASa,EAAa,EACb,EAAW,EAEX,EAAgB,EAChB,EAAc,EAI3B,SAAgB,EAAU,EAAkB,CAC1C,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAM,GAAI,EAAV,SAAA,EAAiB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,MAAM,EAAE,IAAI,MAAM,KAAK,OAAO,KAAK,GAAG,KAAO,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,UAAY,CAAA,CAAO,GAC3G,CAEA,SAAgB,EAAY,EAAkB,CAC5C,OAAO,EAAA,EAAA,KAAA,CAAC,EAAD,CAAM,GAAI,EAAV,SAAA,EAAiB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,MAAM,EAAE,IAAI,MAAM,KAAK,OAAO,KAAK,GAAG,KAAO,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,SAAW,CAAA,CAAO,GAC1G,CASA,SAAgB,EAAc,EAAkB,CAC9C,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAM,MAAM,MAAM,OAAO,MAAM,MAAO,CAAE,QAAS,eAAgB,cAAe,UAAW,EAAG,GAAI,EAAlG,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,6BAA+B,CAAA,GAAC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,oBAAsB,CAAA,CAClE,GAEV"}
|
package/dist/core/web/public/next/assets/{verse-model-CSzzdyu2.js → verse-model-MMySehjj.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{s as e}from"./index-BG177cPN.js";import{D as t}from"./VerseConsoleApp-DeuBEvAO.js";import{i as n,n as r,r as i,t as a}from"./compaction-point-VL9oegWS.js";var o=4e5,s=36e5,c={claude:25e3,codex:15e3,grok:2e4,local:15e3},l=25e3;function u(e){return e?c[e]??25e3:l}c.local+8e3+r+a;var d={"claude-opus-5.5":`claude-opus-5-5`};function f(e){return d[e]??e}function p(e,t){if(!e)return null;if(t===`expansive`)return e.expansive??null;let n=i(e.contextWindow);return n===null?null:{contextWindow:n,autoCompactAt:i(e.autoCompactAt??null)}}function m(e){let t=p(e,`standard`),n=p(e,`expansive`);return n?!t||(n.autoCompactAt??n.contextWindow)>(t.autoCompactAt??t.contextWindow):!1}function h(e,t){if(t===`expansive`)return null;let n=i(e?.contextWindow??null);return n!==null&&n>4e5&&m(e)?o:null}var g=.8,_=.95;function v(e){let t=Math.max(0,Math.floor(e.contextTokens||0)),n=i(e.contextWindow),r=i(e.autoCompactAt??null),a=n===null?null:t/n,o=r===null?null:t/r,s=o??a,c=e.contextTokensExact!==!1,l=`unknown`;return!c&&s!==null&&s>=1?l=`unknown`:n!==null&&t>n?l=`over`:s!==null&&(l=s>=.95?`danger`:s>=.8?`warn`:`ok`),{tokens:t,window:n,autoCompactAt:r,ofWindow:a,ofCompaction:o,untilCompaction:r===null?null:Math.max(0,r-t),tone:l,exact:c}}function y(e){let t=e.inputTokens+e.cacheReadTokens+e.cacheCreationTokens;return t>0?e.cacheReadTokens/t:null}function b(e){return Math.ceil(Math.max(0,e)/4)}function x(e,t,n=l){let r=p(t,`standard`);if(!r)return null;let i=Math.max(0,e)+Math.max(0,n),a=r.autoCompactAt??r.contextWindow;if(i<=a*.6)return`fits`;if(i<=a)return`tight`;let o=p(t,`expansive`);return o&&i<=(o.autoCompactAt??o.contextWindow)?`expansive`:`split`}function S(e){return e>=1e6?`${(e/1e6).toFixed(e%1e6==0?0:1)}M`:e>=1e3?`${Math.round(e/1e3)}k`:String(e)}function ee(e){let t=v(e.usage),n=[],r=`none`,i=e=>{(e===`urge`||e===`suggest`&&r===`none`)&&(r=e)};t.exact&&(t.tone===`over`?(i(`urge`),n.push(`Context (${S(t.tokens)}) is past the ${S(t.window??0)} window.`)):t.ofCompaction!==null&&t.ofCompaction>=.8&&(i(`suggest`),n.push(`About ${S(t.untilCompaction??0)} tokens left before the CLI auto-compacts.`)));let a=e.compactionCount??0;if(a>=2&&(i(`suggest`),n.push(`Compacted ${a} times — early turns now survive only as summaries.`)),e.lastActivityAt){let r=e.now-Date.parse(e.lastActivityAt);t.exact&&Number.isFinite(r)&&r>=36e5&&t.tokens>=1e5&&(i(`suggest`),n.push(`Idle over an hour: the prompt cache has likely expired, so the next turn re-reads ~${S(t.tokens)} tokens at full cost.`))}return{level:r,reasons:n}}function te(e){if((e.session.contextMode??`standard`)!==`standard`||!m(e.option))return{suggest:!1,reason:null};let t=e.session.compactionCount??0;return t>=2?{suggest:!0,reason:`This session has compacted ${t} times; expansive mode keeps more of it in view.`}:typeof e.workingSetTokens==`number`&&x(e.workingSetTokens,e.option)===`expansive`?{suggest:!0,reason:`The reachable code (~${S(e.workingSetTokens)} tokens) only fits the expansive budget.`}:{suggest:!1,reason:null}}function ne(e){return e===`claude`||e===`codex`}function re(e){let t=null;for(let n of e)(n.type===`usage`||n.type===`turn-done`||n.type===`cancelled`||n.type===`context`&&n.turnId!==null)&&typeof n.at==`string`&&(t===null||n.at>t)&&(t=n.at);return t}function C(e){return e==null||!Number.isFinite(e)?`—`:Math.round(e)<1e3?String(Math.round(e)):Math.round(e/1e3)<1e3?`${Math.round(e/1e3)}k`:`${(e/1e6).toFixed(1).replace(/\.0$/,``)}M`}var w=e({CODEX_EXPANSIVE_METERING_NOTE:()=>L,ENGINE_LABEL:()=>E,ENGINE_ORDER:()=>T,SEAT_CAPACITY_WORD:()=>B,WINDOW_SOURCE_TEXT:()=>F,firstRunnableModel:()=>R,formatContextWindow:()=>$,formatDuration:()=>K,formatElapsed:()=>G,formatRelative:()=>q,groupSeats:()=>U,groupSessions:()=>W,isAbsolutePath:()=>Z,isVerseEngine:()=>D,modelLabel:()=>j,modelOptionFor:()=>M,prettyJson:()=>X,projectName:()=>O,seatById:()=>k,seatCapacity:()=>H,seatLabel:()=>A,seatPillLabel:()=>Q,seatUnavailableReason:()=>z,seatWindowLabel:()=>V,sessionContextBudget:()=>P,summarizeToolInput:()=>J,truncate:()=>Y,windowSourceText:()=>I}),T=[`claude`,`codex`,`grok`,`local`],E={claude:`Claude`,codex:`Codex`,grok:`Grok`,local:`Local`};function D(e){return T.includes(e)}function O(e,t=[]){let n=t.find(t=>t.path===e);return n?n.name:e.split(/[\\/]/).filter(Boolean).at(-1)??e}function k(e,t){return e.find(e=>e.id===t)}function A(e,t){return k(e,t.seatId)?.label??E[t.engine]}function j(e,t){return k(e,t.seatId)?.models.find(e=>e.id===t.model)?.label??t.model}function M(e,t){let n=k(e,t.seatId);if(!n)return null;let r=n.models.find(e=>e.id===t.model);if(r)return r;let i=f(t.model);return n.models.find(e=>f(e.id)===i)??null}function N(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?e:null}function P(e,t){let r=t.usage,i=t.contextMode??`standard`,a=M(e,t),o={contextTokens:typeof r.contextTokens==`number`&&Number.isFinite(r.contextTokens)?Math.max(0,r.contextTokens):0,exact:r.contextTokensExact!==!1,mode:i,option:a},s=p(a,i),c=N(r.contextWindow);if(c!==null&&(t.engine===`local`||r.contextWindowSource===`runtime`)){let e=N(r.autoCompactAt??null)??n({engine:t.engine,runtimeWindow:c,budget:t.engine===`local`?null:s,autocompactWindow:t.engine===`claude`?h(a,i):null,maxOutputTokens:a?.maxOutputTokens??null}),l=t.engine===`local`?r.contextWindowSource??null:`runtime`;return{...o,contextWindow:c,autoCompactAt:e,source:l}}if(s)return{...o,contextWindow:s.contextWindow,autoCompactAt:s.autoCompactAt,source:a?.windowSource??`fallback`};if(c!==null)return{...o,contextWindow:c,autoCompactAt:N(r.autoCompactAt??null),source:r.contextWindowSource??null};let l=N(k(e,t.seatId)?.contextWindow??null);return{...o,contextWindow:l,autoCompactAt:null,source:l===null?null:`fallback`}}var F={runtime:`reported by the CLI on the last turn`,"provider-catalog":`from this seat's own model catalog`,"cli-catalog":`from the pinned CLI's built-in model table`,documented:`from the provider's published model table`,fallback:`a default estimate — the CLI has not reported the real window yet`};function I(e,t){return t===`local`?`${e===`runtime`?`measured from the local model server`:e===`fallback`?`a default estimate — the model server did not report one`:F[e]}; Verse passes this window to Claude Code for this chat`:F[e]}var L=`OpenAI reportedly also counts requests above 272k tokens at about 2× against plan limits, so a turn near the expansive limit may cost roughly twice that.`;function R(e){return e.models.find(e=>!e.unavailableReason)??null}function z(e){return e.health.state===`unavailable`?e.health.summary??`seat unavailable`:null}var B={ready:`usable`,tight:`tight`,blocked:`blocked`,unread:`no reading`},ie=85;function V(e){let t={five_hour:`5-hour window`,seven_day:`weekly window`,codex:`weekly window`};if(t[e])return t[e];let n=/^seven_day_(.+)$/.exec(e);return n?`weekly ${n[1].replace(/_/g,` `)} window`:`${e.replace(/_/g,` `)} window`}function H(e){let n=z(e);if(n!==null)return{cls:`blocked`,usedPercent:null,text:n};let r=e.health.windows.filter(e=>typeof e.usedPercent==`number`&&Number.isFinite(e.usedPercent));if(r.length===0)return{cls:`unread`,usedPercent:null,text:`no capacity reading`};let i=r.reduce((e,t)=>t.usedPercent>e.usedPercent?t:e),a=Math.max(0,Math.min(100,i.usedPercent)),o=V(i.id);return a>=100?{cls:`blocked`,usedPercent:null,text:`${o} limit reached`}:{cls:a>=ie?`tight`:`ready`,usedPercent:a,text:`${t(a)} of ${o} used`}}function U(e){return T.map(t=>({engine:t,seats:e.filter(e=>e.engine===t)})).filter(e=>e.seats.length>0)}function W(e,t,n=``){let r=n.trim().toLowerCase(),i=r?e.filter(e=>e.title.toLowerCase().includes(r)||e.projectPath.toLowerCase().includes(r)||e.model.toLowerCase().includes(r)||e.seatId.toLowerCase().includes(r)):[...e],a=new Map;for(let e of i){let t=a.get(e.projectPath)??[];t.push(e),a.set(e.projectPath,t)}let o=[];for(let[e,n]of a)n.sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt)),o.push({projectPath:e,name:O(e,t),enrolled:t.find(t=>t.path===e)?.enrolled??!1,sessions:n});return o.sort((e,t)=>t.sessions[0].updatedAt.localeCompare(e.sessions[0].updatedAt)),o}function G(e){if(!Number.isFinite(e)||e<0)return`0s`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);return n<60?`${n}m ${t%60}s`:`${Math.floor(n/60)}h ${n%60}m`}function K(e){return!Number.isFinite(e)||e<0?`—`:e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:G(e)}function q(e,t=Date.now()){let n=Date.parse(e);if(!Number.isFinite(n))return``;let r=Math.round((t-n)/1e3);if(r<0||r<60)return`now`;let i=Math.floor(r/60);if(i<60)return`${i}m`;let a=Math.floor(i/60);if(a<24)return`${a}h`;let o=Math.floor(a/24);return o<7?`${o}d`:new Date(n).toLocaleDateString([],{month:`short`,day:`numeric`})}function J(e){if(e==null)return``;if(typeof e==`string`)return Y(e,96);if(typeof e!=`object`)return Y(String(e),96);let t=e;for(let e of[`command`,`cmd`,`file_path`,`path`,`pattern`,`query`,`url`,`description`,`prompt`,`text`]){let n=t[e];if(typeof n==`string`&&n.trim())return Y(n.trim().replace(/\s+/g,` `),96)}let n=Object.keys(t);if(n.length===0)return``;let r=t[n[0]],i=typeof r==`string`?r:JSON.stringify(r);return Y(`${n[0]}: ${i??``}`.replace(/\s+/g,` `),96)}function Y(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function X(e){if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)??``}catch{return String(e)}}function Z(e){return/^(?:\/|~(?:\/|$)|[a-zA-Z]:[\\/]|\\\\)/.test(e)&&![...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)>=127&&e.charCodeAt(0)<=159)}function Q(e,t){let n=A(e,t),r=j(e,t);return!r||n.toLowerCase().includes(r.toLowerCase())?n:`${n} · ${r}`}function $(e){return e==null||!Number.isInteger(e)||e<1024||e%1024!=0?C(e):e<1048576?`${e/1024}k`:`${(e/1048576).toFixed(1).replace(/\.0$/,``)}M`}export{_ as A,m as B,P as C,C as D,I as E,ne as F,u as H,b as I,te as L,p as M,y as N,re as O,f as P,x as R,V as S,w as T,v as V,O as _,R as a,Q as b,G as c,W as d,Z as f,X as g,M as h,F as i,g as j,s as k,q as l,j as m,E as n,$ as o,D as p,B as r,K as s,L as t,U as u,k as v,J as w,z as x,H as y,ee as z};
|
|
2
|
-
//# sourceMappingURL=verse-model-
|
|
1
|
+
import{s as e}from"./index-QesfXBsb.js";import{D as t}from"./VerseConsoleApp-BCY5uSok.js";import{i as n,n as r,r as i,t as a}from"./compaction-point-VL9oegWS.js";var o=4e5,s=36e5,c={claude:25e3,codex:15e3,grok:2e4,local:15e3},l=25e3;function u(e){return e?c[e]??25e3:l}c.local+8e3+r+a;var d={"claude-opus-5.5":`claude-opus-5-5`};function f(e){return d[e]??e}function p(e,t){if(!e)return null;if(t===`expansive`)return e.expansive??null;let n=i(e.contextWindow);return n===null?null:{contextWindow:n,autoCompactAt:i(e.autoCompactAt??null)}}function m(e){let t=p(e,`standard`),n=p(e,`expansive`);return n?!t||(n.autoCompactAt??n.contextWindow)>(t.autoCompactAt??t.contextWindow):!1}function h(e,t){if(t===`expansive`)return null;let n=i(e?.contextWindow??null);return n!==null&&n>4e5&&m(e)?o:null}var g=.8,_=.95;function v(e){let t=Math.max(0,Math.floor(e.contextTokens||0)),n=i(e.contextWindow),r=i(e.autoCompactAt??null),a=n===null?null:t/n,o=r===null?null:t/r,s=o??a,c=e.contextTokensExact!==!1,l=`unknown`;return!c&&s!==null&&s>=1?l=`unknown`:n!==null&&t>n?l=`over`:s!==null&&(l=s>=.95?`danger`:s>=.8?`warn`:`ok`),{tokens:t,window:n,autoCompactAt:r,ofWindow:a,ofCompaction:o,untilCompaction:r===null?null:Math.max(0,r-t),tone:l,exact:c}}function y(e){let t=e.inputTokens+e.cacheReadTokens+e.cacheCreationTokens;return t>0?e.cacheReadTokens/t:null}function b(e){return Math.ceil(Math.max(0,e)/4)}function x(e,t,n=l){let r=p(t,`standard`);if(!r)return null;let i=Math.max(0,e)+Math.max(0,n),a=r.autoCompactAt??r.contextWindow;if(i<=a*.6)return`fits`;if(i<=a)return`tight`;let o=p(t,`expansive`);return o&&i<=(o.autoCompactAt??o.contextWindow)?`expansive`:`split`}function S(e){return e>=1e6?`${(e/1e6).toFixed(e%1e6==0?0:1)}M`:e>=1e3?`${Math.round(e/1e3)}k`:String(e)}function ee(e){let t=v(e.usage),n=[],r=`none`,i=e=>{(e===`urge`||e===`suggest`&&r===`none`)&&(r=e)};t.exact&&(t.tone===`over`?(i(`urge`),n.push(`Context (${S(t.tokens)}) is past the ${S(t.window??0)} window.`)):t.ofCompaction!==null&&t.ofCompaction>=.8&&(i(`suggest`),n.push(`About ${S(t.untilCompaction??0)} tokens left before the CLI auto-compacts.`)));let a=e.compactionCount??0;if(a>=2&&(i(`suggest`),n.push(`Compacted ${a} times — early turns now survive only as summaries.`)),e.lastActivityAt){let r=e.now-Date.parse(e.lastActivityAt);t.exact&&Number.isFinite(r)&&r>=36e5&&t.tokens>=1e5&&(i(`suggest`),n.push(`Idle over an hour: the prompt cache has likely expired, so the next turn re-reads ~${S(t.tokens)} tokens at full cost.`))}return{level:r,reasons:n}}function te(e){if((e.session.contextMode??`standard`)!==`standard`||!m(e.option))return{suggest:!1,reason:null};let t=e.session.compactionCount??0;return t>=2?{suggest:!0,reason:`This session has compacted ${t} times; expansive mode keeps more of it in view.`}:typeof e.workingSetTokens==`number`&&x(e.workingSetTokens,e.option)===`expansive`?{suggest:!0,reason:`The reachable code (~${S(e.workingSetTokens)} tokens) only fits the expansive budget.`}:{suggest:!1,reason:null}}function ne(e){return e===`claude`||e===`codex`}function re(e){let t=null;for(let n of e)(n.type===`usage`||n.type===`turn-done`||n.type===`cancelled`||n.type===`context`&&n.turnId!==null)&&typeof n.at==`string`&&(t===null||n.at>t)&&(t=n.at);return t}function C(e){return e==null||!Number.isFinite(e)?`—`:Math.round(e)<1e3?String(Math.round(e)):Math.round(e/1e3)<1e3?`${Math.round(e/1e3)}k`:`${(e/1e6).toFixed(1).replace(/\.0$/,``)}M`}var w=e({CODEX_EXPANSIVE_METERING_NOTE:()=>L,ENGINE_LABEL:()=>E,ENGINE_ORDER:()=>T,SEAT_CAPACITY_WORD:()=>B,WINDOW_SOURCE_TEXT:()=>F,firstRunnableModel:()=>R,formatContextWindow:()=>$,formatDuration:()=>K,formatElapsed:()=>G,formatRelative:()=>q,groupSeats:()=>U,groupSessions:()=>W,isAbsolutePath:()=>Z,isVerseEngine:()=>D,modelLabel:()=>j,modelOptionFor:()=>M,prettyJson:()=>X,projectName:()=>O,seatById:()=>k,seatCapacity:()=>H,seatLabel:()=>A,seatPillLabel:()=>Q,seatUnavailableReason:()=>z,seatWindowLabel:()=>V,sessionContextBudget:()=>P,summarizeToolInput:()=>J,truncate:()=>Y,windowSourceText:()=>I}),T=[`claude`,`codex`,`grok`,`local`],E={claude:`Claude`,codex:`Codex`,grok:`Grok`,local:`Local`};function D(e){return T.includes(e)}function O(e,t=[]){let n=t.find(t=>t.path===e);return n?n.name:e.split(/[\\/]/).filter(Boolean).at(-1)??e}function k(e,t){return e.find(e=>e.id===t)}function A(e,t){return k(e,t.seatId)?.label??E[t.engine]}function j(e,t){return k(e,t.seatId)?.models.find(e=>e.id===t.model)?.label??t.model}function M(e,t){let n=k(e,t.seatId);if(!n)return null;let r=n.models.find(e=>e.id===t.model);if(r)return r;let i=f(t.model);return n.models.find(e=>f(e.id)===i)??null}function N(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?e:null}function P(e,t){let r=t.usage,i=t.contextMode??`standard`,a=M(e,t),o={contextTokens:typeof r.contextTokens==`number`&&Number.isFinite(r.contextTokens)?Math.max(0,r.contextTokens):0,exact:r.contextTokensExact!==!1,mode:i,option:a},s=p(a,i),c=N(r.contextWindow);if(c!==null&&(t.engine===`local`||r.contextWindowSource===`runtime`)){let e=N(r.autoCompactAt??null)??n({engine:t.engine,runtimeWindow:c,budget:t.engine===`local`?null:s,autocompactWindow:t.engine===`claude`?h(a,i):null,maxOutputTokens:a?.maxOutputTokens??null}),l=t.engine===`local`?r.contextWindowSource??null:`runtime`;return{...o,contextWindow:c,autoCompactAt:e,source:l}}if(s)return{...o,contextWindow:s.contextWindow,autoCompactAt:s.autoCompactAt,source:a?.windowSource??`fallback`};if(c!==null)return{...o,contextWindow:c,autoCompactAt:N(r.autoCompactAt??null),source:r.contextWindowSource??null};let l=N(k(e,t.seatId)?.contextWindow??null);return{...o,contextWindow:l,autoCompactAt:null,source:l===null?null:`fallback`}}var F={runtime:`reported by the CLI on the last turn`,"provider-catalog":`from this seat's own model catalog`,"cli-catalog":`from the pinned CLI's built-in model table`,documented:`from the provider's published model table`,fallback:`a default estimate — the CLI has not reported the real window yet`};function I(e,t){return t===`local`?`${e===`runtime`?`measured from the local model server`:e===`fallback`?`a default estimate — the model server did not report one`:F[e]}; Verse passes this window to Claude Code for this chat`:F[e]}var L=`OpenAI reportedly also counts requests above 272k tokens at about 2× against plan limits, so a turn near the expansive limit may cost roughly twice that.`;function R(e){return e.models.find(e=>!e.unavailableReason)??null}function z(e){return e.health.state===`unavailable`?e.health.summary??`seat unavailable`:null}var B={ready:`usable`,tight:`tight`,blocked:`blocked`,unread:`no reading`},ie=85;function V(e){let t={five_hour:`5-hour window`,seven_day:`weekly window`,codex:`weekly window`};if(t[e])return t[e];let n=/^seven_day_(.+)$/.exec(e);return n?`weekly ${n[1].replace(/_/g,` `)} window`:`${e.replace(/_/g,` `)} window`}function H(e){let n=z(e);if(n!==null)return{cls:`blocked`,usedPercent:null,text:n};let r=e.health.windows.filter(e=>typeof e.usedPercent==`number`&&Number.isFinite(e.usedPercent));if(r.length===0)return{cls:`unread`,usedPercent:null,text:`no capacity reading`};let i=r.reduce((e,t)=>t.usedPercent>e.usedPercent?t:e),a=Math.max(0,Math.min(100,i.usedPercent)),o=V(i.id);return a>=100?{cls:`blocked`,usedPercent:null,text:`${o} limit reached`}:{cls:a>=ie?`tight`:`ready`,usedPercent:a,text:`${t(a)} of ${o} used`}}function U(e){return T.map(t=>({engine:t,seats:e.filter(e=>e.engine===t)})).filter(e=>e.seats.length>0)}function W(e,t,n=``){let r=n.trim().toLowerCase(),i=r?e.filter(e=>e.title.toLowerCase().includes(r)||e.projectPath.toLowerCase().includes(r)||e.model.toLowerCase().includes(r)||e.seatId.toLowerCase().includes(r)):[...e],a=new Map;for(let e of i){let t=a.get(e.projectPath)??[];t.push(e),a.set(e.projectPath,t)}let o=[];for(let[e,n]of a)n.sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt)),o.push({projectPath:e,name:O(e,t),enrolled:t.find(t=>t.path===e)?.enrolled??!1,sessions:n});return o.sort((e,t)=>t.sessions[0].updatedAt.localeCompare(e.sessions[0].updatedAt)),o}function G(e){if(!Number.isFinite(e)||e<0)return`0s`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);return n<60?`${n}m ${t%60}s`:`${Math.floor(n/60)}h ${n%60}m`}function K(e){return!Number.isFinite(e)||e<0?`—`:e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:G(e)}function q(e,t=Date.now()){let n=Date.parse(e);if(!Number.isFinite(n))return``;let r=Math.round((t-n)/1e3);if(r<0||r<60)return`now`;let i=Math.floor(r/60);if(i<60)return`${i}m`;let a=Math.floor(i/60);if(a<24)return`${a}h`;let o=Math.floor(a/24);return o<7?`${o}d`:new Date(n).toLocaleDateString([],{month:`short`,day:`numeric`})}function J(e){if(e==null)return``;if(typeof e==`string`)return Y(e,96);if(typeof e!=`object`)return Y(String(e),96);let t=e;for(let e of[`command`,`cmd`,`file_path`,`path`,`pattern`,`query`,`url`,`description`,`prompt`,`text`]){let n=t[e];if(typeof n==`string`&&n.trim())return Y(n.trim().replace(/\s+/g,` `),96)}let n=Object.keys(t);if(n.length===0)return``;let r=t[n[0]],i=typeof r==`string`?r:JSON.stringify(r);return Y(`${n[0]}: ${i??``}`.replace(/\s+/g,` `),96)}function Y(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function X(e){if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)??``}catch{return String(e)}}function Z(e){return/^(?:\/|~(?:\/|$)|[a-zA-Z]:[\\/]|\\\\)/.test(e)&&![...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)>=127&&e.charCodeAt(0)<=159)}function Q(e,t){let n=A(e,t),r=j(e,t);return!r||n.toLowerCase().includes(r.toLowerCase())?n:`${n} · ${r}`}function $(e){return e==null||!Number.isInteger(e)||e<1024||e%1024!=0?C(e):e<1048576?`${e/1024}k`:`${(e/1048576).toFixed(1).replace(/\.0$/,``)}M`}export{_ as A,m as B,P as C,C as D,I as E,ne as F,u as H,b as I,te as L,p as M,y as N,re as O,f as P,x as R,V as S,w as T,v as V,O as _,R as a,Q as b,G as c,W as d,Z as f,X as g,M as h,F as i,g as j,s as k,q as l,j as m,E as n,$ as o,D as p,B as r,K as s,L as t,U as u,k as v,J as w,z as x,H as y,ee as z};
|
|
2
|
+
//# sourceMappingURL=verse-model-MMySehjj.js.map
|