@ashlr/hub 3.12.0 → 3.14.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 +157 -0
- package/README.md +29 -16
- package/dist/authority-surface.json +274 -148
- package/dist/build-identity.json +2 -2
- package/dist/cli/authority.d.ts +145 -33
- package/dist/cli/authority.js +1292 -315
- package/dist/cli/authority.js.map +1 -1
- package/dist/cli/cloud.js +12 -3
- package/dist/cli/cloud.js.map +1 -1
- package/dist/cli/comms.d.ts +33 -19
- package/dist/cli/comms.js +128 -151
- package/dist/cli/comms.js.map +1 -1
- package/dist/cli/completions.js +1 -1
- package/dist/cli/completions.js.map +1 -1
- package/dist/cli/daemon.js +29 -0
- package/dist/cli/daemon.js.map +1 -1
- package/dist/cli/director.d.ts +8 -12
- package/dist/cli/director.js +17 -52
- package/dist/cli/director.js.map +1 -1
- package/dist/cli/fleet.js +4 -1
- package/dist/cli/fleet.js.map +1 -1
- package/dist/cli/help.js +1 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/leader.d.ts +27 -3
- package/dist/cli/leader.js +253 -4
- package/dist/cli/leader.js.map +1 -1
- package/dist/core/authority/protected-paths.js +11 -0
- package/dist/core/authority/protected-paths.js.map +1 -1
- package/dist/core/authority/resident.d.ts +101 -0
- package/dist/core/authority/resident.js +246 -0
- package/dist/core/authority/resident.js.map +1 -0
- package/dist/core/authority/server-enforcement.d.ts +110 -0
- package/dist/core/authority/server-enforcement.js +260 -0
- package/dist/core/authority/server-enforcement.js.map +1 -0
- package/dist/core/authority/standing-grant.d.ts +24 -4
- package/dist/core/authority/standing-grant.js +19 -3
- package/dist/core/authority/standing-grant.js.map +1 -1
- package/dist/core/authority/types.d.ts +43 -0
- package/dist/core/authority/types.js +6 -0
- package/dist/core/authority/types.js.map +1 -1
- package/dist/core/cloud/budget.js +11 -1
- package/dist/core/cloud/budget.js.map +1 -1
- package/dist/core/cloud/cloud-api.d.ts +25 -2
- package/dist/core/cloud/cloud-api.js +139 -5
- package/dist/core/cloud/cloud-api.js.map +1 -1
- package/dist/core/cloud/pr-actions.d.ts +93 -0
- package/dist/core/cloud/pr-actions.js +436 -0
- package/dist/core/cloud/pr-actions.js.map +1 -0
- package/dist/core/cloud/pr-preview.d.ts +128 -0
- package/dist/core/cloud/pr-preview.js +228 -0
- package/dist/core/cloud/pr-preview.js.map +1 -0
- package/dist/core/cloud/store.d.ts +2 -0
- package/dist/core/cloud/store.js +28 -0
- package/dist/core/cloud/store.js.map +1 -1
- package/dist/core/cloud/timeline-api.d.ts +24 -0
- package/dist/core/cloud/timeline-api.js +46 -0
- package/dist/core/cloud/timeline-api.js.map +1 -0
- package/dist/core/cloud/timeline-types.d.ts +62 -0
- package/dist/core/cloud/timeline-types.js +36 -0
- package/dist/core/cloud/timeline-types.js.map +1 -0
- package/dist/core/cloud/timeline.d.ts +102 -0
- package/dist/core/cloud/timeline.js +925 -0
- package/dist/core/cloud/timeline.js.map +1 -0
- package/dist/core/cloud/tracker.js +67 -0
- package/dist/core/cloud/tracker.js.map +1 -1
- package/dist/core/cloud/types.d.ts +38 -0
- package/dist/core/cloud/types.js +1 -1
- package/dist/core/cloud/types.js.map +1 -1
- package/dist/core/comms/change-digest.d.ts +130 -0
- package/dist/core/comms/change-digest.js +451 -0
- package/dist/core/comms/change-digest.js.map +1 -0
- package/dist/core/comms/director-prompt.d.ts +4 -5
- package/dist/core/comms/director-prompt.js +4 -71
- package/dist/core/comms/director-prompt.js.map +1 -1
- package/dist/core/comms/director.d.ts +24 -61
- package/dist/core/comms/director.js +29 -382
- package/dist/core/comms/director.js.map +1 -1
- package/dist/core/comms/dispatch.d.ts +37 -12
- package/dist/core/comms/dispatch.js +244 -177
- package/dist/core/comms/dispatch.js.map +1 -1
- package/dist/core/comms/elon-dialogue.d.ts +23 -15
- package/dist/core/comms/elon-dialogue.js +36 -307
- package/dist/core/comms/elon-dialogue.js.map +1 -1
- package/dist/core/comms/fleet-pulse.js +4 -7
- package/dist/core/comms/fleet-pulse.js.map +1 -1
- package/dist/core/comms/handlers.d.ts +10 -6
- package/dist/core/comms/handlers.js +14 -48
- package/dist/core/comms/handlers.js.map +1 -1
- package/dist/core/comms/migrations.d.ts +47 -0
- package/dist/core/comms/migrations.js +125 -0
- package/dist/core/comms/migrations.js.map +1 -0
- package/dist/core/comms/requests.d.ts +32 -5
- package/dist/core/comms/requests.js +101 -5
- package/dist/core/comms/requests.js.map +1 -1
- package/dist/core/comms/telegram-channel.d.ts +104 -0
- package/dist/core/comms/telegram-channel.js +622 -0
- package/dist/core/comms/telegram-channel.js.map +1 -0
- package/dist/core/comms/telegram-thread-map.d.ts +56 -0
- package/dist/core/comms/telegram-thread-map.js +144 -0
- package/dist/core/comms/telegram-thread-map.js.map +1 -0
- package/dist/core/daemon/capacity-publisher.d.ts +8 -1
- package/dist/core/daemon/capacity-publisher.js +40 -2
- package/dist/core/daemon/capacity-publisher.js.map +1 -1
- package/dist/core/daemon/loop.js +18 -4
- package/dist/core/daemon/loop.js.map +1 -1
- package/dist/core/daemon/service-install-authority.d.ts +10 -2
- package/dist/core/daemon/service-install-authority.js +14 -5
- package/dist/core/daemon/service-install-authority.js.map +1 -1
- package/dist/core/daemon/service.d.ts +15 -0
- package/dist/core/daemon/service.js +26 -0
- package/dist/core/daemon/service.js.map +1 -1
- package/dist/core/daemon/tick-deadline.d.ts +44 -0
- package/dist/core/daemon/tick-deadline.js +83 -0
- package/dist/core/daemon/tick-deadline.js.map +1 -0
- package/dist/core/daemon/tick-hooks.d.ts +7 -0
- package/dist/core/daemon/tick-hooks.js.map +1 -1
- package/dist/core/daemon/tick-progress.d.ts +39 -0
- package/dist/core/daemon/tick-progress.js +194 -0
- package/dist/core/daemon/tick-progress.js.map +1 -0
- package/dist/core/dashboard.js +3 -1
- package/dist/core/dashboard.js.map +1 -1
- package/dist/core/fleet/cloud-intake.d.ts +95 -0
- package/dist/core/fleet/cloud-intake.js +557 -0
- package/dist/core/fleet/cloud-intake.js.map +1 -0
- package/dist/core/fleet/dispatch-router.d.ts +13 -0
- package/dist/core/fleet/dispatch-router.js +32 -8
- package/dist/core/fleet/dispatch-router.js.map +1 -1
- package/dist/core/fleet/fleet-merge-state.d.ts +16 -0
- package/dist/core/fleet/fleet-merge-state.js.map +1 -1
- package/dist/core/fleet/host-merge.d.ts +14 -0
- package/dist/core/fleet/host-merge.js +24 -2
- package/dist/core/fleet/host-merge.js.map +1 -1
- package/dist/core/fleet/merge-gates.d.ts +21 -0
- package/dist/core/fleet/merge-gates.js +39 -5
- package/dist/core/fleet/merge-gates.js.map +1 -1
- package/dist/core/fleet/mirrors.d.ts +162 -6
- package/dist/core/fleet/mirrors.js +1051 -49
- package/dist/core/fleet/mirrors.js.map +1 -1
- package/dist/core/fleet/standing-merge-pass.d.ts +8 -0
- package/dist/core/fleet/standing-merge-pass.js +102 -1
- package/dist/core/fleet/standing-merge-pass.js.map +1 -1
- package/dist/core/fleet/status.d.ts +17 -0
- package/dist/core/fleet/status.js +22 -0
- package/dist/core/fleet/status.js.map +1 -1
- package/dist/core/fleet/tick-hooks-live.d.ts +10 -1
- package/dist/core/fleet/tick-hooks-live.js +57 -8
- package/dist/core/fleet/tick-hooks-live.js.map +1 -1
- package/dist/core/fleet/verify-check-run.d.ts +90 -0
- package/dist/core/fleet/verify-check-run.js +274 -0
- package/dist/core/fleet/verify-check-run.js.map +1 -0
- package/dist/core/git.d.ts +17 -0
- package/dist/core/git.js +124 -25
- package/dist/core/git.js.map +1 -1
- package/dist/core/goals/open-goals.d.ts +47 -0
- package/dist/core/goals/open-goals.js +33 -0
- package/dist/core/goals/open-goals.js.map +1 -0
- package/dist/core/inbox/merge.d.ts +5 -0
- package/dist/core/inbox/merge.js +58 -2
- package/dist/core/inbox/merge.js.map +1 -1
- package/dist/core/integrations/locus.d.ts +28 -0
- package/dist/core/integrations/locus.js +155 -30
- package/dist/core/integrations/locus.js.map +1 -1
- package/dist/core/integrations/telegram-format.d.ts +40 -0
- package/dist/core/integrations/telegram-format.js +123 -0
- package/dist/core/integrations/telegram-format.js.map +1 -0
- package/dist/core/integrations/telegram.d.ts +60 -4
- package/dist/core/integrations/telegram.js +161 -28
- package/dist/core/integrations/telegram.js.map +1 -1
- package/dist/core/mcp-registry.d.ts +12 -0
- package/dist/core/mcp-registry.js +70 -0
- package/dist/core/mcp-registry.js.map +1 -1
- package/dist/core/observability/rollup.d.ts +12 -10
- package/dist/core/observability/rollup.js +44 -17
- package/dist/core/observability/rollup.js.map +1 -1
- package/dist/core/resources/connection-monitor.d.ts +9 -0
- package/dist/core/resources/connection-monitor.js +19 -9
- package/dist/core/resources/connection-monitor.js.map +1 -1
- package/dist/core/resources/quota-refresh-lease.d.ts +17 -0
- package/dist/core/resources/quota-refresh-lease.js +34 -1
- package/dist/core/resources/quota-refresh-lease.js.map +1 -1
- package/dist/core/routing/budget-api.d.ts +18 -1
- package/dist/core/routing/budget-api.js +120 -10
- package/dist/core/routing/budget-api.js.map +1 -1
- package/dist/core/routing/budget-store.d.ts +22 -1
- package/dist/core/routing/budget-store.js +22 -8
- package/dist/core/routing/budget-store.js.map +1 -1
- package/dist/core/routing/readiness-types.d.ts +82 -0
- package/dist/core/routing/readiness-types.js +23 -0
- package/dist/core/routing/readiness-types.js.map +1 -0
- package/dist/core/routing/readiness.d.ts +103 -0
- package/dist/core/routing/readiness.js +480 -0
- package/dist/core/routing/readiness.js.map +1 -0
- package/dist/core/sandbox/confine.js +22 -1
- package/dist/core/sandbox/confine.js.map +1 -1
- package/dist/core/sandbox/policy.d.ts +23 -0
- package/dist/core/sandbox/policy.js +100 -0
- package/dist/core/sandbox/policy.js.map +1 -1
- package/dist/core/types.d.ts +13 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/universe/builtins/preparation/manifest.json +1 -1
- package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +1204 -939
- package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +1319 -1054
- package/dist/core/usage/frontier-usage.d.ts +20 -2
- package/dist/core/usage/frontier-usage.js +75 -17
- package/dist/core/usage/frontier-usage.js.map +1 -1
- package/dist/core/verse/account-health.js +9 -3
- package/dist/core/verse/account-health.js.map +1 -1
- package/dist/core/verse/accounts.d.ts +45 -0
- package/dist/core/verse/accounts.js +246 -17
- package/dist/core/verse/accounts.js.map +1 -1
- package/dist/core/verse/activity-api.d.ts +5 -1
- package/dist/core/verse/activity-api.js +62 -14
- package/dist/core/verse/activity-api.js.map +1 -1
- package/dist/core/verse/apps-api.js +23 -11
- package/dist/core/verse/apps-api.js.map +1 -1
- package/dist/core/verse/apps.d.ts +11 -9
- package/dist/core/verse/apps.js +2 -2
- package/dist/core/verse/apps.js.map +1 -1
- package/dist/core/verse/authority-api.d.ts +17 -3
- package/dist/core/verse/authority-api.js +122 -7
- package/dist/core/verse/authority-api.js.map +1 -1
- package/dist/core/verse/autonomy-ladder.d.ts +172 -0
- package/dist/core/verse/autonomy-ladder.js +251 -0
- package/dist/core/verse/autonomy-ladder.js.map +1 -0
- package/dist/core/verse/context-fit.js +7 -5
- package/dist/core/verse/context-fit.js.map +1 -1
- package/dist/core/verse/control-api.d.ts +23 -1
- package/dist/core/verse/control-api.js +117 -10
- package/dist/core/verse/control-api.js.map +1 -1
- package/dist/core/verse/fleet-live-api.js +13 -5
- package/dist/core/verse/fleet-live-api.js.map +1 -1
- package/dist/core/verse/folder-io.d.ts +50 -0
- package/dist/core/verse/folder-io.js +142 -0
- package/dist/core/verse/folder-io.js.map +1 -0
- package/dist/core/verse/git-api.js +5 -4
- package/dist/core/verse/git-api.js.map +1 -1
- package/dist/core/verse/git-ops.d.ts +10 -1
- package/dist/core/verse/git-ops.js +18 -2
- package/dist/core/verse/git-ops.js.map +1 -1
- package/dist/core/verse/github-api.d.ts +1 -1
- package/dist/core/verse/github-api.js +5 -4
- package/dist/core/verse/github-api.js.map +1 -1
- package/dist/core/verse/github-repo.js +118 -14
- package/dist/core/verse/github-repo.js.map +1 -1
- package/dist/core/verse/leader-api.d.ts +5 -4
- package/dist/core/verse/leader-api.js +237 -10
- package/dist/core/verse/leader-api.js.map +1 -1
- package/dist/core/verse/local-models.d.ts +10 -0
- package/dist/core/verse/local-models.js +10 -1
- package/dist/core/verse/local-models.js.map +1 -1
- package/dist/core/verse/login-path.d.ts +73 -0
- package/dist/core/verse/login-path.js +123 -14
- package/dist/core/verse/login-path.js.map +1 -1
- package/dist/core/verse/mcp-control-api.js +4 -4
- package/dist/core/verse/mcp-control-api.js.map +1 -1
- package/dist/core/verse/mcp-scope.d.ts +22 -0
- package/dist/core/verse/mcp-scope.js +41 -1
- package/dist/core/verse/mcp-scope.js.map +1 -1
- package/dist/core/verse/mcp-seat-view.d.ts +10 -0
- package/dist/core/verse/mcp-seat-view.js +30 -4
- package/dist/core/verse/mcp-seat-view.js.map +1 -1
- package/dist/core/verse/overnight-api.js +20 -2
- package/dist/core/verse/overnight-api.js.map +1 -1
- package/dist/core/verse/path-guard.d.ts +24 -0
- package/dist/core/verse/path-guard.js +91 -22
- package/dist/core/verse/path-guard.js.map +1 -1
- package/dist/core/verse/preview-api.js +22 -0
- package/dist/core/verse/preview-api.js.map +1 -1
- package/dist/core/verse/projects.d.ts +21 -0
- package/dist/core/verse/projects.js +82 -0
- package/dist/core/verse/projects.js.map +1 -1
- package/dist/core/verse/seat-readiness.d.ts +25 -0
- package/dist/core/verse/seat-readiness.js +43 -6
- package/dist/core/verse/seat-readiness.js.map +1 -1
- package/dist/core/verse/session-controls-api.js +5 -3
- package/dist/core/verse/session-controls-api.js.map +1 -1
- package/dist/core/verse/session-handoff.d.ts +26 -0
- package/dist/core/verse/session-handoff.js +90 -12
- package/dist/core/verse/session-handoff.js.map +1 -1
- package/dist/core/verse/terminal-api.js +7 -4
- package/dist/core/verse/terminal-api.js.map +1 -1
- package/dist/core/verse/terminal.js +9 -5
- package/dist/core/verse/terminal.js.map +1 -1
- package/dist/core/verse/verse-api.d.ts +3 -1
- package/dist/core/verse/verse-api.js +87 -27
- package/dist/core/verse/verse-api.js.map +1 -1
- package/dist/core/verse/workspaces.d.ts +51 -0
- package/dist/core/verse/workspaces.js +177 -47
- package/dist/core/verse/workspaces.js.map +1 -1
- package/dist/core/vision/leader-apply.d.ts +40 -0
- package/dist/core/vision/leader-apply.js +101 -30
- package/dist/core/vision/leader-apply.js.map +1 -1
- package/dist/core/vision/leader-cadence.d.ts +114 -0
- package/dist/core/vision/leader-cadence.js +127 -0
- package/dist/core/vision/leader-cadence.js.map +1 -0
- package/dist/core/vision/leader-goal-evidence.d.ts +25 -0
- package/dist/core/vision/leader-goal-evidence.js +36 -0
- package/dist/core/vision/leader-goal-evidence.js.map +1 -0
- package/dist/core/vision/leader-health.d.ts +53 -0
- package/dist/core/vision/leader-health.js +92 -0
- package/dist/core/vision/leader-health.js.map +1 -0
- package/dist/core/vision/leader-operator.d.ts +176 -0
- package/dist/core/vision/leader-operator.js +355 -0
- package/dist/core/vision/leader-operator.js.map +1 -0
- package/dist/core/vision/leader-run-chain.d.ts +41 -0
- package/dist/core/vision/leader-run-chain.js +54 -0
- package/dist/core/vision/leader-run-chain.js.map +1 -0
- package/dist/core/vision/leader-seat-plan.d.ts +68 -0
- package/dist/core/vision/leader-seat-plan.js +93 -0
- package/dist/core/vision/leader-seat-plan.js.map +1 -0
- package/dist/core/vision/leader-seat.d.ts +71 -5
- package/dist/core/vision/leader-seat.js +235 -33
- package/dist/core/vision/leader-seat.js.map +1 -1
- package/dist/core/vision/leader-thread-types.d.ts +104 -0
- package/dist/core/vision/leader-thread-types.js +9 -0
- package/dist/core/vision/leader-thread-types.js.map +1 -0
- package/dist/core/vision/leader-thread.d.ts +138 -0
- package/dist/core/vision/leader-thread.js +926 -0
- package/dist/core/vision/leader-thread.js.map +1 -0
- package/dist/core/vision/leader-types.d.ts +75 -1
- package/dist/core/vision/leader.d.ts +88 -18
- package/dist/core/vision/leader.js +269 -69
- package/dist/core/vision/leader.js.map +1 -1
- package/dist/core/web/public/next/assets/{ActionMenu-B4-39f2S.js → ActionMenu-CIiX2X8w.js} +2 -2
- package/dist/core/web/public/next/assets/{ActionMenu-B4-39f2S.js.map → ActionMenu-CIiX2X8w.js.map} +1 -1
- package/dist/core/web/public/next/assets/Advanced-DHsysoIL.js +2 -0
- package/dist/core/web/public/next/assets/{Advanced-B-LqYXvd.js.map → Advanced-DHsysoIL.js.map} +1 -1
- package/dist/core/web/public/next/assets/App-CMeAocmW.js +7 -0
- package/dist/core/web/public/next/assets/{App-E2zCDRxm.js.map → App-CMeAocmW.js.map} +1 -1
- package/dist/core/web/public/next/assets/AppsSection-DISYnMnc.js +2 -0
- package/dist/core/web/public/next/assets/{AppsSection-8wXPPhZb.js.map → AppsSection-DISYnMnc.js.map} +1 -1
- package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js +2 -0
- package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-CEPSZToP.js +3 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-CEPSZToP.js.map +1 -0
- package/dist/core/web/public/next/assets/AutonomyOffState-CmSSTHVe.css +1 -0
- package/dist/core/web/public/next/assets/AutonomySection-DWc3ciAD.js +2 -0
- package/dist/core/web/public/next/assets/{AutonomySection-B46igJKR.js.map → AutonomySection-DWc3ciAD.js.map} +1 -1
- package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js +2 -0
- package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js.map +1 -0
- package/dist/core/web/public/next/assets/{BranchBar-BRkrEQGs.js → BranchBar-BxhdiIpx.js} +2 -2
- package/dist/core/web/public/next/assets/{BranchBar-BRkrEQGs.js.map → BranchBar-BxhdiIpx.js.map} +1 -1
- package/dist/core/web/public/next/assets/BudgetControl-C-0KhjRS.js +2 -0
- package/dist/core/web/public/next/assets/BudgetControl-C-0KhjRS.js.map +1 -0
- package/dist/core/web/public/next/assets/{Button-BhO-WKPp.js → Button-D90dzI_o.js} +2 -2
- package/dist/core/web/public/next/assets/{Button-BhO-WKPp.js.map → Button-D90dzI_o.js.map} +1 -1
- package/dist/core/web/public/next/assets/{CapacityStrip-CkFz5vq2.js → CapacityStrip-qKDBC65C.js} +2 -2
- package/dist/core/web/public/next/assets/{CapacityStrip-CkFz5vq2.js.map → CapacityStrip-qKDBC65C.js.map} +1 -1
- package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js +2 -0
- package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js.map +1 -0
- package/dist/core/web/public/next/assets/ChartFrame-DyjmyV8N.css +1 -0
- package/dist/core/web/public/next/assets/ChatSection-DlT4QU6a.js +3 -0
- package/dist/core/web/public/next/assets/ChatSection-DlT4QU6a.js.map +1 -0
- package/dist/core/web/public/next/assets/{CloudBudgetForm-Bd91iStN.js → CloudBudgetForm-BrNun_Yu.js} +2 -2
- package/dist/core/web/public/next/assets/{CloudBudgetForm-Bd91iStN.js.map → CloudBudgetForm-BrNun_Yu.js.map} +1 -1
- package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js +2 -0
- package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js.map +1 -0
- package/dist/core/web/public/next/assets/CommandSection-B0xuU-yZ.css +1 -0
- package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js +3 -0
- package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js.map +1 -0
- package/dist/core/web/public/next/assets/{ConfirmDialog-Bv4hdK2T.js → ConfirmDialog-BR4nZQ2D.js} +2 -2
- package/dist/core/web/public/next/assets/{ConfirmDialog-Bv4hdK2T.js.map → ConfirmDialog-BR4nZQ2D.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DeleteChatDialog-CH1Ix8Eh.js → DeleteChatDialog-BCfP12GH.js} +2 -2
- package/dist/core/web/public/next/assets/{DeleteChatDialog-CH1Ix8Eh.js.map → DeleteChatDialog-BCfP12GH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Dialog-BSsIFNqD.js → Dialog-D3msQlCj.js} +2 -2
- package/dist/core/web/public/next/assets/{Dialog-BSsIFNqD.js.map → Dialog-D3msQlCj.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DiffPane-BpNuJmth.js → DiffPane-Ix6hvXlY.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffPane-BpNuJmth.js.map → DiffPane-Ix6hvXlY.js.map} +1 -1
- package/dist/core/web/public/next/assets/{DiffViewer-CJarUvs0.js → DiffViewer-C4WKsCIe.js} +2 -2
- package/dist/core/web/public/next/assets/{DiffViewer-CJarUvs0.js.map → DiffViewer-C4WKsCIe.js.map} +1 -1
- package/dist/core/web/public/next/assets/DockHost-aWP7liri.js +2 -0
- package/dist/core/web/public/next/assets/{DockHost-DW9q0NdR.js.map → DockHost-aWP7liri.js.map} +1 -1
- package/dist/core/web/public/next/assets/{EmptyState-DPrd2aak.js → EmptyState-D2IRy3Cg.js} +2 -2
- package/dist/core/web/public/next/assets/{EmptyState-DPrd2aak.js.map → EmptyState-D2IRy3Cg.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Epistemic-D7MxSmED.js → Epistemic-DMr18muX.js} +2 -2
- package/dist/core/web/public/next/assets/{Epistemic-D7MxSmED.js.map → Epistemic-DMr18muX.js.map} +1 -1
- package/dist/core/web/public/next/assets/EvidenceTimeline-DXmmz6Fi.js +2 -0
- package/dist/core/web/public/next/assets/EvidenceTimeline-DXmmz6Fi.js.map +1 -0
- package/dist/core/web/public/next/assets/EvidenceTimeline-PBDAiSuG.css +1 -0
- package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js +3 -0
- package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js.map +1 -0
- package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js +2 -0
- package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js.map +1 -0
- package/dist/core/web/public/next/assets/{GearTray-CIPtzeIx.js → GearTray-Dt-ee32-.js} +2 -2
- package/dist/core/web/public/next/assets/{GearTray-CIPtzeIx.js.map → GearTray-Dt-ee32-.js.map} +1 -1
- package/dist/core/web/public/next/assets/GrowthSection-P9EUfGeA.js +2 -0
- package/dist/core/web/public/next/assets/{GrowthSection-iiQg6wvK.js.map → GrowthSection-P9EUfGeA.js.map} +1 -1
- package/dist/core/web/public/next/assets/{HandoffDialog-DrQ6ofuy.js → HandoffDialog-CLJQLe7M.js} +2 -2
- package/dist/core/web/public/next/assets/{HandoffDialog-DrQ6ofuy.js.map → HandoffDialog-CLJQLe7M.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Input-C0MQxEM6.js → Input-D_KRJA9V.js} +2 -2
- package/dist/core/web/public/next/assets/{Input-C0MQxEM6.js.map → Input-D_KRJA9V.js.map} +1 -1
- package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js +2 -0
- package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderCard-DNsbLwY3.css +1 -0
- package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js +2 -0
- package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js.map +1 -0
- package/dist/core/web/public/next/assets/LeaderConversation-DPHUTq6W.css +1 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js +2 -0
- package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js.map +1 -0
- package/dist/core/web/public/next/assets/McpSection-DGbRcyv8.js +2 -0
- package/dist/core/web/public/next/assets/{McpSection-BRuCcTjT.js.map → McpSection-DGbRcyv8.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdown-bRvD5nSc.js → MessageMarkdown-DFvk06qG.js} +3 -3
- package/dist/core/web/public/next/assets/{MessageMarkdown-bRvD5nSc.js.map → MessageMarkdown-DFvk06qG.js.map} +1 -1
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-FjjkPKA2.js → MessageMarkdownRenderer-BAv4oEUf.js} +2 -2
- package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-FjjkPKA2.js.map → MessageMarkdownRenderer-BAv4oEUf.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Meter-CFNLpwA-.js → Meter-CMj-VafN.js} +2 -2
- package/dist/core/web/public/next/assets/{Meter-CFNLpwA-.js.map → Meter-CMj-VafN.js.map} +1 -1
- package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js +3 -0
- package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js.map +1 -0
- package/dist/core/web/public/next/assets/{MutationTokenDialog-T7gv3a9r.js → MutationTokenDialog-DbnO8aYi.js} +2 -2
- package/dist/core/web/public/next/assets/{MutationTokenDialog-T7gv3a9r.js.map → MutationTokenDialog-DbnO8aYi.js.map} +1 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js +3 -0
- package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js.map +1 -0
- package/dist/core/web/public/next/assets/NeedsYouList-CCsijdWt.js +2 -0
- package/dist/core/web/public/next/assets/{NeedsYouList-BgH8ezqf.js.map → NeedsYouList-CCsijdWt.js.map} +1 -1
- package/dist/core/web/public/next/assets/NeedsYouList-CH6Mq-E_.css +1 -0
- package/dist/core/web/public/next/assets/NewChatDialog-BlCHtOIr.js +3 -0
- package/dist/core/web/public/next/assets/{NewChatDialog-Db5Xjrk8.js.map → NewChatDialog-BlCHtOIr.js.map} +1 -1
- package/dist/core/web/public/next/assets/OnboardingFlow-Cy9BA9eR.js +3 -0
- package/dist/core/web/public/next/assets/OnboardingFlow-Cy9BA9eR.js.map +1 -0
- package/dist/core/web/public/next/assets/OnboardingGate-BXpNFoLt.js +3 -0
- package/dist/core/web/public/next/assets/{OnboardingGate-C4VXn7BJ.js.map → OnboardingGate-BXpNFoLt.js.map} +1 -1
- package/dist/core/web/public/next/assets/PreviewPane-COid5A0f.js +2 -0
- package/dist/core/web/public/next/assets/{PreviewPane-BPBbcROb.js.map → PreviewPane-COid5A0f.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ProviderLogo-CT2cSfkg.js → ProviderLogo-Cq-CYIwT.js} +2 -2
- package/dist/core/web/public/next/assets/{ProviderLogo-CT2cSfkg.js.map → ProviderLogo-Cq-CYIwT.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RailStatus-Vgl0GYtd.js → RailStatus-Co5UB6We.js} +2 -2
- package/dist/core/web/public/next/assets/{RailStatus-Vgl0GYtd.js.map → RailStatus-Co5UB6We.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RefreshIndicator-CSyqpY_q.js → RefreshIndicator-DO9ibnSq.js} +2 -2
- package/dist/core/web/public/next/assets/{RefreshIndicator-CSyqpY_q.js.map → RefreshIndicator-DO9ibnSq.js.map} +1 -1
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-Dr2WRgkq.js +7 -0
- package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-BX2nkdmZ.js.map → ResourcePoolConsoleApp-Dr2WRgkq.js.map} +1 -1
- package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js +3 -0
- package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js +2 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js.map +1 -0
- package/dist/core/web/public/next/assets/ResourcesDrawer-DrGoO8KG.css +1 -0
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-BaC7YVzR.js → RouteErrorBoundary-SkNhhUbt.js} +2 -2
- package/dist/core/web/public/next/assets/{RouteErrorBoundary-BaC7YVzR.js.map → RouteErrorBoundary-SkNhhUbt.js.map} +1 -1
- package/dist/core/web/public/next/assets/{RunInCloudAction-D5PDHJPE.js → RunInCloudAction-BXPlZwJQ.js} +2 -2
- package/dist/core/web/public/next/assets/{RunInCloudAction-D5PDHJPE.js.map → RunInCloudAction-BXPlZwJQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SeatSelector-Cg75LInq.js → SeatSelector-J5R3zDkB.js} +3 -3
- package/dist/core/web/public/next/assets/{SeatSelector-Cg75LInq.js.map → SeatSelector-J5R3zDkB.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Segmented-CametjLt.js → Segmented-CGh_-tBb.js} +2 -2
- package/dist/core/web/public/next/assets/{Segmented-CametjLt.js.map → Segmented-CGh_-tBb.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Select-De52fghU.js → Select-CWnmUzs3.js} +2 -2
- package/dist/core/web/public/next/assets/{Select-De52fghU.js.map → Select-CWnmUzs3.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionGate-CzlcNq3O.js → SessionGate-sp4KsnUo.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionGate-CzlcNq3O.js.map → SessionGate-sp4KsnUo.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionInsightChip-Bk_Owa7u.js → SessionInsightChip-DLFAzdbi.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionInsightChip-Bk_Owa7u.js.map → SessionInsightChip-DLFAzdbi.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SessionSearch-C6C8DHN8.js → SessionSearch-DbFjwR1h.js} +2 -2
- package/dist/core/web/public/next/assets/{SessionSearch-C6C8DHN8.js.map → SessionSearch-DbFjwR1h.js.map} +1 -1
- package/dist/core/web/public/next/assets/{SettingsSection-mI9wQYZg.js → SettingsSection-Ch23msJ5.js} +2 -2
- package/dist/core/web/public/next/assets/SettingsSection-Ch23msJ5.js.map +1 -0
- package/dist/core/web/public/next/assets/SetupChecklist-Bd76MBAR.js +2 -0
- package/dist/core/web/public/next/assets/SetupChecklist-Bd76MBAR.js.map +1 -0
- package/dist/core/web/public/next/assets/SetupChecklist-BhZpFLsj.css +1 -0
- package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js +3 -0
- package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js.map +1 -0
- package/dist/core/web/public/next/assets/{Sheet-CJhK9Dqv.js → Sheet-BZ2AG4Eo.js} +2 -2
- package/dist/core/web/public/next/assets/{Sheet-CJhK9Dqv.js.map → Sheet-BZ2AG4Eo.js.map} +1 -1
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-DDW-i9Fc.js → ShortcutsOverlay-C8n8y3zf.js} +2 -2
- package/dist/core/web/public/next/assets/{ShortcutsOverlay-DDW-i9Fc.js.map → ShortcutsOverlay-C8n8y3zf.js.map} +1 -1
- package/dist/core/web/public/next/assets/Sidebar-DN--cPYN.js +3 -0
- package/dist/core/web/public/next/assets/Sidebar-DN--cPYN.js.map +1 -0
- package/dist/core/web/public/next/assets/{Slider-Bwd9HfXl.js → Slider-KVoJLDD6.js} +2 -2
- package/dist/core/web/public/next/assets/{Slider-Bwd9HfXl.js.map → Slider-KVoJLDD6.js.map} +1 -1
- package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js +2 -0
- package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js.map +1 -0
- package/dist/core/web/public/next/assets/StatTile-CNCqDoPO.css +1 -0
- package/dist/core/web/public/next/assets/{StatusBadge-DHKRtttH.js → StatusBadge-CXsYqmdU.js} +2 -2
- package/dist/core/web/public/next/assets/{StatusBadge-DHKRtttH.js.map → StatusBadge-CXsYqmdU.js.map} +1 -1
- package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js +2 -0
- package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js.map +1 -0
- package/dist/core/web/public/next/assets/{Surface-D--LXgQm.js → Surface-BfDmQcKe.js} +2 -2
- package/dist/core/web/public/next/assets/{Surface-D--LXgQm.js.map → Surface-BfDmQcKe.js.map} +1 -1
- package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js +2 -0
- package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js.map +1 -0
- package/dist/core/web/public/next/assets/Swimlane-Bf4Rjoy9.css +1 -0
- package/dist/core/web/public/next/assets/{Switch-PMixU6b0.js → Switch-9NtO_6Lj.js} +2 -2
- package/dist/core/web/public/next/assets/{Switch-PMixU6b0.js.map → Switch-9NtO_6Lj.js.map} +1 -1
- package/dist/core/web/public/next/assets/{Tag-fordBsrJ.js → Tag-DscCRFcN.js} +2 -2
- package/dist/core/web/public/next/assets/{Tag-fordBsrJ.js.map → Tag-DscCRFcN.js.map} +1 -1
- package/dist/core/web/public/next/assets/{TerminalPane-BSnGdUuF.js → TerminalPane-B668-DJW.js} +5 -5
- package/dist/core/web/public/next/assets/{TerminalPane-BSnGdUuF.js.map → TerminalPane-B668-DJW.js.map} +1 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-BUV_brY7.js +2 -0
- package/dist/core/web/public/next/assets/{UniverseConsoleApp-DtXFhAhw.js.map → UniverseConsoleApp-BUV_brY7.js.map} +1 -1
- package/dist/core/web/public/next/assets/{UniverseView-sWm3pnTW.js → UniverseView-DG70zH0W.js} +4 -4
- package/dist/core/web/public/next/assets/{UniverseView-sWm3pnTW.js.map → UniverseView-DG70zH0W.js.map} +1 -1
- package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js +3 -0
- package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js.map +1 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js +3 -0
- package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js.map +1 -0
- package/dist/core/web/public/next/assets/Workspace-D1nP9BhD.js +10 -0
- package/dist/core/web/public/next/assets/{Workspace-BQSZFSeO.js.map → Workspace-D1nP9BhD.js.map} +1 -1
- package/dist/core/web/public/next/assets/actions-CY-PjpGc.js +2 -0
- package/dist/core/web/public/next/assets/{actions-Ci6I4C0l.js.map → actions-CY-PjpGc.js.map} +1 -1
- package/dist/core/web/public/next/assets/actions-DkWhhWIg.css +1 -0
- package/dist/core/web/public/next/assets/{apps-model-DlwnfqwJ.js → apps-model-Du02KhAf.js} +2 -2
- package/dist/core/web/public/next/assets/{apps-model-DlwnfqwJ.js.map → apps-model-Du02KhAf.js.map} +1 -1
- package/dist/core/web/public/next/assets/{authority-model-BFuPezSo.js → authority-model-79SeuKlJ.js} +2 -2
- package/dist/core/web/public/next/assets/{authority-model-BFuPezSo.js.map → authority-model-79SeuKlJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/autonomy-ladder-BGWmZzP7.css +1 -0
- package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js +2 -0
- package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js.map +1 -0
- package/dist/core/web/public/next/assets/budget-queries-D8QV5XtH.js +2 -0
- package/dist/core/web/public/next/assets/{budget-queries-DsAjH8ac.js.map → budget-queries-D8QV5XtH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{capacity-strip-model-Dn1cNOhz.js → capacity-strip-model-BwZ1ZbkU.js} +2 -2
- package/dist/core/web/public/next/assets/{capacity-strip-model-Dn1cNOhz.js.map → capacity-strip-model-BwZ1ZbkU.js.map} +1 -1
- package/dist/core/web/public/next/assets/charts-BZ50mZD_.js +2 -0
- package/dist/core/web/public/next/assets/charts-BZ50mZD_.js.map +1 -0
- package/dist/core/web/public/next/assets/charts-ClCB18la.css +1 -0
- package/dist/core/web/public/next/assets/cloud-model-BDivRMqv.js +2 -0
- package/dist/core/web/public/next/assets/{cloud-model-CX407gPY.js.map → cloud-model-BDivRMqv.js.map} +1 -1
- package/dist/core/web/public/next/assets/{cloud-queries-QAhpExlz.js → cloud-queries-BPQQ5_pJ.js} +2 -2
- package/dist/core/web/public/next/assets/{cloud-queries-QAhpExlz.js.map → cloud-queries-BPQQ5_pJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js → colors-DvK0wMHH.js} +2 -2
- package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js.map → colors-DvK0wMHH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{command-catalog-CF0cQQac.js → command-catalog-BIntSa9l.js} +2 -2
- package/dist/core/web/public/next/assets/command-catalog-BIntSa9l.js.map +1 -0
- package/dist/core/web/public/next/assets/{context-model-Co4wh3SM.js → context-model-Br8t9jgG.js} +2 -2
- package/dist/core/web/public/next/assets/{context-model-Co4wh3SM.js.map → context-model-Br8t9jgG.js.map} +1 -1
- package/dist/core/web/public/next/assets/{context-model-DV1zCfAm.js → context-model-CokrgEUq.js} +3 -3
- package/dist/core/web/public/next/assets/{context-model-DV1zCfAm.js.map → context-model-CokrgEUq.js.map} +1 -1
- package/dist/core/web/public/next/assets/context-queries-eL3caKVG.js +2 -0
- package/dist/core/web/public/next/assets/{context-queries-CktFQqSS.js.map → context-queries-eL3caKVG.js.map} +1 -1
- package/dist/core/web/public/next/assets/{control-queries-DAvlh_YM.js → control-queries-B9K-wmcB.js} +2 -2
- package/dist/core/web/public/next/assets/{control-queries-DAvlh_YM.js.map → control-queries-B9K-wmcB.js.map} +1 -1
- package/dist/core/web/public/next/assets/copy-setup-XMgCC5f8.js +2 -0
- package/dist/core/web/public/next/assets/copy-setup-XMgCC5f8.js.map +1 -0
- package/dist/core/web/public/next/assets/{dock-icons-BFuBbqJl.js → dock-icons-BJ6ZqB2t.js} +2 -2
- package/dist/core/web/public/next/assets/{dock-icons-BFuBbqJl.js.map → dock-icons-BJ6ZqB2t.js.map} +1 -1
- package/dist/core/web/public/next/assets/{fleet-model-Dfd5JyLR.js → fleet-model-BvDR3gjp.js} +2 -2
- package/dist/core/web/public/next/assets/{fleet-model-Dfd5JyLR.js.map → fleet-model-BvDR3gjp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{fleet-queries-RtMTd5rR.js → fleet-queries-W2UFVMZJ.js} +2 -2
- package/dist/core/web/public/next/assets/{fleet-queries-RtMTd5rR.js.map → fleet-queries-W2UFVMZJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{focus-trap-BdrbWfC4.js → focus-trap-CtI1SlMX.js} +2 -2
- package/dist/core/web/public/next/assets/{focus-trap-BdrbWfC4.js.map → focus-trap-CtI1SlMX.js.map} +1 -1
- package/dist/core/web/public/next/assets/format-CH4g_sl1.js +2 -0
- package/dist/core/web/public/next/assets/format-CH4g_sl1.js.map +1 -0
- package/dist/core/web/public/next/assets/{format-DKrNjdwD.js → format-D7nBg2bn.js} +2 -2
- package/dist/core/web/public/next/assets/{format-DKrNjdwD.js.map → format-D7nBg2bn.js.map} +1 -1
- package/dist/core/web/public/next/assets/{git-model-_BnI_Ogh.js → git-model-Dnkd1TnK.js} +2 -2
- package/dist/core/web/public/next/assets/{git-model-_BnI_Ogh.js.map → git-model-Dnkd1TnK.js.map} +1 -1
- package/dist/core/web/public/next/assets/global-CMNW_dqn.js +2 -0
- package/dist/core/web/public/next/assets/{global-CNNGMril.js.map → global-CMNW_dqn.js.map} +1 -1
- package/dist/core/web/public/next/assets/guarded-runners-YeAc9wLQ.js +2 -0
- package/dist/core/web/public/next/assets/{guarded-runners-DPh2d32e.js.map → guarded-runners-YeAc9wLQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{icons-0haWy6nh.js → icons-D1sYbCTQ.js} +2 -2
- package/dist/core/web/public/next/assets/{icons-0haWy6nh.js.map → icons-D1sYbCTQ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{index-QesfXBsb.js → index-DZ-UQ7v8.js} +3 -3
- package/dist/core/web/public/next/assets/{index-QesfXBsb.js.map → index-DZ-UQ7v8.js.map} +1 -1
- package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js +2 -0
- package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js.map +1 -0
- package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js +2 -0
- package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js.map +1 -0
- package/dist/core/web/public/next/assets/{live-model-De-q0ZFK.js → live-model-D_32RAOR.js} +2 -2
- package/dist/core/web/public/next/assets/live-model-D_32RAOR.js.map +1 -0
- package/dist/core/web/public/next/assets/{mind.module-BrK2nFOL.js → mind.module-7hA92hRg.js} +2 -2
- package/dist/core/web/public/next/assets/{mind.module-BrK2nFOL.js.map → mind.module-7hA92hRg.js.map} +1 -1
- package/dist/core/web/public/next/assets/mutations-DQPbFdRJ.js +2 -0
- package/dist/core/web/public/next/assets/{mutations-DTCtKCn_.js.map → mutations-DQPbFdRJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{nav-KmGX0CVz.js → nav-0dOYe2rJ.js} +2 -2
- package/dist/core/web/public/next/assets/{nav-KmGX0CVz.js.map → nav-0dOYe2rJ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{overnight-queries-mlO0xzsr.js → overnight-queries-C4wOnFtE.js} +2 -2
- package/dist/core/web/public/next/assets/{overnight-queries-mlO0xzsr.js.map → overnight-queries-C4wOnFtE.js.map} +1 -1
- package/dist/core/web/public/next/assets/primitives-2A5Eq8FQ.js +1 -0
- package/dist/core/web/public/next/assets/{queries-CyBE8nsW.js → queries-BTXWdZzU.js} +2 -2
- package/dist/core/web/public/next/assets/{queries-CyBE8nsW.js.map → queries-BTXWdZzU.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reasoning-pref-CaoA4_Vl.js → reasoning-pref-Ca6lN6x_.js} +2 -2
- package/dist/core/web/public/next/assets/{reasoning-pref-CaoA4_Vl.js.map → reasoning-pref-Ca6lN6x_.js.map} +1 -1
- package/dist/core/web/public/next/assets/{reveal-anchor-BP1VqnPU.js → reveal-anchor-DfNLgK_I.js} +2 -2
- package/dist/core/web/public/next/assets/{reveal-anchor-BP1VqnPU.js.map → reveal-anchor-DfNLgK_I.js.map} +1 -1
- package/dist/core/web/public/next/assets/seat-subscription-C5uPHBsN.js +2 -0
- package/dist/core/web/public/next/assets/{seat-subscription-C5Tvr0WQ.js.map → seat-subscription-C5uPHBsN.js.map} +1 -1
- package/dist/core/web/public/next/assets/{sidebar-model-B5Qk95k_.js → sidebar-model-CLCdqwkR.js} +2 -2
- package/dist/core/web/public/next/assets/{sidebar-model-B5Qk95k_.js.map → sidebar-model-CLCdqwkR.js.map} +1 -1
- package/dist/core/web/public/next/assets/{slots-DHKQDoE6.js → slots-C-qBeu-8.js} +3 -3
- package/dist/core/web/public/next/assets/{slots-DHKQDoE6.js.map → slots-C-qBeu-8.js.map} +1 -1
- package/dist/core/web/public/next/assets/{surface-data-CchClvHo.js → surface-data-Dj71tdD-.js} +2 -2
- package/dist/core/web/public/next/assets/{surface-data-CchClvHo.js.map → surface-data-Dj71tdD-.js.map} +1 -1
- package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js +2 -0
- package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js.map +1 -0
- package/dist/core/web/public/next/assets/{tasks-model-D6WFVULI.js → tasks-model-O8yR5YXp.js} +2 -2
- package/dist/core/web/public/next/assets/{tasks-model-D6WFVULI.js.map → tasks-model-O8yR5YXp.js.map} +1 -1
- package/dist/core/web/public/next/assets/{terminal-icons-BvCvuXk2.js → terminal-icons-CoRZq9iO.js} +2 -2
- package/dist/core/web/public/next/assets/{terminal-icons-BvCvuXk2.js.map → terminal-icons-CoRZq9iO.js.map} +1 -1
- package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js +2 -0
- package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js.map +1 -0
- package/dist/core/web/public/next/assets/types-IYKrYLku.js +2 -0
- package/dist/core/web/public/next/assets/types-IYKrYLku.js.map +1 -0
- package/dist/core/web/public/next/assets/{usage-queries-D1SU1t7r.js → usage-queries-AdjEyEtn.js} +2 -2
- package/dist/core/web/public/next/assets/{usage-queries-D1SU1t7r.js.map → usage-queries-AdjEyEtn.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-guarded-action-BZmBv7CJ.js → use-guarded-action-CuuMHeDX.js} +2 -2
- package/dist/core/web/public/next/assets/{use-guarded-action-BZmBv7CJ.js.map → use-guarded-action-CuuMHeDX.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-ticker-CkJ4-0wU.js → use-ticker-BBcp02SZ.js} +2 -2
- package/dist/core/web/public/next/assets/{use-ticker-CkJ4-0wU.js.map → use-ticker-BBcp02SZ.js.map} +1 -1
- package/dist/core/web/public/next/assets/{use-token-gate-CYcfk_GS.js → use-token-gate-CbXVYQYI.js} +2 -2
- package/dist/core/web/public/next/assets/{use-token-gate-CYcfk_GS.js.map → use-token-gate-CbXVYQYI.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useOnboarding-CujRS6PK.js → useOnboarding-C_Fpe_sH.js} +2 -2
- package/dist/core/web/public/next/assets/{useOnboarding-CujRS6PK.js.map → useOnboarding-C_Fpe_sH.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useSeatsRefresh-BEaQdkZs.js → useSeatsRefresh-Co1CnxLc.js} +2 -2
- package/dist/core/web/public/next/assets/{useSeatsRefresh-BEaQdkZs.js.map → useSeatsRefresh-Co1CnxLc.js.map} +1 -1
- package/dist/core/web/public/next/assets/{useVerseTranscript-BQ0J6Xhx.js → useVerseTranscript-DgbigUlV.js} +2 -2
- package/dist/core/web/public/next/assets/{useVerseTranscript-BQ0J6Xhx.js.map → useVerseTranscript-DgbigUlV.js.map} +1 -1
- package/dist/core/web/public/next/assets/{verse-icons-DndgEgKS.js → verse-icons-S56hIiXS.js} +2 -2
- package/dist/core/web/public/next/assets/{verse-icons-DndgEgKS.js.map → verse-icons-S56hIiXS.js.map} +1 -1
- package/dist/core/web/public/next/assets/verse-model-DAVevkNe.js +2 -0
- package/dist/core/web/public/next/assets/{verse-model-MMySehjj.js.map → verse-model-DAVevkNe.js.map} +1 -1
- package/dist/core/web/public/next/assets/{warmup-CNEH_-be.js → warmup-B_RAtNZ_.js} +3 -3
- package/dist/core/web/public/next/assets/{warmup-CNEH_-be.js.map → warmup-B_RAtNZ_.js.map} +1 -1
- package/dist/core/web/public/next/assets/why-seat-model-M_r0wX3b.js +2 -0
- package/dist/core/web/public/next/assets/why-seat-model-M_r0wX3b.js.map +1 -0
- package/dist/core/web/public/next/assets/{workspace-model-Dukb2wwv.js → workspace-model-dji5-Al3.js} +2 -2
- package/dist/core/web/public/next/assets/{workspace-model-Dukb2wwv.js.map → workspace-model-dji5-Al3.js.map} +1 -1
- package/dist/core/web/public/next/index.html +1 -1
- package/dist/core/web/read-projection-worker.js +2 -1
- package/dist/core/web/read-projection-worker.js.map +1 -1
- package/dist/core/web/read-projections.d.ts +3 -0
- package/dist/core/web/read-projections.js +2 -2
- package/dist/core/web/read-projections.js.map +1 -1
- package/dist/core/web/visibility.js +3 -4
- package/dist/core/web/visibility.js.map +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/docs/AUTONOMY-GAP.md +1 -1
- package/package.json +3 -2
- package/dist/core/web/public/next/assets/Advanced-B-LqYXvd.js +0 -2
- package/dist/core/web/public/next/assets/App-E2zCDRxm.js +0 -7
- package/dist/core/web/public/next/assets/AppsSection-8wXPPhZb.js +0 -2
- package/dist/core/web/public/next/assets/AreaTrend-BFimExYn.js +0 -2
- package/dist/core/web/public/next/assets/AreaTrend-BFimExYn.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js +0 -2
- package/dist/core/web/public/next/assets/AutonomyOffState-B5eEkmiz.js.map +0 -1
- package/dist/core/web/public/next/assets/AutonomyOffState-DmbE71vI.css +0 -1
- package/dist/core/web/public/next/assets/AutonomySection-B46igJKR.js +0 -2
- package/dist/core/web/public/next/assets/BudgetControl-T_RjPrw9.js +0 -2
- package/dist/core/web/public/next/assets/BudgetControl-T_RjPrw9.js.map +0 -1
- package/dist/core/web/public/next/assets/ChartFrame-BVuBe6RP.css +0 -1
- package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js +0 -2
- package/dist/core/web/public/next/assets/ChartFrame-SygZ7B3x.js.map +0 -1
- package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js +0 -3
- package/dist/core/web/public/next/assets/ChatSection-D6WybBpB.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js +0 -2
- package/dist/core/web/public/next/assets/CommandPalette-B6SgDJH-.js.map +0 -1
- package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +0 -1
- package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js +0 -2
- package/dist/core/web/public/next/assets/CommandSection-DgMGoepd.js.map +0 -1
- package/dist/core/web/public/next/assets/DockHost-DW9q0NdR.js +0 -2
- package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js +0 -3
- package/dist/core/web/public/next/assets/FleetSection-BdZN6rGS.js.map +0 -1
- package/dist/core/web/public/next/assets/Funnel-BeNQZWv2.js +0 -2
- package/dist/core/web/public/next/assets/Funnel-BeNQZWv2.js.map +0 -1
- package/dist/core/web/public/next/assets/GrowthSection-iiQg6wvK.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js +0 -2
- package/dist/core/web/public/next/assets/LeaderCard-BRr3_yE-.js.map +0 -1
- package/dist/core/web/public/next/assets/MatrixHeatmap-DZvZeWXL.js +0 -2
- package/dist/core/web/public/next/assets/MatrixHeatmap-DZvZeWXL.js.map +0 -1
- package/dist/core/web/public/next/assets/McpSection-BRuCcTjT.js +0 -2
- package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js +0 -2
- package/dist/core/web/public/next/assets/MindSection-BTIiQS8P.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouDrawer-lYN4G_aM.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouDrawer-lYN4G_aM.js.map +0 -1
- package/dist/core/web/public/next/assets/NeedsYouList-BgH8ezqf.js +0 -2
- package/dist/core/web/public/next/assets/NeedsYouList-CruOt4JT.css +0 -1
- package/dist/core/web/public/next/assets/NewChatDialog-Db5Xjrk8.js +0 -3
- package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js +0 -2
- package/dist/core/web/public/next/assets/OnboardingFlow-LoY-zuSe.js.map +0 -1
- package/dist/core/web/public/next/assets/OnboardingGate-C4VXn7BJ.js +0 -3
- package/dist/core/web/public/next/assets/PreviewPane-BPBbcROb.js +0 -2
- package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-BX2nkdmZ.js +0 -7
- package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js +0 -3
- package/dist/core/web/public/next/assets/ResourcesChrome-B2U2lO1H.js.map +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +0 -1
- package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js +0 -2
- package/dist/core/web/public/next/assets/ResourcesDrawer-DlUKOjl9.js.map +0 -1
- package/dist/core/web/public/next/assets/SettingsSection-mI9wQYZg.js.map +0 -1
- package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js +0 -3
- package/dist/core/web/public/next/assets/Sidebar-DT7ykaqS.js.map +0 -1
- package/dist/core/web/public/next/assets/StatTile-BuLMsJMx.css +0 -1
- package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js +0 -2
- package/dist/core/web/public/next/assets/StatTile-DPZ5yyaU.js.map +0 -1
- package/dist/core/web/public/next/assets/StepBand-DQykLkk_.js +0 -2
- package/dist/core/web/public/next/assets/StepBand-DQykLkk_.js.map +0 -1
- package/dist/core/web/public/next/assets/Swimlane-BzH6OCee.js +0 -2
- package/dist/core/web/public/next/assets/Swimlane-BzH6OCee.js.map +0 -1
- package/dist/core/web/public/next/assets/Swimlane-o6_Zsrnr.css +0 -1
- package/dist/core/web/public/next/assets/UniverseConsoleApp-DtXFhAhw.js +0 -2
- package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js +0 -3
- package/dist/core/web/public/next/assets/UsageSection-CiD1DbuF.js.map +0 -1
- package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js +0 -3
- package/dist/core/web/public/next/assets/VerseConsoleApp-BCY5uSok.js.map +0 -1
- package/dist/core/web/public/next/assets/Workspace-BQSZFSeO.js +0 -10
- package/dist/core/web/public/next/assets/actions-BmIf9avl.css +0 -1
- package/dist/core/web/public/next/assets/actions-Ci6I4C0l.js +0 -2
- package/dist/core/web/public/next/assets/budget-queries-DsAjH8ac.js +0 -2
- package/dist/core/web/public/next/assets/charts-C_xJbJiw.js +0 -2
- package/dist/core/web/public/next/assets/charts-C_xJbJiw.js.map +0 -1
- package/dist/core/web/public/next/assets/charts-DhKTrQLw.css +0 -1
- package/dist/core/web/public/next/assets/cloud-model-CX407gPY.js +0 -2
- package/dist/core/web/public/next/assets/command-catalog-CF0cQQac.js.map +0 -1
- package/dist/core/web/public/next/assets/context-queries-CktFQqSS.js +0 -2
- package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js +0 -2
- package/dist/core/web/public/next/assets/copy-setup-CqRSfELB.js.map +0 -1
- package/dist/core/web/public/next/assets/format-Dk4Fmxax.js +0 -2
- package/dist/core/web/public/next/assets/format-Dk4Fmxax.js.map +0 -1
- package/dist/core/web/public/next/assets/global-CNNGMril.js +0 -2
- package/dist/core/web/public/next/assets/guarded-runners-DPh2d32e.js +0 -2
- package/dist/core/web/public/next/assets/live-model-De-q0ZFK.js.map +0 -1
- package/dist/core/web/public/next/assets/mutations-DTCtKCn_.js +0 -2
- package/dist/core/web/public/next/assets/primitives-D0Fb3TtS.js +0 -1
- package/dist/core/web/public/next/assets/seat-subscription-C5Tvr0WQ.js +0 -2
- package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js +0 -2
- package/dist/core/web/public/next/assets/surface-prefetch-BWr0LBQn.js.map +0 -1
- package/dist/core/web/public/next/assets/types-D5XOdyw8.js +0 -2
- package/dist/core/web/public/next/assets/types-D5XOdyw8.js.map +0 -1
- package/dist/core/web/public/next/assets/verse-model-MMySehjj.js +0 -2
- package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js +0 -2
- package/dist/core/web/public/next/assets/why-seat-model-jlDTwYSc.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-queries-D1SU1t7r.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/usage/usage-contract.ts","../../../../../../src/web-ui/routes/verse/usage/usage-queries.ts"],"sourcesContent":["/**\n * routes/verse/usage/usage-contract.ts\n *\n * ┌───────────────────────────────────────────────────────────────────────┐\n * │ INTEGRATION — RECONCILED AGAINST OWNER T'S REAL ROUTES (V2.1) │\n * │ │\n * │ GET /api/verse/accounts → VerseAccountsSnapshot │\n * │ GET /api/verse/usage-series → {window, byDay, estimated, caveats} │\n * │ GET /api/verse/local-models → VerseLocalModelsSnapshot │\n * │ │\n * │ T's types now exist and are imported below as the WIRE shapes. The │\n * │ interfaces in this file are no longer stand-ins for them: they are │\n * │ the DISPLAY shapes this section renders, and they differ from the │\n * │ wire on purpose in three places the seam actually required — │\n * │ │\n * │ 1. local-models arrives as TWO runtime reports (ollama, lmStudio) │\n * │ plus a `machine` budget. This section shows one list of models │\n * │ against one budget, so `projectLocalModels` flattens them. │\n * │ 2. usage-series arrives as `{byDay}`, not `{days}` (T's documented │\n * │ deviation 1). The projector reads `byDay` and still accepts │\n * │ `days`/a bare array so an older server degrades rather than dies. │\n * │ 3. `unsupported` is not a wire field. T reports the version-pin │\n * │ failure in `reason` as the verbatim probe code, so it is DERIVED │\n * │ here from that code plus T's exported pin constant rather than │\n * │ being added to T's contract late in the run. │\n * │ │\n * │ The `WIRE_*_KEYS` blocks below are the executable seam contract: │\n * │ every canonical field name this module reads is pinned to `keyof` the │\n * │ corresponding core type, so a rename in src/core/verse breaks THIS │\n * │ build instead of silently degrading the panel to \"unknown\" at run │\n * │ time — which is exactly how this seam was broken when integration │\n * │ started. │\n * └───────────────────────────────────────────────────────────────────────┘\n *\n * Why every read goes through a structural narrower instead of a cast:\n *\n * - This section must render correctly against a server that does NOT have\n * T's routes (404) and against one that has an earlier spelling of them.\n * A cast would turn a field-name drift into `undefined.something` at\n * render time; a narrower turns it into an honest \"unknown\" with a reason.\n * - Nothing here is ever coerced. A missing percentage stays `null`, never\n * 0 — `usedPercent: 0` and \"no reading\" are different facts and the UI\n * draws them differently (docs/VERSE-TELEMETRY-V2.md, closing rules).\n *\n * SECURITY (docs/VERSE-CONTRACT-V2.md ground rules): a native-profile\n * launcher command must never reach a surface. `sanitizeCommand` below is a\n * client-side backstop on top of the server's own stripping — if a payload\n * ever carries a launcher path, this module drops it rather than printing it.\n *\n * Pure: no React, no I/O.\n */\n// EVERY import from src/core here MUST be type-only.\n//\n// `core/verse/accounts.ts` is the server's collector: it pulls node:fs,\n// node:child_process, the quota lease and the connection monitor. A VALUE\n// import of even a one-word constant from it drags that entire graph into the\n// browser bundle — `vite build` externalizes the node built-ins and the build\n// fails. Type-only imports are erased, so the seam guards below cost nothing\n// at runtime. The two constants this module needs are therefore re-declared\n// locally and PINNED TO CORE'S LITERAL TYPES (see below), which gives the same\n// drift protection with no emitted import.\nimport type {\n VerseAccountRecord,\n VerseAccountWindow,\n VerseAccountsCollectorStatus,\n VerseAccountsSnapshot,\n VerseCodexCredits,\n} from '../../../../core/verse/accounts.js';\nimport type {\n VerseLocalModel,\n VerseLocalModelsSnapshot,\n VerseLocalRuntimeReport,\n} from '../../../../core/verse/local-models.js';\nimport type { DailyUsage as CoreDailyUsage } from '../../../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Seam contract — compile-time only, zero runtime cost.\n//\n// Each entry pins a field name this module reads off the wire to `keyof` the\n// core type that produces it. Renaming a field in src/core/verse now fails\n// `npm run typecheck:web` here, at the seam, rather than turning a live panel\n// into a silent \"unknown\".\n// ---------------------------------------------------------------------------\n\nconst WIRE_ACCOUNT_KEYS = {\n id: 'id',\n label: 'label',\n provider: 'provider',\n state: 'state',\n authentication: 'authentication',\n health: 'health',\n planType: 'planType',\n observedAt: 'observedAt',\n windows: 'windows',\n binding: 'binding',\n credits: 'credits',\n reason: 'reason',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountRecord>;\n\nconst WIRE_WINDOW_KEYS = {\n id: 'id',\n usedPercent: 'usedPercent',\n resetsAt: 'resetsAt',\n nativeReport: 'nativeReport',\n limitReached: 'limitReached',\n measured: 'measured',\n} as const satisfies Record<string, keyof VerseAccountWindow>;\n\nconst WIRE_CREDITS_KEYS = {\n hasCredits: 'hasCredits',\n unlimited: 'unlimited',\n balance: 'balance',\n} as const satisfies Record<string, keyof VerseCodexCredits>;\n\nconst WIRE_ACCOUNTS_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n refreshing: 'refreshing',\n accounts: 'accounts',\n collector: 'collector',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountsSnapshot>;\n\nconst WIRE_COLLECTOR_KEYS = {\n owner: 'owner',\n note: 'note',\n} as const satisfies Record<string, keyof VerseAccountsCollectorStatus>;\n\nconst WIRE_LOCAL_SNAPSHOT_KEYS = {\n machine: 'machine',\n ollama: 'ollama',\n lmStudio: 'lmStudio',\n} as const satisfies Record<string, keyof VerseLocalModelsSnapshot>;\n\nconst WIRE_LOCAL_RUNTIME_KEYS = {\n reachable: 'reachable',\n models: 'models',\n reason: 'reason',\n // V2.1: a RETAINED known-good reading rather than a fresh probe. Both must\n // be projected — a stale reading presented as fresh is the exact failure\n // this seam exists to prevent.\n stale: 'stale',\n staleForMs: 'staleForMs',\n} as const satisfies Record<string, keyof VerseLocalRuntimeReport>;\n\nconst WIRE_LOCAL_MODEL_KEYS = {\n id: 'id',\n label: 'label',\n state: 'state',\n sizeBytes: 'sizeBytes',\n sizeVramBytes: 'sizeVramBytes',\n placement: 'placement',\n gpuPercent: 'gpuPercent',\n memoryPercent: 'memoryPercent',\n family: 'family',\n arch: 'arch',\n expiresAt: 'expiresAt',\n contextLength: 'contextLength',\n nativeContextLength: 'nativeContextLength',\n parameterSize: 'parameterSize',\n quantization: 'quantization',\n capabilities: 'capabilities',\n supportsTools: 'supportsTools',\n} as const satisfies Record<string, keyof VerseLocalModel>;\n\n/**\n * Claude's version-pin constants, re-declared rather than imported.\n *\n * The annotations are the drift guard: `typeof import(...)` is a TYPE position,\n * so it is erased at build time, but it resolves to core's literal type\n * (`'2.1.257'`, `'usage-version-unsupported'`). Change either constant in\n * `core/verse/accounts.ts` and this file stops compiling — the same protection\n * a value import would give, without pulling node:fs into the browser.\n */\ntype CoreAccountsModule = typeof import('../../../../core/verse/accounts.js');\n\nexport const CLAUDE_VERSION_REASON: CoreAccountsModule['VERSE_CLAUDE_VERSION_REASON'] =\n 'usage-version-unsupported';\n\nexport const CLAUDE_USAGE_PINNED_VERSION: CoreAccountsModule['VERSE_CLAUDE_USAGE_PINNED_VERSION'] =\n '2.1.280';\n\n/** `byDay` is the wire key (T's deviation 1); `DailyUsage` below mirrors core. */\nconst WIRE_DAILY_USAGE_KEYS = {\n day: 'day',\n tokensIn: 'tokensIn',\n tokensOut: 'tokensOut',\n estCostUsd: 'estCostUsd',\n sessions: 'sessions',\n cacheRead: 'cacheRead',\n cacheWrite: 'cacheWrite',\n cacheHitRate: 'cacheHitRate',\n} as const satisfies Record<string, keyof CoreDailyUsage>;\n\n// Referenced so the guards are not dead code under `noUnusedLocals`.\nexport const WIRE_CONTRACT_KEYS = {\n account: WIRE_ACCOUNT_KEYS,\n window: WIRE_WINDOW_KEYS,\n credits: WIRE_CREDITS_KEYS,\n accountsSnapshot: WIRE_ACCOUNTS_SNAPSHOT_KEYS,\n collector: WIRE_COLLECTOR_KEYS,\n localSnapshot: WIRE_LOCAL_SNAPSHOT_KEYS,\n localRuntime: WIRE_LOCAL_RUNTIME_KEYS,\n localModel: WIRE_LOCAL_MODEL_KEYS,\n dailyUsage: WIRE_DAILY_USAGE_KEYS,\n} as const;\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/accounts\n// ---------------------------------------------------------------------------\n\n/** Provider ids this surface knows how to describe. */\nexport type AccountProvider = 'claude' | 'codex' | 'grok';\n\n/**\n * One quota window on an account.\n *\n * `resetsAt` is an ISO string when the provider gave a real timestamp (Codex\n * publishes an epoch the server normalizes). Claude's is STRUCTURALLY always\n * null and the human sentence lives in `nativeReport.resetDescription`, which\n * is rendered verbatim and never turned into a countdown.\n */\nexport interface AccountWindow {\n id: string;\n /** Human label when the server supplies one; otherwise `id` is shown. */\n label: string | null;\n /** 0–100. `null` is \"no reading\", never 0. */\n usedPercent: number | null;\n /** ISO 8601, or null. */\n resetsAt: string | null;\n /** Verbatim provider prose, e.g. \"resets Sep 25 at 7pm (America/New_York)\". */\n resetDescription: string | null;\n /**\n * True when the provider signalled `rateLimitReachedType` — the upstream\n * writes the SENTINEL 100, which is a flag, not a measurement. Rendered as\n * \"limit reached\", never as \"100% used\".\n */\n limitReached: boolean;\n /**\n * False when `usedPercent` is a FLAGGED SENTINEL rather than a reading.\n *\n * Codex writes `rateLimitReachedType` upstream as the value 100, so a bare\n * 100 is indistinguishable from a genuinely measured 100 by the time it\n * arrives. The server distinguishes them; this surface must not collapse\n * them back together. Absent on the wire → assumed measured UNLESS the\n * limit flag is set, which is the only case where the sentinel is written.\n */\n measured: boolean;\n}\n\n/**\n * Codex credits. Independent of the window: a 100%-used week with a spendable\n * balance is NOT blocked, and this surface must not say it is.\n */\nexport interface AccountCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Raw decimal string from the provider, kept verbatim for the title text. */\n balance: string | null;\n /** `balance` parsed, or null when it was absent/unparseable. */\n balanceValue: number | null;\n}\n\nexport interface Account {\n id: string;\n label: string;\n provider: AccountProvider;\n state: 'checking' | 'observed' | 'signed-out' | 'unavailable';\n authentication: 'signed-in' | 'signed-out' | 'unknown';\n /**\n * The connection monitor's own health verdict. Claude's is ALWAYS `unknown`\n * by construction (docs/VERSE-TELEMETRY-V2.md) — that is not a fault and is\n * never rendered as one.\n */\n health: string | null;\n planType: string | null;\n observedAt: string | null;\n windows: AccountWindow[];\n /**\n * The server's computed binding window (highest used percent). Kept as its\n * own field rather than recomputed blindly, but `accounts-model.ts` verifies\n * it against `windows` and falls back to computing it when absent.\n */\n binding: AccountWindow | null;\n credits: AccountCredits | null;\n /** Plain-language reason for a non-observed state. */\n reason: string | null;\n /**\n * Present when a probe failed CLOSED on a version pin (Claude's probe is\n * pinned to a specific Claude Code build). The fix is a one-line constant\n * bump, so the UI names it instead of showing a silent \"unknown\".\n */\n unsupported: { code: string; pinnedVersion: string | null } | null;\n /** Already sanitized — see `sanitizeCommand`. Null when nothing safe to show. */\n reconnectCommand: string | null;\n /**\n * The server's plain-language facts for this account (`VerseAccountRecord.\n * notes`). Grok's \"reconnect through `ashlr resources`, profile path withheld\n * on purpose\" lives here, which is why this surface shows notes rather than\n * only the machine-readable `reason`.\n */\n notes: string[];\n}\n\nexport interface AccountsSnapshot {\n sampledAt: string | null;\n refreshing: boolean;\n accounts: Account[];\n /**\n * Set when another collector process owns the quota-refresh lease, so these\n * readings are read-only and may be staler than this server's poll interval.\n */\n collectorNote: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/usage-series?window=7d|30d\n// ---------------------------------------------------------------------------\n\nexport type SeriesWindow = '7d' | '30d';\n\n/** `buildRollup(window, cfg).byDay` — see docs/VERSE-TELEMETRY-V2.md. */\nexport interface DailyUsage {\n /** YYYY-MM-DD. */\n day: string;\n tokensIn: number;\n tokensOut: number;\n /** ESTIMATED from a static price table. Never a billed figure. */\n estCostUsd: number;\n sessions: number;\n /** Optional: absent means the rollup carried no cache columns for that day. */\n cacheRead: number | null;\n cacheWrite: number | null;\n /** 0–1 fraction, or null. */\n cacheHitRate: number | null;\n}\n\nexport interface UsageSeries {\n window: SeriesWindow;\n days: DailyUsage[];\n generatedAt: string | null;\n /**\n * The server states outright that every cost column here is estimated.\n * Carried through rather than re-asserted locally so the disclosure the UI\n * prints is the one the producer actually made.\n */\n estimated: boolean;\n /** The server's own caveats, rendered verbatim beside the charts. */\n caveats: string[];\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models\n// ---------------------------------------------------------------------------\n\nexport interface LocalModel {\n name: string;\n /** Which runtime reported it, so a flattened list stays attributable. */\n runtime: 'ollama' | 'lmstudio' | null;\n /** Resident in memory right now (Ollama /api/ps), vs merely installed. */\n loaded: boolean;\n /** Total resident bytes, or null when not reported. */\n sizeBytes: number | null;\n /** Of `sizeBytes`, how much sits in VRAM. null = not reported. */\n sizeVramBytes: number | null;\n /**\n * Where the weights actually sit. `split` is the one that matters: a model\n * that only half-fits the GPU runs at a fraction of the speed of one that\n * fits, and that is the difference between usable and not.\n */\n placement: 'gpu' | 'cpu' | 'split' | 'unknown';\n /** The runtime's own GPU share, 0–100. Preferred over recomputing it. */\n gpuPercent: number | null;\n /** Resident size against total machine memory, 0–100, else null. */\n memoryPercent: number | null;\n family: string | null;\n arch: string | null;\n /** Keep-alive expiry (ISO). Only meaningful while `loaded`. */\n expiresAt: string | null;\n /** e.g. \"79.7B\". Provider string, never parsed into a number for display. */\n parameterSize: string | null;\n /** e.g. \"Q4_K_M\". */\n quantization: string | null;\n /** Native context from model_info[\"<arch>.context_length\"]. */\n nativeContext: number | null;\n /** Context Ashlr actually configures for this seat, when it differs. */\n configuredContext: number | null;\n /**\n * `capabilities` from /api/show. `null` means the capability list was not\n * reported — which is NOT the same as \"does not support tools\".\n */\n capabilities: string[] | null;\n /**\n * The runtime's own answer to \"can this drive an agentic session\", which is\n * AUTHORITATIVE over `capabilities` and must be preferred when non-null.\n *\n * This matters: owner T sends `capabilities: []` when a runtime reported no\n * capability list, and reading that array alone would render \"no tools\" —\n * a hard, wrong gate — where T's `supportsTools: null` correctly means\n * \"unknown\". Deriving tool support from the array alone was a real defect\n * at this seam, not a cosmetic one.\n */\n supportsTools: boolean | null;\n}\n\n/**\n * One runtime's own reachability, kept per-runtime rather than folded into the\n * flattened list, because STALENESS is per-runtime and must be stated.\n *\n * `stale` means the server served a RETAINED known-good reading after a probe\n * TIMED OUT (core `VERSE_LOCAL_LAST_GOOD_TTL_MS`). That is the honest choice\n * server-side — a timeout is \"no answer yet\", not \"the runtime is gone\" — but\n * it obliges this surface to say plainly that the numbers are N seconds old\n * rather than presenting them as fresh.\n */\nexport interface LocalRuntimeStatus {\n runtime: 'ollama' | 'lmstudio';\n reachable: boolean;\n /** Machine-readable degradation code; never rendered as a sentence. */\n reason: string | null;\n /** True when this report is a retained reading rather than a fresh probe. */\n stale: boolean;\n /** Age of that retained reading in ms. Null when `stale` is false. */\n staleForMs: number | null;\n modelCount: number;\n}\n\nexport interface LocalModelsSnapshot {\n reachable: boolean;\n models: LocalModel[];\n /** Machine memory budget in bytes, or null when the server did not say. */\n memoryBudgetBytes: number | null;\n /** Machine memory reported free right now, or null. */\n freeMemoryBytes: number | null;\n reason: string | null;\n /** Per-runtime reachability and staleness. Empty on a flat legacy body. */\n runtimes: LocalRuntimeStatus[];\n /** The server's own plain-language caveats for this snapshot. */\n notes: string[];\n sampledAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Narrowing helpers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction str(source: Record<string, unknown>, key: string): string | null {\n const v = source[key];\n return typeof v === 'string' && v.length > 0 ? v : null;\n}\n\nfunction num(source: Record<string, unknown>, key: string): number | null {\n const v = source[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n}\n\nfunction bool(source: Record<string, unknown>, key: string, fallback = false): boolean {\n const v = source[key];\n return typeof v === 'boolean' ? v : fallback;\n}\n\nfunction list(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\n/**\n * Drop anything that looks like a native-profile launcher invocation or an\n * absolute path into the private account store. The server is supposed to\n * strip these; this is the client-side backstop, because the cost of printing\n * one is unacceptable and the cost of showing \"no command\" is a sentence.\n */\nconst FORBIDDEN_COMMAND = /(launcher\\.mjs|native-profiles|account-connections|console-startup|\\/\\.ashlr\\b|Bearer\\s|--token\\b)/i;\n\nexport function sanitizeCommand(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 200) return null;\n if (FORBIDDEN_COMMAND.test(trimmed)) return null;\n // A newline would let a payload smuggle a second command onto the surface.\n if (/[\\r\\n]/.test(trimmed)) return null;\n return trimmed;\n}\n\nfunction clampPercent(value: number | null): number | null {\n if (value === null) return null;\n return Math.max(0, Math.min(100, value));\n}\n\nfunction projectWindow(raw: unknown): AccountWindow | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id') ?? str(r, 'label');\n if (id === null) return null;\n const native = record(r['nativeReport']);\n const limitReached = bool(r, 'limitReached') || bool(r, 'rateLimitReached');\n const measuredRaw = r['measured'];\n return {\n id,\n label: str(r, 'label'),\n usedPercent: clampPercent(num(r, 'usedPercent') ?? num(r, 'used_percent')),\n resetsAt: str(r, 'resetsAt') ?? str(r, 'resets_at'),\n resetDescription:\n (native ? str(native, 'resetDescription') : null) ?? str(r, 'resetDescription'),\n limitReached,\n // Absent → measured, EXCEPT under a limit flag, which is the one case the\n // upstream writes the sentinel 100. Defaulting a flagged window to\n // `measured: true` would let a denial print as \"100% used\".\n measured: typeof measuredRaw === 'boolean' ? measuredRaw : !limitReached,\n };\n}\n\nfunction projectCredits(raw: unknown): AccountCredits | null {\n const r = record(raw);\n if (!r) return null;\n const balance = str(r, 'balance');\n const parsed = balance === null ? num(r, 'balance') : Number.parseFloat(balance);\n return {\n hasCredits: bool(r, 'hasCredits') || bool(r, 'has_credits'),\n unlimited: bool(r, 'unlimited'),\n balance,\n balanceValue: typeof parsed === 'number' && Number.isFinite(parsed) ? parsed : null,\n };\n}\n\nconst PROVIDERS: readonly string[] = ['claude', 'codex', 'grok'];\n\nfunction projectAccount(raw: unknown): Account | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id');\n const provider = str(r, 'provider');\n if (id === null || provider === null || !PROVIDERS.includes(provider)) return null;\n\n const windows = list(r['windows'])\n .map(projectWindow)\n .filter((w): w is AccountWindow => w !== null);\n\n const state = str(r, 'state');\n const auth = str(r, 'authentication');\n const unsupportedRaw = record(r['unsupported']);\n\n return {\n id,\n label: str(r, 'label') ?? id,\n provider: provider as AccountProvider,\n state:\n state === 'checking' || state === 'observed' || state === 'signed-out' || state === 'unavailable'\n ? state\n : 'unavailable',\n authentication: auth === 'signed-in' || auth === 'signed-out' ? auth : 'unknown',\n health: str(r, 'health'),\n planType: str(r, 'planType') ?? str(r, 'plan_type'),\n observedAt: str(r, 'observedAt'),\n windows,\n binding: projectWindow(r['binding']),\n credits: projectCredits(r['credits']),\n reason: str(r, 'reason'),\n unsupported: projectUnsupported(r, unsupportedRaw),\n reconnectCommand: sanitizeCommand(r['reconnectCommand']),\n notes: list(r['notes']).filter((n): n is string => typeof n === 'string'),\n };\n}\n\n/**\n * A version-pinned probe that failed CLOSED, named rather than swallowed.\n *\n * `unsupported` is not a field on the wire. Owner T reports the failure as the\n * verbatim probe code in `reason` (`usage-version-unsupported`) and states the\n * pin in `notes`, so this derives the structured form from those rather than\n * requiring a late contract change. An explicit `unsupported` object is still\n * honoured first, so a server that grows one later wins without a client edit.\n */\nfunction projectUnsupported(\n r: Record<string, unknown>,\n explicit: Record<string, unknown> | null,\n): Account['unsupported'] {\n if (explicit) {\n return {\n code: str(explicit, 'code') ?? CLAUDE_VERSION_REASON,\n pinnedVersion: str(explicit, 'pinnedVersion') ?? str(explicit, 'version'),\n };\n }\n const reason = str(r, 'reason');\n if (reason !== CLAUDE_VERSION_REASON) return null;\n return { code: reason, pinnedVersion: CLAUDE_USAGE_PINNED_VERSION };\n}\n\n/**\n * The read-only banner. Owner T reports lease ownership as a structured\n * `collector` status, not a flat `collectorNote`, so the note is derived from\n * it — and ONLY when another process owns the lease, because that is the one\n * case where these readings may be staler than this server's poll interval.\n * A stray `collectorNote` string is still accepted for forward compatibility.\n */\nfunction projectCollectorNote(root: Record<string, unknown>): string | null {\n const flat = str(root, 'collectorNote');\n if (flat) return flat;\n const collector = record(root['collector']);\n if (!collector) return null;\n if (str(collector, 'owner') !== 'another-collector') return null;\n return (\n str(collector, 'note') ??\n 'Another collector process owns the quota-refresh lease, so these readings are read-only and may be staler than this server’s poll interval.'\n );\n}\n\nexport function projectAccountsSnapshot(raw: unknown): AccountsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n const rawAccounts = Array.isArray(root['accounts']) ? root['accounts'] : Array.isArray(raw) ? raw : null;\n if (rawAccounts === null) return null;\n return {\n sampledAt: str(root, 'sampledAt'),\n refreshing: bool(root, 'refreshing'),\n accounts: rawAccounts.map(projectAccount).filter((a): a is Account => a !== null),\n collectorNote: projectCollectorNote(root),\n };\n}\n\nfunction projectDay(raw: unknown): DailyUsage | null {\n const r = record(raw);\n if (!r) return null;\n const day = str(r, 'day');\n if (day === null || !/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return null;\n return {\n day,\n tokensIn: num(r, 'tokensIn') ?? 0,\n tokensOut: num(r, 'tokensOut') ?? 0,\n estCostUsd: num(r, 'estCostUsd') ?? 0,\n sessions: num(r, 'sessions') ?? 0,\n cacheRead: num(r, 'cacheRead'),\n cacheWrite: num(r, 'cacheWrite'),\n cacheHitRate: num(r, 'cacheHitRate'),\n };\n}\n\n/**\n * `byDay` is the wire key. Owner T wraps the series as\n * `{window, byDay, estimated, caveats}` rather than returning a bare array\n * (documented deviation 1), so `byDay` is read FIRST. `days` and a bare array\n * remain accepted so an older or differently-shaped server degrades to a\n * rendered series instead of a dead panel.\n */\nexport function projectUsageSeries(raw: unknown, requested: SeriesWindow): UsageSeries | null {\n const root = record(raw);\n const rawDays = root\n ? Array.isArray(root['byDay'])\n ? root['byDay']\n : Array.isArray(root['days'])\n ? root['days']\n : null\n : Array.isArray(raw)\n ? raw\n : null;\n if (rawDays === null) return null;\n const windowValue = root ? str(root, 'window') : null;\n return {\n window: windowValue === '7d' || windowValue === '30d' ? windowValue : requested,\n days: rawDays\n .map(projectDay)\n .filter((d): d is DailyUsage => d !== null)\n .sort((a, b) => a.day.localeCompare(b.day)),\n generatedAt: root ? str(root, 'generatedAt') : null,\n // The producer asserts estimation explicitly. Absent → still true: every\n // cost column on this route is price-table derived, and defaulting the\n // disclosure OFF would drop it exactly when the server is older.\n estimated: root ? bool(root, 'estimated', true) : true,\n caveats: root ? list(root['caveats']).filter((c): c is string => typeof c === 'string') : [],\n };\n}\n\nfunction projectLocalModel(raw: unknown, runtime: LocalModel['runtime']): LocalModel | null {\n const r = record(raw);\n if (!r) return null;\n // `label`/`id` are owner T's spellings; `name`/`model` are the Ollama-native\n // ones a differently-shaped server might send.\n const name = str(r, 'label') ?? str(r, 'id') ?? str(r, 'name') ?? str(r, 'model');\n if (name === null) return null;\n const caps = r['capabilities'];\n const state = str(r, 'state');\n const supportsTools = r['supportsTools'];\n\n // `nativeContextLength` is the architecture maximum; `contextLength` is what\n // the runtime actually configured for the loaded instance. They are two\n // different facts and the panel shows the gap between them, so they must not\n // collapse onto one field.\n const nativeContext = num(r, 'nativeContextLength') ?? num(r, 'nativeContext');\n const configuredContext = num(r, 'contextLength') ?? num(r, 'configuredContext');\n\n const placement = str(r, 'placement');\n\n return {\n name,\n runtime,\n loaded: state !== null ? state === 'loaded' : bool(r, 'loaded') || bool(r, 'resident'),\n sizeBytes: num(r, 'sizeBytes') ?? num(r, 'size'),\n sizeVramBytes: num(r, 'sizeVramBytes') ?? num(r, 'size_vram'),\n placement:\n placement === 'gpu' || placement === 'cpu' || placement === 'split' ? placement : 'unknown',\n gpuPercent: clampPercent(num(r, 'gpuPercent')),\n memoryPercent: clampPercent(num(r, 'memoryPercent')),\n family: str(r, 'family'),\n arch: str(r, 'arch'),\n expiresAt: str(r, 'expiresAt') ?? str(r, 'expires_at'),\n parameterSize: str(r, 'parameterSize') ?? str(r, 'parameter_size'),\n quantization: str(r, 'quantization') ?? str(r, 'quantization_level'),\n nativeContext,\n // Only a genuine narrowing is worth showing. When the runtime reports the\n // same number twice there is no truncation to report.\n configuredContext:\n configuredContext !== null && nativeContext !== null && configuredContext === nativeContext\n ? null\n : configuredContext,\n capabilities: Array.isArray(caps) ? caps.filter((c): c is string => typeof c === 'string') : null,\n supportsTools: typeof supportsTools === 'boolean' ? supportsTools : null,\n };\n}\n\nfunction projectRuntimeReport(\n raw: unknown,\n runtime: NonNullable<LocalModel['runtime']>,\n): { status: LocalRuntimeStatus; models: LocalModel[] } | null {\n const r = record(raw);\n if (!r) return null;\n const rawModels = Array.isArray(r['models']) ? r['models'] : null;\n if (rawModels === null) return null;\n const models = rawModels\n .map((m) => projectLocalModel(m, runtime))\n .filter((m): m is LocalModel => m !== null);\n const stale = bool(r, 'stale');\n return {\n models,\n status: {\n runtime,\n reachable: bool(r, 'reachable'),\n reason: str(r, 'reason'),\n stale,\n // Only meaningful under `stale`. A staleForMs on a fresh report would be\n // a contradiction, and printing it would age a current reading.\n staleForMs: stale ? num(r, 'staleForMs') : null,\n modelCount: models.length,\n },\n };\n}\n\n/**\n * Owner T reports local availability per RUNTIME (`ollama`, `lmStudio`) with a\n * shared `machine` budget. This panel answers one question — \"what can I run\n * right now, and against how much memory\" — so the runtimes are flattened into\n * one list, each row keeping its `runtime` so it stays attributable.\n *\n * Reachability is the OR of the runtimes: one dead runtime is not an unreachable\n * local stack. `reason` is only carried when NOTHING is reachable, because a\n * degradation note beside a working list would misdescribe what is on screen.\n *\n * A flat `{reachable, models, memoryBudgetBytes}` body is still accepted, so an\n * older or differently-shaped server degrades rather than rendering nothing.\n */\nexport function projectLocalModels(raw: unknown): LocalModelsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n\n const ollama = projectRuntimeReport(root['ollama'], 'ollama');\n const lmStudio = projectRuntimeReport(root['lmStudio'] ?? root['lmstudio'], 'lmstudio');\n\n if (ollama !== null || lmStudio !== null) {\n const reports = [ollama, lmStudio].filter((x): x is NonNullable<typeof x> => x !== null);\n const reachable = reports.some((x) => x.status.reachable);\n const machine = record(root['machine']);\n return {\n reachable,\n models: reports.flatMap((x) => x.models),\n memoryBudgetBytes:\n (machine ? num(machine, 'totalMemoryBytes') : null) ??\n num(root, 'memoryBudgetBytes') ??\n num(root, 'memoryBudget'),\n freeMemoryBytes: machine ? num(machine, 'freeMemoryBytes') : null,\n reason: reachable\n ? null\n : (reports.map((x) => x.status.reason).find((x) => x !== null) ?? null),\n runtimes: reports.map((x) => x.status),\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n }\n\n const rawModels = Array.isArray(root['models']) ? root['models'] : null;\n if (rawModels === null) return null;\n return {\n reachable: bool(root, 'reachable', true),\n models: rawModels.map((m) => projectLocalModel(m, null)).filter((m): m is LocalModel => m !== null),\n memoryBudgetBytes: num(root, 'memoryBudgetBytes') ?? num(root, 'memoryBudget'),\n freeMemoryBytes: num(root, 'freeMemoryBytes'),\n reason: str(root, 'reason'),\n // A flat legacy body carries no per-runtime reachability, so there is\n // nothing to attribute and nothing to call stale. An empty list says that\n // honestly; a fabricated entry would not.\n runtimes: [],\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n}\n","/**\n * routes/verse/usage/usage-queries.ts — the reads behind the Usage section.\n *\n * `/api/control` is fetched through the shared `controlSnapshotQuery` so this\n * section rides the same cache (and the same SSE invalidation) as every other\n * view rather than opening a second copy of a large snapshot.\n *\n * `/api/verse/control` is owner B's new route. It is fetched through a\n * NON-throwing wrapper because this section must still render when the route\n * is absent (server started without --allow-dispatch, or B's route not landed\n * yet): a missing configured-caps source is a degraded panel, not a dead\n * section. 401 is the one error that still propagates — an expired read\n * session is an unauthorized state for the whole surface, not a degraded one.\n *\n * The cache key is deliberately NOT shared with the Autonomy section's own\n * read of the same route: this module stores a wrapper shape, and two owners\n * writing different value types under one key would be a real bug.\n */\nimport type { FrontierUsage } from '../../../../core/usage/frontier-usage.js';\nimport { ApiError, apiGet } from '../../../data/client.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { projectLocalModels, type SeriesWindow } from './usage-contract.js';\n\nexport const USAGE_FRONTIER_KEY = 'verse-usage-frontier';\nexport const USAGE_VERSE_CONTROL_KEY = 'verse-usage-control';\n\n/** GET /api/usage — per-engine frontier usage (see core/usage/frontier-usage.ts). */\nexport const frontierUsageQuery: QueryDef<FrontierUsage> = {\n key: USAGE_FRONTIER_KEY,\n fetch: (signal) => apiGet<FrontierUsage>('/api/usage', signal),\n};\n\nexport interface VerseControlRead {\n /** Raw body; narrowed by `projectVerseControl` (owner B's types are not landed). */\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeControlFailure(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return 'This server does not expose /api/verse/control, so configured caps and today’s spend are unavailable here.';\n }\n return `Configured caps unavailable (HTTP ${err.status}).`;\n }\n return 'Configured caps unavailable: the request failed.';\n}\n\nexport const verseControlQuery: QueryDef<VerseControlRead> = {\n key: USAGE_VERSE_CONTROL_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>('/api/verse/control', signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeControlFailure(err) };\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Owner T's routes (GET /api/verse/{accounts,usage-series,local-models})\n// ---------------------------------------------------------------------------\n//\n// These three are fetched through the SAME non-throwing wrapper pattern as\n// /api/verse/control, for the same reason and one more: they are landing in\n// parallel with this section. A server that predates them answers 404, and a\n// 404 here means \"this panel is degraded\", not \"the Usage view is broken\".\n// 401 still propagates, because an expired read session is an unauthorized\n// state for the whole surface.\n//\n// The bodies are narrowed structurally by usage-contract.ts rather than cast,\n// so a field-name drift between T's route and this client degrades to an\n// honest \"unknown\" instead of throwing at render time.\n\nexport const USAGE_ACCOUNTS_KEY = 'verse-usage-accounts';\nexport const USAGE_LOCAL_MODELS_KEY = 'verse-usage-local-models';\nexport const USAGE_SERIES_KEY_PREFIX = 'verse-usage-series';\n\n/** A read that is allowed to be absent. `raw` is null when it was. */\nexport interface OptionalRead {\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeOptionalFailure(path: string, err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This server does not expose ${path} yet, so this panel has no source.`;\n }\n return `${path} answered HTTP ${err.status}.`;\n }\n return `${path} could not be reached.`;\n}\n\nfunction optionalGet(path: string): (signal?: AbortSignal) => Promise<OptionalRead> {\n return async (signal) => {\n try {\n const raw = await apiGet<unknown>(path, signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeOptionalFailure(path, err) };\n }\n };\n}\n\n/** GET /api/verse/accounts — per-account state, windows, credits, plan. */\nexport const verseAccountsQuery: QueryDef<OptionalRead> = {\n key: USAGE_ACCOUNTS_KEY,\n fetch: optionalGet('/api/verse/accounts'),\n};\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models — and why this one read retries\n// ---------------------------------------------------------------------------\n//\n// `/api/verse/local-models` probes the runtimes live on every request, with a\n// 2s per-probe timeout (core/verse/local-models.ts\n// VERSE_LOCAL_PROBE_TIMEOUT_MS). A probe that times out is reported as\n// `{reachable: false, reason: 'ollama-unreachable'}` in a perfectly ordinary\n// HTTP 200 — which is correct on the server's terms (it genuinely did not get\n// an answer) but is NOT the same fact as \"Ollama is not running\", and nothing\n// in the payload distinguishes the two.\n//\n// That distinction matters here because this section is the thing that causes\n// the timeout. Mounting Usage, and every press of its Refresh button, fires\n// seven reads at once, several of which spawn short-lived account-probe\n// processes server-side; measured against a live Ollama with twelve models,\n// roughly one burst in ten starves the 2s probe and comes back\n// `ollama-unreachable`. Nothing re-reads this route afterwards — it has no SSE\n// invalidation key — so that one false negative is what the operator stares\n// at, and pressing Refresh re-creates the very burst that produced it.\n//\n// So a reported-unreachable local stack is RE-READ, up to twice, with a short\n// gap for the burst to drain. This is not \"ignore the failure\": the retries\n// are bounded, each one is a real request, and whatever the last read says is\n// what this section renders — a runtime that is genuinely down answers fast\n// (connection refused, not a timeout) and still reports unreachable, three\n// times, in well under a second.\n//\n// Only an AVAILABLE read is retried. A 404/500 (`available: false`) is a\n// statement about the route, not about the runtime, and re-asking cannot\n// change it.\n\n/** Two extra reads at most, spaced so the section's own request burst drains. */\nconst LOCAL_MODELS_RETRY_DELAYS_MS = [350, 1200] as const;\n\nconst readLocalModels = optionalGet('/api/verse/local-models');\n\nfunction reportsNothingReachable(read: OptionalRead): boolean {\n if (!read.available) return false;\n const snapshot = projectLocalModels(read.raw);\n return snapshot !== null && !snapshot.reachable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** GET /api/verse/local-models — resident vs installed, VRAM split, tools. */\nexport const verseLocalModelsQuery: QueryDef<OptionalRead> = {\n key: USAGE_LOCAL_MODELS_KEY,\n fetch: async (signal) => {\n let read = await readLocalModels(signal);\n for (const delayMs of LOCAL_MODELS_RETRY_DELAYS_MS) {\n if (!reportsNothingReachable(read)) return read;\n await sleep(delayMs, signal);\n read = await readLocalModels(signal);\n }\n return read;\n },\n};\n\n// One QueryDef per window, created once at module scope: useQuery keys on\n// `def.key`, and minting a fresh object per render would be harmless but\n// useRefresh/useRefetch's useCallback deps would churn for no reason.\nconst SERIES_QUERIES: Record<SeriesWindow, QueryDef<OptionalRead>> = {\n '7d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:7d`,\n fetch: optionalGet('/api/verse/usage-series?window=7d'),\n },\n '30d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:30d`,\n fetch: optionalGet('/api/verse/usage-series?window=30d'),\n },\n};\n\nexport function usageSeriesQuery(window: SeriesWindow): QueryDef<OptionalRead> {\n return SERIES_QUERIES[window];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usage-queries-AdjEyEtn.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/usage/usage-contract.ts","../../../../../../src/web-ui/routes/verse/usage/usage-queries.ts"],"sourcesContent":["/**\n * routes/verse/usage/usage-contract.ts\n *\n * ┌───────────────────────────────────────────────────────────────────────┐\n * │ INTEGRATION — RECONCILED AGAINST OWNER T'S REAL ROUTES (V2.1) │\n * │ │\n * │ GET /api/verse/accounts → VerseAccountsSnapshot │\n * │ GET /api/verse/usage-series → {window, byDay, estimated, caveats} │\n * │ GET /api/verse/local-models → VerseLocalModelsSnapshot │\n * │ │\n * │ T's types now exist and are imported below as the WIRE shapes. The │\n * │ interfaces in this file are no longer stand-ins for them: they are │\n * │ the DISPLAY shapes this section renders, and they differ from the │\n * │ wire on purpose in three places the seam actually required — │\n * │ │\n * │ 1. local-models arrives as TWO runtime reports (ollama, lmStudio) │\n * │ plus a `machine` budget. This section shows one list of models │\n * │ against one budget, so `projectLocalModels` flattens them. │\n * │ 2. usage-series arrives as `{byDay}`, not `{days}` (T's documented │\n * │ deviation 1). The projector reads `byDay` and still accepts │\n * │ `days`/a bare array so an older server degrades rather than dies. │\n * │ 3. `unsupported` is not a wire field. T reports the version-pin │\n * │ failure in `reason` as the verbatim probe code, so it is DERIVED │\n * │ here from that code plus T's exported pin constant rather than │\n * │ being added to T's contract late in the run. │\n * │ │\n * │ The `WIRE_*_KEYS` blocks below are the executable seam contract: │\n * │ every canonical field name this module reads is pinned to `keyof` the │\n * │ corresponding core type, so a rename in src/core/verse breaks THIS │\n * │ build instead of silently degrading the panel to \"unknown\" at run │\n * │ time — which is exactly how this seam was broken when integration │\n * │ started. │\n * └───────────────────────────────────────────────────────────────────────┘\n *\n * Why every read goes through a structural narrower instead of a cast:\n *\n * - This section must render correctly against a server that does NOT have\n * T's routes (404) and against one that has an earlier spelling of them.\n * A cast would turn a field-name drift into `undefined.something` at\n * render time; a narrower turns it into an honest \"unknown\" with a reason.\n * - Nothing here is ever coerced. A missing percentage stays `null`, never\n * 0 — `usedPercent: 0` and \"no reading\" are different facts and the UI\n * draws them differently (docs/VERSE-TELEMETRY-V2.md, closing rules).\n *\n * SECURITY (docs/VERSE-CONTRACT-V2.md ground rules): a native-profile\n * launcher command must never reach a surface. `sanitizeCommand` below is a\n * client-side backstop on top of the server's own stripping — if a payload\n * ever carries a launcher path, this module drops it rather than printing it.\n *\n * Pure: no React, no I/O.\n */\n// EVERY import from src/core here MUST be type-only.\n//\n// `core/verse/accounts.ts` is the server's collector: it pulls node:fs,\n// node:child_process, the quota lease and the connection monitor. A VALUE\n// import of even a one-word constant from it drags that entire graph into the\n// browser bundle — `vite build` externalizes the node built-ins and the build\n// fails. Type-only imports are erased, so the seam guards below cost nothing\n// at runtime. The two constants this module needs are therefore re-declared\n// locally and PINNED TO CORE'S LITERAL TYPES (see below), which gives the same\n// drift protection with no emitted import.\nimport type {\n VerseAccountRecord,\n VerseAccountWindow,\n VerseAccountsCollectorStatus,\n VerseAccountsSnapshot,\n VerseCodexCredits,\n} from '../../../../core/verse/accounts.js';\nimport type {\n VerseLocalModel,\n VerseLocalModelsSnapshot,\n VerseLocalRuntimeReport,\n} from '../../../../core/verse/local-models.js';\nimport type { DailyUsage as CoreDailyUsage } from '../../../../core/types.js';\n\n// ---------------------------------------------------------------------------\n// Seam contract — compile-time only, zero runtime cost.\n//\n// Each entry pins a field name this module reads off the wire to `keyof` the\n// core type that produces it. Renaming a field in src/core/verse now fails\n// `npm run typecheck:web` here, at the seam, rather than turning a live panel\n// into a silent \"unknown\".\n// ---------------------------------------------------------------------------\n\nconst WIRE_ACCOUNT_KEYS = {\n id: 'id',\n label: 'label',\n provider: 'provider',\n state: 'state',\n authentication: 'authentication',\n health: 'health',\n planType: 'planType',\n observedAt: 'observedAt',\n windows: 'windows',\n binding: 'binding',\n credits: 'credits',\n reason: 'reason',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountRecord>;\n\nconst WIRE_WINDOW_KEYS = {\n id: 'id',\n usedPercent: 'usedPercent',\n resetsAt: 'resetsAt',\n nativeReport: 'nativeReport',\n limitReached: 'limitReached',\n measured: 'measured',\n} as const satisfies Record<string, keyof VerseAccountWindow>;\n\nconst WIRE_CREDITS_KEYS = {\n hasCredits: 'hasCredits',\n unlimited: 'unlimited',\n balance: 'balance',\n} as const satisfies Record<string, keyof VerseCodexCredits>;\n\nconst WIRE_ACCOUNTS_SNAPSHOT_KEYS = {\n sampledAt: 'sampledAt',\n refreshing: 'refreshing',\n accounts: 'accounts',\n collector: 'collector',\n notes: 'notes',\n} as const satisfies Record<string, keyof VerseAccountsSnapshot>;\n\nconst WIRE_COLLECTOR_KEYS = {\n owner: 'owner',\n note: 'note',\n} as const satisfies Record<string, keyof VerseAccountsCollectorStatus>;\n\nconst WIRE_LOCAL_SNAPSHOT_KEYS = {\n machine: 'machine',\n ollama: 'ollama',\n lmStudio: 'lmStudio',\n} as const satisfies Record<string, keyof VerseLocalModelsSnapshot>;\n\nconst WIRE_LOCAL_RUNTIME_KEYS = {\n reachable: 'reachable',\n models: 'models',\n reason: 'reason',\n // V2.1: a RETAINED known-good reading rather than a fresh probe. Both must\n // be projected — a stale reading presented as fresh is the exact failure\n // this seam exists to prevent.\n stale: 'stale',\n staleForMs: 'staleForMs',\n} as const satisfies Record<string, keyof VerseLocalRuntimeReport>;\n\nconst WIRE_LOCAL_MODEL_KEYS = {\n id: 'id',\n label: 'label',\n state: 'state',\n sizeBytes: 'sizeBytes',\n sizeVramBytes: 'sizeVramBytes',\n placement: 'placement',\n gpuPercent: 'gpuPercent',\n memoryPercent: 'memoryPercent',\n family: 'family',\n arch: 'arch',\n expiresAt: 'expiresAt',\n contextLength: 'contextLength',\n nativeContextLength: 'nativeContextLength',\n parameterSize: 'parameterSize',\n quantization: 'quantization',\n capabilities: 'capabilities',\n supportsTools: 'supportsTools',\n} as const satisfies Record<string, keyof VerseLocalModel>;\n\n/**\n * Claude's version-pin constants, re-declared rather than imported.\n *\n * The annotations are the drift guard: `typeof import(...)` is a TYPE position,\n * so it is erased at build time, but it resolves to core's literal type\n * (`'2.1.257'`, `'usage-version-unsupported'`). Change either constant in\n * `core/verse/accounts.ts` and this file stops compiling — the same protection\n * a value import would give, without pulling node:fs into the browser.\n */\ntype CoreAccountsModule = typeof import('../../../../core/verse/accounts.js');\n\nexport const CLAUDE_VERSION_REASON: CoreAccountsModule['VERSE_CLAUDE_VERSION_REASON'] =\n 'usage-version-unsupported';\n\nexport const CLAUDE_USAGE_PINNED_VERSION: CoreAccountsModule['VERSE_CLAUDE_USAGE_PINNED_VERSION'] =\n '2.1.280';\n\n/** `byDay` is the wire key (T's deviation 1); `DailyUsage` below mirrors core. */\nconst WIRE_DAILY_USAGE_KEYS = {\n day: 'day',\n tokensIn: 'tokensIn',\n tokensOut: 'tokensOut',\n estCostUsd: 'estCostUsd',\n sessions: 'sessions',\n cacheRead: 'cacheRead',\n cacheWrite: 'cacheWrite',\n cacheHitRate: 'cacheHitRate',\n} as const satisfies Record<string, keyof CoreDailyUsage>;\n\n// Referenced so the guards are not dead code under `noUnusedLocals`.\nexport const WIRE_CONTRACT_KEYS = {\n account: WIRE_ACCOUNT_KEYS,\n window: WIRE_WINDOW_KEYS,\n credits: WIRE_CREDITS_KEYS,\n accountsSnapshot: WIRE_ACCOUNTS_SNAPSHOT_KEYS,\n collector: WIRE_COLLECTOR_KEYS,\n localSnapshot: WIRE_LOCAL_SNAPSHOT_KEYS,\n localRuntime: WIRE_LOCAL_RUNTIME_KEYS,\n localModel: WIRE_LOCAL_MODEL_KEYS,\n dailyUsage: WIRE_DAILY_USAGE_KEYS,\n} as const;\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/accounts\n// ---------------------------------------------------------------------------\n\n/** Provider ids this surface knows how to describe. */\nexport type AccountProvider = 'claude' | 'codex' | 'grok';\n\n/**\n * One quota window on an account.\n *\n * `resetsAt` is an ISO string when the provider gave a real timestamp (Codex\n * publishes an epoch the server normalizes). Claude's is STRUCTURALLY always\n * null and the human sentence lives in `nativeReport.resetDescription`, which\n * is rendered verbatim and never turned into a countdown.\n */\nexport interface AccountWindow {\n id: string;\n /** Human label when the server supplies one; otherwise `id` is shown. */\n label: string | null;\n /** 0–100. `null` is \"no reading\", never 0. */\n usedPercent: number | null;\n /** ISO 8601, or null. */\n resetsAt: string | null;\n /** Verbatim provider prose, e.g. \"resets Sep 25 at 7pm (America/New_York)\". */\n resetDescription: string | null;\n /**\n * True when the provider signalled `rateLimitReachedType` — the upstream\n * writes the SENTINEL 100, which is a flag, not a measurement. Rendered as\n * \"limit reached\", never as \"100% used\".\n */\n limitReached: boolean;\n /**\n * False when `usedPercent` is a FLAGGED SENTINEL rather than a reading.\n *\n * Codex writes `rateLimitReachedType` upstream as the value 100, so a bare\n * 100 is indistinguishable from a genuinely measured 100 by the time it\n * arrives. The server distinguishes them; this surface must not collapse\n * them back together. Absent on the wire → assumed measured UNLESS the\n * limit flag is set, which is the only case where the sentinel is written.\n */\n measured: boolean;\n}\n\n/**\n * Codex credits. Independent of the window: a 100%-used week with a spendable\n * balance is NOT blocked, and this surface must not say it is.\n */\nexport interface AccountCredits {\n hasCredits: boolean;\n unlimited: boolean;\n /** Raw decimal string from the provider, kept verbatim for the title text. */\n balance: string | null;\n /** `balance` parsed, or null when it was absent/unparseable. */\n balanceValue: number | null;\n}\n\nexport interface Account {\n id: string;\n label: string;\n provider: AccountProvider;\n state: 'checking' | 'observed' | 'signed-out' | 'unavailable';\n authentication: 'signed-in' | 'signed-out' | 'unknown';\n /**\n * The connection monitor's own health verdict. Claude's is ALWAYS `unknown`\n * by construction (docs/VERSE-TELEMETRY-V2.md) — that is not a fault and is\n * never rendered as one.\n */\n health: string | null;\n planType: string | null;\n observedAt: string | null;\n windows: AccountWindow[];\n /**\n * The server's computed binding window (highest used percent). Kept as its\n * own field rather than recomputed blindly, but `accounts-model.ts` verifies\n * it against `windows` and falls back to computing it when absent.\n */\n binding: AccountWindow | null;\n credits: AccountCredits | null;\n /** Plain-language reason for a non-observed state. */\n reason: string | null;\n /**\n * Present when a probe failed CLOSED on a version pin (Claude's probe is\n * pinned to a specific Claude Code build). The fix is a one-line constant\n * bump, so the UI names it instead of showing a silent \"unknown\".\n */\n unsupported: { code: string; pinnedVersion: string | null } | null;\n /** Already sanitized — see `sanitizeCommand`. Null when nothing safe to show. */\n reconnectCommand: string | null;\n /**\n * The server's plain-language facts for this account (`VerseAccountRecord.\n * notes`). Grok's \"reconnect through `ashlr resources`, profile path withheld\n * on purpose\" lives here, which is why this surface shows notes rather than\n * only the machine-readable `reason`.\n */\n notes: string[];\n}\n\nexport interface AccountsSnapshot {\n sampledAt: string | null;\n refreshing: boolean;\n accounts: Account[];\n /**\n * Set when another collector process owns the quota-refresh lease, so these\n * readings are read-only and may be staler than this server's poll interval.\n */\n collectorNote: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/usage-series?window=7d|30d\n// ---------------------------------------------------------------------------\n\nexport type SeriesWindow = '7d' | '30d';\n\n/** `buildRollup(window, cfg).byDay` — see docs/VERSE-TELEMETRY-V2.md. */\nexport interface DailyUsage {\n /** YYYY-MM-DD. */\n day: string;\n tokensIn: number;\n tokensOut: number;\n /** ESTIMATED from a static price table. Never a billed figure. */\n estCostUsd: number;\n sessions: number;\n /** Optional: absent means the rollup carried no cache columns for that day. */\n cacheRead: number | null;\n cacheWrite: number | null;\n /** 0–1 fraction, or null. */\n cacheHitRate: number | null;\n}\n\nexport interface UsageSeries {\n window: SeriesWindow;\n days: DailyUsage[];\n generatedAt: string | null;\n /**\n * The server states outright that every cost column here is estimated.\n * Carried through rather than re-asserted locally so the disclosure the UI\n * prints is the one the producer actually made.\n */\n estimated: boolean;\n /** The server's own caveats, rendered verbatim beside the charts. */\n caveats: string[];\n}\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models\n// ---------------------------------------------------------------------------\n\nexport interface LocalModel {\n name: string;\n /** Which runtime reported it, so a flattened list stays attributable. */\n runtime: 'ollama' | 'lmstudio' | null;\n /** Resident in memory right now (Ollama /api/ps), vs merely installed. */\n loaded: boolean;\n /** Total resident bytes, or null when not reported. */\n sizeBytes: number | null;\n /** Of `sizeBytes`, how much sits in VRAM. null = not reported. */\n sizeVramBytes: number | null;\n /**\n * Where the weights actually sit. `split` is the one that matters: a model\n * that only half-fits the GPU runs at a fraction of the speed of one that\n * fits, and that is the difference between usable and not.\n */\n placement: 'gpu' | 'cpu' | 'split' | 'unknown';\n /** The runtime's own GPU share, 0–100. Preferred over recomputing it. */\n gpuPercent: number | null;\n /** Resident size against total machine memory, 0–100, else null. */\n memoryPercent: number | null;\n family: string | null;\n arch: string | null;\n /** Keep-alive expiry (ISO). Only meaningful while `loaded`. */\n expiresAt: string | null;\n /** e.g. \"79.7B\". Provider string, never parsed into a number for display. */\n parameterSize: string | null;\n /** e.g. \"Q4_K_M\". */\n quantization: string | null;\n /** Native context from model_info[\"<arch>.context_length\"]. */\n nativeContext: number | null;\n /** Context Ashlr actually configures for this seat, when it differs. */\n configuredContext: number | null;\n /**\n * `capabilities` from /api/show. `null` means the capability list was not\n * reported — which is NOT the same as \"does not support tools\".\n */\n capabilities: string[] | null;\n /**\n * The runtime's own answer to \"can this drive an agentic session\", which is\n * AUTHORITATIVE over `capabilities` and must be preferred when non-null.\n *\n * This matters: owner T sends `capabilities: []` when a runtime reported no\n * capability list, and reading that array alone would render \"no tools\" —\n * a hard, wrong gate — where T's `supportsTools: null` correctly means\n * \"unknown\". Deriving tool support from the array alone was a real defect\n * at this seam, not a cosmetic one.\n */\n supportsTools: boolean | null;\n}\n\n/**\n * One runtime's own reachability, kept per-runtime rather than folded into the\n * flattened list, because STALENESS is per-runtime and must be stated.\n *\n * `stale` means the server served a RETAINED known-good reading after a probe\n * TIMED OUT (core `VERSE_LOCAL_LAST_GOOD_TTL_MS`). That is the honest choice\n * server-side — a timeout is \"no answer yet\", not \"the runtime is gone\" — but\n * it obliges this surface to say plainly that the numbers are N seconds old\n * rather than presenting them as fresh.\n */\nexport interface LocalRuntimeStatus {\n runtime: 'ollama' | 'lmstudio';\n reachable: boolean;\n /** Machine-readable degradation code; never rendered as a sentence. */\n reason: string | null;\n /** True when this report is a retained reading rather than a fresh probe. */\n stale: boolean;\n /** Age of that retained reading in ms. Null when `stale` is false. */\n staleForMs: number | null;\n modelCount: number;\n}\n\nexport interface LocalModelsSnapshot {\n reachable: boolean;\n models: LocalModel[];\n /** Machine memory budget in bytes, or null when the server did not say. */\n memoryBudgetBytes: number | null;\n /** Machine memory reported free right now, or null. */\n freeMemoryBytes: number | null;\n reason: string | null;\n /** Per-runtime reachability and staleness. Empty on a flat legacy body. */\n runtimes: LocalRuntimeStatus[];\n /** The server's own plain-language caveats for this snapshot. */\n notes: string[];\n sampledAt: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Narrowing helpers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction str(source: Record<string, unknown>, key: string): string | null {\n const v = source[key];\n return typeof v === 'string' && v.length > 0 ? v : null;\n}\n\nfunction num(source: Record<string, unknown>, key: string): number | null {\n const v = source[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n}\n\nfunction bool(source: Record<string, unknown>, key: string, fallback = false): boolean {\n const v = source[key];\n return typeof v === 'boolean' ? v : fallback;\n}\n\nfunction list(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n\n/**\n * Drop anything that looks like a native-profile launcher invocation or an\n * absolute path into the private account store. The server is supposed to\n * strip these; this is the client-side backstop, because the cost of printing\n * one is unacceptable and the cost of showing \"no command\" is a sentence.\n */\nconst FORBIDDEN_COMMAND = /(launcher\\.mjs|native-profiles|account-connections|console-startup|\\/\\.ashlr\\b|Bearer\\s|--token\\b)/i;\n\nexport function sanitizeCommand(value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed.length === 0 || trimmed.length > 200) return null;\n if (FORBIDDEN_COMMAND.test(trimmed)) return null;\n // A newline would let a payload smuggle a second command onto the surface.\n if (/[\\r\\n]/.test(trimmed)) return null;\n return trimmed;\n}\n\nfunction clampPercent(value: number | null): number | null {\n if (value === null) return null;\n return Math.max(0, Math.min(100, value));\n}\n\nfunction projectWindow(raw: unknown): AccountWindow | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id') ?? str(r, 'label');\n if (id === null) return null;\n const native = record(r['nativeReport']);\n const limitReached = bool(r, 'limitReached') || bool(r, 'rateLimitReached');\n const measuredRaw = r['measured'];\n return {\n id,\n label: str(r, 'label'),\n usedPercent: clampPercent(num(r, 'usedPercent') ?? num(r, 'used_percent')),\n resetsAt: str(r, 'resetsAt') ?? str(r, 'resets_at'),\n resetDescription:\n (native ? str(native, 'resetDescription') : null) ?? str(r, 'resetDescription'),\n limitReached,\n // Absent → measured, EXCEPT under a limit flag, which is the one case the\n // upstream writes the sentinel 100. Defaulting a flagged window to\n // `measured: true` would let a denial print as \"100% used\".\n measured: typeof measuredRaw === 'boolean' ? measuredRaw : !limitReached,\n };\n}\n\nfunction projectCredits(raw: unknown): AccountCredits | null {\n const r = record(raw);\n if (!r) return null;\n const balance = str(r, 'balance');\n const parsed = balance === null ? num(r, 'balance') : Number.parseFloat(balance);\n return {\n hasCredits: bool(r, 'hasCredits') || bool(r, 'has_credits'),\n unlimited: bool(r, 'unlimited'),\n balance,\n balanceValue: typeof parsed === 'number' && Number.isFinite(parsed) ? parsed : null,\n };\n}\n\nconst PROVIDERS: readonly string[] = ['claude', 'codex', 'grok'];\n\nfunction projectAccount(raw: unknown): Account | null {\n const r = record(raw);\n if (!r) return null;\n const id = str(r, 'id');\n const provider = str(r, 'provider');\n if (id === null || provider === null || !PROVIDERS.includes(provider)) return null;\n\n const windows = list(r['windows'])\n .map(projectWindow)\n .filter((w): w is AccountWindow => w !== null);\n\n const state = str(r, 'state');\n const auth = str(r, 'authentication');\n const unsupportedRaw = record(r['unsupported']);\n\n return {\n id,\n label: str(r, 'label') ?? id,\n provider: provider as AccountProvider,\n state:\n state === 'checking' || state === 'observed' || state === 'signed-out' || state === 'unavailable'\n ? state\n : 'unavailable',\n authentication: auth === 'signed-in' || auth === 'signed-out' ? auth : 'unknown',\n health: str(r, 'health'),\n planType: str(r, 'planType') ?? str(r, 'plan_type'),\n observedAt: str(r, 'observedAt'),\n windows,\n binding: projectWindow(r['binding']),\n credits: projectCredits(r['credits']),\n reason: str(r, 'reason'),\n unsupported: projectUnsupported(r, unsupportedRaw),\n reconnectCommand: sanitizeCommand(r['reconnectCommand']),\n notes: list(r['notes']).filter((n): n is string => typeof n === 'string'),\n };\n}\n\n/**\n * A version-pinned probe that failed CLOSED, named rather than swallowed.\n *\n * `unsupported` is not a field on the wire. Owner T reports the failure as the\n * verbatim probe code in `reason` (`usage-version-unsupported`) and states the\n * pin in `notes`, so this derives the structured form from those rather than\n * requiring a late contract change. An explicit `unsupported` object is still\n * honoured first, so a server that grows one later wins without a client edit.\n */\nfunction projectUnsupported(\n r: Record<string, unknown>,\n explicit: Record<string, unknown> | null,\n): Account['unsupported'] {\n if (explicit) {\n return {\n code: str(explicit, 'code') ?? CLAUDE_VERSION_REASON,\n pinnedVersion: str(explicit, 'pinnedVersion') ?? str(explicit, 'version'),\n };\n }\n const reason = str(r, 'reason');\n if (reason !== CLAUDE_VERSION_REASON) return null;\n return { code: reason, pinnedVersion: CLAUDE_USAGE_PINNED_VERSION };\n}\n\n/**\n * The read-only banner. Owner T reports lease ownership as a structured\n * `collector` status, not a flat `collectorNote`, so the note is derived from\n * it — and ONLY when another process owns the lease, because that is the one\n * case where these readings may be staler than this server's poll interval.\n * A stray `collectorNote` string is still accepted for forward compatibility.\n */\nfunction projectCollectorNote(root: Record<string, unknown>): string | null {\n const flat = str(root, 'collectorNote');\n if (flat) return flat;\n const collector = record(root['collector']);\n if (!collector) return null;\n if (str(collector, 'owner') !== 'another-collector') return null;\n return (\n str(collector, 'note') ??\n 'Another collector process owns the quota-refresh lease, so these readings are read-only and may be staler than this server’s poll interval.'\n );\n}\n\nexport function projectAccountsSnapshot(raw: unknown): AccountsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n const rawAccounts = Array.isArray(root['accounts']) ? root['accounts'] : Array.isArray(raw) ? raw : null;\n if (rawAccounts === null) return null;\n return {\n sampledAt: str(root, 'sampledAt'),\n refreshing: bool(root, 'refreshing'),\n accounts: rawAccounts.map(projectAccount).filter((a): a is Account => a !== null),\n collectorNote: projectCollectorNote(root),\n };\n}\n\nfunction projectDay(raw: unknown): DailyUsage | null {\n const r = record(raw);\n if (!r) return null;\n const day = str(r, 'day');\n if (day === null || !/^\\d{4}-\\d{2}-\\d{2}$/.test(day)) return null;\n return {\n day,\n tokensIn: num(r, 'tokensIn') ?? 0,\n tokensOut: num(r, 'tokensOut') ?? 0,\n estCostUsd: num(r, 'estCostUsd') ?? 0,\n sessions: num(r, 'sessions') ?? 0,\n cacheRead: num(r, 'cacheRead'),\n cacheWrite: num(r, 'cacheWrite'),\n cacheHitRate: num(r, 'cacheHitRate'),\n };\n}\n\n/**\n * `byDay` is the wire key. Owner T wraps the series as\n * `{window, byDay, estimated, caveats}` rather than returning a bare array\n * (documented deviation 1), so `byDay` is read FIRST. `days` and a bare array\n * remain accepted so an older or differently-shaped server degrades to a\n * rendered series instead of a dead panel.\n */\nexport function projectUsageSeries(raw: unknown, requested: SeriesWindow): UsageSeries | null {\n const root = record(raw);\n const rawDays = root\n ? Array.isArray(root['byDay'])\n ? root['byDay']\n : Array.isArray(root['days'])\n ? root['days']\n : null\n : Array.isArray(raw)\n ? raw\n : null;\n if (rawDays === null) return null;\n const windowValue = root ? str(root, 'window') : null;\n return {\n window: windowValue === '7d' || windowValue === '30d' ? windowValue : requested,\n days: rawDays\n .map(projectDay)\n .filter((d): d is DailyUsage => d !== null)\n .sort((a, b) => a.day.localeCompare(b.day)),\n generatedAt: root ? str(root, 'generatedAt') : null,\n // The producer asserts estimation explicitly. Absent → still true: every\n // cost column on this route is price-table derived, and defaulting the\n // disclosure OFF would drop it exactly when the server is older.\n estimated: root ? bool(root, 'estimated', true) : true,\n caveats: root ? list(root['caveats']).filter((c): c is string => typeof c === 'string') : [],\n };\n}\n\nfunction projectLocalModel(raw: unknown, runtime: LocalModel['runtime']): LocalModel | null {\n const r = record(raw);\n if (!r) return null;\n // `label`/`id` are owner T's spellings; `name`/`model` are the Ollama-native\n // ones a differently-shaped server might send.\n const name = str(r, 'label') ?? str(r, 'id') ?? str(r, 'name') ?? str(r, 'model');\n if (name === null) return null;\n const caps = r['capabilities'];\n const state = str(r, 'state');\n const supportsTools = r['supportsTools'];\n\n // `nativeContextLength` is the architecture maximum; `contextLength` is what\n // the runtime actually configured for the loaded instance. They are two\n // different facts and the panel shows the gap between them, so they must not\n // collapse onto one field.\n const nativeContext = num(r, 'nativeContextLength') ?? num(r, 'nativeContext');\n const configuredContext = num(r, 'contextLength') ?? num(r, 'configuredContext');\n\n const placement = str(r, 'placement');\n\n return {\n name,\n runtime,\n loaded: state !== null ? state === 'loaded' : bool(r, 'loaded') || bool(r, 'resident'),\n sizeBytes: num(r, 'sizeBytes') ?? num(r, 'size'),\n sizeVramBytes: num(r, 'sizeVramBytes') ?? num(r, 'size_vram'),\n placement:\n placement === 'gpu' || placement === 'cpu' || placement === 'split' ? placement : 'unknown',\n gpuPercent: clampPercent(num(r, 'gpuPercent')),\n memoryPercent: clampPercent(num(r, 'memoryPercent')),\n family: str(r, 'family'),\n arch: str(r, 'arch'),\n expiresAt: str(r, 'expiresAt') ?? str(r, 'expires_at'),\n parameterSize: str(r, 'parameterSize') ?? str(r, 'parameter_size'),\n quantization: str(r, 'quantization') ?? str(r, 'quantization_level'),\n nativeContext,\n // Only a genuine narrowing is worth showing. When the runtime reports the\n // same number twice there is no truncation to report.\n configuredContext:\n configuredContext !== null && nativeContext !== null && configuredContext === nativeContext\n ? null\n : configuredContext,\n capabilities: Array.isArray(caps) ? caps.filter((c): c is string => typeof c === 'string') : null,\n supportsTools: typeof supportsTools === 'boolean' ? supportsTools : null,\n };\n}\n\nfunction projectRuntimeReport(\n raw: unknown,\n runtime: NonNullable<LocalModel['runtime']>,\n): { status: LocalRuntimeStatus; models: LocalModel[] } | null {\n const r = record(raw);\n if (!r) return null;\n const rawModels = Array.isArray(r['models']) ? r['models'] : null;\n if (rawModels === null) return null;\n const models = rawModels\n .map((m) => projectLocalModel(m, runtime))\n .filter((m): m is LocalModel => m !== null);\n const stale = bool(r, 'stale');\n return {\n models,\n status: {\n runtime,\n reachable: bool(r, 'reachable'),\n reason: str(r, 'reason'),\n stale,\n // Only meaningful under `stale`. A staleForMs on a fresh report would be\n // a contradiction, and printing it would age a current reading.\n staleForMs: stale ? num(r, 'staleForMs') : null,\n modelCount: models.length,\n },\n };\n}\n\n/**\n * Owner T reports local availability per RUNTIME (`ollama`, `lmStudio`) with a\n * shared `machine` budget. This panel answers one question — \"what can I run\n * right now, and against how much memory\" — so the runtimes are flattened into\n * one list, each row keeping its `runtime` so it stays attributable.\n *\n * Reachability is the OR of the runtimes: one dead runtime is not an unreachable\n * local stack. `reason` is only carried when NOTHING is reachable, because a\n * degradation note beside a working list would misdescribe what is on screen.\n *\n * A flat `{reachable, models, memoryBudgetBytes}` body is still accepted, so an\n * older or differently-shaped server degrades rather than rendering nothing.\n */\nexport function projectLocalModels(raw: unknown): LocalModelsSnapshot | null {\n const root = record(raw);\n if (!root) return null;\n\n const ollama = projectRuntimeReport(root['ollama'], 'ollama');\n const lmStudio = projectRuntimeReport(root['lmStudio'] ?? root['lmstudio'], 'lmstudio');\n\n if (ollama !== null || lmStudio !== null) {\n const reports = [ollama, lmStudio].filter((x): x is NonNullable<typeof x> => x !== null);\n const reachable = reports.some((x) => x.status.reachable);\n const machine = record(root['machine']);\n return {\n reachable,\n models: reports.flatMap((x) => x.models),\n memoryBudgetBytes:\n (machine ? num(machine, 'totalMemoryBytes') : null) ??\n num(root, 'memoryBudgetBytes') ??\n num(root, 'memoryBudget'),\n freeMemoryBytes: machine ? num(machine, 'freeMemoryBytes') : null,\n reason: reachable\n ? null\n : (reports.map((x) => x.status.reason).find((x) => x !== null) ?? null),\n runtimes: reports.map((x) => x.status),\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n }\n\n const rawModels = Array.isArray(root['models']) ? root['models'] : null;\n if (rawModels === null) return null;\n return {\n reachable: bool(root, 'reachable', true),\n models: rawModels.map((m) => projectLocalModel(m, null)).filter((m): m is LocalModel => m !== null),\n memoryBudgetBytes: num(root, 'memoryBudgetBytes') ?? num(root, 'memoryBudget'),\n freeMemoryBytes: num(root, 'freeMemoryBytes'),\n reason: str(root, 'reason'),\n // A flat legacy body carries no per-runtime reachability, so there is\n // nothing to attribute and nothing to call stale. An empty list says that\n // honestly; a fabricated entry would not.\n runtimes: [],\n notes: list(root['notes']).filter((n): n is string => typeof n === 'string'),\n sampledAt: str(root, 'sampledAt'),\n };\n}\n","/**\n * routes/verse/usage/usage-queries.ts — the reads behind the Usage section.\n *\n * `/api/control` is fetched through the shared `controlSnapshotQuery` so this\n * section rides the same cache (and the same SSE invalidation) as every other\n * view rather than opening a second copy of a large snapshot.\n *\n * `/api/verse/control` is owner B's new route. It is fetched through a\n * NON-throwing wrapper because this section must still render when the route\n * is absent (server started without --allow-dispatch, or B's route not landed\n * yet): a missing configured-caps source is a degraded panel, not a dead\n * section. 401 is the one error that still propagates — an expired read\n * session is an unauthorized state for the whole surface, not a degraded one.\n *\n * The cache key is deliberately NOT shared with the Autonomy section's own\n * read of the same route: this module stores a wrapper shape, and two owners\n * writing different value types under one key would be a real bug.\n */\nimport type { FrontierUsage } from '../../../../core/usage/frontier-usage.js';\nimport { ApiError, apiGet } from '../../../data/client.js';\nimport type { QueryDef } from '../../../data/queries.js';\nimport { projectLocalModels, type SeriesWindow } from './usage-contract.js';\n\nexport const USAGE_FRONTIER_KEY = 'verse-usage-frontier';\nexport const USAGE_VERSE_CONTROL_KEY = 'verse-usage-control';\n\n/** GET /api/usage — per-engine frontier usage (see core/usage/frontier-usage.ts). */\nexport const frontierUsageQuery: QueryDef<FrontierUsage> = {\n key: USAGE_FRONTIER_KEY,\n fetch: (signal) => apiGet<FrontierUsage>('/api/usage', signal),\n};\n\nexport interface VerseControlRead {\n /** Raw body; narrowed by `projectVerseControl` (owner B's types are not landed). */\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeControlFailure(err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return 'This server does not expose /api/verse/control, so configured caps and today’s spend are unavailable here.';\n }\n return `Configured caps unavailable (HTTP ${err.status}).`;\n }\n return 'Configured caps unavailable: the request failed.';\n}\n\nexport const verseControlQuery: QueryDef<VerseControlRead> = {\n key: USAGE_VERSE_CONTROL_KEY,\n fetch: async (signal) => {\n try {\n const raw = await apiGet<unknown>('/api/verse/control', signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeControlFailure(err) };\n }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Owner T's routes (GET /api/verse/{accounts,usage-series,local-models})\n// ---------------------------------------------------------------------------\n//\n// These three are fetched through the SAME non-throwing wrapper pattern as\n// /api/verse/control, for the same reason and one more: they are landing in\n// parallel with this section. A server that predates them answers 404, and a\n// 404 here means \"this panel is degraded\", not \"the Usage view is broken\".\n// 401 still propagates, because an expired read session is an unauthorized\n// state for the whole surface.\n//\n// The bodies are narrowed structurally by usage-contract.ts rather than cast,\n// so a field-name drift between T's route and this client degrades to an\n// honest \"unknown\" instead of throwing at render time.\n\nexport const USAGE_ACCOUNTS_KEY = 'verse-usage-accounts';\nexport const USAGE_LOCAL_MODELS_KEY = 'verse-usage-local-models';\nexport const USAGE_SERIES_KEY_PREFIX = 'verse-usage-series';\n\n/** A read that is allowed to be absent. `raw` is null when it was. */\nexport interface OptionalRead {\n raw: unknown;\n available: boolean;\n reason: string | null;\n}\n\nfunction describeOptionalFailure(path: string, err: unknown): string {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n return `This server does not expose ${path} yet, so this panel has no source.`;\n }\n return `${path} answered HTTP ${err.status}.`;\n }\n return `${path} could not be reached.`;\n}\n\nfunction optionalGet(path: string): (signal?: AbortSignal) => Promise<OptionalRead> {\n return async (signal) => {\n try {\n const raw = await apiGet<unknown>(path, signal);\n return { raw, available: true, reason: null };\n } catch (err) {\n if (err instanceof ApiError && err.status === 401) throw err;\n if (err instanceof DOMException && err.name === 'AbortError') throw err;\n return { raw: null, available: false, reason: describeOptionalFailure(path, err) };\n }\n };\n}\n\n/** GET /api/verse/accounts — per-account state, windows, credits, plan. */\nexport const verseAccountsQuery: QueryDef<OptionalRead> = {\n key: USAGE_ACCOUNTS_KEY,\n fetch: optionalGet('/api/verse/accounts'),\n};\n\n// ---------------------------------------------------------------------------\n// GET /api/verse/local-models — and why this one read retries\n// ---------------------------------------------------------------------------\n//\n// `/api/verse/local-models` probes the runtimes live on every request, with a\n// 2s per-probe timeout (core/verse/local-models.ts\n// VERSE_LOCAL_PROBE_TIMEOUT_MS). A probe that times out is reported as\n// `{reachable: false, reason: 'ollama-unreachable'}` in a perfectly ordinary\n// HTTP 200 — which is correct on the server's terms (it genuinely did not get\n// an answer) but is NOT the same fact as \"Ollama is not running\", and nothing\n// in the payload distinguishes the two.\n//\n// That distinction matters here because this section is the thing that causes\n// the timeout. Mounting Usage, and every press of its Refresh button, fires\n// seven reads at once, several of which spawn short-lived account-probe\n// processes server-side; measured against a live Ollama with twelve models,\n// roughly one burst in ten starves the 2s probe and comes back\n// `ollama-unreachable`. Nothing re-reads this route afterwards — it has no SSE\n// invalidation key — so that one false negative is what the operator stares\n// at, and pressing Refresh re-creates the very burst that produced it.\n//\n// So a reported-unreachable local stack is RE-READ, up to twice, with a short\n// gap for the burst to drain. This is not \"ignore the failure\": the retries\n// are bounded, each one is a real request, and whatever the last read says is\n// what this section renders — a runtime that is genuinely down answers fast\n// (connection refused, not a timeout) and still reports unreachable, three\n// times, in well under a second.\n//\n// Only an AVAILABLE read is retried. A 404/500 (`available: false`) is a\n// statement about the route, not about the runtime, and re-asking cannot\n// change it.\n\n/** Two extra reads at most, spaced so the section's own request burst drains. */\nconst LOCAL_MODELS_RETRY_DELAYS_MS = [350, 1200] as const;\n\nconst readLocalModels = optionalGet('/api/verse/local-models');\n\nfunction reportsNothingReachable(read: OptionalRead): boolean {\n if (!read.available) return false;\n const snapshot = projectLocalModels(read.raw);\n return snapshot !== null && !snapshot.reachable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** GET /api/verse/local-models — resident vs installed, VRAM split, tools. */\nexport const verseLocalModelsQuery: QueryDef<OptionalRead> = {\n key: USAGE_LOCAL_MODELS_KEY,\n fetch: async (signal) => {\n let read = await readLocalModels(signal);\n for (const delayMs of LOCAL_MODELS_RETRY_DELAYS_MS) {\n if (!reportsNothingReachable(read)) return read;\n await sleep(delayMs, signal);\n read = await readLocalModels(signal);\n }\n return read;\n },\n};\n\n// One QueryDef per window, created once at module scope: useQuery keys on\n// `def.key`, and minting a fresh object per render would be harmless but\n// useRefresh/useRefetch's useCallback deps would churn for no reason.\nconst SERIES_QUERIES: Record<SeriesWindow, QueryDef<OptionalRead>> = {\n '7d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:7d`,\n fetch: optionalGet('/api/verse/usage-series?window=7d'),\n },\n '30d': {\n key: `${USAGE_SERIES_KEY_PREFIX}:30d`,\n fetch: optionalGet('/api/verse/usage-series?window=30d'),\n },\n};\n\nexport function usageSeriesQuery(window: SeriesWindow): QueryDef<OptionalRead> {\n return SERIES_QUERIES[window];\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=use-guarded-action-
|
|
1
|
+
import{a as e,c as t}from"./index-DZ-UQ7v8.js";import{A as n,o as r,s as i}from"./global-CMNW_dqn.js";import{y as a}from"./format-CH4g_sl1.js";import{n as o}from"./control-queries-B9K-wmcB.js";var s=t(e(),1);function c(e){return e instanceof i?`This server runs without dispatch, so that action is unavailable.`:e instanceof o?e.message:e instanceof r?e.status===401?"The mutation token was rejected. Unlock again with the token `ashlr verse` printed.":e.detail?a(e.detail):e.status===400?a(e.message):e.status===409?`The server refused the action, and sent no reason.`:a(e.message):e instanceof Error?a(e.message):`That action failed. Try again.`}function l(){let[e,t]=(0,s.useState)(!1),[r,a]=(0,s.useState)(null),[o,l]=(0,s.useState)(!1),[u,d]=(0,s.useState)(!1),[f,p]=(0,s.useState)(``),m=(0,s.useRef)(null),h=(0,s.useCallback)(async(e,n)=>{t(!0),a(null);try{let t=await e();n?.(t)}catch(e){e instanceof i?l(!0):a(c(e))}finally{t(!1)}},[]),g=(0,s.useCallback)((e,t,r)=>{a(null);let i=r;if(n()){h(e,i);return}m.current={fn:e,onResult:i},p(t),d(!0)},[h]),_=(0,s.useCallback)(()=>{d(!1);let e=m.current;m.current=null,e&&n()&&h(e.fn,e.onResult)},[h]);return{request:g,busy:e,error:r,clearError:(0,s.useCallback)(()=>a(null),[]),readOnly:o,tokenOpen:u,tokenReason:f,closeToken:_}}export{l as n,c as t};
|
|
2
|
+
//# sourceMappingURL=use-guarded-action-CuuMHeDX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-guarded-action-
|
|
1
|
+
{"version":3,"file":"use-guarded-action-CuuMHeDX.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-DZ-UQ7v8.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-BBcp02SZ.js.map
|
package/dist/core/web/public/next/assets/{use-ticker-CkJ4-0wU.js.map → use-ticker-BBcp02SZ.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-ticker-
|
|
1
|
+
{"version":3,"file":"use-ticker-BBcp02SZ.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-CYcfk_GS.js → use-token-gate-CbXVYQYI.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-DZ-UQ7v8.js";import{A as n,o as r,s as i}from"./global-CMNW_dqn.js";import{i as a}from"./VerseConsoleApp-CWU6R3By.js";import{y as o}from"./format-CH4g_sl1.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-CbXVYQYI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-token-gate-
|
|
1
|
+
{"version":3,"file":"use-token-gate-CbXVYQYI.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-CujRS6PK.js → useOnboarding-C_Fpe_sH.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-DZ-UQ7v8.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-C_Fpe_sH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOnboarding-
|
|
1
|
+
{"version":3,"file":"useOnboarding-C_Fpe_sH.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-BEaQdkZs.js → useSeatsRefresh-Co1CnxLc.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-DZ-UQ7v8.js";import{U as n,g as r,h as i,l as a,q as o}from"./global-CMNW_dqn.js";import{S as s,n as c}from"./VerseConsoleApp-CWU6R3By.js";import{C as l,E as u}from"./capacity-strip-model-BwZ1ZbkU.js";var d=t(e(),1),f=3e4;function p(e=!0){let t=i(u),n=r(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=n(c).data,t=()=>s.fetch();return e===void 0?o(c,t):o(c,l(async()=>{let t=await a(h);return g(n(`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-Co1CnxLc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSeatsRefresh-
|
|
1
|
+
{"version":3,"file":"useSeatsRefresh-Co1CnxLc.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-DZ-UQ7v8.js";import{Et as n}from"./VerseConsoleApp-CWU6R3By.js";import{a as r,m as i,o as a}from"./verse-store-DNVRuiJL.js";import{o}from"./slots-C-qBeu-8.js";import{n as s}from"./ChatSection-DlT4QU6a.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-DgbigUlV.js.map
|