@ashlr/hub 3.13.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.
Files changed (625) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/dist/authority-surface.json +204 -124
  3. package/dist/build-identity.json +2 -2
  4. package/dist/cli/authority.js +112 -18
  5. package/dist/cli/authority.js.map +1 -1
  6. package/dist/cli/comms.d.ts +33 -19
  7. package/dist/cli/comms.js +128 -151
  8. package/dist/cli/comms.js.map +1 -1
  9. package/dist/cli/completions.js +1 -1
  10. package/dist/cli/completions.js.map +1 -1
  11. package/dist/cli/daemon.js +29 -0
  12. package/dist/cli/daemon.js.map +1 -1
  13. package/dist/cli/director.d.ts +8 -12
  14. package/dist/cli/director.js +17 -52
  15. package/dist/cli/director.js.map +1 -1
  16. package/dist/cli/fleet.js +4 -1
  17. package/dist/cli/fleet.js.map +1 -1
  18. package/dist/cli/help.js +1 -0
  19. package/dist/cli/help.js.map +1 -1
  20. package/dist/cli/leader.d.ts +27 -3
  21. package/dist/cli/leader.js +253 -4
  22. package/dist/cli/leader.js.map +1 -1
  23. package/dist/core/authority/server-enforcement.d.ts +110 -0
  24. package/dist/core/authority/server-enforcement.js +260 -0
  25. package/dist/core/authority/server-enforcement.js.map +1 -0
  26. package/dist/core/authority/standing-grant.d.ts +24 -4
  27. package/dist/core/authority/standing-grant.js +19 -3
  28. package/dist/core/authority/standing-grant.js.map +1 -1
  29. package/dist/core/cloud/timeline.js +13 -7
  30. package/dist/core/cloud/timeline.js.map +1 -1
  31. package/dist/core/comms/change-digest.d.ts +130 -0
  32. package/dist/core/comms/change-digest.js +451 -0
  33. package/dist/core/comms/change-digest.js.map +1 -0
  34. package/dist/core/comms/director-prompt.d.ts +4 -5
  35. package/dist/core/comms/director-prompt.js +4 -71
  36. package/dist/core/comms/director-prompt.js.map +1 -1
  37. package/dist/core/comms/director.d.ts +24 -61
  38. package/dist/core/comms/director.js +29 -382
  39. package/dist/core/comms/director.js.map +1 -1
  40. package/dist/core/comms/dispatch.d.ts +37 -12
  41. package/dist/core/comms/dispatch.js +244 -177
  42. package/dist/core/comms/dispatch.js.map +1 -1
  43. package/dist/core/comms/elon-dialogue.d.ts +23 -15
  44. package/dist/core/comms/elon-dialogue.js +36 -307
  45. package/dist/core/comms/elon-dialogue.js.map +1 -1
  46. package/dist/core/comms/fleet-pulse.js +4 -7
  47. package/dist/core/comms/fleet-pulse.js.map +1 -1
  48. package/dist/core/comms/handlers.d.ts +10 -6
  49. package/dist/core/comms/handlers.js +14 -48
  50. package/dist/core/comms/handlers.js.map +1 -1
  51. package/dist/core/comms/migrations.d.ts +47 -0
  52. package/dist/core/comms/migrations.js +125 -0
  53. package/dist/core/comms/migrations.js.map +1 -0
  54. package/dist/core/comms/requests.d.ts +32 -5
  55. package/dist/core/comms/requests.js +101 -5
  56. package/dist/core/comms/requests.js.map +1 -1
  57. package/dist/core/comms/telegram-channel.d.ts +104 -0
  58. package/dist/core/comms/telegram-channel.js +622 -0
  59. package/dist/core/comms/telegram-channel.js.map +1 -0
  60. package/dist/core/comms/telegram-thread-map.d.ts +56 -0
  61. package/dist/core/comms/telegram-thread-map.js +144 -0
  62. package/dist/core/comms/telegram-thread-map.js.map +1 -0
  63. package/dist/core/daemon/capacity-publisher.d.ts +8 -1
  64. package/dist/core/daemon/capacity-publisher.js +40 -2
  65. package/dist/core/daemon/capacity-publisher.js.map +1 -1
  66. package/dist/core/daemon/loop.js +18 -4
  67. package/dist/core/daemon/loop.js.map +1 -1
  68. package/dist/core/daemon/tick-deadline.d.ts +44 -0
  69. package/dist/core/daemon/tick-deadline.js +83 -0
  70. package/dist/core/daemon/tick-deadline.js.map +1 -0
  71. package/dist/core/daemon/tick-hooks.d.ts +7 -0
  72. package/dist/core/daemon/tick-hooks.js.map +1 -1
  73. package/dist/core/daemon/tick-progress.d.ts +39 -0
  74. package/dist/core/daemon/tick-progress.js +194 -0
  75. package/dist/core/daemon/tick-progress.js.map +1 -0
  76. package/dist/core/dashboard.js +3 -1
  77. package/dist/core/dashboard.js.map +1 -1
  78. package/dist/core/fleet/fleet-merge-state.d.ts +6 -0
  79. package/dist/core/fleet/fleet-merge-state.js.map +1 -1
  80. package/dist/core/fleet/host-merge.d.ts +9 -0
  81. package/dist/core/fleet/host-merge.js +13 -2
  82. package/dist/core/fleet/host-merge.js.map +1 -1
  83. package/dist/core/fleet/merge-gates.d.ts +13 -0
  84. package/dist/core/fleet/merge-gates.js +14 -0
  85. package/dist/core/fleet/merge-gates.js.map +1 -1
  86. package/dist/core/fleet/mirrors.d.ts +162 -6
  87. package/dist/core/fleet/mirrors.js +1051 -49
  88. package/dist/core/fleet/mirrors.js.map +1 -1
  89. package/dist/core/fleet/standing-merge-pass.d.ts +8 -0
  90. package/dist/core/fleet/standing-merge-pass.js +72 -1
  91. package/dist/core/fleet/standing-merge-pass.js.map +1 -1
  92. package/dist/core/fleet/status.d.ts +17 -0
  93. package/dist/core/fleet/status.js +22 -0
  94. package/dist/core/fleet/status.js.map +1 -1
  95. package/dist/core/fleet/tick-hooks-live.d.ts +1 -1
  96. package/dist/core/fleet/tick-hooks-live.js +13 -3
  97. package/dist/core/fleet/tick-hooks-live.js.map +1 -1
  98. package/dist/core/git.d.ts +17 -0
  99. package/dist/core/git.js +124 -25
  100. package/dist/core/git.js.map +1 -1
  101. package/dist/core/goals/open-goals.d.ts +47 -0
  102. package/dist/core/goals/open-goals.js +33 -0
  103. package/dist/core/goals/open-goals.js.map +1 -0
  104. package/dist/core/inbox/merge.d.ts +5 -0
  105. package/dist/core/inbox/merge.js +58 -2
  106. package/dist/core/inbox/merge.js.map +1 -1
  107. package/dist/core/integrations/locus.d.ts +28 -0
  108. package/dist/core/integrations/locus.js +155 -30
  109. package/dist/core/integrations/locus.js.map +1 -1
  110. package/dist/core/integrations/telegram-format.d.ts +40 -0
  111. package/dist/core/integrations/telegram-format.js +123 -0
  112. package/dist/core/integrations/telegram-format.js.map +1 -0
  113. package/dist/core/integrations/telegram.d.ts +60 -4
  114. package/dist/core/integrations/telegram.js +161 -28
  115. package/dist/core/integrations/telegram.js.map +1 -1
  116. package/dist/core/mcp-registry.d.ts +12 -0
  117. package/dist/core/mcp-registry.js +70 -0
  118. package/dist/core/mcp-registry.js.map +1 -1
  119. package/dist/core/observability/rollup.d.ts +12 -10
  120. package/dist/core/observability/rollup.js +44 -17
  121. package/dist/core/observability/rollup.js.map +1 -1
  122. package/dist/core/resources/connection-monitor.d.ts +9 -0
  123. package/dist/core/resources/connection-monitor.js +19 -9
  124. package/dist/core/resources/connection-monitor.js.map +1 -1
  125. package/dist/core/resources/quota-refresh-lease.d.ts +17 -0
  126. package/dist/core/resources/quota-refresh-lease.js +34 -1
  127. package/dist/core/resources/quota-refresh-lease.js.map +1 -1
  128. package/dist/core/routing/budget-api.d.ts +7 -1
  129. package/dist/core/routing/budget-api.js +56 -2
  130. package/dist/core/routing/budget-api.js.map +1 -1
  131. package/dist/core/routing/readiness-types.d.ts +82 -0
  132. package/dist/core/routing/readiness-types.js +23 -0
  133. package/dist/core/routing/readiness-types.js.map +1 -0
  134. package/dist/core/routing/readiness.d.ts +103 -0
  135. package/dist/core/routing/readiness.js +480 -0
  136. package/dist/core/routing/readiness.js.map +1 -0
  137. package/dist/core/sandbox/confine.js +22 -1
  138. package/dist/core/sandbox/confine.js.map +1 -1
  139. package/dist/core/sandbox/policy.d.ts +23 -0
  140. package/dist/core/sandbox/policy.js +100 -0
  141. package/dist/core/sandbox/policy.js.map +1 -1
  142. package/dist/core/types.d.ts +13 -0
  143. package/dist/core/types.js.map +1 -1
  144. package/dist/core/universe/builtins/preparation/manifest.json +1 -1
  145. package/dist/core/universe/builtins/preparation/preparation-bridge.mjs +1204 -939
  146. package/dist/core/universe/builtins/preparation/preparation-verification-fixtures.mjs +1319 -1054
  147. package/dist/core/usage/frontier-usage.d.ts +20 -2
  148. package/dist/core/usage/frontier-usage.js +75 -17
  149. package/dist/core/usage/frontier-usage.js.map +1 -1
  150. package/dist/core/verse/accounts.d.ts +45 -0
  151. package/dist/core/verse/accounts.js +246 -17
  152. package/dist/core/verse/accounts.js.map +1 -1
  153. package/dist/core/verse/apps-api.js +23 -11
  154. package/dist/core/verse/apps-api.js.map +1 -1
  155. package/dist/core/verse/apps.d.ts +11 -9
  156. package/dist/core/verse/apps.js +2 -2
  157. package/dist/core/verse/apps.js.map +1 -1
  158. package/dist/core/verse/authority-api.d.ts +8 -2
  159. package/dist/core/verse/authority-api.js +40 -5
  160. package/dist/core/verse/authority-api.js.map +1 -1
  161. package/dist/core/verse/autonomy-ladder.d.ts +172 -0
  162. package/dist/core/verse/autonomy-ladder.js +251 -0
  163. package/dist/core/verse/autonomy-ladder.js.map +1 -0
  164. package/dist/core/verse/context-fit.js +7 -5
  165. package/dist/core/verse/context-fit.js.map +1 -1
  166. package/dist/core/verse/control-api.d.ts +23 -1
  167. package/dist/core/verse/control-api.js +117 -10
  168. package/dist/core/verse/control-api.js.map +1 -1
  169. package/dist/core/verse/fleet-live-api.js +13 -5
  170. package/dist/core/verse/fleet-live-api.js.map +1 -1
  171. package/dist/core/verse/folder-io.d.ts +50 -0
  172. package/dist/core/verse/folder-io.js +142 -0
  173. package/dist/core/verse/folder-io.js.map +1 -0
  174. package/dist/core/verse/git-api.js +5 -4
  175. package/dist/core/verse/git-api.js.map +1 -1
  176. package/dist/core/verse/git-ops.d.ts +10 -1
  177. package/dist/core/verse/git-ops.js +18 -2
  178. package/dist/core/verse/git-ops.js.map +1 -1
  179. package/dist/core/verse/github-api.d.ts +1 -1
  180. package/dist/core/verse/github-api.js +5 -4
  181. package/dist/core/verse/github-api.js.map +1 -1
  182. package/dist/core/verse/github-repo.js +118 -14
  183. package/dist/core/verse/github-repo.js.map +1 -1
  184. package/dist/core/verse/leader-api.d.ts +5 -4
  185. package/dist/core/verse/leader-api.js +237 -10
  186. package/dist/core/verse/leader-api.js.map +1 -1
  187. package/dist/core/verse/local-models.d.ts +10 -0
  188. package/dist/core/verse/local-models.js +10 -1
  189. package/dist/core/verse/local-models.js.map +1 -1
  190. package/dist/core/verse/login-path.d.ts +73 -0
  191. package/dist/core/verse/login-path.js +123 -14
  192. package/dist/core/verse/login-path.js.map +1 -1
  193. package/dist/core/verse/mcp-control-api.js +4 -4
  194. package/dist/core/verse/mcp-control-api.js.map +1 -1
  195. package/dist/core/verse/mcp-scope.d.ts +22 -0
  196. package/dist/core/verse/mcp-scope.js +41 -1
  197. package/dist/core/verse/mcp-scope.js.map +1 -1
  198. package/dist/core/verse/mcp-seat-view.d.ts +10 -0
  199. package/dist/core/verse/mcp-seat-view.js +30 -4
  200. package/dist/core/verse/mcp-seat-view.js.map +1 -1
  201. package/dist/core/verse/overnight-api.js +20 -2
  202. package/dist/core/verse/overnight-api.js.map +1 -1
  203. package/dist/core/verse/path-guard.d.ts +24 -0
  204. package/dist/core/verse/path-guard.js +91 -22
  205. package/dist/core/verse/path-guard.js.map +1 -1
  206. package/dist/core/verse/preview-api.js +22 -0
  207. package/dist/core/verse/preview-api.js.map +1 -1
  208. package/dist/core/verse/projects.d.ts +21 -0
  209. package/dist/core/verse/projects.js +82 -0
  210. package/dist/core/verse/projects.js.map +1 -1
  211. package/dist/core/verse/session-controls-api.js +5 -3
  212. package/dist/core/verse/session-controls-api.js.map +1 -1
  213. package/dist/core/verse/session-handoff.d.ts +26 -0
  214. package/dist/core/verse/session-handoff.js +90 -12
  215. package/dist/core/verse/session-handoff.js.map +1 -1
  216. package/dist/core/verse/terminal-api.js +7 -4
  217. package/dist/core/verse/terminal-api.js.map +1 -1
  218. package/dist/core/verse/terminal.js +9 -5
  219. package/dist/core/verse/terminal.js.map +1 -1
  220. package/dist/core/verse/verse-api.js +81 -27
  221. package/dist/core/verse/verse-api.js.map +1 -1
  222. package/dist/core/verse/workspaces.d.ts +51 -0
  223. package/dist/core/verse/workspaces.js +177 -47
  224. package/dist/core/verse/workspaces.js.map +1 -1
  225. package/dist/core/vision/leader-apply.d.ts +40 -0
  226. package/dist/core/vision/leader-apply.js +101 -30
  227. package/dist/core/vision/leader-apply.js.map +1 -1
  228. package/dist/core/vision/leader-cadence.d.ts +114 -0
  229. package/dist/core/vision/leader-cadence.js +127 -0
  230. package/dist/core/vision/leader-cadence.js.map +1 -0
  231. package/dist/core/vision/leader-goal-evidence.d.ts +25 -0
  232. package/dist/core/vision/leader-goal-evidence.js +36 -0
  233. package/dist/core/vision/leader-goal-evidence.js.map +1 -0
  234. package/dist/core/vision/leader-health.d.ts +53 -0
  235. package/dist/core/vision/leader-health.js +92 -0
  236. package/dist/core/vision/leader-health.js.map +1 -0
  237. package/dist/core/vision/leader-operator.d.ts +176 -0
  238. package/dist/core/vision/leader-operator.js +355 -0
  239. package/dist/core/vision/leader-operator.js.map +1 -0
  240. package/dist/core/vision/leader-run-chain.d.ts +41 -0
  241. package/dist/core/vision/leader-run-chain.js +54 -0
  242. package/dist/core/vision/leader-run-chain.js.map +1 -0
  243. package/dist/core/vision/leader-seat-plan.d.ts +68 -0
  244. package/dist/core/vision/leader-seat-plan.js +93 -0
  245. package/dist/core/vision/leader-seat-plan.js.map +1 -0
  246. package/dist/core/vision/leader-seat.d.ts +71 -5
  247. package/dist/core/vision/leader-seat.js +235 -33
  248. package/dist/core/vision/leader-seat.js.map +1 -1
  249. package/dist/core/vision/leader-thread-types.d.ts +104 -0
  250. package/dist/core/vision/leader-thread-types.js +9 -0
  251. package/dist/core/vision/leader-thread-types.js.map +1 -0
  252. package/dist/core/vision/leader-thread.d.ts +138 -0
  253. package/dist/core/vision/leader-thread.js +926 -0
  254. package/dist/core/vision/leader-thread.js.map +1 -0
  255. package/dist/core/vision/leader-types.d.ts +75 -1
  256. package/dist/core/vision/leader.d.ts +88 -18
  257. package/dist/core/vision/leader.js +269 -69
  258. package/dist/core/vision/leader.js.map +1 -1
  259. package/dist/core/web/public/next/assets/{ActionMenu-Dwjk6rUQ.js → ActionMenu-CIiX2X8w.js} +2 -2
  260. package/dist/core/web/public/next/assets/{ActionMenu-Dwjk6rUQ.js.map → ActionMenu-CIiX2X8w.js.map} +1 -1
  261. package/dist/core/web/public/next/assets/Advanced-DHsysoIL.js +2 -0
  262. package/dist/core/web/public/next/assets/{Advanced-cVYTAsfB.js.map → Advanced-DHsysoIL.js.map} +1 -1
  263. package/dist/core/web/public/next/assets/{App-IsaWDsdF.js → App-CMeAocmW.js} +5 -5
  264. package/dist/core/web/public/next/assets/{App-IsaWDsdF.js.map → App-CMeAocmW.js.map} +1 -1
  265. package/dist/core/web/public/next/assets/AppsSection-DISYnMnc.js +2 -0
  266. package/dist/core/web/public/next/assets/{AppsSection-DDqeSrty.js.map → AppsSection-DISYnMnc.js.map} +1 -1
  267. package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js +2 -0
  268. package/dist/core/web/public/next/assets/AreaTrend-DK2Y2TbZ.js.map +1 -0
  269. package/dist/core/web/public/next/assets/{AutonomyOffState-CpFYS3tQ.js → AutonomyOffState-CEPSZToP.js} +3 -3
  270. package/dist/core/web/public/next/assets/{AutonomyOffState-CpFYS3tQ.js.map → AutonomyOffState-CEPSZToP.js.map} +1 -1
  271. package/dist/core/web/public/next/assets/AutonomySection-DWc3ciAD.js +2 -0
  272. package/dist/core/web/public/next/assets/{AutonomySection-Dwn8UtOy.js.map → AutonomySection-DWc3ciAD.js.map} +1 -1
  273. package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js +2 -0
  274. package/dist/core/web/public/next/assets/AutonomyStatus-CYaHjJ9U.js.map +1 -0
  275. package/dist/core/web/public/next/assets/{BranchBar-ISZ7xUCj.js → BranchBar-BxhdiIpx.js} +2 -2
  276. package/dist/core/web/public/next/assets/{BranchBar-ISZ7xUCj.js.map → BranchBar-BxhdiIpx.js.map} +1 -1
  277. package/dist/core/web/public/next/assets/{BudgetControl-BARVp-En.js → BudgetControl-C-0KhjRS.js} +2 -2
  278. package/dist/core/web/public/next/assets/{BudgetControl-BARVp-En.js.map → BudgetControl-C-0KhjRS.js.map} +1 -1
  279. package/dist/core/web/public/next/assets/{Button-DtE0rlWD.js → Button-D90dzI_o.js} +2 -2
  280. package/dist/core/web/public/next/assets/{Button-DtE0rlWD.js.map → Button-D90dzI_o.js.map} +1 -1
  281. package/dist/core/web/public/next/assets/{CapacityStrip-DKbKA_Aa.js → CapacityStrip-qKDBC65C.js} +2 -2
  282. package/dist/core/web/public/next/assets/{CapacityStrip-DKbKA_Aa.js.map → CapacityStrip-qKDBC65C.js.map} +1 -1
  283. package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js +2 -0
  284. package/dist/core/web/public/next/assets/ChartFrame-DY-GVUb3.js.map +1 -0
  285. package/dist/core/web/public/next/assets/ChartFrame-DyjmyV8N.css +1 -0
  286. package/dist/core/web/public/next/assets/ChatSection-DlT4QU6a.js +3 -0
  287. package/dist/core/web/public/next/assets/{ChatSection-C9myY4ei.js.map → ChatSection-DlT4QU6a.js.map} +1 -1
  288. package/dist/core/web/public/next/assets/{CloudBudgetForm-CvjK4Oh6.js → CloudBudgetForm-BrNun_Yu.js} +2 -2
  289. package/dist/core/web/public/next/assets/{CloudBudgetForm-CvjK4Oh6.js.map → CloudBudgetForm-BrNun_Yu.js.map} +1 -1
  290. package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js +2 -0
  291. package/dist/core/web/public/next/assets/CommandPalette-C5lDDKN0.js.map +1 -0
  292. package/dist/core/web/public/next/assets/CommandSection-B0xuU-yZ.css +1 -0
  293. package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js +3 -0
  294. package/dist/core/web/public/next/assets/CommandSection-DXFvPgKp.js.map +1 -0
  295. package/dist/core/web/public/next/assets/{ConfirmDialog-CLUhzaBj.js → ConfirmDialog-BR4nZQ2D.js} +2 -2
  296. package/dist/core/web/public/next/assets/{ConfirmDialog-CLUhzaBj.js.map → ConfirmDialog-BR4nZQ2D.js.map} +1 -1
  297. package/dist/core/web/public/next/assets/{DeleteChatDialog-C_eDhV8b.js → DeleteChatDialog-BCfP12GH.js} +2 -2
  298. package/dist/core/web/public/next/assets/{DeleteChatDialog-C_eDhV8b.js.map → DeleteChatDialog-BCfP12GH.js.map} +1 -1
  299. package/dist/core/web/public/next/assets/{Dialog-BRd_B9OE.js → Dialog-D3msQlCj.js} +2 -2
  300. package/dist/core/web/public/next/assets/{Dialog-BRd_B9OE.js.map → Dialog-D3msQlCj.js.map} +1 -1
  301. package/dist/core/web/public/next/assets/{DiffPane-Cpr9soB2.js → DiffPane-Ix6hvXlY.js} +2 -2
  302. package/dist/core/web/public/next/assets/{DiffPane-Cpr9soB2.js.map → DiffPane-Ix6hvXlY.js.map} +1 -1
  303. package/dist/core/web/public/next/assets/{DiffViewer-CNwd0W3Q.js → DiffViewer-C4WKsCIe.js} +2 -2
  304. package/dist/core/web/public/next/assets/{DiffViewer-CNwd0W3Q.js.map → DiffViewer-C4WKsCIe.js.map} +1 -1
  305. package/dist/core/web/public/next/assets/DockHost-aWP7liri.js +2 -0
  306. package/dist/core/web/public/next/assets/{DockHost-BcEq2qaS.js.map → DockHost-aWP7liri.js.map} +1 -1
  307. package/dist/core/web/public/next/assets/{EmptyState-DsN1H6MC.js → EmptyState-D2IRy3Cg.js} +2 -2
  308. package/dist/core/web/public/next/assets/{EmptyState-DsN1H6MC.js.map → EmptyState-D2IRy3Cg.js.map} +1 -1
  309. package/dist/core/web/public/next/assets/{Epistemic-fycQTBRO.js → Epistemic-DMr18muX.js} +2 -2
  310. package/dist/core/web/public/next/assets/{Epistemic-fycQTBRO.js.map → Epistemic-DMr18muX.js.map} +1 -1
  311. package/dist/core/web/public/next/assets/{EvidenceTimeline-sCCAdnBK.js → EvidenceTimeline-DXmmz6Fi.js} +2 -2
  312. package/dist/core/web/public/next/assets/{EvidenceTimeline-sCCAdnBK.js.map → EvidenceTimeline-DXmmz6Fi.js.map} +1 -1
  313. package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js +3 -0
  314. package/dist/core/web/public/next/assets/FleetSection-BfplcwFU.js.map +1 -0
  315. package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js +2 -0
  316. package/dist/core/web/public/next/assets/Funnel-Dh2yVHws.js.map +1 -0
  317. package/dist/core/web/public/next/assets/{GearTray-CpDt0xwj.js → GearTray-Dt-ee32-.js} +2 -2
  318. package/dist/core/web/public/next/assets/{GearTray-CpDt0xwj.js.map → GearTray-Dt-ee32-.js.map} +1 -1
  319. package/dist/core/web/public/next/assets/GrowthSection-P9EUfGeA.js +2 -0
  320. package/dist/core/web/public/next/assets/{GrowthSection-BvZezOsX.js.map → GrowthSection-P9EUfGeA.js.map} +1 -1
  321. package/dist/core/web/public/next/assets/{HandoffDialog-B1G6gQyk.js → HandoffDialog-CLJQLe7M.js} +2 -2
  322. package/dist/core/web/public/next/assets/{HandoffDialog-B1G6gQyk.js.map → HandoffDialog-CLJQLe7M.js.map} +1 -1
  323. package/dist/core/web/public/next/assets/{Input-CI0yBHmn.js → Input-D_KRJA9V.js} +2 -2
  324. package/dist/core/web/public/next/assets/{Input-CI0yBHmn.js.map → Input-D_KRJA9V.js.map} +1 -1
  325. package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js +2 -0
  326. package/dist/core/web/public/next/assets/LeaderCard-D-7DlJuR.js.map +1 -0
  327. package/dist/core/web/public/next/assets/LeaderCard-DNsbLwY3.css +1 -0
  328. package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js +2 -0
  329. package/dist/core/web/public/next/assets/LeaderConversation-DGZjWI-E.js.map +1 -0
  330. package/dist/core/web/public/next/assets/LeaderConversation-DPHUTq6W.css +1 -0
  331. package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js +2 -0
  332. package/dist/core/web/public/next/assets/MatrixHeatmap-C7BCG2d7.js.map +1 -0
  333. package/dist/core/web/public/next/assets/McpSection-DGbRcyv8.js +2 -0
  334. package/dist/core/web/public/next/assets/{McpSection-nuXer4K-.js.map → McpSection-DGbRcyv8.js.map} +1 -1
  335. package/dist/core/web/public/next/assets/{MessageMarkdown-BCe4TsXk.js → MessageMarkdown-DFvk06qG.js} +3 -3
  336. package/dist/core/web/public/next/assets/{MessageMarkdown-BCe4TsXk.js.map → MessageMarkdown-DFvk06qG.js.map} +1 -1
  337. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DL3LU5kL.js → MessageMarkdownRenderer-BAv4oEUf.js} +2 -2
  338. package/dist/core/web/public/next/assets/{MessageMarkdownRenderer-DL3LU5kL.js.map → MessageMarkdownRenderer-BAv4oEUf.js.map} +1 -1
  339. package/dist/core/web/public/next/assets/{Meter-b69LM0mU.js → Meter-CMj-VafN.js} +2 -2
  340. package/dist/core/web/public/next/assets/{Meter-b69LM0mU.js.map → Meter-CMj-VafN.js.map} +1 -1
  341. package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js +3 -0
  342. package/dist/core/web/public/next/assets/MindSection-C6kLPIjt.js.map +1 -0
  343. package/dist/core/web/public/next/assets/{MutationTokenDialog-Bm34BNVV.js → MutationTokenDialog-DbnO8aYi.js} +2 -2
  344. package/dist/core/web/public/next/assets/{MutationTokenDialog-Bm34BNVV.js.map → MutationTokenDialog-DbnO8aYi.js.map} +1 -1
  345. package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js +3 -0
  346. package/dist/core/web/public/next/assets/NeedsYouDrawer-crsiX-Nc.js.map +1 -0
  347. package/dist/core/web/public/next/assets/{NeedsYouList-D5Kk549g.js → NeedsYouList-CCsijdWt.js} +2 -2
  348. package/dist/core/web/public/next/assets/{NeedsYouList-D5Kk549g.js.map → NeedsYouList-CCsijdWt.js.map} +1 -1
  349. package/dist/core/web/public/next/assets/NewChatDialog-BlCHtOIr.js +3 -0
  350. package/dist/core/web/public/next/assets/{NewChatDialog-BqFTWgHU.js.map → NewChatDialog-BlCHtOIr.js.map} +1 -1
  351. package/dist/core/web/public/next/assets/{OnboardingFlow-DcDsguAM.js → OnboardingFlow-Cy9BA9eR.js} +3 -3
  352. package/dist/core/web/public/next/assets/{OnboardingFlow-DcDsguAM.js.map → OnboardingFlow-Cy9BA9eR.js.map} +1 -1
  353. package/dist/core/web/public/next/assets/OnboardingGate-BXpNFoLt.js +3 -0
  354. package/dist/core/web/public/next/assets/{OnboardingGate-BZafM1Vf.js.map → OnboardingGate-BXpNFoLt.js.map} +1 -1
  355. package/dist/core/web/public/next/assets/PreviewPane-COid5A0f.js +2 -0
  356. package/dist/core/web/public/next/assets/{PreviewPane-zT3gK9TD.js.map → PreviewPane-COid5A0f.js.map} +1 -1
  357. package/dist/core/web/public/next/assets/{ProviderLogo-AwHn2sKm.js → ProviderLogo-Cq-CYIwT.js} +2 -2
  358. package/dist/core/web/public/next/assets/{ProviderLogo-AwHn2sKm.js.map → ProviderLogo-Cq-CYIwT.js.map} +1 -1
  359. package/dist/core/web/public/next/assets/{RailStatus-xHrovWvI.js → RailStatus-Co5UB6We.js} +2 -2
  360. package/dist/core/web/public/next/assets/{RailStatus-xHrovWvI.js.map → RailStatus-Co5UB6We.js.map} +1 -1
  361. package/dist/core/web/public/next/assets/{RefreshIndicator-SEFZlMB2.js → RefreshIndicator-DO9ibnSq.js} +2 -2
  362. package/dist/core/web/public/next/assets/{RefreshIndicator-SEFZlMB2.js.map → RefreshIndicator-DO9ibnSq.js.map} +1 -1
  363. package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-Dr2WRgkq.js +7 -0
  364. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-CAxPQ4sZ.js.map → ResourcePoolConsoleApp-Dr2WRgkq.js.map} +1 -1
  365. package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js +3 -0
  366. package/dist/core/web/public/next/assets/ResourcesChrome-CwMnbqI1.js.map +1 -0
  367. package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js +2 -0
  368. package/dist/core/web/public/next/assets/ResourcesDrawer-B_Xp_JNc.js.map +1 -0
  369. package/dist/core/web/public/next/assets/ResourcesDrawer-DrGoO8KG.css +1 -0
  370. package/dist/core/web/public/next/assets/{RouteErrorBoundary-C8WGiixc.js → RouteErrorBoundary-SkNhhUbt.js} +2 -2
  371. package/dist/core/web/public/next/assets/{RouteErrorBoundary-C8WGiixc.js.map → RouteErrorBoundary-SkNhhUbt.js.map} +1 -1
  372. package/dist/core/web/public/next/assets/{RunInCloudAction-1-IPLYhf.js → RunInCloudAction-BXPlZwJQ.js} +2 -2
  373. package/dist/core/web/public/next/assets/{RunInCloudAction-1-IPLYhf.js.map → RunInCloudAction-BXPlZwJQ.js.map} +1 -1
  374. package/dist/core/web/public/next/assets/{SeatSelector-DpwNiX8F.js → SeatSelector-J5R3zDkB.js} +3 -3
  375. package/dist/core/web/public/next/assets/{SeatSelector-DpwNiX8F.js.map → SeatSelector-J5R3zDkB.js.map} +1 -1
  376. package/dist/core/web/public/next/assets/{Segmented-Wt1ATod9.js → Segmented-CGh_-tBb.js} +2 -2
  377. package/dist/core/web/public/next/assets/{Segmented-Wt1ATod9.js.map → Segmented-CGh_-tBb.js.map} +1 -1
  378. package/dist/core/web/public/next/assets/{Select-By-V9lMc.js → Select-CWnmUzs3.js} +2 -2
  379. package/dist/core/web/public/next/assets/{Select-By-V9lMc.js.map → Select-CWnmUzs3.js.map} +1 -1
  380. package/dist/core/web/public/next/assets/{SessionGate-WROS02tK.js → SessionGate-sp4KsnUo.js} +2 -2
  381. package/dist/core/web/public/next/assets/{SessionGate-WROS02tK.js.map → SessionGate-sp4KsnUo.js.map} +1 -1
  382. package/dist/core/web/public/next/assets/{SessionInsightChip-DNUcruwp.js → SessionInsightChip-DLFAzdbi.js} +2 -2
  383. package/dist/core/web/public/next/assets/{SessionInsightChip-DNUcruwp.js.map → SessionInsightChip-DLFAzdbi.js.map} +1 -1
  384. package/dist/core/web/public/next/assets/{SessionSearch-UHtt7a8f.js → SessionSearch-DbFjwR1h.js} +2 -2
  385. package/dist/core/web/public/next/assets/{SessionSearch-UHtt7a8f.js.map → SessionSearch-DbFjwR1h.js.map} +1 -1
  386. package/dist/core/web/public/next/assets/{SettingsSection-Bf74l0Gj.js → SettingsSection-Ch23msJ5.js} +2 -2
  387. package/dist/core/web/public/next/assets/SettingsSection-Ch23msJ5.js.map +1 -0
  388. package/dist/core/web/public/next/assets/{SetupChecklist-CzpEcfOl.js → SetupChecklist-Bd76MBAR.js} +2 -2
  389. package/dist/core/web/public/next/assets/{SetupChecklist-CzpEcfOl.js.map → SetupChecklist-Bd76MBAR.js.map} +1 -1
  390. package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js +3 -0
  391. package/dist/core/web/public/next/assets/ShadowDecisions-C5RAY91f.js.map +1 -0
  392. package/dist/core/web/public/next/assets/{Sheet-HkBOBMTT.js → Sheet-BZ2AG4Eo.js} +2 -2
  393. package/dist/core/web/public/next/assets/{Sheet-HkBOBMTT.js.map → Sheet-BZ2AG4Eo.js.map} +1 -1
  394. package/dist/core/web/public/next/assets/{ShortcutsOverlay-DiigiT8H.js → ShortcutsOverlay-C8n8y3zf.js} +2 -2
  395. package/dist/core/web/public/next/assets/{ShortcutsOverlay-DiigiT8H.js.map → ShortcutsOverlay-C8n8y3zf.js.map} +1 -1
  396. package/dist/core/web/public/next/assets/Sidebar-DN--cPYN.js +3 -0
  397. package/dist/core/web/public/next/assets/{Sidebar-C9YtBYVZ.js.map → Sidebar-DN--cPYN.js.map} +1 -1
  398. package/dist/core/web/public/next/assets/{Slider-DaEDws-b.js → Slider-KVoJLDD6.js} +2 -2
  399. package/dist/core/web/public/next/assets/{Slider-DaEDws-b.js.map → Slider-KVoJLDD6.js.map} +1 -1
  400. package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js +2 -0
  401. package/dist/core/web/public/next/assets/StatTile-C4KgjltA.js.map +1 -0
  402. package/dist/core/web/public/next/assets/StatTile-CNCqDoPO.css +1 -0
  403. package/dist/core/web/public/next/assets/{StatusBadge-CXG3iNL4.js → StatusBadge-CXsYqmdU.js} +2 -2
  404. package/dist/core/web/public/next/assets/{StatusBadge-CXG3iNL4.js.map → StatusBadge-CXsYqmdU.js.map} +1 -1
  405. package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js +2 -0
  406. package/dist/core/web/public/next/assets/StepBand-BMtVOFpK.js.map +1 -0
  407. package/dist/core/web/public/next/assets/{Surface-5bNA08tK.js → Surface-BfDmQcKe.js} +2 -2
  408. package/dist/core/web/public/next/assets/{Surface-5bNA08tK.js.map → Surface-BfDmQcKe.js.map} +1 -1
  409. package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js +2 -0
  410. package/dist/core/web/public/next/assets/Swimlane-B9Exxekk.js.map +1 -0
  411. package/dist/core/web/public/next/assets/Swimlane-Bf4Rjoy9.css +1 -0
  412. package/dist/core/web/public/next/assets/{Switch-BmCzfFnu.js → Switch-9NtO_6Lj.js} +2 -2
  413. package/dist/core/web/public/next/assets/{Switch-BmCzfFnu.js.map → Switch-9NtO_6Lj.js.map} +1 -1
  414. package/dist/core/web/public/next/assets/{Tag-WSUIaMVy.js → Tag-DscCRFcN.js} +2 -2
  415. package/dist/core/web/public/next/assets/{Tag-WSUIaMVy.js.map → Tag-DscCRFcN.js.map} +1 -1
  416. package/dist/core/web/public/next/assets/{TerminalPane-BVFgYX6K.js → TerminalPane-B668-DJW.js} +5 -5
  417. package/dist/core/web/public/next/assets/{TerminalPane-BVFgYX6K.js.map → TerminalPane-B668-DJW.js.map} +1 -1
  418. package/dist/core/web/public/next/assets/UniverseConsoleApp-BUV_brY7.js +2 -0
  419. package/dist/core/web/public/next/assets/{UniverseConsoleApp-BpphLqoz.js.map → UniverseConsoleApp-BUV_brY7.js.map} +1 -1
  420. package/dist/core/web/public/next/assets/{UniverseView-DbpbSMwO.js → UniverseView-DG70zH0W.js} +4 -4
  421. package/dist/core/web/public/next/assets/{UniverseView-DbpbSMwO.js.map → UniverseView-DG70zH0W.js.map} +1 -1
  422. package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js +3 -0
  423. package/dist/core/web/public/next/assets/UsageSection-DY7uOTm1.js.map +1 -0
  424. package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js +3 -0
  425. package/dist/core/web/public/next/assets/VerseConsoleApp-CWU6R3By.js.map +1 -0
  426. package/dist/core/web/public/next/assets/Workspace-D1nP9BhD.js +10 -0
  427. package/dist/core/web/public/next/assets/{Workspace-RXy0pqp6.js.map → Workspace-D1nP9BhD.js.map} +1 -1
  428. package/dist/core/web/public/next/assets/actions-CY-PjpGc.js +2 -0
  429. package/dist/core/web/public/next/assets/{actions-BZTidCXZ.js.map → actions-CY-PjpGc.js.map} +1 -1
  430. package/dist/core/web/public/next/assets/actions-DkWhhWIg.css +1 -0
  431. package/dist/core/web/public/next/assets/{apps-model-CHO133qt.js → apps-model-Du02KhAf.js} +2 -2
  432. package/dist/core/web/public/next/assets/{apps-model-CHO133qt.js.map → apps-model-Du02KhAf.js.map} +1 -1
  433. package/dist/core/web/public/next/assets/{authority-model-8NeAEwAF.js → authority-model-79SeuKlJ.js} +2 -2
  434. package/dist/core/web/public/next/assets/{authority-model-8NeAEwAF.js.map → authority-model-79SeuKlJ.js.map} +1 -1
  435. package/dist/core/web/public/next/assets/autonomy-ladder-BGWmZzP7.css +1 -0
  436. package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js +2 -0
  437. package/dist/core/web/public/next/assets/autonomy-ladder.module-ArDv4bkr.js.map +1 -0
  438. package/dist/core/web/public/next/assets/budget-queries-D8QV5XtH.js +2 -0
  439. package/dist/core/web/public/next/assets/{budget-queries-DFF-3ICg.js.map → budget-queries-D8QV5XtH.js.map} +1 -1
  440. package/dist/core/web/public/next/assets/{capacity-strip-model-5ViUgUlP.js → capacity-strip-model-BwZ1ZbkU.js} +2 -2
  441. package/dist/core/web/public/next/assets/{capacity-strip-model-5ViUgUlP.js.map → capacity-strip-model-BwZ1ZbkU.js.map} +1 -1
  442. package/dist/core/web/public/next/assets/charts-BZ50mZD_.js +2 -0
  443. package/dist/core/web/public/next/assets/charts-BZ50mZD_.js.map +1 -0
  444. package/dist/core/web/public/next/assets/charts-ClCB18la.css +1 -0
  445. package/dist/core/web/public/next/assets/{cloud-model-CfRydq8N.js → cloud-model-BDivRMqv.js} +2 -2
  446. package/dist/core/web/public/next/assets/{cloud-model-CfRydq8N.js.map → cloud-model-BDivRMqv.js.map} +1 -1
  447. package/dist/core/web/public/next/assets/{cloud-queries-DmptbjS8.js → cloud-queries-BPQQ5_pJ.js} +2 -2
  448. package/dist/core/web/public/next/assets/{cloud-queries-DmptbjS8.js.map → cloud-queries-BPQQ5_pJ.js.map} +1 -1
  449. package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js → colors-DvK0wMHH.js} +2 -2
  450. package/dist/core/web/public/next/assets/{colors-BZ3a9wFf.js.map → colors-DvK0wMHH.js.map} +1 -1
  451. package/dist/core/web/public/next/assets/{command-catalog-ffCAijVY.js → command-catalog-BIntSa9l.js} +2 -2
  452. package/dist/core/web/public/next/assets/command-catalog-BIntSa9l.js.map +1 -0
  453. package/dist/core/web/public/next/assets/{context-model-CDeyP0cA.js → context-model-Br8t9jgG.js} +2 -2
  454. package/dist/core/web/public/next/assets/{context-model-CDeyP0cA.js.map → context-model-Br8t9jgG.js.map} +1 -1
  455. package/dist/core/web/public/next/assets/{context-model-Bb15chFt.js → context-model-CokrgEUq.js} +3 -3
  456. package/dist/core/web/public/next/assets/{context-model-Bb15chFt.js.map → context-model-CokrgEUq.js.map} +1 -1
  457. package/dist/core/web/public/next/assets/context-queries-eL3caKVG.js +2 -0
  458. package/dist/core/web/public/next/assets/{context-queries-_9bFWb9v.js.map → context-queries-eL3caKVG.js.map} +1 -1
  459. package/dist/core/web/public/next/assets/{control-queries-CXtmZZH6.js → control-queries-B9K-wmcB.js} +2 -2
  460. package/dist/core/web/public/next/assets/{control-queries-CXtmZZH6.js.map → control-queries-B9K-wmcB.js.map} +1 -1
  461. package/dist/core/web/public/next/assets/{copy-setup-BIp0iaiZ.js → copy-setup-XMgCC5f8.js} +2 -2
  462. package/dist/core/web/public/next/assets/{copy-setup-BIp0iaiZ.js.map → copy-setup-XMgCC5f8.js.map} +1 -1
  463. package/dist/core/web/public/next/assets/{dock-icons-Cc43W7r4.js → dock-icons-BJ6ZqB2t.js} +2 -2
  464. package/dist/core/web/public/next/assets/{dock-icons-Cc43W7r4.js.map → dock-icons-BJ6ZqB2t.js.map} +1 -1
  465. package/dist/core/web/public/next/assets/{fleet-model-DOK8ZtEt.js → fleet-model-BvDR3gjp.js} +2 -2
  466. package/dist/core/web/public/next/assets/{fleet-model-DOK8ZtEt.js.map → fleet-model-BvDR3gjp.js.map} +1 -1
  467. package/dist/core/web/public/next/assets/{fleet-queries-BeEAqD6y.js → fleet-queries-W2UFVMZJ.js} +2 -2
  468. package/dist/core/web/public/next/assets/{fleet-queries-BeEAqD6y.js.map → fleet-queries-W2UFVMZJ.js.map} +1 -1
  469. package/dist/core/web/public/next/assets/{focus-trap-ChZ5EFfM.js → focus-trap-CtI1SlMX.js} +2 -2
  470. package/dist/core/web/public/next/assets/{focus-trap-ChZ5EFfM.js.map → focus-trap-CtI1SlMX.js.map} +1 -1
  471. package/dist/core/web/public/next/assets/{format-BmH2yWL6.js → format-CH4g_sl1.js} +2 -2
  472. package/dist/core/web/public/next/assets/{format-BmH2yWL6.js.map → format-CH4g_sl1.js.map} +1 -1
  473. package/dist/core/web/public/next/assets/{format-DKrNjdwD.js → format-D7nBg2bn.js} +2 -2
  474. package/dist/core/web/public/next/assets/{format-DKrNjdwD.js.map → format-D7nBg2bn.js.map} +1 -1
  475. package/dist/core/web/public/next/assets/{git-model-BFwAVbxF.js → git-model-Dnkd1TnK.js} +2 -2
  476. package/dist/core/web/public/next/assets/{git-model-BFwAVbxF.js.map → git-model-Dnkd1TnK.js.map} +1 -1
  477. package/dist/core/web/public/next/assets/global-CMNW_dqn.js +2 -0
  478. package/dist/core/web/public/next/assets/{global-y_exIyAP.js.map → global-CMNW_dqn.js.map} +1 -1
  479. package/dist/core/web/public/next/assets/guarded-runners-YeAc9wLQ.js +2 -0
  480. package/dist/core/web/public/next/assets/{guarded-runners-Cd4POBtI.js.map → guarded-runners-YeAc9wLQ.js.map} +1 -1
  481. package/dist/core/web/public/next/assets/{icons-CygCEFWs.js → icons-D1sYbCTQ.js} +2 -2
  482. package/dist/core/web/public/next/assets/{icons-CygCEFWs.js.map → icons-D1sYbCTQ.js.map} +1 -1
  483. package/dist/core/web/public/next/assets/{index-CyK31YRm.js → index-DZ-UQ7v8.js} +3 -3
  484. package/dist/core/web/public/next/assets/{index-CyK31YRm.js.map → index-DZ-UQ7v8.js.map} +1 -1
  485. package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js +2 -0
  486. package/dist/core/web/public/next/assets/leader-focus-BjeJv7CW.js.map +1 -0
  487. package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js +2 -0
  488. package/dist/core/web/public/next/assets/leader-thread-types-CDb-VPPO.js.map +1 -0
  489. package/dist/core/web/public/next/assets/{live-model-D7hilYFk.js → live-model-D_32RAOR.js} +2 -2
  490. package/dist/core/web/public/next/assets/{live-model-D7hilYFk.js.map → live-model-D_32RAOR.js.map} +1 -1
  491. package/dist/core/web/public/next/assets/{mind.module-B15k0Y9q.js → mind.module-7hA92hRg.js} +2 -2
  492. package/dist/core/web/public/next/assets/{mind.module-B15k0Y9q.js.map → mind.module-7hA92hRg.js.map} +1 -1
  493. package/dist/core/web/public/next/assets/mutations-DQPbFdRJ.js +2 -0
  494. package/dist/core/web/public/next/assets/{mutations-CWlxEMEm.js.map → mutations-DQPbFdRJ.js.map} +1 -1
  495. package/dist/core/web/public/next/assets/{nav-mimleI0R.js → nav-0dOYe2rJ.js} +2 -2
  496. package/dist/core/web/public/next/assets/{nav-mimleI0R.js.map → nav-0dOYe2rJ.js.map} +1 -1
  497. package/dist/core/web/public/next/assets/{overnight-queries-DJ4mZKSj.js → overnight-queries-C4wOnFtE.js} +2 -2
  498. package/dist/core/web/public/next/assets/{overnight-queries-DJ4mZKSj.js.map → overnight-queries-C4wOnFtE.js.map} +1 -1
  499. package/dist/core/web/public/next/assets/primitives-2A5Eq8FQ.js +1 -0
  500. package/dist/core/web/public/next/assets/{queries-Bw1McHTj.js → queries-BTXWdZzU.js} +2 -2
  501. package/dist/core/web/public/next/assets/{queries-Bw1McHTj.js.map → queries-BTXWdZzU.js.map} +1 -1
  502. package/dist/core/web/public/next/assets/{reasoning-pref-KkhI_5-j.js → reasoning-pref-Ca6lN6x_.js} +2 -2
  503. package/dist/core/web/public/next/assets/{reasoning-pref-KkhI_5-j.js.map → reasoning-pref-Ca6lN6x_.js.map} +1 -1
  504. package/dist/core/web/public/next/assets/{reveal-anchor-CCCx_kfT.js → reveal-anchor-DfNLgK_I.js} +2 -2
  505. package/dist/core/web/public/next/assets/{reveal-anchor-CCCx_kfT.js.map → reveal-anchor-DfNLgK_I.js.map} +1 -1
  506. package/dist/core/web/public/next/assets/seat-subscription-C5uPHBsN.js +2 -0
  507. package/dist/core/web/public/next/assets/{seat-subscription-BhUUz7VL.js.map → seat-subscription-C5uPHBsN.js.map} +1 -1
  508. package/dist/core/web/public/next/assets/{sidebar-model-Dcd437cf.js → sidebar-model-CLCdqwkR.js} +2 -2
  509. package/dist/core/web/public/next/assets/{sidebar-model-Dcd437cf.js.map → sidebar-model-CLCdqwkR.js.map} +1 -1
  510. package/dist/core/web/public/next/assets/{slots-BL_J5mmV.js → slots-C-qBeu-8.js} +3 -3
  511. package/dist/core/web/public/next/assets/{slots-BL_J5mmV.js.map → slots-C-qBeu-8.js.map} +1 -1
  512. package/dist/core/web/public/next/assets/{surface-data-C3UAQ4QX.js → surface-data-Dj71tdD-.js} +2 -2
  513. package/dist/core/web/public/next/assets/{surface-data-C3UAQ4QX.js.map → surface-data-Dj71tdD-.js.map} +1 -1
  514. package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js +2 -0
  515. package/dist/core/web/public/next/assets/surface-prefetch-B0WdJOJG.js.map +1 -0
  516. package/dist/core/web/public/next/assets/{tasks-model-CzHvclVm.js → tasks-model-O8yR5YXp.js} +2 -2
  517. package/dist/core/web/public/next/assets/{tasks-model-CzHvclVm.js.map → tasks-model-O8yR5YXp.js.map} +1 -1
  518. package/dist/core/web/public/next/assets/{terminal-icons-BwgQTQP0.js → terminal-icons-CoRZq9iO.js} +2 -2
  519. package/dist/core/web/public/next/assets/{terminal-icons-BwgQTQP0.js.map → terminal-icons-CoRZq9iO.js.map} +1 -1
  520. package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js +2 -0
  521. package/dist/core/web/public/next/assets/thread-data-DQB_g66d.js.map +1 -0
  522. package/dist/core/web/public/next/assets/{usage-queries-pXxvy54x.js → usage-queries-AdjEyEtn.js} +2 -2
  523. package/dist/core/web/public/next/assets/{usage-queries-pXxvy54x.js.map → usage-queries-AdjEyEtn.js.map} +1 -1
  524. package/dist/core/web/public/next/assets/{use-guarded-action-EgVWjM5c.js → use-guarded-action-CuuMHeDX.js} +2 -2
  525. package/dist/core/web/public/next/assets/{use-guarded-action-EgVWjM5c.js.map → use-guarded-action-CuuMHeDX.js.map} +1 -1
  526. package/dist/core/web/public/next/assets/{use-ticker-BoqFxRFG.js → use-ticker-BBcp02SZ.js} +2 -2
  527. package/dist/core/web/public/next/assets/{use-ticker-BoqFxRFG.js.map → use-ticker-BBcp02SZ.js.map} +1 -1
  528. package/dist/core/web/public/next/assets/{use-token-gate-DSNIIpI6.js → use-token-gate-CbXVYQYI.js} +2 -2
  529. package/dist/core/web/public/next/assets/{use-token-gate-DSNIIpI6.js.map → use-token-gate-CbXVYQYI.js.map} +1 -1
  530. package/dist/core/web/public/next/assets/{useOnboarding-Bk0VnkxQ.js → useOnboarding-C_Fpe_sH.js} +2 -2
  531. package/dist/core/web/public/next/assets/{useOnboarding-Bk0VnkxQ.js.map → useOnboarding-C_Fpe_sH.js.map} +1 -1
  532. package/dist/core/web/public/next/assets/{useSeatsRefresh-q7Id9RcW.js → useSeatsRefresh-Co1CnxLc.js} +2 -2
  533. package/dist/core/web/public/next/assets/{useSeatsRefresh-q7Id9RcW.js.map → useSeatsRefresh-Co1CnxLc.js.map} +1 -1
  534. package/dist/core/web/public/next/assets/{useVerseTranscript-CqH51rt9.js → useVerseTranscript-DgbigUlV.js} +2 -2
  535. package/dist/core/web/public/next/assets/{useVerseTranscript-CqH51rt9.js.map → useVerseTranscript-DgbigUlV.js.map} +1 -1
  536. package/dist/core/web/public/next/assets/{verse-icons-DsG1dOQx.js → verse-icons-S56hIiXS.js} +2 -2
  537. package/dist/core/web/public/next/assets/{verse-icons-DsG1dOQx.js.map → verse-icons-S56hIiXS.js.map} +1 -1
  538. package/dist/core/web/public/next/assets/verse-model-DAVevkNe.js +2 -0
  539. package/dist/core/web/public/next/assets/{verse-model-JTuvRBVK.js.map → verse-model-DAVevkNe.js.map} +1 -1
  540. package/dist/core/web/public/next/assets/{warmup-Bv1RumVq.js → warmup-B_RAtNZ_.js} +3 -3
  541. package/dist/core/web/public/next/assets/{warmup-Bv1RumVq.js.map → warmup-B_RAtNZ_.js.map} +1 -1
  542. package/dist/core/web/public/next/assets/{why-seat-model-Cau8qG6O.js → why-seat-model-M_r0wX3b.js} +2 -2
  543. package/dist/core/web/public/next/assets/{why-seat-model-Cau8qG6O.js.map → why-seat-model-M_r0wX3b.js.map} +1 -1
  544. package/dist/core/web/public/next/assets/{workspace-model-D-SLfads.js → workspace-model-dji5-Al3.js} +2 -2
  545. package/dist/core/web/public/next/assets/{workspace-model-D-SLfads.js.map → workspace-model-dji5-Al3.js.map} +1 -1
  546. package/dist/core/web/public/next/index.html +1 -1
  547. package/dist/core/web/read-projection-worker.js +2 -1
  548. package/dist/core/web/read-projection-worker.js.map +1 -1
  549. package/dist/core/web/read-projections.d.ts +3 -0
  550. package/dist/core/web/read-projections.js +2 -2
  551. package/dist/core/web/read-projections.js.map +1 -1
  552. package/dist/core/web/visibility.js +3 -4
  553. package/dist/core/web/visibility.js.map +1 -1
  554. package/dist/release-dependency-inventory.json +1 -1
  555. package/package.json +3 -2
  556. package/dist/core/web/public/next/assets/Advanced-cVYTAsfB.js +0 -2
  557. package/dist/core/web/public/next/assets/AppsSection-DDqeSrty.js +0 -2
  558. package/dist/core/web/public/next/assets/AreaTrend-C32rUaxm.js +0 -2
  559. package/dist/core/web/public/next/assets/AreaTrend-C32rUaxm.js.map +0 -1
  560. package/dist/core/web/public/next/assets/AutonomySection-Dwn8UtOy.js +0 -2
  561. package/dist/core/web/public/next/assets/ChartFrame-BVuBe6RP.css +0 -1
  562. package/dist/core/web/public/next/assets/ChartFrame-DK_BDXCt.js +0 -2
  563. package/dist/core/web/public/next/assets/ChartFrame-DK_BDXCt.js.map +0 -1
  564. package/dist/core/web/public/next/assets/ChatSection-C9myY4ei.js +0 -3
  565. package/dist/core/web/public/next/assets/CommandPalette-DzPsth0u.js +0 -2
  566. package/dist/core/web/public/next/assets/CommandPalette-DzPsth0u.js.map +0 -1
  567. package/dist/core/web/public/next/assets/CommandSection-Brp73iox.js +0 -3
  568. package/dist/core/web/public/next/assets/CommandSection-Brp73iox.js.map +0 -1
  569. package/dist/core/web/public/next/assets/CommandSection-CvAVd1w4.css +0 -1
  570. package/dist/core/web/public/next/assets/DockHost-BcEq2qaS.js +0 -2
  571. package/dist/core/web/public/next/assets/FleetSection-BG8iGraG.js +0 -3
  572. package/dist/core/web/public/next/assets/FleetSection-BG8iGraG.js.map +0 -1
  573. package/dist/core/web/public/next/assets/Funnel-B88_wpA4.js +0 -2
  574. package/dist/core/web/public/next/assets/Funnel-B88_wpA4.js.map +0 -1
  575. package/dist/core/web/public/next/assets/GrowthSection-BvZezOsX.js +0 -2
  576. package/dist/core/web/public/next/assets/LeaderCard-BxxiEg4e.js +0 -2
  577. package/dist/core/web/public/next/assets/LeaderCard-BxxiEg4e.js.map +0 -1
  578. package/dist/core/web/public/next/assets/MatrixHeatmap-iPFEU2Tv.js +0 -2
  579. package/dist/core/web/public/next/assets/MatrixHeatmap-iPFEU2Tv.js.map +0 -1
  580. package/dist/core/web/public/next/assets/McpSection-nuXer4K-.js +0 -2
  581. package/dist/core/web/public/next/assets/MindSection-Dc5v5rH3.js +0 -2
  582. package/dist/core/web/public/next/assets/MindSection-Dc5v5rH3.js.map +0 -1
  583. package/dist/core/web/public/next/assets/NeedsYouDrawer-N1cWJjpz.js +0 -3
  584. package/dist/core/web/public/next/assets/NeedsYouDrawer-N1cWJjpz.js.map +0 -1
  585. package/dist/core/web/public/next/assets/NewChatDialog-BqFTWgHU.js +0 -3
  586. package/dist/core/web/public/next/assets/OnboardingGate-BZafM1Vf.js +0 -3
  587. package/dist/core/web/public/next/assets/PreviewPane-zT3gK9TD.js +0 -2
  588. package/dist/core/web/public/next/assets/ResourcePoolConsoleApp-CAxPQ4sZ.js +0 -7
  589. package/dist/core/web/public/next/assets/ResourcesChrome-BnhnEdJe.js +0 -3
  590. package/dist/core/web/public/next/assets/ResourcesChrome-BnhnEdJe.js.map +0 -1
  591. package/dist/core/web/public/next/assets/ResourcesDrawer-BAFGodny.js +0 -2
  592. package/dist/core/web/public/next/assets/ResourcesDrawer-BAFGodny.js.map +0 -1
  593. package/dist/core/web/public/next/assets/ResourcesDrawer-BCFJ2Uq8.css +0 -1
  594. package/dist/core/web/public/next/assets/SettingsSection-Bf74l0Gj.js.map +0 -1
  595. package/dist/core/web/public/next/assets/Sidebar-C9YtBYVZ.js +0 -3
  596. package/dist/core/web/public/next/assets/StatTile-BuLMsJMx.css +0 -1
  597. package/dist/core/web/public/next/assets/StatTile-CTX41O6y.js +0 -2
  598. package/dist/core/web/public/next/assets/StatTile-CTX41O6y.js.map +0 -1
  599. package/dist/core/web/public/next/assets/StepBand-jJTqYIdX.js +0 -2
  600. package/dist/core/web/public/next/assets/StepBand-jJTqYIdX.js.map +0 -1
  601. package/dist/core/web/public/next/assets/Swimlane-LrslsGxw.js +0 -2
  602. package/dist/core/web/public/next/assets/Swimlane-LrslsGxw.js.map +0 -1
  603. package/dist/core/web/public/next/assets/Swimlane-o6_Zsrnr.css +0 -1
  604. package/dist/core/web/public/next/assets/UniverseConsoleApp-BpphLqoz.js +0 -2
  605. package/dist/core/web/public/next/assets/UsageSection-CUlaKtws.js +0 -3
  606. package/dist/core/web/public/next/assets/UsageSection-CUlaKtws.js.map +0 -1
  607. package/dist/core/web/public/next/assets/VerseConsoleApp-DXDv1aOi.js +0 -3
  608. package/dist/core/web/public/next/assets/VerseConsoleApp-DXDv1aOi.js.map +0 -1
  609. package/dist/core/web/public/next/assets/Workspace-RXy0pqp6.js +0 -10
  610. package/dist/core/web/public/next/assets/actions-BZTidCXZ.js +0 -2
  611. package/dist/core/web/public/next/assets/actions-BmIf9avl.css +0 -1
  612. package/dist/core/web/public/next/assets/budget-queries-DFF-3ICg.js +0 -2
  613. package/dist/core/web/public/next/assets/charts-CzxWrZn7.js +0 -2
  614. package/dist/core/web/public/next/assets/charts-CzxWrZn7.js.map +0 -1
  615. package/dist/core/web/public/next/assets/charts-DhKTrQLw.css +0 -1
  616. package/dist/core/web/public/next/assets/command-catalog-ffCAijVY.js.map +0 -1
  617. package/dist/core/web/public/next/assets/context-queries-_9bFWb9v.js +0 -2
  618. package/dist/core/web/public/next/assets/global-y_exIyAP.js +0 -2
  619. package/dist/core/web/public/next/assets/guarded-runners-Cd4POBtI.js +0 -2
  620. package/dist/core/web/public/next/assets/mutations-CWlxEMEm.js +0 -2
  621. package/dist/core/web/public/next/assets/primitives-DMijqcu0.js +0 -1
  622. package/dist/core/web/public/next/assets/seat-subscription-BhUUz7VL.js +0 -2
  623. package/dist/core/web/public/next/assets/surface-prefetch-BXKjPsV5.js +0 -2
  624. package/dist/core/web/public/next/assets/surface-prefetch-BXKjPsV5.js.map +0 -1
  625. package/dist/core/web/public/next/assets/verse-model-JTuvRBVK.js +0 -2
@@ -1,2 +1,2 @@
1
- import{c as e}from"./global-y_exIyAP.js";var t={key:`dashboard-snapshot`,fetch:t=>e(`/api/snapshot`,t)},n={key:`control-snapshot`,fetch:t=>e(`/api/control`,t)},r={key:`agent-os-snapshot`,fetch:t=>e(`/api/agent-os`,t)},i={key:`universe-overview`,fetch:t=>e(`/api/universe`,t)};function a(t){return{key:`universe-graph-${t}`,fetch:n=>e(`/api/universe/graph?universeId=${encodeURIComponent(t)}`,n)}}var o={key:`runs`,fetch:t=>e(`/api/runs`,t)};function s(t){return{key:`run-detail-${t}`,fetch:n=>e(`/api/run/${encodeURIComponent(t)}`,n)}}var c={key:`swarms`,fetch:t=>e(`/api/swarms`,t)};function l(t){return{key:`swarm-detail-${t}`,fetch:n=>e(`/api/swarm/${encodeURIComponent(t)}`,n)}}var u={key:`daemon`,fetch:t=>e(`/api/daemon-observation`,t)},d={key:`fleet`,fetch:t=>e(`/api/fleet`,t)},f={key:`fleet-activity`,fetch:t=>e(`/api/fleet-activity`,t)},p={key:`goals`,fetch:t=>e(`/api/goals`,t)},m={key:`vision-mission`,fetch:t=>e(`/api/vision/mission`,t)},h={key:`inbox`,fetch:t=>e(`/api/inbox`,t)};function g(t={}){let n=new URLSearchParams;t.status!==void 0&&n.set(`status`,t.status),t.since!==void 0&&n.set(`since`,t.since),t.limit!==void 0&&n.set(`limit`,String(t.limit));let r=n.toString();return{key:`inbox-list:${t.status??`pending`}:${t.since??``}:${t.limit??``}`,fetch:t=>e(`/api/inbox${r?`?${r}`:``}`,t)}}function _(t){return{key:`proposal-detail-${t}`,fetch:n=>e(`/api/inbox/${encodeURIComponent(t)}`,n)}}var v={key:`control-logs-observation`,fetch:t=>e(`/api/logs-observation?tail=200`,t)};function y(t){return{key:`pulse-${t}`,fetch:n=>e(`/api/pulse?window=${t}`,n)}}function b(e){return typeof e==`object`&&!!e&&`entry`in e&&`score`in e}function x(t){let n=t.trim();return{key:n?`genome-search-${n}`:`genome-list`,fetch:t=>e(n?`/api/genome?q=${encodeURIComponent(n)}`:`/api/genome`,t)}}function S(t){return{key:`models-${t}`,fetch:n=>e(`/api/models?window=${t}`,n)}}var C={key:`portfolio`,fetch:t=>e(`/api/portfolio`,t)};export{m as C,i as S,s as _,t as a,c as b,x as c,h as d,b as f,y as g,_ as h,u as i,p as l,C as m,v as n,f as o,S as p,n as r,d as s,r as t,g as u,o as v,a as x,l as y};
2
- //# sourceMappingURL=queries-Bw1McHTj.js.map
1
+ import{l as e}from"./global-CMNW_dqn.js";var t={key:`dashboard-snapshot`,fetch:t=>e(`/api/snapshot`,t)},n={key:`control-snapshot`,fetch:t=>e(`/api/control`,t)},r={key:`agent-os-snapshot`,fetch:t=>e(`/api/agent-os`,t)},i={key:`universe-overview`,fetch:t=>e(`/api/universe`,t)};function a(t){return{key:`universe-graph-${t}`,fetch:n=>e(`/api/universe/graph?universeId=${encodeURIComponent(t)}`,n)}}var o={key:`runs`,fetch:t=>e(`/api/runs`,t)};function s(t){return{key:`run-detail-${t}`,fetch:n=>e(`/api/run/${encodeURIComponent(t)}`,n)}}var c={key:`swarms`,fetch:t=>e(`/api/swarms`,t)};function l(t){return{key:`swarm-detail-${t}`,fetch:n=>e(`/api/swarm/${encodeURIComponent(t)}`,n)}}var u={key:`daemon`,fetch:t=>e(`/api/daemon-observation`,t)},d={key:`fleet`,fetch:t=>e(`/api/fleet`,t)},f={key:`fleet-activity`,fetch:t=>e(`/api/fleet-activity`,t)},p={key:`goals`,fetch:t=>e(`/api/goals`,t)},m={key:`vision-mission`,fetch:t=>e(`/api/vision/mission`,t)},h={key:`inbox`,fetch:t=>e(`/api/inbox`,t)};function g(t={}){let n=new URLSearchParams;t.status!==void 0&&n.set(`status`,t.status),t.since!==void 0&&n.set(`since`,t.since),t.limit!==void 0&&n.set(`limit`,String(t.limit));let r=n.toString();return{key:`inbox-list:${t.status??`pending`}:${t.since??``}:${t.limit??``}`,fetch:t=>e(`/api/inbox${r?`?${r}`:``}`,t)}}function _(t){return{key:`proposal-detail-${t}`,fetch:n=>e(`/api/inbox/${encodeURIComponent(t)}`,n)}}var v={key:`control-logs-observation`,fetch:t=>e(`/api/logs-observation?tail=200`,t)};function y(t){return{key:`pulse-${t}`,fetch:n=>e(`/api/pulse?window=${t}`,n)}}function b(e){return typeof e==`object`&&!!e&&`entry`in e&&`score`in e}function x(t){let n=t.trim();return{key:n?`genome-search-${n}`:`genome-list`,fetch:t=>e(n?`/api/genome?q=${encodeURIComponent(n)}`:`/api/genome`,t)}}function S(t){return{key:`models-${t}`,fetch:n=>e(`/api/models?window=${t}`,n)}}var C={key:`portfolio`,fetch:t=>e(`/api/portfolio`,t)};export{m as C,i as S,s as _,t as a,c as b,x as c,h as d,b as f,y as g,_ as h,u as i,p as l,C as m,v as n,f as o,S as p,n as r,d as s,r as t,g as u,o as v,a as x,l as y};
2
+ //# sourceMappingURL=queries-BTXWdZzU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"queries-Bw1McHTj.js","names":[],"sources":["../../../../../../src/web-ui/data/queries.ts"],"sourcesContent":["/**\n * data/queries.ts — one typed accessor per backend resource. Each pairs a\n * stable cache key (also the SSE invalidation target — see sse.ts's\n * EVENT_TO_CACHE_KEYS) with the exact GET call and response type. Views\n * never call apiGet directly; they call these through useQuery (hooks.ts)\n * so caching, de-dupe, and SSE-driven refresh are automatic.\n */\nimport { apiGet } from './client.js';\nimport type { UniverseGraph } from '../../core/universe/graph-types.js';\nimport type {\n AgentOsSnapshotResponse,\n UniverseOverview,\n ControlLogEntry,\n ControlSnapshot,\n DashboardSnapshot,\n DecisionEntry,\n FleetActivitySnapshot,\n FleetStatus,\n Proposal,\n ProposalStatus,\n PublicDaemonObservation,\n RunState,\n SwarmRun,\n ActivityRollup,\n GenomeEntry,\n RecallHit,\n PortfolioSummary,\n ModelStatsReadResult,\n} from './api-types.js';\nimport type { SourceQuality } from './api-types.js';\n\nexport interface QueryDef<T> {\n key: string;\n fetch: (signal?: AbortSignal) => Promise<T>;\n}\n\nexport const dashboardSnapshotQuery: QueryDef<DashboardSnapshot> = {\n key: 'dashboard-snapshot',\n fetch: (signal) => apiGet<DashboardSnapshot>('/api/snapshot', signal),\n};\n\nexport const controlSnapshotQuery: QueryDef<ControlSnapshot> = {\n key: 'control-snapshot',\n fetch: (signal) => apiGet<ControlSnapshot>('/api/control', signal),\n};\n\nexport const agentOsSnapshotQuery: QueryDef<AgentOsSnapshotResponse> = {\n key: 'agent-os-snapshot',\n fetch: (signal) => apiGet<AgentOsSnapshotResponse>('/api/agent-os', signal),\n};\n\nexport const universeOverviewQuery: QueryDef<UniverseOverview> = {\n key: 'universe-overview',\n fetch: (signal) => apiGet<UniverseOverview>('/api/universe', signal),\n};\n\n/** Read only on demand; never invalidate this alongside the overview poll. */\nexport function universeGraphQuery(universeId: string): QueryDef<UniverseGraph> {\n return {\n key: `universe-graph-${universeId}`,\n fetch: (signal) => apiGet<UniverseGraph>(`/api/universe/graph?universeId=${encodeURIComponent(universeId)}`, signal),\n };\n}\n\n// NOTE: there is no standalone GET /api/visibility route — VisibilitySnapshot\n// is an optional field on DashboardSnapshot (`.visibility`), populated by\n// buildSnapshot() server-side. Read it off dashboardSnapshotQuery's data\n// rather than issuing a second request for it.\n\n/**\n * GET /api/runs returns the bare array (see src/core/web/api.ts:1121-1125,\n * `listRuns({limit:200})` -> `RunState[]`) — NOT `{runs: [...]}`. The prior\n * `RunSummary`/`runsQuery` pair here was speculative and didn't match the\n * real response shape; it was unused (FleetDashboardView reads its compact\n * run summaries off `DashboardSnapshot['runs']` instead, a different,\n * deliberately-thin shape). Replaced with the real, fully-typed contract.\n */\nexport const runsQuery: QueryDef<RunState[]> = {\n key: 'runs',\n fetch: (signal) => apiGet<RunState[]>('/api/runs', signal),\n};\n\nexport function runDetailQuery(id: string): QueryDef<RunState> {\n return {\n key: `run-detail-${id}`,\n fetch: (signal) => apiGet<RunState>(`/api/run/${encodeURIComponent(id)}`, signal),\n };\n}\n\nexport const swarmsQuery: QueryDef<SwarmRun[]> = {\n key: 'swarms',\n fetch: (signal) => apiGet<SwarmRun[]>('/api/swarms', signal),\n};\n\nexport function swarmDetailQuery(id: string): QueryDef<SwarmRun> {\n return {\n key: `swarm-detail-${id}`,\n fetch: (signal) => apiGet<SwarmRun>(`/api/swarm/${encodeURIComponent(id)}`, signal),\n };\n}\n\n/**\n * Same PublicDaemonObservation the backend embeds at ControlSnapshot.daemonObservation\n * — fetched standalone here because /control/daemon renders a fuller detail page\n * than DaemonPanel's dashboard-compact view and wants the raw observation\n * (including `ticks`) independent of whether the rest of /api/control succeeds.\n * Cache key 'daemon' deliberately matches sse.ts's existing (previously orphaned)\n * `daemon` / `daemon-observation` -> ['daemon'] mapping so this now actually\n * live-updates.\n */\nexport const daemonObservationQuery: QueryDef<PublicDaemonObservation> = {\n key: 'daemon',\n fetch: (signal) => apiGet<PublicDaemonObservation>('/api/daemon-observation', signal),\n};\n\nexport const fleetStatusQuery: QueryDef<FleetStatus> = {\n key: 'fleet',\n fetch: (signal) => apiGet<FleetStatus>('/api/fleet', signal),\n};\n\nexport const fleetActivityQuery: QueryDef<FleetActivitySnapshot> = {\n key: 'fleet-activity',\n fetch: (signal) => apiGet<FleetActivitySnapshot>('/api/fleet-activity', signal),\n};\n\n/**\n * GET /api/goals returns a bare array of ad-hoc per-goal projections built\n * inline in src/core/web/api.ts (`path === '/api/goals'`, ~line 1654) — there\n * is no exported backend type for this shape (unlike every other resource\n * here), so this interface is hand-written to match that handler exactly\n * rather than re-exported. Keep it in sync with api.ts if that handler's\n * shape changes.\n */\nexport interface GoalMilestoneSummary {\n title: string;\n status: string;\n order: number;\n}\n\nexport interface GoalSummary {\n id: string;\n objective: string;\n status: string;\n milestones: GoalMilestoneSummary[];\n progress: {\n fractionDone: number;\n counts: Record<string, number>;\n nextActionableId: string | null;\n };\n}\n\nexport const goalsQuery: QueryDef<GoalSummary[]> = {\n key: 'goals',\n fetch: (signal) => apiGet<GoalSummary[]>('/api/goals', signal),\n};\n\n/**\n * GET /api/vision/mission — buildVisionMissionSnapshot() in src/core/web/api.ts\n * is itself typed `Promise<Record<string, unknown>>` on the backend (no\n * exported interface to import), so this is a narrow hand-written contract\n * covering only the fields the Goals view actually reads: top-level `state`\n * (mirrors the SourceQuality.sourceState vocabulary) and the per-source\n * epistemic breakdown under `sources`. `briefing`/`preview`/`shadow` are\n * deliberately left as `unknown` — the view does not render briefing prose.\n */\nexport interface VisionMissionSourceStatus {\n sourceState: 'healthy' | 'degraded' | 'missing' | 'unknown';\n sourcePresent?: boolean;\n complete: boolean;\n reason?: string;\n}\n\nexport interface VisionMissionSnapshot {\n schemaVersion: number;\n state: string;\n authority: string;\n briefing: unknown;\n sources: {\n briefing: VisionMissionSourceStatus | null;\n goals: VisionMissionSourceStatus | null;\n enrollment: VisionMissionSourceStatus | null;\n proposals: VisionMissionSourceStatus | null;\n };\n}\n\nexport const visionMissionQuery: QueryDef<VisionMissionSnapshot> = {\n key: 'vision-mission',\n fetch: (signal) => apiGet<VisionMissionSnapshot>('/api/vision/mission', signal),\n};\n\nexport interface InboxProposal {\n id: string;\n title: string;\n kind: string;\n repo: string;\n origin: string;\n createdAt: string;\n}\n\nexport const inboxQuery: QueryDef<{ pending: number; proposals: InboxProposal[] }> = {\n key: 'inbox',\n fetch: (signal) => apiGet('/api/inbox', signal),\n};\n\n/**\n * `?status=&since=&limit=` view over GET /api/inbox (src/core/web/api.ts\n * INBOX_STATUS_QUERY_VALUES) — the history surface `inboxQuery` above never\n * had: it's hardcoded pending-only. `status: undefined` = server default\n * (pending); `'all'` = every status. Keyed per filter combo so switching\n * status/since/limit doesn't fight over one cache entry, and so sse.ts can\n * sweep every live combo (`invalidatePrefix('inbox-list:')`) on the 'inbox'\n * SSE event without knowing which combos are mounted.\n */\nexport type InboxHistoryStatus = ProposalStatus | 'all';\n\nexport interface InboxListFilters {\n status?: InboxHistoryStatus;\n /** ISO timestamp or YYYY-MM-DD, passed straight through to the server. */\n since?: string;\n limit?: number;\n}\n\nexport interface InboxListResponse {\n pending: number;\n total: number;\n /**\n * Full `Proposal[]`, not the narrow `InboxProposal` shape above — the\n * server has always sent full sanitized Proposal records here\n * (`listProposals()`); `InboxProposal` just under-typed it for the\n * original pending-badge use case. The history view needs `status` and\n * `decisionReason` per row (triage: \"why was this rejected\") without an\n * N+1 decisions-ledger read per row, and both live directly on Proposal.\n */\n proposals: Proposal[];\n /** True when more rows matched than were returned (hit the server cap). */\n truncated: boolean;\n filters: { status: InboxHistoryStatus; since: string | null; limit: number | null };\n}\n\nexport function inboxListQuery(filters: InboxListFilters = {}): QueryDef<InboxListResponse> {\n const params = new URLSearchParams();\n if (filters.status !== undefined) params.set('status', filters.status);\n if (filters.since !== undefined) params.set('since', filters.since);\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n const qs = params.toString();\n return {\n key: `inbox-list:${filters.status ?? 'pending'}:${filters.since ?? ''}:${filters.limit ?? ''}`,\n fetch: (signal) => apiGet<InboxListResponse>(`/api/inbox${qs ? `?${qs}` : ''}`, signal),\n };\n}\n\n/**\n * Evidence behind a judge's verdict for one proposal — joined server-side\n * (src/core/web/api.ts GET /api/inbox/:id) from the decisions ledger, which\n * is the ONLY place `judgeReasonCode` lives (Proposal itself never carries\n * it). `judge-parse-failure`/`judge-network-failure` are infra failures,\n * never a considered `judge-review` — render them distinctly, never folded\n * together. When the ledger read is degraded or no row matches this\n * proposal, `sourceQuality` says so; render \"unknown\" via <Epistemic/>\n * rather than treating an empty `decisions` array as \"never judged\".\n */\nexport interface InboxDecisionEvidence {\n sourceQuality: SourceQuality;\n decisions: DecisionEntry[];\n}\n\n/**\n * GET /api/inbox/:id — full proposal detail including diff/taste/verdict\n * (src/core/web/api.ts:1240-1255, `loadProposal(id)`) plus `decisionEvidence`\n * (readDecisionsDetailed({proposalId}), added alongside the inbox history\n * view). Used by the work journal's \"why did it do that\" drill-in (M416) —\n * `/api/inbox` only ever returns pending proposals, but a decided\n * proposal's id (surfaced via fleet-activity's recentMerges/recentActions,\n * or via inboxListQuery's history view) still resolves here as long as its\n * on-disk record hasn't been pruned.\n */\nexport function proposalDetailQuery(id: string): QueryDef<Proposal & { decisionEvidence: InboxDecisionEvidence }> {\n return {\n key: `proposal-detail-${id}`,\n fetch: (signal) =>\n apiGet<Proposal & { decisionEvidence: InboxDecisionEvidence }>(`/api/inbox/${encodeURIComponent(id)}`, signal),\n };\n}\n\n/**\n * GET /api/logs-observation?tail=200 — the provenance-bearing sibling of\n * GET /api/logs (src/core/web/api.ts:~1543-1560): same daemon tick/merge\n * log, plus `sourceQuality` so a degraded/incomplete log can be rendered\n * honestly via <Epistemic/> instead of silently showing a truncated or\n * stale list as complete. `entries` is `null` when the source itself is not\n * healthy+complete (server-side contract, not a client guess). Used by the\n * work journal (M416) as one of several merged history sources — NOT a\n * substitute for full on-disk history: this is capped at 200 entries\n * server-side and only carries daemon tick/merge/info/dispatch events, not\n * raw run stdout or the ~672 historical proposals living only on disk.\n */\nexport interface ControlLogsObservation {\n entries: ControlLogEntry[] | null;\n sourceQuality: SourceQuality;\n}\n\nexport const controlLogsObservationQuery: QueryDef<ControlLogsObservation> = {\n key: 'control-logs-observation',\n fetch: (signal) => apiGet<ControlLogsObservation>('/api/logs-observation?tail=200', signal),\n};\n\n// ---------------------------------------------------------------------------\n// Intelligence + Portfolio (charts/dataviz work)\n// ---------------------------------------------------------------------------\n\nexport type PulseWindow = '1d' | '7d' | '30d';\n\n/** GET /api/pulse?window= — buildRollup() (src/core/observability/rollup.ts).\n * Parameterized like runDetailQuery/swarmDetailQuery above: a distinct cache\n * key per window so switching windows doesn't fight over one cache entry. */\nexport function pulseQuery(window: PulseWindow): QueryDef<ActivityRollup> {\n return {\n key: `pulse-${window}`,\n fetch: (signal) => apiGet<ActivityRollup>(`/api/pulse?window=${window}`, signal),\n };\n}\n\n/**\n * GET /api/genome[?q=] — src/core/web/api.ts:1189-1201. Two response shapes\n * depending on `q`: empty/absent `q` returns `GenomeEntry[]` (list mode,\n * `loadGenome()`); a non-empty `q` returns `RecallHit[]` (query mode,\n * `recall()`, `{entry, score, method}`). Use `isRecallHit` to discriminate —\n * the view can't know which shape it got from the type alone since both are\n * arrays. Keyed per query string so a debounced search doesn't stomp the\n * browse-mode cache entry.\n */\nexport type GenomeResult = GenomeEntry[] | RecallHit[];\n\nexport function isRecallHit(item: GenomeEntry | RecallHit): item is RecallHit {\n return typeof item === 'object' && item !== null && 'entry' in item && 'score' in item;\n}\n\nexport function genomeQuery(q: string): QueryDef<GenomeResult> {\n const trimmed = q.trim();\n return {\n key: trimmed ? `genome-search-${trimmed}` : 'genome-list',\n fetch: (signal) =>\n apiGet<GenomeResult>(trimmed ? `/api/genome?q=${encodeURIComponent(trimmed)}` : '/api/genome', signal),\n };\n}\n\nexport type ModelStatsWindow = '7d' | '30d' | 'all';\n\n/** GET /api/models?window= — computeModelStatsDetailed() joined per-model\n * economics (src/core/fleet/model-stats.ts). NOTE: a second, dead\n * `/api/models` handler later in api.ts's if-chain (local-model provider\n * probe off ControlSnapshot.models) is unreachable — this one always wins\n * since route matching is first-match. */\nexport function modelsQuery(window: ModelStatsWindow): QueryDef<ModelStatsReadResult & { window: ModelStatsWindow }> {\n return {\n key: `models-${window}`,\n fetch: (signal) => apiGet(`/api/models?window=${window}`, signal),\n };\n}\n\n/**\n * GET /api/portfolio — src/core/web/api.ts:1105-1109. Returns\n * `DashboardSnapshot.portfolio ?? null`: `null` on an older producer or\n * empty enrollment, not an error — render that as an honest \"not available\"\n * state, never as a zeroed chart.\n */\nexport const portfolioQuery: QueryDef<PortfolioSummary | null> = {\n key: 'portfolio',\n fetch: (signal) => apiGet<PortfolioSummary | null>('/api/portfolio', signal),\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"queries-BTXWdZzU.js","names":[],"sources":["../../../../../../src/web-ui/data/queries.ts"],"sourcesContent":["/**\n * data/queries.ts — one typed accessor per backend resource. Each pairs a\n * stable cache key (also the SSE invalidation target — see sse.ts's\n * EVENT_TO_CACHE_KEYS) with the exact GET call and response type. Views\n * never call apiGet directly; they call these through useQuery (hooks.ts)\n * so caching, de-dupe, and SSE-driven refresh are automatic.\n */\nimport { apiGet } from './client.js';\nimport type { UniverseGraph } from '../../core/universe/graph-types.js';\nimport type {\n AgentOsSnapshotResponse,\n UniverseOverview,\n ControlLogEntry,\n ControlSnapshot,\n DashboardSnapshot,\n DecisionEntry,\n FleetActivitySnapshot,\n FleetStatus,\n Proposal,\n ProposalStatus,\n PublicDaemonObservation,\n RunState,\n SwarmRun,\n ActivityRollup,\n GenomeEntry,\n RecallHit,\n PortfolioSummary,\n ModelStatsReadResult,\n} from './api-types.js';\nimport type { SourceQuality } from './api-types.js';\n\nexport interface QueryDef<T> {\n key: string;\n fetch: (signal?: AbortSignal) => Promise<T>;\n}\n\nexport const dashboardSnapshotQuery: QueryDef<DashboardSnapshot> = {\n key: 'dashboard-snapshot',\n fetch: (signal) => apiGet<DashboardSnapshot>('/api/snapshot', signal),\n};\n\nexport const controlSnapshotQuery: QueryDef<ControlSnapshot> = {\n key: 'control-snapshot',\n fetch: (signal) => apiGet<ControlSnapshot>('/api/control', signal),\n};\n\nexport const agentOsSnapshotQuery: QueryDef<AgentOsSnapshotResponse> = {\n key: 'agent-os-snapshot',\n fetch: (signal) => apiGet<AgentOsSnapshotResponse>('/api/agent-os', signal),\n};\n\nexport const universeOverviewQuery: QueryDef<UniverseOverview> = {\n key: 'universe-overview',\n fetch: (signal) => apiGet<UniverseOverview>('/api/universe', signal),\n};\n\n/** Read only on demand; never invalidate this alongside the overview poll. */\nexport function universeGraphQuery(universeId: string): QueryDef<UniverseGraph> {\n return {\n key: `universe-graph-${universeId}`,\n fetch: (signal) => apiGet<UniverseGraph>(`/api/universe/graph?universeId=${encodeURIComponent(universeId)}`, signal),\n };\n}\n\n// NOTE: there is no standalone GET /api/visibility route — VisibilitySnapshot\n// is an optional field on DashboardSnapshot (`.visibility`), populated by\n// buildSnapshot() server-side. Read it off dashboardSnapshotQuery's data\n// rather than issuing a second request for it.\n\n/**\n * GET /api/runs returns the bare array (see src/core/web/api.ts:1121-1125,\n * `listRuns({limit:200})` -> `RunState[]`) — NOT `{runs: [...]}`. The prior\n * `RunSummary`/`runsQuery` pair here was speculative and didn't match the\n * real response shape; it was unused (FleetDashboardView reads its compact\n * run summaries off `DashboardSnapshot['runs']` instead, a different,\n * deliberately-thin shape). Replaced with the real, fully-typed contract.\n */\nexport const runsQuery: QueryDef<RunState[]> = {\n key: 'runs',\n fetch: (signal) => apiGet<RunState[]>('/api/runs', signal),\n};\n\nexport function runDetailQuery(id: string): QueryDef<RunState> {\n return {\n key: `run-detail-${id}`,\n fetch: (signal) => apiGet<RunState>(`/api/run/${encodeURIComponent(id)}`, signal),\n };\n}\n\nexport const swarmsQuery: QueryDef<SwarmRun[]> = {\n key: 'swarms',\n fetch: (signal) => apiGet<SwarmRun[]>('/api/swarms', signal),\n};\n\nexport function swarmDetailQuery(id: string): QueryDef<SwarmRun> {\n return {\n key: `swarm-detail-${id}`,\n fetch: (signal) => apiGet<SwarmRun>(`/api/swarm/${encodeURIComponent(id)}`, signal),\n };\n}\n\n/**\n * Same PublicDaemonObservation the backend embeds at ControlSnapshot.daemonObservation\n * — fetched standalone here because /control/daemon renders a fuller detail page\n * than DaemonPanel's dashboard-compact view and wants the raw observation\n * (including `ticks`) independent of whether the rest of /api/control succeeds.\n * Cache key 'daemon' deliberately matches sse.ts's existing (previously orphaned)\n * `daemon` / `daemon-observation` -> ['daemon'] mapping so this now actually\n * live-updates.\n */\nexport const daemonObservationQuery: QueryDef<PublicDaemonObservation> = {\n key: 'daemon',\n fetch: (signal) => apiGet<PublicDaemonObservation>('/api/daemon-observation', signal),\n};\n\nexport const fleetStatusQuery: QueryDef<FleetStatus> = {\n key: 'fleet',\n fetch: (signal) => apiGet<FleetStatus>('/api/fleet', signal),\n};\n\nexport const fleetActivityQuery: QueryDef<FleetActivitySnapshot> = {\n key: 'fleet-activity',\n fetch: (signal) => apiGet<FleetActivitySnapshot>('/api/fleet-activity', signal),\n};\n\n/**\n * GET /api/goals returns a bare array of ad-hoc per-goal projections built\n * inline in src/core/web/api.ts (`path === '/api/goals'`, ~line 1654) — there\n * is no exported backend type for this shape (unlike every other resource\n * here), so this interface is hand-written to match that handler exactly\n * rather than re-exported. Keep it in sync with api.ts if that handler's\n * shape changes.\n */\nexport interface GoalMilestoneSummary {\n title: string;\n status: string;\n order: number;\n}\n\nexport interface GoalSummary {\n id: string;\n objective: string;\n status: string;\n milestones: GoalMilestoneSummary[];\n progress: {\n fractionDone: number;\n counts: Record<string, number>;\n nextActionableId: string | null;\n };\n}\n\nexport const goalsQuery: QueryDef<GoalSummary[]> = {\n key: 'goals',\n fetch: (signal) => apiGet<GoalSummary[]>('/api/goals', signal),\n};\n\n/**\n * GET /api/vision/mission — buildVisionMissionSnapshot() in src/core/web/api.ts\n * is itself typed `Promise<Record<string, unknown>>` on the backend (no\n * exported interface to import), so this is a narrow hand-written contract\n * covering only the fields the Goals view actually reads: top-level `state`\n * (mirrors the SourceQuality.sourceState vocabulary) and the per-source\n * epistemic breakdown under `sources`. `briefing`/`preview`/`shadow` are\n * deliberately left as `unknown` — the view does not render briefing prose.\n */\nexport interface VisionMissionSourceStatus {\n sourceState: 'healthy' | 'degraded' | 'missing' | 'unknown';\n sourcePresent?: boolean;\n complete: boolean;\n reason?: string;\n}\n\nexport interface VisionMissionSnapshot {\n schemaVersion: number;\n state: string;\n authority: string;\n briefing: unknown;\n sources: {\n briefing: VisionMissionSourceStatus | null;\n goals: VisionMissionSourceStatus | null;\n enrollment: VisionMissionSourceStatus | null;\n proposals: VisionMissionSourceStatus | null;\n };\n}\n\nexport const visionMissionQuery: QueryDef<VisionMissionSnapshot> = {\n key: 'vision-mission',\n fetch: (signal) => apiGet<VisionMissionSnapshot>('/api/vision/mission', signal),\n};\n\nexport interface InboxProposal {\n id: string;\n title: string;\n kind: string;\n repo: string;\n origin: string;\n createdAt: string;\n}\n\nexport const inboxQuery: QueryDef<{ pending: number; proposals: InboxProposal[] }> = {\n key: 'inbox',\n fetch: (signal) => apiGet('/api/inbox', signal),\n};\n\n/**\n * `?status=&since=&limit=` view over GET /api/inbox (src/core/web/api.ts\n * INBOX_STATUS_QUERY_VALUES) — the history surface `inboxQuery` above never\n * had: it's hardcoded pending-only. `status: undefined` = server default\n * (pending); `'all'` = every status. Keyed per filter combo so switching\n * status/since/limit doesn't fight over one cache entry, and so sse.ts can\n * sweep every live combo (`invalidatePrefix('inbox-list:')`) on the 'inbox'\n * SSE event without knowing which combos are mounted.\n */\nexport type InboxHistoryStatus = ProposalStatus | 'all';\n\nexport interface InboxListFilters {\n status?: InboxHistoryStatus;\n /** ISO timestamp or YYYY-MM-DD, passed straight through to the server. */\n since?: string;\n limit?: number;\n}\n\nexport interface InboxListResponse {\n pending: number;\n total: number;\n /**\n * Full `Proposal[]`, not the narrow `InboxProposal` shape above — the\n * server has always sent full sanitized Proposal records here\n * (`listProposals()`); `InboxProposal` just under-typed it for the\n * original pending-badge use case. The history view needs `status` and\n * `decisionReason` per row (triage: \"why was this rejected\") without an\n * N+1 decisions-ledger read per row, and both live directly on Proposal.\n */\n proposals: Proposal[];\n /** True when more rows matched than were returned (hit the server cap). */\n truncated: boolean;\n filters: { status: InboxHistoryStatus; since: string | null; limit: number | null };\n}\n\nexport function inboxListQuery(filters: InboxListFilters = {}): QueryDef<InboxListResponse> {\n const params = new URLSearchParams();\n if (filters.status !== undefined) params.set('status', filters.status);\n if (filters.since !== undefined) params.set('since', filters.since);\n if (filters.limit !== undefined) params.set('limit', String(filters.limit));\n const qs = params.toString();\n return {\n key: `inbox-list:${filters.status ?? 'pending'}:${filters.since ?? ''}:${filters.limit ?? ''}`,\n fetch: (signal) => apiGet<InboxListResponse>(`/api/inbox${qs ? `?${qs}` : ''}`, signal),\n };\n}\n\n/**\n * Evidence behind a judge's verdict for one proposal — joined server-side\n * (src/core/web/api.ts GET /api/inbox/:id) from the decisions ledger, which\n * is the ONLY place `judgeReasonCode` lives (Proposal itself never carries\n * it). `judge-parse-failure`/`judge-network-failure` are infra failures,\n * never a considered `judge-review` — render them distinctly, never folded\n * together. When the ledger read is degraded or no row matches this\n * proposal, `sourceQuality` says so; render \"unknown\" via <Epistemic/>\n * rather than treating an empty `decisions` array as \"never judged\".\n */\nexport interface InboxDecisionEvidence {\n sourceQuality: SourceQuality;\n decisions: DecisionEntry[];\n}\n\n/**\n * GET /api/inbox/:id — full proposal detail including diff/taste/verdict\n * (src/core/web/api.ts:1240-1255, `loadProposal(id)`) plus `decisionEvidence`\n * (readDecisionsDetailed({proposalId}), added alongside the inbox history\n * view). Used by the work journal's \"why did it do that\" drill-in (M416) —\n * `/api/inbox` only ever returns pending proposals, but a decided\n * proposal's id (surfaced via fleet-activity's recentMerges/recentActions,\n * or via inboxListQuery's history view) still resolves here as long as its\n * on-disk record hasn't been pruned.\n */\nexport function proposalDetailQuery(id: string): QueryDef<Proposal & { decisionEvidence: InboxDecisionEvidence }> {\n return {\n key: `proposal-detail-${id}`,\n fetch: (signal) =>\n apiGet<Proposal & { decisionEvidence: InboxDecisionEvidence }>(`/api/inbox/${encodeURIComponent(id)}`, signal),\n };\n}\n\n/**\n * GET /api/logs-observation?tail=200 — the provenance-bearing sibling of\n * GET /api/logs (src/core/web/api.ts:~1543-1560): same daemon tick/merge\n * log, plus `sourceQuality` so a degraded/incomplete log can be rendered\n * honestly via <Epistemic/> instead of silently showing a truncated or\n * stale list as complete. `entries` is `null` when the source itself is not\n * healthy+complete (server-side contract, not a client guess). Used by the\n * work journal (M416) as one of several merged history sources — NOT a\n * substitute for full on-disk history: this is capped at 200 entries\n * server-side and only carries daemon tick/merge/info/dispatch events, not\n * raw run stdout or the ~672 historical proposals living only on disk.\n */\nexport interface ControlLogsObservation {\n entries: ControlLogEntry[] | null;\n sourceQuality: SourceQuality;\n}\n\nexport const controlLogsObservationQuery: QueryDef<ControlLogsObservation> = {\n key: 'control-logs-observation',\n fetch: (signal) => apiGet<ControlLogsObservation>('/api/logs-observation?tail=200', signal),\n};\n\n// ---------------------------------------------------------------------------\n// Intelligence + Portfolio (charts/dataviz work)\n// ---------------------------------------------------------------------------\n\nexport type PulseWindow = '1d' | '7d' | '30d';\n\n/** GET /api/pulse?window= — buildRollup() (src/core/observability/rollup.ts).\n * Parameterized like runDetailQuery/swarmDetailQuery above: a distinct cache\n * key per window so switching windows doesn't fight over one cache entry. */\nexport function pulseQuery(window: PulseWindow): QueryDef<ActivityRollup> {\n return {\n key: `pulse-${window}`,\n fetch: (signal) => apiGet<ActivityRollup>(`/api/pulse?window=${window}`, signal),\n };\n}\n\n/**\n * GET /api/genome[?q=] — src/core/web/api.ts:1189-1201. Two response shapes\n * depending on `q`: empty/absent `q` returns `GenomeEntry[]` (list mode,\n * `loadGenome()`); a non-empty `q` returns `RecallHit[]` (query mode,\n * `recall()`, `{entry, score, method}`). Use `isRecallHit` to discriminate —\n * the view can't know which shape it got from the type alone since both are\n * arrays. Keyed per query string so a debounced search doesn't stomp the\n * browse-mode cache entry.\n */\nexport type GenomeResult = GenomeEntry[] | RecallHit[];\n\nexport function isRecallHit(item: GenomeEntry | RecallHit): item is RecallHit {\n return typeof item === 'object' && item !== null && 'entry' in item && 'score' in item;\n}\n\nexport function genomeQuery(q: string): QueryDef<GenomeResult> {\n const trimmed = q.trim();\n return {\n key: trimmed ? `genome-search-${trimmed}` : 'genome-list',\n fetch: (signal) =>\n apiGet<GenomeResult>(trimmed ? `/api/genome?q=${encodeURIComponent(trimmed)}` : '/api/genome', signal),\n };\n}\n\nexport type ModelStatsWindow = '7d' | '30d' | 'all';\n\n/** GET /api/models?window= — computeModelStatsDetailed() joined per-model\n * economics (src/core/fleet/model-stats.ts). NOTE: a second, dead\n * `/api/models` handler later in api.ts's if-chain (local-model provider\n * probe off ControlSnapshot.models) is unreachable — this one always wins\n * since route matching is first-match. */\nexport function modelsQuery(window: ModelStatsWindow): QueryDef<ModelStatsReadResult & { window: ModelStatsWindow }> {\n return {\n key: `models-${window}`,\n fetch: (signal) => apiGet(`/api/models?window=${window}`, signal),\n };\n}\n\n/**\n * GET /api/portfolio — src/core/web/api.ts:1105-1109. Returns\n * `DashboardSnapshot.portfolio ?? null`: `null` on an older producer or\n * empty enrollment, not an error — render that as an honest \"not available\"\n * state, never as a zeroed chart.\n */\nexport const portfolioQuery: QueryDef<PortfolioSummary | null> = {\n key: 'portfolio',\n fetch: (signal) => apiGet<PortfolioSummary | null>('/api/portfolio', signal),\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as e,c as t}from"./index-CyK31YRm.js";import{D as n,F as r,M as i,O as a,U as o,l as s,o as c}from"./global-y_exIyAP.js";import{$t as l,Jt as u,Kt as d,Qt as f,Zt as p,i as m,r as h}from"./VerseConsoleApp-DXDv1aOi.js";async function g(e){try{let t=await e.json();return{detail:typeof t.error==`string`&&t.error?t.error:null,code:typeof t.code==`string`&&t.code?t.code:null}}catch{return{detail:null,code:null}}}async function _(e,t){let n=await fetch(e,{method:`GET`,credentials:`same-origin`,headers:{"x-ashlr-read-client":a()},...t?{signal:t}:{}});if(n.status===401)throw i(),new c(`Read session expired.`,401,e);if(!n.ok){let{detail:t,code:r}=await g(n);throw new c(`GET ${e} failed (HTTP ${n.status})${t?`: ${t}`:``}.`,n.status,e,t,r)}return await n.json()}async function v(e,t,i){let a=n();if(!a)throw new m;let o=await s(e,t,a,i);return r(),o}var y=encodeURIComponent;function b(e,t){return _(`${f}/${y(e)}`,t)}async function x(e,t){let n=await v(`${f}/${y(e)}`,t);return t.model!==void 0&&o(h),n}function S(e){return _(l,e)}function C(e){return v(l,e)}function w(e,t,n){return v(`${d}/${y(e)}`,t,n)}function T(e,t){return v(`${d}/${y(e)}/${y(t)}/delete`,{})}function E(e,t){return _(`${p}/${y(e)}`,t)}function D(e,t,n={}){return v(`${p}/${y(e)}`,n.sendNow?{text:t,sendNow:!0}:{text:t})}function O(e,t){return v(`${p}/${y(e)}/${y(t)}/delete`,{})}function k(e,t){return v(`${p}/${y(e)}/${y(t)}/send`,{})}function A(e,t,n){let r=new URLSearchParams({sessionId:e,q:t});return _(`${u}?${r.toString()}`,n)}var j=t(e(),1),M=[`collapsed`,`expanded`,`hidden`],N={collapsed:`Collapsed`,expanded:`Expanded`,hidden:`Hidden`},P=`ashlr.verse.reasoning.v1`,F=`collapsed`;function I(e){return typeof e==`string`&&M.includes(e)}function L(){try{let e=localStorage.getItem(P);return I(e)?e:F}catch{return F}}var R=null,z=new Set;function B(){return R===null&&(R=L()),R}function V(e){if(I(e)&&e!==B()){R=e;try{localStorage.setItem(P,e)}catch{}for(let e of[...z])e()}}function H(e){return z.add(e),()=>z.delete(e)}function U(){return(0,j.useSyncExternalStore)(H,B,B)}export{T as a,E as c,A as d,k as f,w as h,U as i,b as l,x as m,N as n,D as o,C as p,V as r,S as s,M as t,O as u};
2
- //# sourceMappingURL=reasoning-pref-KkhI_5-j.js.map
1
+ import{a as e,c as t}from"./index-DZ-UQ7v8.js";import{I as n,N as r,O as i,W as a,k as o,o as s,u as c}from"./global-CMNW_dqn.js";import{$t as l,Jt as u,Kt as d,Qt as f,Zt as p,i as m,r as h}from"./VerseConsoleApp-CWU6R3By.js";async function g(e){try{let t=await e.json();return{detail:typeof t.error==`string`&&t.error?t.error:null,code:typeof t.code==`string`&&t.code?t.code:null}}catch{return{detail:null,code:null}}}async function _(e,t){let n=await fetch(e,{method:`GET`,credentials:`same-origin`,headers:{"x-ashlr-read-client":o()},...t?{signal:t}:{}});if(n.status===401)throw r(),new s(`Read session expired.`,401,e);if(!n.ok){let{detail:t,code:r}=await g(n);throw new s(`GET ${e} failed (HTTP ${n.status})${t?`: ${t}`:``}.`,n.status,e,t,r)}return await n.json()}async function v(e,t,r){let a=i();if(!a)throw new m;let o=await c(e,t,a,r);return n(),o}var y=encodeURIComponent;function b(e,t){return _(`${f}/${y(e)}`,t)}async function x(e,t){let n=await v(`${f}/${y(e)}`,t);return t.model!==void 0&&a(h),n}function S(e){return _(l,e)}function C(e){return v(l,e)}function w(e,t,n){return v(`${d}/${y(e)}`,t,n)}function T(e,t){return v(`${d}/${y(e)}/${y(t)}/delete`,{})}function E(e,t){return _(`${p}/${y(e)}`,t)}function D(e,t,n={}){return v(`${p}/${y(e)}`,n.sendNow?{text:t,sendNow:!0}:{text:t})}function O(e,t){return v(`${p}/${y(e)}/${y(t)}/delete`,{})}function k(e,t){return v(`${p}/${y(e)}/${y(t)}/send`,{})}function A(e,t,n){let r=new URLSearchParams({sessionId:e,q:t});return _(`${u}?${r.toString()}`,n)}var j=t(e(),1),M=[`collapsed`,`expanded`,`hidden`],N={collapsed:`Collapsed`,expanded:`Expanded`,hidden:`Hidden`},P=`ashlr.verse.reasoning.v1`,F=`collapsed`;function I(e){return typeof e==`string`&&M.includes(e)}function L(){try{let e=localStorage.getItem(P);return I(e)?e:F}catch{return F}}var R=null,z=new Set;function B(){return R===null&&(R=L()),R}function V(e){if(I(e)&&e!==B()){R=e;try{localStorage.setItem(P,e)}catch{}for(let e of[...z])e()}}function H(e){return z.add(e),()=>z.delete(e)}function U(){return(0,j.useSyncExternalStore)(H,B,B)}export{T as a,E as c,A as d,k as f,w as h,U as i,b as l,x as m,N as n,D as o,C as p,V as r,S as s,M as t,O as u};
2
+ //# sourceMappingURL=reasoning-pref-Ca6lN6x_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reasoning-pref-KkhI_5-j.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/composer/composer-queries.ts","../../../../../../src/web-ui/routes/verse/chat/reasoning-pref.ts"],"sourcesContent":["/**\n * routes/verse/composer/composer-queries.ts — every call the 3.10 composer\n * makes (unit C3; core/verse/session-controls-api.ts is the server side).\n *\n * Same conventions as ../context/context-queries.ts:\n * - WRITES pull the held mutation token, throw `VerseMutationLockedError`\n * when none is held (so the caller's token gate can ask for it), and touch\n * the hold on success;\n * - READS carry the read-client proof and keep the server's refusal sentence\n * (`ApiError.detail`), because these routes answer a refused read with a\n * sentence written for a person.\n *\n * Spend: none of these start a model call EXCEPT the two that exist to send —\n * a queued follow-up when nothing is running, and [Send now]. Both go through\n * the engine's one `sendTurn` chokepoint, like POST /sessions/:id/turns.\n */\nimport { getMutationToken, getReadClientProof, reportSessionExpired, touchMutationHold } from '../../../data/auth-store.js';\nimport { invalidate } from '../../../data/cache.js';\nimport { ApiError, apiPost } from '../../../data/client.js';\nimport type {\n VerseAttachment,\n VerseAttachmentUpload,\n VerseFilesResponse,\n VerseQueueResponse,\n VerseSessionControlDefaults,\n VerseSessionControlDefaultsUpdate,\n VerseSessionControlsResponse,\n VerseSessionControlsUpdate,\n} from '../../../../core/verse/workbench-types.js';\nimport {\n VERSE_ATTACHMENTS_PATH,\n VERSE_FILES_PATH,\n VERSE_QUEUE_PATH,\n VERSE_SESSION_CONTROL_DEFAULTS_PATH,\n VERSE_SESSION_CONTROLS_PATH,\n} from '../../../../core/verse/workbench-types.js';\nimport { VERSE_SESSIONS_KEY, VerseMutationLockedError } from '../verse-queries.js';\n\n/** POST /queue and /send answer with the queue plus the turn they started, if any. */\nexport type VerseQueueSendResult = VerseQueueResponse & { sentTurnId: string | null };\n\nasync function refusalDetail(res: Response): Promise<{ detail: string | null; code: string | null }> {\n try {\n const body = (await res.json()) as { error?: unknown; code?: unknown };\n return {\n detail: typeof body.error === 'string' && body.error ? body.error : null,\n code: typeof body.code === 'string' && body.code ? body.code : null,\n };\n } catch {\n return { detail: null, code: null };\n }\n}\n\nasync function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(path, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { 'x-ashlr-read-client': getReadClientProof() },\n ...(signal ? { signal } : {}),\n });\n if (res.status === 401) {\n reportSessionExpired();\n throw new ApiError('Read session expired.', 401, path);\n }\n if (!res.ok) {\n const { detail, code } = await refusalDetail(res);\n throw new ApiError(`GET ${path} failed (HTTP ${res.status})${detail ? `: ${detail}` : ''}.`, res.status, path, detail, code);\n }\n return (await res.json()) as T;\n}\n\nasync function post<T>(path: string, body: unknown, signal?: AbortSignal): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseMutationLockedError();\n const result = await apiPost<T>(path, body, token, signal);\n touchMutationHold();\n return result;\n}\n\nconst enc = encodeURIComponent;\n\n// ---------------------------------------------------------------------------\n// Controls\n// ---------------------------------------------------------------------------\n\nexport function fetchSessionControls(sessionId: string, signal?: AbortSignal): Promise<VerseSessionControlsResponse> {\n return getJson(`${VERSE_SESSION_CONTROLS_PATH}/${enc(sessionId)}`, signal);\n}\n\nexport async function updateSessionControls(sessionId: string, update: VerseSessionControlsUpdate): Promise<VerseSessionControlsResponse> {\n const result = await post<VerseSessionControlsResponse>(`${VERSE_SESSION_CONTROLS_PATH}/${enc(sessionId)}`, update);\n // A model switch changes the record the header and the chat list draw.\n if (update.model !== undefined) invalidate(VERSE_SESSIONS_KEY);\n return result;\n}\n\nexport function fetchControlDefaults(signal?: AbortSignal): Promise<VerseSessionControlDefaults> {\n return getJson(VERSE_SESSION_CONTROL_DEFAULTS_PATH, signal);\n}\n\nexport function updateControlDefaults(update: VerseSessionControlDefaultsUpdate): Promise<VerseSessionControlDefaults> {\n return post(VERSE_SESSION_CONTROL_DEFAULTS_PATH, update);\n}\n\n// ---------------------------------------------------------------------------\n// Attachments\n// ---------------------------------------------------------------------------\n\nexport function uploadAttachment(sessionId: string, upload: VerseAttachmentUpload, signal?: AbortSignal): Promise<VerseAttachment> {\n return post(`${VERSE_ATTACHMENTS_PATH}/${enc(sessionId)}`, upload, signal);\n}\n\nexport function deleteAttachment(sessionId: string, attachmentId: string): Promise<{ sessionId: string; items: VerseAttachment[] }> {\n return post(`${VERSE_ATTACHMENTS_PATH}/${enc(sessionId)}/${enc(attachmentId)}/delete`, {});\n}\n\n// ---------------------------------------------------------------------------\n// Queue\n// ---------------------------------------------------------------------------\n\nexport function fetchQueue(sessionId: string, signal?: AbortSignal): Promise<VerseQueueResponse> {\n return getJson(`${VERSE_QUEUE_PATH}/${enc(sessionId)}`, signal);\n}\n\nexport function enqueueFollowUp(sessionId: string, text: string, opts: { sendNow?: boolean } = {}): Promise<VerseQueueSendResult> {\n return post(`${VERSE_QUEUE_PATH}/${enc(sessionId)}`, opts.sendNow ? { text, sendNow: true } : { text });\n}\n\nexport function removeFollowUp(sessionId: string, queueId: string): Promise<VerseQueueResponse> {\n return post(`${VERSE_QUEUE_PATH}/${enc(sessionId)}/${enc(queueId)}/delete`, {});\n}\n\nexport function sendFollowUpNow(sessionId: string, queueId: string): Promise<VerseQueueSendResult> {\n return post(`${VERSE_QUEUE_PATH}/${enc(sessionId)}/${enc(queueId)}/send`, {});\n}\n\n// ---------------------------------------------------------------------------\n// Files (`@`)\n// ---------------------------------------------------------------------------\n\n/** The chat's cwd root rides along (additive), so a match there is written relative. */\nexport type VerseFilesResult = VerseFilesResponse & { primaryRoot?: string | null };\n\nexport function searchSessionFiles(sessionId: string, query: string, signal?: AbortSignal): Promise<VerseFilesResult> {\n const params = new URLSearchParams({ sessionId, q: query });\n return getJson(`${VERSE_FILES_PATH}?${params.toString()}`, signal);\n}\n","/**\n * routes/verse/chat/reasoning-pref.ts — how the transcript shows the model's\n * reasoning (SPEC-310C §2 \"Settings offers Expanded, Collapsed or Hidden\";\n * unit C2 owns the behaviour, C1's Settings ▸ Chat panel renders the control).\n *\n * collapsed (default) a block streams in a three-line window while the\n * model thinks, then folds to \"Thought 12s · ~1.8k tok ▸\";\n * expanded the same stream, but a finished block stays open;\n * hidden no reasoning in the transcript at all — the live status line\n * still says \"Thinking · 12s\", so a long think is never mistaken\n * for a hang.\n *\n * A per-device preference, so it lives in this browser's storage under its\n * own key (the precedent of resources-collapse / chat-panel-sizing: display\n * preferences that are not part of the shell's v3 blob). Framework-free store\n * + one hook; every read and write is try/catch'd because storage can be\n * absent (private window, blocked site data).\n */\nimport { useSyncExternalStore } from 'react';\n\nexport const REASONING_DISPLAYS = ['collapsed', 'expanded', 'hidden'] as const;\nexport type ReasoningDisplay = (typeof REASONING_DISPLAYS)[number];\n\nexport const REASONING_DISPLAY_LABEL: Readonly<Record<ReasoningDisplay, string>> = {\n collapsed: 'Collapsed',\n expanded: 'Expanded',\n hidden: 'Hidden',\n};\n\nexport const REASONING_DISPLAY_KEY = 'ashlr.verse.reasoning.v1';\nexport const DEFAULT_REASONING_DISPLAY: ReasoningDisplay = 'collapsed';\n\nexport function isReasoningDisplay(value: unknown): value is ReasoningDisplay {\n return typeof value === 'string' && (REASONING_DISPLAYS as readonly string[]).includes(value);\n}\n\nfunction read(): ReasoningDisplay {\n try {\n const raw = localStorage.getItem(REASONING_DISPLAY_KEY);\n return isReasoningDisplay(raw) ? raw : DEFAULT_REASONING_DISPLAY;\n } catch {\n return DEFAULT_REASONING_DISPLAY;\n }\n}\n\nlet current: ReasoningDisplay | null = null;\nconst listeners = new Set<() => void>();\n\nexport function getReasoningDisplay(): ReasoningDisplay {\n if (current === null) current = read();\n return current;\n}\n\nexport function setReasoningDisplay(next: ReasoningDisplay): void {\n if (!isReasoningDisplay(next) || next === getReasoningDisplay()) return;\n current = next;\n try {\n localStorage.setItem(REASONING_DISPLAY_KEY, next);\n } catch {\n /* the choice still holds for this page */\n }\n for (const listener of [...listeners]) listener();\n}\n\nexport function subscribeReasoningDisplay(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** Test seam: forget the in-memory value so the next read re-reads storage. */\nexport function resetReasoningDisplay(): void {\n current = null;\n for (const listener of [...listeners]) listener();\n}\n\nexport function useReasoningDisplay(): ReasoningDisplay {\n return useSyncExternalStore(subscribeReasoningDisplay, getReasoningDisplay, getReasoningDisplay);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reasoning-pref-Ca6lN6x_.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/composer/composer-queries.ts","../../../../../../src/web-ui/routes/verse/chat/reasoning-pref.ts"],"sourcesContent":["/**\n * routes/verse/composer/composer-queries.ts — every call the 3.10 composer\n * makes (unit C3; core/verse/session-controls-api.ts is the server side).\n *\n * Same conventions as ../context/context-queries.ts:\n * - WRITES pull the held mutation token, throw `VerseMutationLockedError`\n * when none is held (so the caller's token gate can ask for it), and touch\n * the hold on success;\n * - READS carry the read-client proof and keep the server's refusal sentence\n * (`ApiError.detail`), because these routes answer a refused read with a\n * sentence written for a person.\n *\n * Spend: none of these start a model call EXCEPT the two that exist to send —\n * a queued follow-up when nothing is running, and [Send now]. Both go through\n * the engine's one `sendTurn` chokepoint, like POST /sessions/:id/turns.\n */\nimport { getMutationToken, getReadClientProof, reportSessionExpired, touchMutationHold } from '../../../data/auth-store.js';\nimport { invalidate } from '../../../data/cache.js';\nimport { ApiError, apiPost } from '../../../data/client.js';\nimport type {\n VerseAttachment,\n VerseAttachmentUpload,\n VerseFilesResponse,\n VerseQueueResponse,\n VerseSessionControlDefaults,\n VerseSessionControlDefaultsUpdate,\n VerseSessionControlsResponse,\n VerseSessionControlsUpdate,\n} from '../../../../core/verse/workbench-types.js';\nimport {\n VERSE_ATTACHMENTS_PATH,\n VERSE_FILES_PATH,\n VERSE_QUEUE_PATH,\n VERSE_SESSION_CONTROL_DEFAULTS_PATH,\n VERSE_SESSION_CONTROLS_PATH,\n} from '../../../../core/verse/workbench-types.js';\nimport { VERSE_SESSIONS_KEY, VerseMutationLockedError } from '../verse-queries.js';\n\n/** POST /queue and /send answer with the queue plus the turn they started, if any. */\nexport type VerseQueueSendResult = VerseQueueResponse & { sentTurnId: string | null };\n\nasync function refusalDetail(res: Response): Promise<{ detail: string | null; code: string | null }> {\n try {\n const body = (await res.json()) as { error?: unknown; code?: unknown };\n return {\n detail: typeof body.error === 'string' && body.error ? body.error : null,\n code: typeof body.code === 'string' && body.code ? body.code : null,\n };\n } catch {\n return { detail: null, code: null };\n }\n}\n\nasync function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(path, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { 'x-ashlr-read-client': getReadClientProof() },\n ...(signal ? { signal } : {}),\n });\n if (res.status === 401) {\n reportSessionExpired();\n throw new ApiError('Read session expired.', 401, path);\n }\n if (!res.ok) {\n const { detail, code } = await refusalDetail(res);\n throw new ApiError(`GET ${path} failed (HTTP ${res.status})${detail ? `: ${detail}` : ''}.`, res.status, path, detail, code);\n }\n return (await res.json()) as T;\n}\n\nasync function post<T>(path: string, body: unknown, signal?: AbortSignal): Promise<T> {\n const token = getMutationToken();\n if (!token) throw new VerseMutationLockedError();\n const result = await apiPost<T>(path, body, token, signal);\n touchMutationHold();\n return result;\n}\n\nconst enc = encodeURIComponent;\n\n// ---------------------------------------------------------------------------\n// Controls\n// ---------------------------------------------------------------------------\n\nexport function fetchSessionControls(sessionId: string, signal?: AbortSignal): Promise<VerseSessionControlsResponse> {\n return getJson(`${VERSE_SESSION_CONTROLS_PATH}/${enc(sessionId)}`, signal);\n}\n\nexport async function updateSessionControls(sessionId: string, update: VerseSessionControlsUpdate): Promise<VerseSessionControlsResponse> {\n const result = await post<VerseSessionControlsResponse>(`${VERSE_SESSION_CONTROLS_PATH}/${enc(sessionId)}`, update);\n // A model switch changes the record the header and the chat list draw.\n if (update.model !== undefined) invalidate(VERSE_SESSIONS_KEY);\n return result;\n}\n\nexport function fetchControlDefaults(signal?: AbortSignal): Promise<VerseSessionControlDefaults> {\n return getJson(VERSE_SESSION_CONTROL_DEFAULTS_PATH, signal);\n}\n\nexport function updateControlDefaults(update: VerseSessionControlDefaultsUpdate): Promise<VerseSessionControlDefaults> {\n return post(VERSE_SESSION_CONTROL_DEFAULTS_PATH, update);\n}\n\n// ---------------------------------------------------------------------------\n// Attachments\n// ---------------------------------------------------------------------------\n\nexport function uploadAttachment(sessionId: string, upload: VerseAttachmentUpload, signal?: AbortSignal): Promise<VerseAttachment> {\n return post(`${VERSE_ATTACHMENTS_PATH}/${enc(sessionId)}`, upload, signal);\n}\n\nexport function deleteAttachment(sessionId: string, attachmentId: string): Promise<{ sessionId: string; items: VerseAttachment[] }> {\n return post(`${VERSE_ATTACHMENTS_PATH}/${enc(sessionId)}/${enc(attachmentId)}/delete`, {});\n}\n\n// ---------------------------------------------------------------------------\n// Queue\n// ---------------------------------------------------------------------------\n\nexport function fetchQueue(sessionId: string, signal?: AbortSignal): Promise<VerseQueueResponse> {\n return getJson(`${VERSE_QUEUE_PATH}/${enc(sessionId)}`, signal);\n}\n\nexport function enqueueFollowUp(sessionId: string, text: string, opts: { sendNow?: boolean } = {}): Promise<VerseQueueSendResult> {\n return post(`${VERSE_QUEUE_PATH}/${enc(sessionId)}`, opts.sendNow ? { text, sendNow: true } : { text });\n}\n\nexport function removeFollowUp(sessionId: string, queueId: string): Promise<VerseQueueResponse> {\n return post(`${VERSE_QUEUE_PATH}/${enc(sessionId)}/${enc(queueId)}/delete`, {});\n}\n\nexport function sendFollowUpNow(sessionId: string, queueId: string): Promise<VerseQueueSendResult> {\n return post(`${VERSE_QUEUE_PATH}/${enc(sessionId)}/${enc(queueId)}/send`, {});\n}\n\n// ---------------------------------------------------------------------------\n// Files (`@`)\n// ---------------------------------------------------------------------------\n\n/** The chat's cwd root rides along (additive), so a match there is written relative. */\nexport type VerseFilesResult = VerseFilesResponse & { primaryRoot?: string | null };\n\nexport function searchSessionFiles(sessionId: string, query: string, signal?: AbortSignal): Promise<VerseFilesResult> {\n const params = new URLSearchParams({ sessionId, q: query });\n return getJson(`${VERSE_FILES_PATH}?${params.toString()}`, signal);\n}\n","/**\n * routes/verse/chat/reasoning-pref.ts — how the transcript shows the model's\n * reasoning (SPEC-310C §2 \"Settings offers Expanded, Collapsed or Hidden\";\n * unit C2 owns the behaviour, C1's Settings ▸ Chat panel renders the control).\n *\n * collapsed (default) a block streams in a three-line window while the\n * model thinks, then folds to \"Thought 12s · ~1.8k tok ▸\";\n * expanded the same stream, but a finished block stays open;\n * hidden no reasoning in the transcript at all — the live status line\n * still says \"Thinking · 12s\", so a long think is never mistaken\n * for a hang.\n *\n * A per-device preference, so it lives in this browser's storage under its\n * own key (the precedent of resources-collapse / chat-panel-sizing: display\n * preferences that are not part of the shell's v3 blob). Framework-free store\n * + one hook; every read and write is try/catch'd because storage can be\n * absent (private window, blocked site data).\n */\nimport { useSyncExternalStore } from 'react';\n\nexport const REASONING_DISPLAYS = ['collapsed', 'expanded', 'hidden'] as const;\nexport type ReasoningDisplay = (typeof REASONING_DISPLAYS)[number];\n\nexport const REASONING_DISPLAY_LABEL: Readonly<Record<ReasoningDisplay, string>> = {\n collapsed: 'Collapsed',\n expanded: 'Expanded',\n hidden: 'Hidden',\n};\n\nexport const REASONING_DISPLAY_KEY = 'ashlr.verse.reasoning.v1';\nexport const DEFAULT_REASONING_DISPLAY: ReasoningDisplay = 'collapsed';\n\nexport function isReasoningDisplay(value: unknown): value is ReasoningDisplay {\n return typeof value === 'string' && (REASONING_DISPLAYS as readonly string[]).includes(value);\n}\n\nfunction read(): ReasoningDisplay {\n try {\n const raw = localStorage.getItem(REASONING_DISPLAY_KEY);\n return isReasoningDisplay(raw) ? raw : DEFAULT_REASONING_DISPLAY;\n } catch {\n return DEFAULT_REASONING_DISPLAY;\n }\n}\n\nlet current: ReasoningDisplay | null = null;\nconst listeners = new Set<() => void>();\n\nexport function getReasoningDisplay(): ReasoningDisplay {\n if (current === null) current = read();\n return current;\n}\n\nexport function setReasoningDisplay(next: ReasoningDisplay): void {\n if (!isReasoningDisplay(next) || next === getReasoningDisplay()) return;\n current = next;\n try {\n localStorage.setItem(REASONING_DISPLAY_KEY, next);\n } catch {\n /* the choice still holds for this page */\n }\n for (const listener of [...listeners]) listener();\n}\n\nexport function subscribeReasoningDisplay(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** Test seam: forget the in-memory value so the next read re-reads storage. */\nexport function resetReasoningDisplay(): void {\n current = null;\n for (const listener of [...listeners]) listener();\n}\n\nexport function useReasoningDisplay(): ReasoningDisplay {\n return useSyncExternalStore(subscribeReasoningDisplay, getReasoningDisplay, getReasoningDisplay);\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"./nav-mimleI0R.js";var t=3e3;function n(e){return typeof CSS<`u`&&typeof CSS.escape==`function`?CSS.escape(e):e.replace(/["\\]/g,`\\$&`)}function r(t,r,i=document){let a=i.querySelector(`[data-surface="${n(t)}"]`);return a?a.querySelector(`#${n(e(r))}`)??a.querySelector(`[data-verse-anchor="${n(r)}"]`):null}function i(e){typeof e.scrollIntoView==`function`&&e.scrollIntoView({block:`center`,behavior:`smooth`}),(e.tabIndex>=0||e.matches(`a[href],button,input,select,textarea,[tabindex]`))&&e.focus({preventScroll:!0})}function a({section:e,anchor:n},a=t){if(typeof document>`u`)return Promise.resolve(!1);let o=r(e,n);return o&&!o.closest(`[hidden]`)?(i(o),Promise.resolve(!0)):new Promise(t=>{let o=!1,s=e=>{o||(o=!0,l.disconnect(),window.clearTimeout(u),e&&i(e),t(e!==null))},c=()=>{let t=r(e,n);t&&!t.closest(`[hidden]`)&&s(t)},l=new MutationObserver(c);l.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`hidden`,`id`,`data-verse-anchor`]});let u=window.setTimeout(()=>s(null),a);c()})}export{t as ANCHOR_WAIT_MS,r as findAnchorElement,a as revealAnchor};
2
- //# sourceMappingURL=reveal-anchor-CCCx_kfT.js.map
1
+ import{t as e}from"./nav-0dOYe2rJ.js";var t=3e3;function n(e){return typeof CSS<`u`&&typeof CSS.escape==`function`?CSS.escape(e):e.replace(/["\\]/g,`\\$&`)}function r(t,r,i=document){let a=i.querySelector(`[data-surface="${n(t)}"]`);return a?a.querySelector(`#${n(e(r))}`)??a.querySelector(`[data-verse-anchor="${n(r)}"]`):null}function i(e){typeof e.scrollIntoView==`function`&&e.scrollIntoView({block:`center`,behavior:`smooth`}),(e.tabIndex>=0||e.matches(`a[href],button,input,select,textarea,[tabindex]`))&&e.focus({preventScroll:!0})}function a({section:e,anchor:n},a=t){if(typeof document>`u`)return Promise.resolve(!1);let o=r(e,n);return o&&!o.closest(`[hidden]`)?(i(o),Promise.resolve(!0)):new Promise(t=>{let o=!1,s=e=>{o||(o=!0,l.disconnect(),window.clearTimeout(u),e&&i(e),t(e!==null))},c=()=>{let t=r(e,n);t&&!t.closest(`[hidden]`)&&s(t)},l=new MutationObserver(c);l.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`hidden`,`id`,`data-verse-anchor`]});let u=window.setTimeout(()=>s(null),a);c()})}export{t as ANCHOR_WAIT_MS,r as findAnchorElement,a as revealAnchor};
2
+ //# sourceMappingURL=reveal-anchor-DfNLgK_I.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reveal-anchor-CCCx_kfT.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/reveal-anchor.ts"],"sourcesContent":["/**\n * routes/verse/shell/reveal-anchor.ts — \"go to that card\" for any surface\n * (unit C1; C7 cross-unit request 3).\n *\n * Needs-you items, Leader memos and Command cards point INTO a surface\n * (\"memo:m-7\" on Mind, \"seat:claude-a\" on Apps). Whoever raises it calls\n * `setVerseSection(section, anchor)` (or dispatches VERSE_ANCHOR_EVENT); the\n * shell listens once (VerseApp, through shell/anchor-requests.ts) and reveals\n * the element here.\n *\n * WHY WAIT, AND FOR HOW LONG. The target surface may be a lazy chunk that has\n * not loaded, a keep-alive surface un-hiding, or a list still fetching its\n * rows. Two animation frames (C7's own fallback in command/nav.ts) cover the\n * keep-alive case only; a cold chunk takes longer. So this watches the\n * surface's subtree until the element appears, and gives up quietly after\n * ANCHOR_WAIT_MS — a missing anchor is never an error, the operator is\n * already on the right surface.\n *\n * WHICH ELEMENT. C7 stamps `id=\"c7-anchor-<key>\"` (command/nav.ts anchorId);\n * any other owner may stamp `data-verse-anchor=\"<key>\"` instead of adopting\n * C7's id scheme. The search is scoped to `[data-surface=<section>]` so an\n * identically-keyed card on a HIDDEN keep-alive surface never wins.\n */\nimport { anchorId } from '../command/nav.js';\nimport type { VerseAnchorRequest } from '../verse-ui-store.js';\n\nexport const ANCHOR_WAIT_MS = 3_000;\n\nfunction cssEscape(value: string): string {\n return typeof CSS !== 'undefined' && typeof CSS.escape === 'function' ? CSS.escape(value) : value.replace(/[\"\\\\]/g, '\\\\$&');\n}\n\n/** The anchor's element on `section`'s surface, or null when it is not in the DOM (yet). */\nexport function findAnchorElement(section: string, anchor: string, root: ParentNode = document): HTMLElement | null {\n const host = root.querySelector<HTMLElement>(`[data-surface=\"${cssEscape(section)}\"]`);\n if (!host) return null;\n return (\n host.querySelector<HTMLElement>(`#${cssEscape(anchorId(anchor))}`) ??\n host.querySelector<HTMLElement>(`[data-verse-anchor=\"${cssEscape(anchor)}\"]`)\n );\n}\n\nfunction reveal(el: HTMLElement): void {\n if (typeof el.scrollIntoView === 'function') el.scrollIntoView({ block: 'center', behavior: 'smooth' });\n // Keyboard users land ON the card, not just near it. Only an element that\n // can already take focus is focused — the shell never rewrites another\n // unit's tab order to make a div focusable.\n if (el.tabIndex >= 0 || el.matches('a[href],button,input,select,textarea,[tabindex]')) {\n el.focus({ preventScroll: true });\n }\n}\n\n/**\n * Reveal `anchor` on `section`. Resolves true when it was found and scrolled\n * to, false when it did not appear within `waitMs`. Never throws.\n */\nexport function revealAnchor({ section, anchor }: VerseAnchorRequest, waitMs: number = ANCHOR_WAIT_MS): Promise<boolean> {\n if (typeof document === 'undefined') return Promise.resolve(false);\n const now = findAnchorElement(section, anchor);\n if (now && !now.closest('[hidden]')) {\n reveal(now);\n return Promise.resolve(true);\n }\n return new Promise((resolve) => {\n let done = false;\n const finish = (el: HTMLElement | null) => {\n if (done) return;\n done = true;\n observer.disconnect();\n window.clearTimeout(timer);\n if (el) reveal(el);\n resolve(el !== null);\n };\n const check = () => {\n const el = findAnchorElement(section, anchor);\n // Wait for the surface to be un-hidden too: scrolling a hidden element is a no-op.\n if (el && !el.closest('[hidden]')) finish(el);\n };\n const observer = new MutationObserver(check);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['hidden', 'id', 'data-verse-anchor'] });\n const timer = window.setTimeout(() => finish(null), waitMs);\n check();\n });\n}\n"],"mappings":"sCA0BA,IAAa,EAAiB,IAE9B,SAAS,EAAU,EAAuB,CACxC,OAAO,OAAO,IAAQ,KAAe,OAAO,IAAI,QAAW,WAAa,IAAI,OAAO,CAAK,EAAI,EAAM,QAAQ,SAAU,MAAM,CAC5H,CAGA,SAAgB,EAAkB,EAAiB,EAAgB,EAAmB,SAA8B,CAClH,IAAM,EAAO,EAAK,cAA2B,kBAAkB,EAAU,CAAO,EAAE,GAAG,EAErF,OADK,EAEH,EAAK,cAA2B,IAAI,EAAU,EAAS,CAAM,CAAC,GAAG,GACjE,EAAK,cAA2B,uBAAuB,EAAU,CAAM,EAAE,GAAG,EAH5D,IAKpB,CAEA,SAAS,EAAO,EAAuB,CACjC,OAAO,EAAG,gBAAmB,YAAY,EAAG,eAAe,CAAE,MAAO,SAAU,SAAU,QAAS,CAAC,GAIlG,EAAG,UAAY,GAAK,EAAG,QAAQ,iDAAiD,IAClF,EAAG,MAAM,CAAE,cAAe,EAAK,CAAC,CAEpC,CAMA,SAAgB,EAAa,CAAE,UAAS,UAA8B,EAAiB,EAAkC,CACvH,GAAI,OAAO,SAAa,IAAa,OAAO,QAAQ,QAAQ,EAAK,EACjE,IAAM,EAAM,EAAkB,EAAS,CAAM,EAK7C,OAJI,GAAO,CAAC,EAAI,QAAQ,UAAU,GAChC,EAAO,CAAG,EACH,QAAQ,QAAQ,EAAI,GAEtB,IAAI,QAAS,GAAY,CAC9B,IAAI,EAAO,GACL,EAAU,GAA2B,CACrC,IACJ,EAAO,GACP,EAAS,WAAW,EACpB,OAAO,aAAa,CAAK,EACrB,GAAI,EAAO,CAAE,EACjB,EAAQ,IAAO,IAAI,EACrB,EACM,MAAc,CAClB,IAAM,EAAK,EAAkB,EAAS,CAAM,EAExC,GAAM,CAAC,EAAG,QAAQ,UAAU,GAAG,EAAO,CAAE,CAC9C,EACM,EAAW,IAAI,iBAAiB,CAAK,EAC3C,EAAS,QAAQ,SAAS,KAAM,CAAE,UAAW,GAAM,QAAS,GAAM,WAAY,GAAM,gBAAiB,CAAC,SAAU,KAAM,mBAAmB,CAAE,CAAC,EAC5I,IAAM,EAAQ,OAAO,eAAiB,EAAO,IAAI,EAAG,CAAM,EAC1D,EAAM,CACR,CAAC,CACH"}
1
+ {"version":3,"file":"reveal-anchor-DfNLgK_I.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/reveal-anchor.ts"],"sourcesContent":["/**\n * routes/verse/shell/reveal-anchor.ts — \"go to that card\" for any surface\n * (unit C1; C7 cross-unit request 3).\n *\n * Needs-you items, Leader memos and Command cards point INTO a surface\n * (\"memo:m-7\" on Mind, \"seat:claude-a\" on Apps). Whoever raises it calls\n * `setVerseSection(section, anchor)` (or dispatches VERSE_ANCHOR_EVENT); the\n * shell listens once (VerseApp, through shell/anchor-requests.ts) and reveals\n * the element here.\n *\n * WHY WAIT, AND FOR HOW LONG. The target surface may be a lazy chunk that has\n * not loaded, a keep-alive surface un-hiding, or a list still fetching its\n * rows. Two animation frames (C7's own fallback in command/nav.ts) cover the\n * keep-alive case only; a cold chunk takes longer. So this watches the\n * surface's subtree until the element appears, and gives up quietly after\n * ANCHOR_WAIT_MS — a missing anchor is never an error, the operator is\n * already on the right surface.\n *\n * WHICH ELEMENT. C7 stamps `id=\"c7-anchor-<key>\"` (command/nav.ts anchorId);\n * any other owner may stamp `data-verse-anchor=\"<key>\"` instead of adopting\n * C7's id scheme. The search is scoped to `[data-surface=<section>]` so an\n * identically-keyed card on a HIDDEN keep-alive surface never wins.\n */\nimport { anchorId } from '../command/nav.js';\nimport type { VerseAnchorRequest } from '../verse-ui-store.js';\n\nexport const ANCHOR_WAIT_MS = 3_000;\n\nfunction cssEscape(value: string): string {\n return typeof CSS !== 'undefined' && typeof CSS.escape === 'function' ? CSS.escape(value) : value.replace(/[\"\\\\]/g, '\\\\$&');\n}\n\n/** The anchor's element on `section`'s surface, or null when it is not in the DOM (yet). */\nexport function findAnchorElement(section: string, anchor: string, root: ParentNode = document): HTMLElement | null {\n const host = root.querySelector<HTMLElement>(`[data-surface=\"${cssEscape(section)}\"]`);\n if (!host) return null;\n return (\n host.querySelector<HTMLElement>(`#${cssEscape(anchorId(anchor))}`) ??\n host.querySelector<HTMLElement>(`[data-verse-anchor=\"${cssEscape(anchor)}\"]`)\n );\n}\n\nfunction reveal(el: HTMLElement): void {\n if (typeof el.scrollIntoView === 'function') el.scrollIntoView({ block: 'center', behavior: 'smooth' });\n // Keyboard users land ON the card, not just near it. Only an element that\n // can already take focus is focused — the shell never rewrites another\n // unit's tab order to make a div focusable.\n if (el.tabIndex >= 0 || el.matches('a[href],button,input,select,textarea,[tabindex]')) {\n el.focus({ preventScroll: true });\n }\n}\n\n/**\n * Reveal `anchor` on `section`. Resolves true when it was found and scrolled\n * to, false when it did not appear within `waitMs`. Never throws.\n */\nexport function revealAnchor({ section, anchor }: VerseAnchorRequest, waitMs: number = ANCHOR_WAIT_MS): Promise<boolean> {\n if (typeof document === 'undefined') return Promise.resolve(false);\n const now = findAnchorElement(section, anchor);\n if (now && !now.closest('[hidden]')) {\n reveal(now);\n return Promise.resolve(true);\n }\n return new Promise((resolve) => {\n let done = false;\n const finish = (el: HTMLElement | null) => {\n if (done) return;\n done = true;\n observer.disconnect();\n window.clearTimeout(timer);\n if (el) reveal(el);\n resolve(el !== null);\n };\n const check = () => {\n const el = findAnchorElement(section, anchor);\n // Wait for the surface to be un-hidden too: scrolling a hidden element is a no-op.\n if (el && !el.closest('[hidden]')) finish(el);\n };\n const observer = new MutationObserver(check);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['hidden', 'id', 'data-verse-anchor'] });\n const timer = window.setTimeout(() => finish(null), waitMs);\n check();\n });\n}\n"],"mappings":"sCA0BA,IAAa,EAAiB,IAE9B,SAAS,EAAU,EAAuB,CACxC,OAAO,OAAO,IAAQ,KAAe,OAAO,IAAI,QAAW,WAAa,IAAI,OAAO,CAAK,EAAI,EAAM,QAAQ,SAAU,MAAM,CAC5H,CAGA,SAAgB,EAAkB,EAAiB,EAAgB,EAAmB,SAA8B,CAClH,IAAM,EAAO,EAAK,cAA2B,kBAAkB,EAAU,CAAO,EAAE,GAAG,EAErF,OADK,EAEH,EAAK,cAA2B,IAAI,EAAU,EAAS,CAAM,CAAC,GAAG,GACjE,EAAK,cAA2B,uBAAuB,EAAU,CAAM,EAAE,GAAG,EAH5D,IAKpB,CAEA,SAAS,EAAO,EAAuB,CACjC,OAAO,EAAG,gBAAmB,YAAY,EAAG,eAAe,CAAE,MAAO,SAAU,SAAU,QAAS,CAAC,GAIlG,EAAG,UAAY,GAAK,EAAG,QAAQ,iDAAiD,IAClF,EAAG,MAAM,CAAE,cAAe,EAAK,CAAC,CAEpC,CAMA,SAAgB,EAAa,CAAE,UAAS,UAA8B,EAAiB,EAAkC,CACvH,GAAI,OAAO,SAAa,IAAa,OAAO,QAAQ,QAAQ,EAAK,EACjE,IAAM,EAAM,EAAkB,EAAS,CAAM,EAK7C,OAJI,GAAO,CAAC,EAAI,QAAQ,UAAU,GAChC,EAAO,CAAG,EACH,QAAQ,QAAQ,EAAI,GAEtB,IAAI,QAAS,GAAY,CAC9B,IAAI,EAAO,GACL,EAAU,GAA2B,CACrC,IACJ,EAAO,GACP,EAAS,WAAW,EACpB,OAAO,aAAa,CAAK,EACrB,GAAI,EAAO,CAAE,EACjB,EAAQ,IAAO,IAAI,EACrB,EACM,MAAc,CAClB,IAAM,EAAK,EAAkB,EAAS,CAAM,EAExC,GAAM,CAAC,EAAG,QAAQ,UAAU,GAAG,EAAO,CAAE,CAC9C,EACM,EAAW,IAAI,iBAAiB,CAAK,EAC3C,EAAS,QAAQ,SAAS,KAAM,CAAE,UAAW,GAAM,QAAS,GAAM,WAAY,GAAM,gBAAiB,CAAC,SAAU,KAAM,mBAAmB,CAAE,CAAC,EAC5I,IAAM,EAAQ,OAAO,eAAiB,EAAO,IAAI,EAAG,CAAM,EAC1D,EAAM,CACR,CAAC,CACH"}
@@ -0,0 +1,2 @@
1
+ import{C as e,S as t,b as n,r}from"./verse-model-DAVevkNe.js";import{_ as i,b as a}from"./format-CH4g_sl1.js";var o={ready:`ready`,tight:`tight`,exhausted:`blocked`,"signed-out":`blocked`,unknown:`unread`};function s(e,t=Date.now()){let n=a(e,t);return n===null?null:`resets ${n}`}function c(t,n){let r=`${t}_`,i=n;for(;i.startsWith(r)&&i.length>r.length;)i=i.slice(r.length);return e(i)}function l(e,t,n){let r=t.resetDescription??(t.resetsAt===null?null:s(t.resetsAt,n));return{id:t.id,label:c(e,t.id),usedPercent:t.limitReached||!t.measured?null:t.usedPercent,limitReached:t.limitReached,resetText:r,resetsAt:t.resetsAt}}function u(t,n){let r=typeof t.usedPercent==`number`&&Number.isFinite(t.usedPercent)?Math.max(0,Math.min(100,t.usedPercent)):null,i=r!==null&&r>=100;return{id:t.id,label:e(t.id),usedPercent:i?null:r,limitReached:i,resetText:t.resetsAt===null?null:s(t.resetsAt,n),resetsAt:t.resetsAt}}function d(e){if(e===null)return{phrase:null,title:null};if(e.unlimited)return{phrase:`credits unlimited`,title:null};if(!e.hasCredits)return{phrase:null,title:null};if(e.balance===null)return{phrase:`credits available`,title:null};let t=Number.parseFloat(e.balance);return Number.isFinite(t)?{phrase:`${t.toFixed(2)} credits left`,title:e.balance}:{phrase:`credits available`,title:e.balance}}function f(e){let n=t(e),i=e.health.state===`ready`,a=n===null?i?`ready`:`unread`:`blocked`;return{kind:`local`,plan:null,cls:a,word:r[a],summary:n??(i?`runs on this machine`:`readiness not reported`),binding:null,others:[],credits:null,creditsTitle:null,notes:e.health.summary===null?[]:[e.health.summary],evidenceSource:null,observedAt:e.health.observedAt,extended:!1}}function p(e,i){let a=n(e),o=e.health.windows.map(e=>u(e,i)),s=o.find(e=>e.limitReached)??null,c=o.filter(e=>e.usedPercent!==null),l=c.length===0?null:c.reduce((e,t)=>(t.usedPercent??0)>(e.usedPercent??0)?t:e),d=s??l,f=t(e),p=f===null?a.cls:`blocked`;return{kind:`subscription`,plan:null,cls:p,word:r[p],summary:f??a.text,binding:d,others:d===null?o:o.filter(e=>e.id!==d.id),credits:null,creditsTitle:null,notes:[],evidenceSource:null,observedAt:e.health.observedAt,extended:!1}}function m(e,n=Date.now()){if(e.engine===`local`)return f(e);let a=e.capacity;if(a===void 0)return p(e,n);let s=a.windows.map(t=>l(e.engine,t,n)),c=a.binding,u=c===null?null:s.find(e=>e.id===c.id)??l(e.engine,c,n),m=u===null?s:s.filter(e=>e.id!==u.id),h=e.health.state===`degraded`&&a.usability===`unknown`,g=h?{phrase:null,title:null}:d(a.credits),_=t(e),v=_===null?o[a.usability]:`blocked`,y;return y=a.usability===`signed-out`?`signed out — reconnect this account`:_===null?u===null?`no capacity reading`:u.limitReached?a.usability===`tight`&&g.phrase!==null?`${u.label} limit reached · credits still spendable`:`${u.label} limit reached`:u.usedPercent===null?`no capacity reading`:`${i(u.usedPercent)} of ${u.label} used`:_,h&&(y=u===null?`No current capacity reading; current access unconfirmed`:`Last verified reading: ${y}; current access unconfirmed`),{kind:`subscription`,plan:a.planType,cls:v,word:r[v],summary:y,binding:u,others:m,credits:g.phrase,creditsTitle:g.title,notes:[...a.notes],evidenceSource:a.evidenceSource,observedAt:a.observedAt??e.health.observedAt,extended:!0}}function h(e){return typeof e==`string`&&Number.isFinite(Date.parse(e))}function g(e){return e.limitReached||e.usedPercent!==null&&e.usedPercent>=100}function _(e,t){let n=h(t)?t:null,r=(e.binding===null?e.others:[e.binding,...e.others]).filter(g);if(r.length>0){if(r.some(e=>!h(e.resetsAt)))return null;let e=r.map(e=>e.resetsAt);return n!==null&&e.push(n),e.reduce((e,t)=>Date.parse(t)>Date.parse(e)?t:e)}return n===null?e.binding!==null&&h(e.binding.resetsAt)?e.binding.resetsAt:null:n}function v(e,t){let n=[e.label];return t.plan!==null&&n.push(t.plan),n.push(t.word),n.push(t.summary),t.credits!==null&&n.push(t.credits),t.binding?.resetText!=null&&n.push(t.binding.resetText),n.join(` · `)}function y(e){return e===`tight`||e===`blocked`}export{y as i,m as n,v as r,_ as t};
2
+ //# sourceMappingURL=seat-subscription-C5uPHBsN.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"seat-subscription-BhUUz7VL.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/seat-subscription.ts"],"sourcesContent":["/**\n * routes/verse/seat-subscription.ts — \"what subscription is behind this seat,\n * and how much of it is left\", projected ONCE for every chat surface that\n * shows a seat: the resources panel, the seat selector, the new-chat dialog,\n * the sidebar and the chat header.\n *\n * WHY THIS MODULE EXISTS\n *\n * The resources panel showed a bare \"unknown\" pill for every account — the\n * most-looked-at surface in the app. Measured against a live server,\n * `GET /api/verse/accounts` had all four accounts observed, Claude with three\n * windows and Grok with one, while `bootstrap.seats[].health` was `unknown`\n * forever for Claude and Grok: seat health came from a shared-evidence file\n * scoped `codex-native-metadata`, which structurally cannot carry those two\n * providers. The live data existed and was discarded at the last hop.\n *\n * Owner S's V2.1 contract fixes the supply side — `VerseSeat.capacity`\n * (core/verse/types.ts) now carries the plan, the binding window, the full\n * window list, credits, a usability verdict, the evidence source and the\n * provider's own notes. This module is the single place the chat surfaces\n * read it, so they cannot describe one seat four different ways.\n *\n * TWO SOURCES, ONE VIEW. `capacity` is `undefined` for local seats (an Ollama\n * tag has no subscription) and for a native seat the server could not build a\n * record for. The V1 `health.windows` shape is still read as the fallback, and\n * on that path the verdict is delegated WHOLESALE to\n * `verse-model.seatCapacity` — the seat selector and the composer's seat menu\n * already render those exact words, and two implementations of one rule is\n * how the picker and the panel would drift apart again.\n *\n * HONESTY RULES (docs/VERSE-TELEMETRY-V2.md, closing section) — every one is a\n * place where the obvious projection would lie:\n *\n * 1. THE BINDING WINDOW LEADS. An account is blocked by its WORST window, not\n * its first and not its average. Claude's weekly per-model window sat at\n * 100% while all-models read 58%; leading with 58% is a lie of emphasis.\n * 2. NO SIGNAL IS NOT ZERO. An unread window gets no meter at all. An empty\n * bar reads \"plenty left\" and a full one reads \"exhausted\"; both are false\n * when nothing was measured.\n * 3. THE SENTINEL 100 IS A FLAG. Codex writes `rateLimitReachedType` upstream\n * as the value 100. `measured: false` marks it; it renders as \"limit\n * reached\", never as \"100% used\", and carries no percentage.\n * 4. CREDITS ARE NOT THE WINDOW. A Codex account at 100% of its weekly window\n * with a spendable balance is still usable. The server already encodes\n * that in `usability: 'tight'`; this module reports both facts and never\n * collapses them into one.\n * 5. ONLY A MACHINE-READABLE INSTANT MAY BE FORMATTED. Claude's `resetsAt` is\n * structurally always null and its reset is provider prose; prose is\n * rendered VERBATIM, never parsed and never turned into a countdown.\n *\n * Pure: no React, no I/O.\n */\nimport { describeResetAt } from '../../../core/verse/seat-readiness.js';\nimport type { VerseEngine, VerseSeat } from '../../data/api-types.js';\nimport { percentText } from './autonomy/format.js';\nimport {\n SEAT_CAPACITY_WORD,\n seatCapacity,\n seatUnavailableReason,\n seatWindowLabel,\n type SeatCapacityClass,\n} from './verse-model.js';\n\nexport type { SeatCapacityClass };\n\n/**\n * Owner S's shapes, reached through `VerseSeat` rather than imported by name.\n *\n * This is the drift guard, and it costs nothing: rename or reshape\n * `VerseSeatCapacity` in core/verse/types.ts and every read below stops\n * compiling HERE, at the seam, instead of silently degrading the panel back to\n * the \"unknown\" it was built to fix.\n */\ntype SeatCapacityRecord = NonNullable<VerseSeat['capacity']>;\ntype SeatCapacityWindow = SeatCapacityRecord['windows'][number];\n\n/** One quota window, in the shape every chat surface renders. */\nexport interface SeatWindowView {\n id: string;\n /** Human label, derived from the provider's id. */\n label: string;\n /**\n * 0–100, or null. Null means \"no reading\" OR \"the figure is a sentinel\".\n * NEVER a substituted zero, and a view must not draw a meter for it.\n */\n usedPercent: number | null;\n /** The provider flagged the limit instead of measuring it. */\n limitReached: boolean;\n /**\n * Reset text, ready to render: provider prose VERBATIM when that is what the\n * provider published, a formatted local time when — and only when — it gave\n * a machine-readable instant, null when it gave neither.\n */\n resetText: string | null;\n /**\n * The machine-readable reset instant (ISO), when there was one. The only\n * field a countdown could ever legitimately be derived from; nothing in the\n * chat surfaces derives one today.\n */\n resetsAt: string | null;\n}\n\nexport interface SeatSubscriptionView {\n /**\n * Local seats have no subscription, no quota and no bill — only a readiness\n * — and must not be dressed in meters that imply otherwise.\n */\n kind: 'subscription' | 'local';\n /** Plan tier as the provider names it: \"max\", \"pro\", \"SuperGrok\". */\n plan: string | null;\n cls: SeatCapacityClass;\n /** The class as a word. State is never communicated by colour alone. */\n word: string;\n /**\n * One short phrase for an option label, a pill title or a menu row —\n * \"92% of weekly fable window used\", \"primary window limit reached\".\n */\n summary: string;\n /** The window that actually constrains work. Null when nothing was read. */\n binding: SeatWindowView | null;\n /** Every other window, in provider order. */\n others: SeatWindowView[];\n /** Codex credits as a rendered phrase. Independent of the window. */\n credits: string | null;\n /** The provider's raw balance string, kept verbatim for a title attribute. */\n creditsTitle: string | null;\n /**\n * The provider's own plain-language facts. Owner S's contract says these\n * must be SHOWN rather than left to imply a fault, so they travel here and\n * the panel prints them.\n */\n notes: string[];\n /**\n * Where the windows came from, so nothing implies freshness it lacks.\n * Null on the V1 fallback path, which has no provenance to report.\n */\n evidenceSource: SeatCapacityRecord['evidenceSource'] | null;\n /** When the reading was taken, ISO. Null when nothing was observed. */\n observedAt: string | null;\n /** True when the seat carried owner S's `capacity` record. */\n extended: boolean;\n}\n\n/**\n * S's five-state verdict, mapped onto the four words this app already uses.\n *\n * `signed-out` is BLOCKED-by-action, not unread: we know exactly why there is\n * no capacity and what to do about it. `unknown` is the only genuinely unread\n * state — nobody told us anything, and calling that blocked would assert an\n * outage we never observed.\n *\n * Typed as a total map over S's union, so adding a verdict upstream fails the\n * build here rather than falling through to a silent default.\n */\nconst USABILITY_CLASS: Record<SeatCapacityRecord['usability'], SeatCapacityClass> = {\n ready: 'ready',\n tight: 'tight',\n exhausted: 'blocked',\n 'signed-out': 'blocked',\n unknown: 'unread',\n};\n\n/**\n * A machine-readable instant, formatted — in the app's ONE reset wording,\n * `describeResetAt`'s: \"resets today 11:46 PM\", \"resets Fri 11:46 PM\",\n * \"resets Sep 26, 11:46 PM\". (A second wording here — \"resets Sep 25 at\n * 11:46 PM\" — once reached the chat header and the seat meters while Accounts\n * said \"resets Fri 11:46 PM\" for the same instant.) Prose resets never reach\n * this — they are passed through untouched, because the provider's sentence\n * already carries the timezone it means and reformatting it would be a guess.\n */\nexport function formatResetInstant(iso: string, now: number = Date.now()): string | null {\n const when = describeResetAt(iso, now);\n return when === null ? null : `resets ${when}`;\n}\n\n/**\n * Window ids arrive provider-prefixed and sometimes doubly so\n * (`codex_codex_primary`, `grok_unified_weekly`). Strip the engine's own name\n * off the front before handing the rest to the shared labeller, so the panel\n * reads \"primary window\" rather than \"codex codex primary window\".\n *\n * Only the `capacity` path uses this. The V1 fallback goes through\n * `seatWindowLabel` unaltered, because the seat selector's wording is pinned\n * to it by test.\n */\nexport function seatCapacityWindowLabel(engine: VerseEngine, id: string): string {\n const prefix = `${engine}_`;\n let rest = id;\n while (rest.startsWith(prefix) && rest.length > prefix.length) rest = rest.slice(prefix.length);\n return seatWindowLabel(rest);\n}\n\nfunction toWindowView(engine: VerseEngine, w: SeatCapacityWindow, now: number): SeatWindowView {\n const reset = w.resetDescription ?? (w.resetsAt === null ? null : formatResetInstant(w.resetsAt, now));\n return {\n id: w.id,\n label: seatCapacityWindowLabel(engine, w.id),\n // A flagged limit, and any unmeasured figure, is a sentinel — not a reading.\n usedPercent: w.limitReached || !w.measured ? null : w.usedPercent,\n limitReached: w.limitReached,\n resetText: reset,\n resetsAt: w.resetsAt,\n };\n}\n\n/** The V1 `health.windows` shape, for a seat with no `capacity` record. */\nfunction legacyWindowView(w: VerseSeat['health']['windows'][number], now: number): SeatWindowView {\n const used = typeof w.usedPercent === 'number' && Number.isFinite(w.usedPercent)\n ? Math.max(0, Math.min(100, w.usedPercent))\n : null;\n // Upstream writes a denial as 100, so on this shape a bare 100 cannot be\n // told apart from a measured 100 — and the safe reading of both is \"spent\".\n const flagged = used !== null && used >= 100;\n return {\n id: w.id,\n label: seatWindowLabel(w.id),\n usedPercent: flagged ? null : used,\n limitReached: flagged,\n resetText: w.resetsAt === null ? null : formatResetInstant(w.resetsAt, now),\n resetsAt: w.resetsAt,\n };\n}\n\nfunction creditsPhrase(credits: SeatCapacityRecord['credits']): { phrase: string | null; title: string | null } {\n if (credits === null) return { phrase: null, title: null };\n if (credits.unlimited) return { phrase: 'credits unlimited', title: null };\n if (!credits.hasCredits) return { phrase: null, title: null };\n if (credits.balance === null) return { phrase: 'credits available', title: null };\n const parsed = Number.parseFloat(credits.balance);\n if (!Number.isFinite(parsed)) return { phrase: 'credits available', title: credits.balance };\n // The provider publishes a long decimal (\"2048.4196250000\"). Two places is a\n // rendering choice, not a new number — the raw string rides in the title.\n return { phrase: `${parsed.toFixed(2)} credits left`, title: credits.balance };\n}\n\nfunction localView(seat: VerseSeat): SeatSubscriptionView {\n const unavailable = seatUnavailableReason(seat);\n const ready = seat.health.state === 'ready';\n const cls: SeatCapacityClass = unavailable !== null ? 'blocked' : ready ? 'ready' : 'unread';\n return {\n kind: 'local',\n plan: null,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary: unavailable ?? (ready ? 'runs on this machine' : 'readiness not reported'),\n binding: null,\n others: [],\n credits: null,\n creditsTitle: null,\n notes: seat.health.summary === null ? [] : [seat.health.summary],\n evidenceSource: null,\n observedAt: seat.health.observedAt,\n extended: false,\n };\n}\n\n/** The V1 path: no `capacity` record, so the V1 rule decides, unchanged. */\nfunction fallbackView(seat: VerseSeat, now: number): SeatSubscriptionView {\n const legacy = seatCapacity(seat);\n const windows = seat.health.windows.map((w) => legacyWindowView(w, now));\n const flagged = windows.find((w) => w.limitReached) ?? null;\n const measured = windows.filter((w) => w.usedPercent !== null);\n const worst = measured.length === 0\n ? null\n : measured.reduce((a, b) => ((b.usedPercent ?? 0) > (a.usedPercent ?? 0) ? b : a));\n const binding = flagged ?? worst;\n const unavailable = seatUnavailableReason(seat);\n const cls = unavailable !== null ? 'blocked' : legacy.cls;\n return {\n kind: 'subscription',\n plan: null,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary: unavailable ?? legacy.text,\n binding,\n others: binding === null ? windows : windows.filter((w) => w.id !== binding.id),\n credits: null,\n creditsTitle: null,\n notes: [],\n evidenceSource: null,\n observedAt: seat.health.observedAt,\n extended: false,\n };\n}\n\n/**\n * The whole projection. Local seats short-circuit: they have no subscription,\n * so everything below the readiness line is deliberately empty rather than\n * zeroed. `now` is the clock the reset wording is relative to (\"today\" vs a\n * weekday); it defaults to the real one.\n */\nexport function seatSubscription(seat: VerseSeat, now: number = Date.now()): SeatSubscriptionView {\n if (seat.engine === 'local') return localView(seat);\n const capacity = seat.capacity;\n if (capacity === undefined) return fallbackView(seat, now);\n\n const windows = capacity.windows.map((w) => toWindowView(seat.engine, w, now));\n // Resolve the server's CHOICE of binding window back to this seat's own\n // view of it, so the two can never disagree about a reset or a label.\n const served = capacity.binding;\n const binding = served === null\n ? null\n : (windows.find((w) => w.id === served.id) ?? toWindowView(seat.engine, served, now));\n const others = binding === null ? windows : windows.filter((w) => w.id !== binding.id);\n const lastReading = seat.health.state === 'degraded' && capacity.usability === 'unknown';\n // A failed latest check leaves the old meter visible for context only.\n // Session credits are likewise historical and must not imply spendability.\n const credits = lastReading ? { phrase: null, title: null } : creditsPhrase(capacity.credits);\n\n const unavailable = seatUnavailableReason(seat);\n const cls: SeatCapacityClass = unavailable !== null ? 'blocked' : USABILITY_CLASS[capacity.usability];\n\n let summary: string;\n // Signed out is checked FIRST, before the generic unavailable reason: owner\n // S maps `signed-out` onto `health.state: 'unavailable'` (it is the one\n // account state worth a red dot, because it has a remedy), and the generic\n // reason there is a bare \"seat unavailable\" that says nothing about the fix.\n // A signed-out account has no measurement at all — it is an action, never a\n // 0% meter and never a bare \"unknown\".\n if (capacity.usability === 'signed-out') {\n summary = 'signed out — reconnect this account';\n } else if (unavailable !== null) {\n summary = unavailable;\n } else if (binding === null) {\n summary = 'no capacity reading';\n } else if (binding.limitReached) {\n // The server already weighed credits against the spent window; `tight`\n // there means \"spent, but there is still something to spend\".\n summary = capacity.usability === 'tight' && credits.phrase !== null\n ? `${binding.label} limit reached · credits still spendable`\n : `${binding.label} limit reached`;\n } else if (binding.usedPercent === null) {\n summary = 'no capacity reading';\n } else {\n // The one percent rule: \"99%\", never a rounded \"100%\" beside a \"99%\" bar.\n summary = `${percentText(binding.usedPercent)} of ${binding.label} used`;\n }\n if (lastReading) summary = binding === null\n ? 'No current capacity reading; current access unconfirmed'\n : `Last verified reading: ${summary}; current access unconfirmed`;\n\n return {\n kind: 'subscription',\n plan: capacity.planType,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary,\n binding,\n others,\n credits: credits.phrase,\n creditsTitle: credits.title,\n notes: [...capacity.notes],\n evidenceSource: capacity.evidenceSource,\n observedAt: capacity.observedAt ?? seat.health.observedAt,\n extended: true,\n };\n}\n\n/**\n * How much of a freshness claim the evidence supports. A reading served from\n * another process's shared file, or from an operator-seeded baseline, is not\n * a live probe and must not be presented as one.\n */\nexport function evidenceNote(source: SeatSubscriptionView['evidenceSource']): string | null {\n switch (source) {\n case 'collector':\n return null;\n case 'shared-evidence':\n return 'read from another collector’s shared evidence, not probed here';\n case 'baseline':\n return 'operator-seeded baseline, not a live reading';\n case 'none':\n return 'no evidence source — nothing here was measured';\n default:\n return null;\n }\n}\n\nfunction parseableInstant(iso: string | null | undefined): iso is string {\n return typeof iso === 'string' && Number.isFinite(Date.parse(iso));\n}\n\nfunction isSpentWindow(w: Pick<SeatWindowView, 'limitReached' | 'usedPercent'>): boolean {\n return w.limitReached || (w.usedPercent !== null && w.usedPercent >= 100);\n}\n\n/**\n * When a spent seat is usable again. A seat reopens only once EVERY spent\n * window has reset — a Codex seat whose 5-hour window resets in 2h but whose\n * weekly window is also spent until Wednesday is still spent in 2h — so this\n * is the LATEST reset among the spent windows, matching Fleet's \"eligible\n * again\" (fleet/why-seat-model `eligibleAgain`) and the router's headroom\n * `lastReset`. Every surface that says \"resets …\" / \"usable again in …\" for\n * a spent seat (Accounts, the health banner) asks here.\n *\n * - a spent window with only provider prose (Claude) → null: when \"all of\n * them\" have reset is unknown, and prose is never parsed;\n * - `reported` (the health sweep's instant, which is its binding window's)\n * is folded in — it may know of a window this seat record does not — but\n * it can never make the answer EARLIER than a spent window's reset;\n * - nothing spent → `reported`, else the binding window's own instant.\n */\nexport function seatReopensAt(view: Pick<SeatSubscriptionView, 'binding' | 'others'>, reported?: string | null): string | null {\n const known = parseableInstant(reported) ? reported : null;\n const windows = view.binding === null ? view.others : [view.binding, ...view.others];\n const spent = windows.filter(isSpentWindow);\n if (spent.length > 0) {\n if (spent.some((w) => !parseableInstant(w.resetsAt))) return null;\n const instants = spent.map((w) => w.resetsAt as string);\n if (known !== null) instants.push(known);\n return instants.reduce((a, b) => (Date.parse(b) > Date.parse(a) ? b : a));\n }\n if (known !== null) return known;\n return view.binding !== null && parseableInstant(view.binding.resetsAt) ? view.binding.resetsAt : null;\n}\n\n/**\n * One sentence for a `title` attribute or a screen-reader name: the seat, its\n * plan, its verdict and the evidence behind it.\n */\nexport function seatSubscriptionSentence(seat: VerseSeat, view: SeatSubscriptionView): string {\n const parts = [seat.label];\n if (view.plan !== null) parts.push(view.plan);\n parts.push(view.word);\n parts.push(view.summary);\n if (view.credits !== null) parts.push(view.credits);\n if (view.binding?.resetText != null) parts.push(view.binding.resetText);\n return parts.join(' · ');\n}\n\n/** Tight and blocked are worth surfacing outside the panel; the rest is noise. */\nexport function worthFlagging(cls: SeatCapacityClass): boolean {\n return cls === 'tight' || cls === 'blocked';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"seat-subscription-C5uPHBsN.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/seat-subscription.ts"],"sourcesContent":["/**\n * routes/verse/seat-subscription.ts — \"what subscription is behind this seat,\n * and how much of it is left\", projected ONCE for every chat surface that\n * shows a seat: the resources panel, the seat selector, the new-chat dialog,\n * the sidebar and the chat header.\n *\n * WHY THIS MODULE EXISTS\n *\n * The resources panel showed a bare \"unknown\" pill for every account — the\n * most-looked-at surface in the app. Measured against a live server,\n * `GET /api/verse/accounts` had all four accounts observed, Claude with three\n * windows and Grok with one, while `bootstrap.seats[].health` was `unknown`\n * forever for Claude and Grok: seat health came from a shared-evidence file\n * scoped `codex-native-metadata`, which structurally cannot carry those two\n * providers. The live data existed and was discarded at the last hop.\n *\n * Owner S's V2.1 contract fixes the supply side — `VerseSeat.capacity`\n * (core/verse/types.ts) now carries the plan, the binding window, the full\n * window list, credits, a usability verdict, the evidence source and the\n * provider's own notes. This module is the single place the chat surfaces\n * read it, so they cannot describe one seat four different ways.\n *\n * TWO SOURCES, ONE VIEW. `capacity` is `undefined` for local seats (an Ollama\n * tag has no subscription) and for a native seat the server could not build a\n * record for. The V1 `health.windows` shape is still read as the fallback, and\n * on that path the verdict is delegated WHOLESALE to\n * `verse-model.seatCapacity` — the seat selector and the composer's seat menu\n * already render those exact words, and two implementations of one rule is\n * how the picker and the panel would drift apart again.\n *\n * HONESTY RULES (docs/VERSE-TELEMETRY-V2.md, closing section) — every one is a\n * place where the obvious projection would lie:\n *\n * 1. THE BINDING WINDOW LEADS. An account is blocked by its WORST window, not\n * its first and not its average. Claude's weekly per-model window sat at\n * 100% while all-models read 58%; leading with 58% is a lie of emphasis.\n * 2. NO SIGNAL IS NOT ZERO. An unread window gets no meter at all. An empty\n * bar reads \"plenty left\" and a full one reads \"exhausted\"; both are false\n * when nothing was measured.\n * 3. THE SENTINEL 100 IS A FLAG. Codex writes `rateLimitReachedType` upstream\n * as the value 100. `measured: false` marks it; it renders as \"limit\n * reached\", never as \"100% used\", and carries no percentage.\n * 4. CREDITS ARE NOT THE WINDOW. A Codex account at 100% of its weekly window\n * with a spendable balance is still usable. The server already encodes\n * that in `usability: 'tight'`; this module reports both facts and never\n * collapses them into one.\n * 5. ONLY A MACHINE-READABLE INSTANT MAY BE FORMATTED. Claude's `resetsAt` is\n * structurally always null and its reset is provider prose; prose is\n * rendered VERBATIM, never parsed and never turned into a countdown.\n *\n * Pure: no React, no I/O.\n */\nimport { describeResetAt } from '../../../core/verse/seat-readiness.js';\nimport type { VerseEngine, VerseSeat } from '../../data/api-types.js';\nimport { percentText } from './autonomy/format.js';\nimport {\n SEAT_CAPACITY_WORD,\n seatCapacity,\n seatUnavailableReason,\n seatWindowLabel,\n type SeatCapacityClass,\n} from './verse-model.js';\n\nexport type { SeatCapacityClass };\n\n/**\n * Owner S's shapes, reached through `VerseSeat` rather than imported by name.\n *\n * This is the drift guard, and it costs nothing: rename or reshape\n * `VerseSeatCapacity` in core/verse/types.ts and every read below stops\n * compiling HERE, at the seam, instead of silently degrading the panel back to\n * the \"unknown\" it was built to fix.\n */\ntype SeatCapacityRecord = NonNullable<VerseSeat['capacity']>;\ntype SeatCapacityWindow = SeatCapacityRecord['windows'][number];\n\n/** One quota window, in the shape every chat surface renders. */\nexport interface SeatWindowView {\n id: string;\n /** Human label, derived from the provider's id. */\n label: string;\n /**\n * 0–100, or null. Null means \"no reading\" OR \"the figure is a sentinel\".\n * NEVER a substituted zero, and a view must not draw a meter for it.\n */\n usedPercent: number | null;\n /** The provider flagged the limit instead of measuring it. */\n limitReached: boolean;\n /**\n * Reset text, ready to render: provider prose VERBATIM when that is what the\n * provider published, a formatted local time when — and only when — it gave\n * a machine-readable instant, null when it gave neither.\n */\n resetText: string | null;\n /**\n * The machine-readable reset instant (ISO), when there was one. The only\n * field a countdown could ever legitimately be derived from; nothing in the\n * chat surfaces derives one today.\n */\n resetsAt: string | null;\n}\n\nexport interface SeatSubscriptionView {\n /**\n * Local seats have no subscription, no quota and no bill — only a readiness\n * — and must not be dressed in meters that imply otherwise.\n */\n kind: 'subscription' | 'local';\n /** Plan tier as the provider names it: \"max\", \"pro\", \"SuperGrok\". */\n plan: string | null;\n cls: SeatCapacityClass;\n /** The class as a word. State is never communicated by colour alone. */\n word: string;\n /**\n * One short phrase for an option label, a pill title or a menu row —\n * \"92% of weekly fable window used\", \"primary window limit reached\".\n */\n summary: string;\n /** The window that actually constrains work. Null when nothing was read. */\n binding: SeatWindowView | null;\n /** Every other window, in provider order. */\n others: SeatWindowView[];\n /** Codex credits as a rendered phrase. Independent of the window. */\n credits: string | null;\n /** The provider's raw balance string, kept verbatim for a title attribute. */\n creditsTitle: string | null;\n /**\n * The provider's own plain-language facts. Owner S's contract says these\n * must be SHOWN rather than left to imply a fault, so they travel here and\n * the panel prints them.\n */\n notes: string[];\n /**\n * Where the windows came from, so nothing implies freshness it lacks.\n * Null on the V1 fallback path, which has no provenance to report.\n */\n evidenceSource: SeatCapacityRecord['evidenceSource'] | null;\n /** When the reading was taken, ISO. Null when nothing was observed. */\n observedAt: string | null;\n /** True when the seat carried owner S's `capacity` record. */\n extended: boolean;\n}\n\n/**\n * S's five-state verdict, mapped onto the four words this app already uses.\n *\n * `signed-out` is BLOCKED-by-action, not unread: we know exactly why there is\n * no capacity and what to do about it. `unknown` is the only genuinely unread\n * state — nobody told us anything, and calling that blocked would assert an\n * outage we never observed.\n *\n * Typed as a total map over S's union, so adding a verdict upstream fails the\n * build here rather than falling through to a silent default.\n */\nconst USABILITY_CLASS: Record<SeatCapacityRecord['usability'], SeatCapacityClass> = {\n ready: 'ready',\n tight: 'tight',\n exhausted: 'blocked',\n 'signed-out': 'blocked',\n unknown: 'unread',\n};\n\n/**\n * A machine-readable instant, formatted — in the app's ONE reset wording,\n * `describeResetAt`'s: \"resets today 11:46 PM\", \"resets Fri 11:46 PM\",\n * \"resets Sep 26, 11:46 PM\". (A second wording here — \"resets Sep 25 at\n * 11:46 PM\" — once reached the chat header and the seat meters while Accounts\n * said \"resets Fri 11:46 PM\" for the same instant.) Prose resets never reach\n * this — they are passed through untouched, because the provider's sentence\n * already carries the timezone it means and reformatting it would be a guess.\n */\nexport function formatResetInstant(iso: string, now: number = Date.now()): string | null {\n const when = describeResetAt(iso, now);\n return when === null ? null : `resets ${when}`;\n}\n\n/**\n * Window ids arrive provider-prefixed and sometimes doubly so\n * (`codex_codex_primary`, `grok_unified_weekly`). Strip the engine's own name\n * off the front before handing the rest to the shared labeller, so the panel\n * reads \"primary window\" rather than \"codex codex primary window\".\n *\n * Only the `capacity` path uses this. The V1 fallback goes through\n * `seatWindowLabel` unaltered, because the seat selector's wording is pinned\n * to it by test.\n */\nexport function seatCapacityWindowLabel(engine: VerseEngine, id: string): string {\n const prefix = `${engine}_`;\n let rest = id;\n while (rest.startsWith(prefix) && rest.length > prefix.length) rest = rest.slice(prefix.length);\n return seatWindowLabel(rest);\n}\n\nfunction toWindowView(engine: VerseEngine, w: SeatCapacityWindow, now: number): SeatWindowView {\n const reset = w.resetDescription ?? (w.resetsAt === null ? null : formatResetInstant(w.resetsAt, now));\n return {\n id: w.id,\n label: seatCapacityWindowLabel(engine, w.id),\n // A flagged limit, and any unmeasured figure, is a sentinel — not a reading.\n usedPercent: w.limitReached || !w.measured ? null : w.usedPercent,\n limitReached: w.limitReached,\n resetText: reset,\n resetsAt: w.resetsAt,\n };\n}\n\n/** The V1 `health.windows` shape, for a seat with no `capacity` record. */\nfunction legacyWindowView(w: VerseSeat['health']['windows'][number], now: number): SeatWindowView {\n const used = typeof w.usedPercent === 'number' && Number.isFinite(w.usedPercent)\n ? Math.max(0, Math.min(100, w.usedPercent))\n : null;\n // Upstream writes a denial as 100, so on this shape a bare 100 cannot be\n // told apart from a measured 100 — and the safe reading of both is \"spent\".\n const flagged = used !== null && used >= 100;\n return {\n id: w.id,\n label: seatWindowLabel(w.id),\n usedPercent: flagged ? null : used,\n limitReached: flagged,\n resetText: w.resetsAt === null ? null : formatResetInstant(w.resetsAt, now),\n resetsAt: w.resetsAt,\n };\n}\n\nfunction creditsPhrase(credits: SeatCapacityRecord['credits']): { phrase: string | null; title: string | null } {\n if (credits === null) return { phrase: null, title: null };\n if (credits.unlimited) return { phrase: 'credits unlimited', title: null };\n if (!credits.hasCredits) return { phrase: null, title: null };\n if (credits.balance === null) return { phrase: 'credits available', title: null };\n const parsed = Number.parseFloat(credits.balance);\n if (!Number.isFinite(parsed)) return { phrase: 'credits available', title: credits.balance };\n // The provider publishes a long decimal (\"2048.4196250000\"). Two places is a\n // rendering choice, not a new number — the raw string rides in the title.\n return { phrase: `${parsed.toFixed(2)} credits left`, title: credits.balance };\n}\n\nfunction localView(seat: VerseSeat): SeatSubscriptionView {\n const unavailable = seatUnavailableReason(seat);\n const ready = seat.health.state === 'ready';\n const cls: SeatCapacityClass = unavailable !== null ? 'blocked' : ready ? 'ready' : 'unread';\n return {\n kind: 'local',\n plan: null,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary: unavailable ?? (ready ? 'runs on this machine' : 'readiness not reported'),\n binding: null,\n others: [],\n credits: null,\n creditsTitle: null,\n notes: seat.health.summary === null ? [] : [seat.health.summary],\n evidenceSource: null,\n observedAt: seat.health.observedAt,\n extended: false,\n };\n}\n\n/** The V1 path: no `capacity` record, so the V1 rule decides, unchanged. */\nfunction fallbackView(seat: VerseSeat, now: number): SeatSubscriptionView {\n const legacy = seatCapacity(seat);\n const windows = seat.health.windows.map((w) => legacyWindowView(w, now));\n const flagged = windows.find((w) => w.limitReached) ?? null;\n const measured = windows.filter((w) => w.usedPercent !== null);\n const worst = measured.length === 0\n ? null\n : measured.reduce((a, b) => ((b.usedPercent ?? 0) > (a.usedPercent ?? 0) ? b : a));\n const binding = flagged ?? worst;\n const unavailable = seatUnavailableReason(seat);\n const cls = unavailable !== null ? 'blocked' : legacy.cls;\n return {\n kind: 'subscription',\n plan: null,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary: unavailable ?? legacy.text,\n binding,\n others: binding === null ? windows : windows.filter((w) => w.id !== binding.id),\n credits: null,\n creditsTitle: null,\n notes: [],\n evidenceSource: null,\n observedAt: seat.health.observedAt,\n extended: false,\n };\n}\n\n/**\n * The whole projection. Local seats short-circuit: they have no subscription,\n * so everything below the readiness line is deliberately empty rather than\n * zeroed. `now` is the clock the reset wording is relative to (\"today\" vs a\n * weekday); it defaults to the real one.\n */\nexport function seatSubscription(seat: VerseSeat, now: number = Date.now()): SeatSubscriptionView {\n if (seat.engine === 'local') return localView(seat);\n const capacity = seat.capacity;\n if (capacity === undefined) return fallbackView(seat, now);\n\n const windows = capacity.windows.map((w) => toWindowView(seat.engine, w, now));\n // Resolve the server's CHOICE of binding window back to this seat's own\n // view of it, so the two can never disagree about a reset or a label.\n const served = capacity.binding;\n const binding = served === null\n ? null\n : (windows.find((w) => w.id === served.id) ?? toWindowView(seat.engine, served, now));\n const others = binding === null ? windows : windows.filter((w) => w.id !== binding.id);\n const lastReading = seat.health.state === 'degraded' && capacity.usability === 'unknown';\n // A failed latest check leaves the old meter visible for context only.\n // Session credits are likewise historical and must not imply spendability.\n const credits = lastReading ? { phrase: null, title: null } : creditsPhrase(capacity.credits);\n\n const unavailable = seatUnavailableReason(seat);\n const cls: SeatCapacityClass = unavailable !== null ? 'blocked' : USABILITY_CLASS[capacity.usability];\n\n let summary: string;\n // Signed out is checked FIRST, before the generic unavailable reason: owner\n // S maps `signed-out` onto `health.state: 'unavailable'` (it is the one\n // account state worth a red dot, because it has a remedy), and the generic\n // reason there is a bare \"seat unavailable\" that says nothing about the fix.\n // A signed-out account has no measurement at all — it is an action, never a\n // 0% meter and never a bare \"unknown\".\n if (capacity.usability === 'signed-out') {\n summary = 'signed out — reconnect this account';\n } else if (unavailable !== null) {\n summary = unavailable;\n } else if (binding === null) {\n summary = 'no capacity reading';\n } else if (binding.limitReached) {\n // The server already weighed credits against the spent window; `tight`\n // there means \"spent, but there is still something to spend\".\n summary = capacity.usability === 'tight' && credits.phrase !== null\n ? `${binding.label} limit reached · credits still spendable`\n : `${binding.label} limit reached`;\n } else if (binding.usedPercent === null) {\n summary = 'no capacity reading';\n } else {\n // The one percent rule: \"99%\", never a rounded \"100%\" beside a \"99%\" bar.\n summary = `${percentText(binding.usedPercent)} of ${binding.label} used`;\n }\n if (lastReading) summary = binding === null\n ? 'No current capacity reading; current access unconfirmed'\n : `Last verified reading: ${summary}; current access unconfirmed`;\n\n return {\n kind: 'subscription',\n plan: capacity.planType,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary,\n binding,\n others,\n credits: credits.phrase,\n creditsTitle: credits.title,\n notes: [...capacity.notes],\n evidenceSource: capacity.evidenceSource,\n observedAt: capacity.observedAt ?? seat.health.observedAt,\n extended: true,\n };\n}\n\n/**\n * How much of a freshness claim the evidence supports. A reading served from\n * another process's shared file, or from an operator-seeded baseline, is not\n * a live probe and must not be presented as one.\n */\nexport function evidenceNote(source: SeatSubscriptionView['evidenceSource']): string | null {\n switch (source) {\n case 'collector':\n return null;\n case 'shared-evidence':\n return 'read from another collector’s shared evidence, not probed here';\n case 'baseline':\n return 'operator-seeded baseline, not a live reading';\n case 'none':\n return 'no evidence source — nothing here was measured';\n default:\n return null;\n }\n}\n\nfunction parseableInstant(iso: string | null | undefined): iso is string {\n return typeof iso === 'string' && Number.isFinite(Date.parse(iso));\n}\n\nfunction isSpentWindow(w: Pick<SeatWindowView, 'limitReached' | 'usedPercent'>): boolean {\n return w.limitReached || (w.usedPercent !== null && w.usedPercent >= 100);\n}\n\n/**\n * When a spent seat is usable again. A seat reopens only once EVERY spent\n * window has reset — a Codex seat whose 5-hour window resets in 2h but whose\n * weekly window is also spent until Wednesday is still spent in 2h — so this\n * is the LATEST reset among the spent windows, matching Fleet's \"eligible\n * again\" (fleet/why-seat-model `eligibleAgain`) and the router's headroom\n * `lastReset`. Every surface that says \"resets …\" / \"usable again in …\" for\n * a spent seat (Accounts, the health banner) asks here.\n *\n * - a spent window with only provider prose (Claude) → null: when \"all of\n * them\" have reset is unknown, and prose is never parsed;\n * - `reported` (the health sweep's instant, which is its binding window's)\n * is folded in — it may know of a window this seat record does not — but\n * it can never make the answer EARLIER than a spent window's reset;\n * - nothing spent → `reported`, else the binding window's own instant.\n */\nexport function seatReopensAt(view: Pick<SeatSubscriptionView, 'binding' | 'others'>, reported?: string | null): string | null {\n const known = parseableInstant(reported) ? reported : null;\n const windows = view.binding === null ? view.others : [view.binding, ...view.others];\n const spent = windows.filter(isSpentWindow);\n if (spent.length > 0) {\n if (spent.some((w) => !parseableInstant(w.resetsAt))) return null;\n const instants = spent.map((w) => w.resetsAt as string);\n if (known !== null) instants.push(known);\n return instants.reduce((a, b) => (Date.parse(b) > Date.parse(a) ? b : a));\n }\n if (known !== null) return known;\n return view.binding !== null && parseableInstant(view.binding.resetsAt) ? view.binding.resetsAt : null;\n}\n\n/**\n * One sentence for a `title` attribute or a screen-reader name: the seat, its\n * plan, its verdict and the evidence behind it.\n */\nexport function seatSubscriptionSentence(seat: VerseSeat, view: SeatSubscriptionView): string {\n const parts = [seat.label];\n if (view.plan !== null) parts.push(view.plan);\n parts.push(view.word);\n parts.push(view.summary);\n if (view.credits !== null) parts.push(view.credits);\n if (view.binding?.resetText != null) parts.push(view.binding.resetText);\n return parts.join(' · ');\n}\n\n/** Tight and blocked are worth surfacing outside the panel; the rest is noise. */\nexport function worthFlagging(cls: SeatCapacityClass): boolean {\n return cls === 'tight' || cls === 'blocked';\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{d as e}from"./verse-model-JTuvRBVK.js";var t=[`all`,`running`,`needs-you`,`pinned`],n={all:`All`,running:`Running`,"needs-you":`Needs you`,pinned:`Pinned`};function r(e){let t=new Set;for(let n of e)n.subject.sessionId&&t.add(n.subject.sessionId),n.target.kind===`session`&&t.add(n.target.sessionId);return t}var i=72;function a(e){if(!e)return null;if(e.phase===`tool`&&e.tool)return e.tool;if(e.thinkingTail&&e.thinkingTail.trim()){let t=e.thinkingTail.replace(/\s+/g,` `).trim();return t.length>i?`…${t.slice(t.length-i+1).trimStart()}`:t}switch(e.phase){case`thinking`:return`Thinking`;case`writing`:return`Writing`;case`waiting`:return`Waiting for the model`;case`tool`:return`Running a tool`;default:return null}}function o(e,t){return e?.sessions[t]??null}function s(t){let{sessions:n,projects:i,query:s,filter:c,activity:l,meta:u,localSeen:d,selectedId:f}=t,p=new Map((l?.running??[]).map(e=>[e.sessionId,e])),m=r(l?.needsYou??[]),h=u!==null,g=new Map;for(let e of n){let t=o(u,e.id),n=p.get(e.id),r=e.status===`running`||n!==void 0,i=t?.seenTurnCount??null,s=Math.max(i??-1,d.get(e.id)??-1),c=h?Math.max(s,0):s,_=e.id!==f&&c>=0&&e.turnCount>c?e.turnCount-c:0,v=l?m.has(e.id):e.status===`error`,y=r?{kind:`running`,startedAt:n?.startedAt??null}:e.status===`error`?{kind:`failed`}:_>0?{kind:`unread`,newTurns:_}:{kind:`time`,at:e.updatedAt},b=r?a(n?.live??null):null;g.set(e.id,{session:e,status:y,live:b===null?null:{text:b,startedAt:n?.startedAt??null},pinned:t?.pinned===!0,archived:t?.archived===!0,needsYou:v})}let _=[...g.values()],v={all:_.filter(e=>!e.archived).length,running:_.filter(e=>e.status.kind===`running`).length,"needs-you":_.filter(e=>e.needsYou).length,pinned:_.filter(e=>e.pinned&&!e.archived).length},y=e(_.filter(e=>{switch(c){case`running`:return e.status.kind===`running`;case`needs-you`:return e.needsYou;case`pinned`:return e.pinned;default:return!0}}).map(e=>e.session),i,s),b=[],x=[],S=[],C=[];for(let e of y){let t=[];for(let n of e.sessions){let e=g.get(n.id);e.archived?S.push(e):e.pinned?x.push(e):t.push(e)}t.length>0&&C.push({id:`project:${e.projectPath}`,kind:`project`,label:e.name,projectPath:e.projectPath,enrolled:e.enrolled,rows:t})}let w=(e,t)=>t.session.updatedAt.localeCompare(e.session.updatedAt);return x.length>0&&b.push({id:`pinned`,kind:`pinned`,label:`Pinned`,projectPath:null,enrolled:!1,rows:x.sort(w)}),b.push(...C),S.length>0&&b.push({id:`archived`,kind:`archived`,label:`Archived`,projectPath:null,enrolled:!1,rows:S.sort(w)}),{groups:b,counts:v,metaAvailable:h}}export{a as i,n,s as r,t};
2
- //# sourceMappingURL=sidebar-model-Dcd437cf.js.map
1
+ import{f as e}from"./verse-model-DAVevkNe.js";var t=[`all`,`running`,`needs-you`,`pinned`],n={all:`All`,running:`Running`,"needs-you":`Needs you`,pinned:`Pinned`};function r(e){let t=new Set;for(let n of e)n.subject.sessionId&&t.add(n.subject.sessionId),n.target.kind===`session`&&t.add(n.target.sessionId);return t}var i=72;function a(e){if(!e)return null;if(e.phase===`tool`&&e.tool)return e.tool;if(e.thinkingTail&&e.thinkingTail.trim()){let t=e.thinkingTail.replace(/\s+/g,` `).trim();return t.length>i?`…${t.slice(t.length-i+1).trimStart()}`:t}switch(e.phase){case`thinking`:return`Thinking`;case`writing`:return`Writing`;case`waiting`:return`Waiting for the model`;case`tool`:return`Running a tool`;default:return null}}function o(e,t){return e?.sessions[t]??null}function s(t){let{sessions:n,projects:i,query:s,filter:c,activity:l,meta:u,localSeen:d,selectedId:f}=t,p=new Map((l?.running??[]).map(e=>[e.sessionId,e])),m=r(l?.needsYou??[]),h=u!==null,g=new Map;for(let e of n){let t=o(u,e.id),n=p.get(e.id),r=e.status===`running`||n!==void 0,i=t?.seenTurnCount??null,s=Math.max(i??-1,d.get(e.id)??-1),c=h?Math.max(s,0):s,_=e.id!==f&&c>=0&&e.turnCount>c?e.turnCount-c:0,v=l?m.has(e.id):e.status===`error`,y=r?{kind:`running`,startedAt:n?.startedAt??null}:e.status===`error`?{kind:`failed`}:_>0?{kind:`unread`,newTurns:_}:{kind:`time`,at:e.updatedAt},b=r?a(n?.live??null):null;g.set(e.id,{session:e,status:y,live:b===null?null:{text:b,startedAt:n?.startedAt??null},pinned:t?.pinned===!0,archived:t?.archived===!0,needsYou:v})}let _=[...g.values()],v={all:_.filter(e=>!e.archived).length,running:_.filter(e=>e.status.kind===`running`).length,"needs-you":_.filter(e=>e.needsYou).length,pinned:_.filter(e=>e.pinned&&!e.archived).length},y=e(_.filter(e=>{switch(c){case`running`:return e.status.kind===`running`;case`needs-you`:return e.needsYou;case`pinned`:return e.pinned;default:return!0}}).map(e=>e.session),i,s),b=[],x=[],S=[],C=[];for(let e of y){let t=[];for(let n of e.sessions){let e=g.get(n.id);e.archived?S.push(e):e.pinned?x.push(e):t.push(e)}t.length>0&&C.push({id:`project:${e.projectPath}`,kind:`project`,label:e.name,projectPath:e.projectPath,enrolled:e.enrolled,rows:t})}let w=(e,t)=>t.session.updatedAt.localeCompare(e.session.updatedAt);return x.length>0&&b.push({id:`pinned`,kind:`pinned`,label:`Pinned`,projectPath:null,enrolled:!1,rows:x.sort(w)}),b.push(...C),S.length>0&&b.push({id:`archived`,kind:`archived`,label:`Archived`,projectPath:null,enrolled:!1,rows:S.sort(w)}),{groups:b,counts:v,metaAvailable:h}}export{a as i,n,s as r,t};
2
+ //# sourceMappingURL=sidebar-model-CLCdqwkR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-model-Dcd437cf.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/chat/sidebar-model.ts"],"sourcesContent":["/**\n * routes/verse/chat/sidebar-model.ts — the chat list, as data (SPEC-310C §2\n * \"Sidebar\", unit C2).\n *\n * [ All ] [ Running 2 ] [ Needs you 1 ] [ Pinned 3 ]\n * PINNED ▸ rows\n * <project> … ▸ rows, most recently touched project first\n * ARCHIVED (12) ▸ collapsed\n *\n * Each row states ONE status, the most urgent that applies:\n *\n * running a pulse and the elapsed time — plus a muted second line from\n * activity.live (\"npm test\", or the tail of the live reasoning);\n * failed the last turn errored;\n * unread a turn finished since the operator last looked;\n * time otherwise, how long ago it was touched.\n *\n * The inputs are three sources of different reliability, and the model is\n * explicit about what each is allowed to claim:\n * - the session list (always present): status, turnCount, updatedAt;\n * - activity (C1's route; null until it lands): who is running and what\n * they are doing, and the Needs-you items;\n * - session meta (C1's route; null until it lands): pinned, archived, and\n * how far the operator has read. With no meta, NOTHING is unread — an\n * unknown read state is not an unread one (honesty rule: null = unknown).\n *\n * Pure: no React, no fetch.\n */\nimport type { VerseProject, VerseSession } from '../../../data/api-types.js';\nimport type {\n NeedsYouItem,\n VerseActivityLive,\n VerseActivityResponse,\n VerseSessionMeta,\n VerseSessionMetaResponse,\n} from '../../../../core/verse/workbench-types.js';\nimport { groupSessions } from '../verse-model.js';\n\nexport const SIDEBAR_FILTERS = ['all', 'running', 'needs-you', 'pinned'] as const;\nexport type SidebarFilter = (typeof SIDEBAR_FILTERS)[number];\n\nexport const SIDEBAR_FILTER_LABEL: Readonly<Record<SidebarFilter, string>> = {\n all: 'All',\n running: 'Running',\n 'needs-you': 'Needs you',\n pinned: 'Pinned',\n};\n\nexport type RowStatus =\n | { kind: 'running'; startedAt: string | null }\n | { kind: 'failed' }\n | { kind: 'unread'; newTurns: number }\n | { kind: 'time'; at: string };\n\nexport interface SidebarRow {\n session: VerseSession;\n status: RowStatus;\n /** The running chat's muted second line; null when it is not running or nothing is known. */\n live: { text: string; startedAt: string | null } | null;\n pinned: boolean;\n archived: boolean;\n needsYou: boolean;\n}\n\nexport type SidebarGroupKind = 'pinned' | 'project' | 'archived';\n\nexport interface SidebarGroup {\n id: string;\n kind: SidebarGroupKind;\n label: string;\n /** The project's path (tooltip) for a project group. */\n projectPath: string | null;\n enrolled: boolean;\n rows: SidebarRow[];\n}\n\nexport interface SidebarModel {\n groups: SidebarGroup[];\n counts: Record<SidebarFilter, number>;\n /** Meta is known (C1's route answered) — pin/archive controls can work. */\n metaAvailable: boolean;\n}\n\nexport interface SidebarInput {\n sessions: readonly VerseSession[];\n projects: readonly VerseProject[];\n query: string;\n filter: SidebarFilter;\n activity: VerseActivityResponse | null;\n meta: VerseSessionMetaResponse | null;\n /** turnCount this tab has seen per chat (opened here) — clears a dot before the server confirms. */\n localSeen: ReadonlyMap<string, number>;\n /** The open chat is never unread. */\n selectedId: string | null;\n}\n\n/** Ids of chats a Needs-you item points at (as its subject or its target). */\nexport function needsYouSessionIds(items: readonly NeedsYouItem[]): Set<string> {\n const out = new Set<string>();\n for (const item of items) {\n if (item.subject.sessionId) out.add(item.subject.sessionId);\n if (item.target.kind === 'session') out.add(item.target.sessionId);\n }\n return out;\n}\n\nconst THINKING_TAIL_CHARS = 72;\n\n/** \"npm test\" / \"…the tail of what it is thinking\" / \"Writing\" — never a guess. */\nexport function liveLine(live: VerseActivityLive | null): string | null {\n if (!live) return null;\n if (live.phase === 'tool' && live.tool) return live.tool;\n if (live.thinkingTail && live.thinkingTail.trim()) {\n const tail = live.thinkingTail.replace(/\\s+/g, ' ').trim();\n return tail.length > THINKING_TAIL_CHARS ? `…${tail.slice(tail.length - THINKING_TAIL_CHARS + 1).trimStart()}` : tail;\n }\n switch (live.phase) {\n case 'thinking': return 'Thinking';\n case 'writing': return 'Writing';\n case 'waiting': return 'Waiting for the model';\n case 'tool': return 'Running a tool';\n default: return null;\n }\n}\n\nfunction metaFor(meta: VerseSessionMetaResponse | null, id: string): VerseSessionMeta | null {\n return meta?.sessions[id] ?? null;\n}\n\nexport function buildSidebar(input: SidebarInput): SidebarModel {\n const { sessions, projects, query, filter, activity, meta, localSeen, selectedId } = input;\n const running = new Map((activity?.running ?? []).map((r) => [r.sessionId, r]));\n const needs = needsYouSessionIds(activity?.needsYou ?? []);\n const metaAvailable = meta !== null;\n\n const rows = new Map<string, SidebarRow>();\n for (const session of sessions) {\n const m = metaFor(meta, session.id);\n const activityRow = running.get(session.id);\n const isRunning = session.status === 'running' || activityRow !== undefined;\n const serverSeen = m?.seenTurnCount ?? null;\n const seen = Math.max(serverSeen ?? -1, localSeen.get(session.id) ?? -1);\n // Unread needs a KNOWN read state: meta answered (this chat's entry or,\n // absent one, its default of \"never opened\" = 0) or this tab opened it.\n const knownSeen = metaAvailable ? Math.max(seen, 0) : seen;\n const unread = session.id !== selectedId && knownSeen >= 0 && session.turnCount > knownSeen ? session.turnCount - knownSeen : 0;\n // Without activity, a failed chat is the one \"needs you\" signal the list itself carries.\n const needsYou = activity ? needs.has(session.id) : session.status === 'error';\n const status: RowStatus = isRunning\n ? { kind: 'running', startedAt: activityRow?.startedAt ?? null }\n : session.status === 'error'\n ? { kind: 'failed' }\n : unread > 0\n ? { kind: 'unread', newTurns: unread }\n : { kind: 'time', at: session.updatedAt };\n const text = isRunning ? liveLine(activityRow?.live ?? null) : null;\n rows.set(session.id, {\n session,\n status,\n live: text === null ? null : { text, startedAt: activityRow?.startedAt ?? null },\n pinned: m?.pinned === true,\n archived: m?.archived === true,\n needsYou,\n });\n }\n\n const all = [...rows.values()];\n const counts: Record<SidebarFilter, number> = {\n all: all.filter((r) => !r.archived).length,\n running: all.filter((r) => r.status.kind === 'running').length,\n 'needs-you': all.filter((r) => r.needsYou).length,\n pinned: all.filter((r) => r.pinned && !r.archived).length,\n };\n\n const pass = (row: SidebarRow): boolean => {\n switch (filter) {\n case 'running': return row.status.kind === 'running';\n case 'needs-you': return row.needsYou;\n case 'pinned': return row.pinned;\n default: return true;\n }\n };\n\n // Title/project search reuses the 3.9 grouping (same matching, same order).\n const matched = groupSessions(all.filter(pass).map((r) => r.session), projects, query);\n const groups: SidebarGroup[] = [];\n const pinnedRows: SidebarRow[] = [];\n const archivedRows: SidebarRow[] = [];\n const projectGroups: SidebarGroup[] = [];\n for (const group of matched) {\n const projectRows: SidebarRow[] = [];\n for (const session of group.sessions) {\n const row = rows.get(session.id)!;\n if (row.archived) archivedRows.push(row);\n else if (row.pinned) pinnedRows.push(row);\n else projectRows.push(row);\n }\n if (projectRows.length > 0) {\n projectGroups.push({\n id: `project:${group.projectPath}`,\n kind: 'project',\n label: group.name,\n projectPath: group.projectPath,\n enrolled: group.enrolled,\n rows: projectRows,\n });\n }\n }\n const newest = (a: SidebarRow, b: SidebarRow) => b.session.updatedAt.localeCompare(a.session.updatedAt);\n if (pinnedRows.length > 0) groups.push({ id: 'pinned', kind: 'pinned', label: 'Pinned', projectPath: null, enrolled: false, rows: pinnedRows.sort(newest) });\n groups.push(...projectGroups);\n if (archivedRows.length > 0) groups.push({ id: 'archived', kind: 'archived', label: 'Archived', projectPath: null, enrolled: false, rows: archivedRows.sort(newest) });\n return { groups, counts, metaAvailable };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sidebar-model-CLCdqwkR.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/chat/sidebar-model.ts"],"sourcesContent":["/**\n * routes/verse/chat/sidebar-model.ts — the chat list, as data (SPEC-310C §2\n * \"Sidebar\", unit C2).\n *\n * [ All ] [ Running 2 ] [ Needs you 1 ] [ Pinned 3 ]\n * PINNED ▸ rows\n * <project> … ▸ rows, most recently touched project first\n * ARCHIVED (12) ▸ collapsed\n *\n * Each row states ONE status, the most urgent that applies:\n *\n * running a pulse and the elapsed time — plus a muted second line from\n * activity.live (\"npm test\", or the tail of the live reasoning);\n * failed the last turn errored;\n * unread a turn finished since the operator last looked;\n * time otherwise, how long ago it was touched.\n *\n * The inputs are three sources of different reliability, and the model is\n * explicit about what each is allowed to claim:\n * - the session list (always present): status, turnCount, updatedAt;\n * - activity (C1's route; null until it lands): who is running and what\n * they are doing, and the Needs-you items;\n * - session meta (C1's route; null until it lands): pinned, archived, and\n * how far the operator has read. With no meta, NOTHING is unread — an\n * unknown read state is not an unread one (honesty rule: null = unknown).\n *\n * Pure: no React, no fetch.\n */\nimport type { VerseProject, VerseSession } from '../../../data/api-types.js';\nimport type {\n NeedsYouItem,\n VerseActivityLive,\n VerseActivityResponse,\n VerseSessionMeta,\n VerseSessionMetaResponse,\n} from '../../../../core/verse/workbench-types.js';\nimport { groupSessions } from '../verse-model.js';\n\nexport const SIDEBAR_FILTERS = ['all', 'running', 'needs-you', 'pinned'] as const;\nexport type SidebarFilter = (typeof SIDEBAR_FILTERS)[number];\n\nexport const SIDEBAR_FILTER_LABEL: Readonly<Record<SidebarFilter, string>> = {\n all: 'All',\n running: 'Running',\n 'needs-you': 'Needs you',\n pinned: 'Pinned',\n};\n\nexport type RowStatus =\n | { kind: 'running'; startedAt: string | null }\n | { kind: 'failed' }\n | { kind: 'unread'; newTurns: number }\n | { kind: 'time'; at: string };\n\nexport interface SidebarRow {\n session: VerseSession;\n status: RowStatus;\n /** The running chat's muted second line; null when it is not running or nothing is known. */\n live: { text: string; startedAt: string | null } | null;\n pinned: boolean;\n archived: boolean;\n needsYou: boolean;\n}\n\nexport type SidebarGroupKind = 'pinned' | 'project' | 'archived';\n\nexport interface SidebarGroup {\n id: string;\n kind: SidebarGroupKind;\n label: string;\n /** The project's path (tooltip) for a project group. */\n projectPath: string | null;\n enrolled: boolean;\n rows: SidebarRow[];\n}\n\nexport interface SidebarModel {\n groups: SidebarGroup[];\n counts: Record<SidebarFilter, number>;\n /** Meta is known (C1's route answered) — pin/archive controls can work. */\n metaAvailable: boolean;\n}\n\nexport interface SidebarInput {\n sessions: readonly VerseSession[];\n projects: readonly VerseProject[];\n query: string;\n filter: SidebarFilter;\n activity: VerseActivityResponse | null;\n meta: VerseSessionMetaResponse | null;\n /** turnCount this tab has seen per chat (opened here) — clears a dot before the server confirms. */\n localSeen: ReadonlyMap<string, number>;\n /** The open chat is never unread. */\n selectedId: string | null;\n}\n\n/** Ids of chats a Needs-you item points at (as its subject or its target). */\nexport function needsYouSessionIds(items: readonly NeedsYouItem[]): Set<string> {\n const out = new Set<string>();\n for (const item of items) {\n if (item.subject.sessionId) out.add(item.subject.sessionId);\n if (item.target.kind === 'session') out.add(item.target.sessionId);\n }\n return out;\n}\n\nconst THINKING_TAIL_CHARS = 72;\n\n/** \"npm test\" / \"…the tail of what it is thinking\" / \"Writing\" — never a guess. */\nexport function liveLine(live: VerseActivityLive | null): string | null {\n if (!live) return null;\n if (live.phase === 'tool' && live.tool) return live.tool;\n if (live.thinkingTail && live.thinkingTail.trim()) {\n const tail = live.thinkingTail.replace(/\\s+/g, ' ').trim();\n return tail.length > THINKING_TAIL_CHARS ? `…${tail.slice(tail.length - THINKING_TAIL_CHARS + 1).trimStart()}` : tail;\n }\n switch (live.phase) {\n case 'thinking': return 'Thinking';\n case 'writing': return 'Writing';\n case 'waiting': return 'Waiting for the model';\n case 'tool': return 'Running a tool';\n default: return null;\n }\n}\n\nfunction metaFor(meta: VerseSessionMetaResponse | null, id: string): VerseSessionMeta | null {\n return meta?.sessions[id] ?? null;\n}\n\nexport function buildSidebar(input: SidebarInput): SidebarModel {\n const { sessions, projects, query, filter, activity, meta, localSeen, selectedId } = input;\n const running = new Map((activity?.running ?? []).map((r) => [r.sessionId, r]));\n const needs = needsYouSessionIds(activity?.needsYou ?? []);\n const metaAvailable = meta !== null;\n\n const rows = new Map<string, SidebarRow>();\n for (const session of sessions) {\n const m = metaFor(meta, session.id);\n const activityRow = running.get(session.id);\n const isRunning = session.status === 'running' || activityRow !== undefined;\n const serverSeen = m?.seenTurnCount ?? null;\n const seen = Math.max(serverSeen ?? -1, localSeen.get(session.id) ?? -1);\n // Unread needs a KNOWN read state: meta answered (this chat's entry or,\n // absent one, its default of \"never opened\" = 0) or this tab opened it.\n const knownSeen = metaAvailable ? Math.max(seen, 0) : seen;\n const unread = session.id !== selectedId && knownSeen >= 0 && session.turnCount > knownSeen ? session.turnCount - knownSeen : 0;\n // Without activity, a failed chat is the one \"needs you\" signal the list itself carries.\n const needsYou = activity ? needs.has(session.id) : session.status === 'error';\n const status: RowStatus = isRunning\n ? { kind: 'running', startedAt: activityRow?.startedAt ?? null }\n : session.status === 'error'\n ? { kind: 'failed' }\n : unread > 0\n ? { kind: 'unread', newTurns: unread }\n : { kind: 'time', at: session.updatedAt };\n const text = isRunning ? liveLine(activityRow?.live ?? null) : null;\n rows.set(session.id, {\n session,\n status,\n live: text === null ? null : { text, startedAt: activityRow?.startedAt ?? null },\n pinned: m?.pinned === true,\n archived: m?.archived === true,\n needsYou,\n });\n }\n\n const all = [...rows.values()];\n const counts: Record<SidebarFilter, number> = {\n all: all.filter((r) => !r.archived).length,\n running: all.filter((r) => r.status.kind === 'running').length,\n 'needs-you': all.filter((r) => r.needsYou).length,\n pinned: all.filter((r) => r.pinned && !r.archived).length,\n };\n\n const pass = (row: SidebarRow): boolean => {\n switch (filter) {\n case 'running': return row.status.kind === 'running';\n case 'needs-you': return row.needsYou;\n case 'pinned': return row.pinned;\n default: return true;\n }\n };\n\n // Title/project search reuses the 3.9 grouping (same matching, same order).\n const matched = groupSessions(all.filter(pass).map((r) => r.session), projects, query);\n const groups: SidebarGroup[] = [];\n const pinnedRows: SidebarRow[] = [];\n const archivedRows: SidebarRow[] = [];\n const projectGroups: SidebarGroup[] = [];\n for (const group of matched) {\n const projectRows: SidebarRow[] = [];\n for (const session of group.sessions) {\n const row = rows.get(session.id)!;\n if (row.archived) archivedRows.push(row);\n else if (row.pinned) pinnedRows.push(row);\n else projectRows.push(row);\n }\n if (projectRows.length > 0) {\n projectGroups.push({\n id: `project:${group.projectPath}`,\n kind: 'project',\n label: group.name,\n projectPath: group.projectPath,\n enrolled: group.enrolled,\n rows: projectRows,\n });\n }\n }\n const newest = (a: SidebarRow, b: SidebarRow) => b.session.updatedAt.localeCompare(a.session.updatedAt);\n if (pinnedRows.length > 0) groups.push({ id: 'pinned', kind: 'pinned', label: 'Pinned', projectPath: null, enrolled: false, rows: pinnedRows.sort(newest) });\n groups.push(...projectGroups);\n if (archivedRows.length > 0) groups.push({ id: 'archived', kind: 'archived', label: 'Archived', projectPath: null, enrolled: false, rows: archivedRows.sort(newest) });\n return { groups, counts, metaAvailable };\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/PreviewPane-zT3gK9TD.js","assets/global-y_exIyAP.js","assets/VerseConsoleApp-DXDv1aOi.js","assets/RouteErrorBoundary-C8WGiixc.js","assets/MessageMarkdown-BCe4TsXk.js","assets/Segmented-Wt1ATod9.js","assets/icons-CygCEFWs.js","assets/terminal-icons-BwgQTQP0.js","assets/pane-chrome.module-D7o-fVd0.js","assets/global-BlI2BYa1.css","assets/RouteErrorBoundary-DdxhTdZ6.css","assets/VerseConsoleApp-Cxqr-3qc.css","assets/MessageMarkdown-Cgh5f1-Q.css","assets/Segmented-BnjHbKzH.css","assets/Button-DrnKsvnQ.css","assets/EmptyState-B3YUPGaa.css","assets/pane-chrome-8JmEhHVD.css","assets/PreviewPane-DoMsJSG3.css","assets/TerminalPane-BVFgYX6K.js","assets/verse-model-JTuvRBVK.js","assets/compaction-point-VL9oegWS.js","assets/format-BmH2yWL6.js","assets/format-DKrNjdwD.js","assets/ActionMenu-Dwjk6rUQ.js","assets/command-catalog-ffCAijVY.js","assets/ActionMenu-DPjsLU1g.css","assets/TerminalPane-BwfMbnJz.css","assets/BranchBar-ISZ7xUCj.js","assets/Dialog-BRd_B9OE.js","assets/focus-trap-ChZ5EFfM.js","assets/MutationTokenDialog-Bm34BNVV.js","assets/git-model-BFwAVbxF.js","assets/use-token-gate-DSNIIpI6.js","assets/Dialog-tQ8kFulD.css","assets/MutationTokenDialog-CrfJ0PdD.css","assets/BranchBar-BZNQ50YE.css","assets/DiffPane-Cpr9soB2.js","assets/highlight-CMCZK9jW.js","assets/line-diff-B5Eonif2.js","assets/DiffPane-BAvvbBsf.css","assets/SessionInsightChip-DNUcruwp.js","assets/nav-mimleI0R.js","assets/surface-data-C3UAQ4QX.js","assets/control-queries-CXtmZZH6.js","assets/mutations-CWlxEMEm.js","assets/mind.module-B15k0Y9q.js","assets/colors-BZ3a9wFf.js","assets/calendar-day-BxBYHfX1.js","assets/workspace-model-D-SLfads.js","assets/mind-B9PzLcl0.css"])))=>i.map(i=>d[i]);
2
- import{a as e,c as t,n,t as r}from"./index-CyK31YRm.js";import{t as i}from"./Button-DtE0rlWD.js";import{t as a}from"./EmptyState-DsN1H6MC.js";var o=t(e(),1),s=n(),c={"branch-bar":{path:`git/BranchBar.tsx`,exportName:`BranchBar`,owner:`C5`,kind:`inline`,label:`Branch bar`},"diff-pane":{path:`git/DiffPane.tsx`,exportName:`DiffPane`,owner:`C5`,kind:`pane`,label:`Review`},"terminal-pane":{path:`dock/terminal/TerminalPane.tsx`,exportName:`TerminalPane`,owner:`C4`,kind:`pane`,label:`Terminal`},"preview-pane":{path:`dock/preview/PreviewPane.tsx`,exportName:`PreviewPane`,owner:`C4`,kind:`pane`,label:`Preview`},"session-insight-chip":{path:`mind/SessionInsightChip.tsx`,exportName:`SessionInsightChip`,owner:`C7`,kind:`inline`,label:`Insight`}};Object.keys(c);var l=Object.assign({"../dock/preview/PreviewPane.tsx":()=>r(()=>import(`./PreviewPane-zT3gK9TD.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17])),"../dock/terminal/TerminalPane.tsx":()=>r(()=>import(`./TerminalPane-BVFgYX6K.js`),__vite__mapDeps([18,1,2,3,19,20,21,22,23,6,24,7,8,9,10,11,14,25,15,16,26])),"../git/BranchBar.tsx":()=>r(()=>import(`./BranchBar-ISZ7xUCj.js`),__vite__mapDeps([27,28,29,30,1,2,3,21,22,19,20,31,6,32,33,9,34,10,11,14,35])),"../git/DiffPane.tsx":()=>r(()=>import(`./DiffPane-Cpr9soB2.js`),__vite__mapDeps([36,1,37,5,31,2,3,38,6,8,9,13,10,11,14,15,16,39])),"../mind/SessionInsightChip.tsx":()=>r(()=>import(`./SessionInsightChip-DNUcruwp.js`),__vite__mapDeps([40,1,21,22,2,3,19,20,41,42,43,44,45,46,47,48,9,10,11,49]))});function u(e,t){return t[`../${c[e].path}`]}function d(e,t=l){return u(e,t)!==void 0}function f(e,t=l){let n=u(e,t);if(!n)return null;let{exportName:r}=c[e];return(0,o.lazy)(async()=>{let t=(await n())[r];if(typeof t!=`function`&&(typeof t!=`object`||!t))throw Error(`${c[e].path} exports no ${r}`);return{default:t}})}var p=new Map;function m(e){return p.has(e)||p.set(e,f(e)),p.get(e)}var h=class extends o.Component{state={failed:!1};static getDerivedStateFromError(){return{failed:!0}}componentDidCatch(e,t){console.error(`[verse] ${this.props.label} failed`,e,t.componentStack)}render(){return this.state.failed?this.props.kind===`inline`?null:(0,s.jsx)(g,{label:this.props.label,onRetry:this.props.onRetry}):this.props.children}};function g({label:e,onRetry:t}){return(0,s.jsx)(a,{compact:!0,tone:`error`,title:`${e} could not load`,body:`The rest of the chat still works.`,action:(0,s.jsx)(i,{variant:`subtle`,size:`sm`,onClick:t,children:`Try again`})})}function _({id:e,props:t,resolve:n=m,forget:r=e=>p.delete(e)}){let[i,a]=(0,o.useState)(0),l=n(e);if(!l)return null;let{kind:u,label:d}=c[e];return(0,s.jsx)(h,{kind:u,label:d,onRetry:()=>{r(e),a(e=>e+1)},children:(0,s.jsx)(o.Suspense,{fallback:null,children:(0,s.jsx)(l,{...t})})},i)}function v(e){return(0,s.jsx)(_,{id:`branch-bar`,props:e})}function y(e){return(0,s.jsx)(_,{id:`diff-pane`,props:e})}function b(e){return(0,s.jsx)(_,{id:`terminal-pane`,props:e})}function x(e){return(0,s.jsx)(_,{id:`preview-pane`,props:e})}function S(e){return(0,s.jsx)(_,{id:`session-insight-chip`,props:e})}export{b as a,S as i,y as n,d as o,x as r,v as t};
3
- //# sourceMappingURL=slots-BL_J5mmV.js.map
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/PreviewPane-COid5A0f.js","assets/global-CMNW_dqn.js","assets/VerseConsoleApp-CWU6R3By.js","assets/RouteErrorBoundary-SkNhhUbt.js","assets/MessageMarkdown-DFvk06qG.js","assets/Segmented-CGh_-tBb.js","assets/icons-D1sYbCTQ.js","assets/terminal-icons-CoRZq9iO.js","assets/pane-chrome.module-D7o-fVd0.js","assets/global-BlI2BYa1.css","assets/RouteErrorBoundary-DdxhTdZ6.css","assets/VerseConsoleApp-Cxqr-3qc.css","assets/MessageMarkdown-Cgh5f1-Q.css","assets/Segmented-BnjHbKzH.css","assets/Button-DrnKsvnQ.css","assets/EmptyState-B3YUPGaa.css","assets/pane-chrome-8JmEhHVD.css","assets/PreviewPane-DoMsJSG3.css","assets/TerminalPane-B668-DJW.js","assets/verse-model-DAVevkNe.js","assets/compaction-point-VL9oegWS.js","assets/format-CH4g_sl1.js","assets/format-D7nBg2bn.js","assets/ActionMenu-CIiX2X8w.js","assets/command-catalog-BIntSa9l.js","assets/ActionMenu-DPjsLU1g.css","assets/TerminalPane-BwfMbnJz.css","assets/BranchBar-BxhdiIpx.js","assets/Dialog-D3msQlCj.js","assets/focus-trap-CtI1SlMX.js","assets/MutationTokenDialog-DbnO8aYi.js","assets/git-model-Dnkd1TnK.js","assets/use-token-gate-CbXVYQYI.js","assets/Dialog-tQ8kFulD.css","assets/MutationTokenDialog-CrfJ0PdD.css","assets/BranchBar-BZNQ50YE.css","assets/DiffPane-Ix6hvXlY.js","assets/highlight-CMCZK9jW.js","assets/line-diff-B5Eonif2.js","assets/DiffPane-BAvvbBsf.css","assets/SessionInsightChip-DLFAzdbi.js","assets/surface-data-Dj71tdD-.js","assets/control-queries-B9K-wmcB.js","assets/mutations-DQPbFdRJ.js","assets/nav-0dOYe2rJ.js","assets/mind.module-7hA92hRg.js","assets/colors-DvK0wMHH.js","assets/calendar-day-BxBYHfX1.js","assets/workspace-model-dji5-Al3.js","assets/mind-B9PzLcl0.css"])))=>i.map(i=>d[i]);
2
+ import{a as e,c as t,n,t as r}from"./index-DZ-UQ7v8.js";import{t as i}from"./Button-D90dzI_o.js";import{t as a}from"./EmptyState-D2IRy3Cg.js";var o=t(e(),1),s=n(),c={"branch-bar":{path:`git/BranchBar.tsx`,exportName:`BranchBar`,owner:`C5`,kind:`inline`,label:`Branch bar`},"diff-pane":{path:`git/DiffPane.tsx`,exportName:`DiffPane`,owner:`C5`,kind:`pane`,label:`Review`},"terminal-pane":{path:`dock/terminal/TerminalPane.tsx`,exportName:`TerminalPane`,owner:`C4`,kind:`pane`,label:`Terminal`},"preview-pane":{path:`dock/preview/PreviewPane.tsx`,exportName:`PreviewPane`,owner:`C4`,kind:`pane`,label:`Preview`},"session-insight-chip":{path:`mind/SessionInsightChip.tsx`,exportName:`SessionInsightChip`,owner:`C7`,kind:`inline`,label:`Insight`}};Object.keys(c);var l=Object.assign({"../dock/preview/PreviewPane.tsx":()=>r(()=>import(`./PreviewPane-COid5A0f.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17])),"../dock/terminal/TerminalPane.tsx":()=>r(()=>import(`./TerminalPane-B668-DJW.js`),__vite__mapDeps([18,1,2,3,19,20,21,22,23,6,24,7,8,9,10,11,14,25,15,16,26])),"../git/BranchBar.tsx":()=>r(()=>import(`./BranchBar-BxhdiIpx.js`),__vite__mapDeps([27,28,29,30,1,2,3,21,22,19,20,31,6,32,33,9,34,10,11,14,35])),"../git/DiffPane.tsx":()=>r(()=>import(`./DiffPane-Ix6hvXlY.js`),__vite__mapDeps([36,1,37,5,31,2,3,38,6,8,9,13,10,11,14,15,16,39])),"../mind/SessionInsightChip.tsx":()=>r(()=>import(`./SessionInsightChip-DLFAzdbi.js`),__vite__mapDeps([40,1,21,22,2,3,19,20,41,42,43,44,45,46,47,48,9,10,11,49]))});function u(e,t){return t[`../${c[e].path}`]}function d(e,t=l){return u(e,t)!==void 0}function f(e,t=l){let n=u(e,t);if(!n)return null;let{exportName:r}=c[e];return(0,o.lazy)(async()=>{let t=(await n())[r];if(typeof t!=`function`&&(typeof t!=`object`||!t))throw Error(`${c[e].path} exports no ${r}`);return{default:t}})}var p=new Map;function m(e){return p.has(e)||p.set(e,f(e)),p.get(e)}var h=class extends o.Component{state={failed:!1};static getDerivedStateFromError(){return{failed:!0}}componentDidCatch(e,t){console.error(`[verse] ${this.props.label} failed`,e,t.componentStack)}render(){return this.state.failed?this.props.kind===`inline`?null:(0,s.jsx)(g,{label:this.props.label,onRetry:this.props.onRetry}):this.props.children}};function g({label:e,onRetry:t}){return(0,s.jsx)(a,{compact:!0,tone:`error`,title:`${e} could not load`,body:`The rest of the chat still works.`,action:(0,s.jsx)(i,{variant:`subtle`,size:`sm`,onClick:t,children:`Try again`})})}function _({id:e,props:t,resolve:n=m,forget:r=e=>p.delete(e)}){let[i,a]=(0,o.useState)(0),l=n(e);if(!l)return null;let{kind:u,label:d}=c[e];return(0,s.jsx)(h,{kind:u,label:d,onRetry:()=>{r(e),a(e=>e+1)},children:(0,s.jsx)(o.Suspense,{fallback:null,children:(0,s.jsx)(l,{...t})})},i)}function v(e){return(0,s.jsx)(_,{id:`branch-bar`,props:e})}function y(e){return(0,s.jsx)(_,{id:`diff-pane`,props:e})}function b(e){return(0,s.jsx)(_,{id:`terminal-pane`,props:e})}function x(e){return(0,s.jsx)(_,{id:`preview-pane`,props:e})}function S(e){return(0,s.jsx)(_,{id:`session-insight-chip`,props:e})}export{b as a,S as i,y as n,d as o,x as r,v as t};
3
+ //# sourceMappingURL=slots-C-qBeu-8.js.map
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/slots.tsx"],"sourcesContent":["/**\n * routes/verse/shell/slots.tsx — where Chat mounts other units' UI (unit C0;\n * SPEC-310C §7 \"Slots\").\n *\n * C2 owns the chat, the dock and the header; C4, C5 and C7 own things that\n * render INSIDE them. Rather than C2 importing their files — which would not\n * compile until every one of them landed, and would drag each into C2's\n * chunk — C2 renders these slots. Each resolves ONE fixed file lazily and:\n * - renders nothing until that file lands (and `isSlotAvailable` says so,\n * so C2 can hide the toggle for a pane that does not exist yet);\n * - loads in its own chunk (xterm and the diff viewer stay off the chat's\n * critical path — SPEC-310C budgets: chat critical JS ≤ 350 KB);\n * - is fenced by an error boundary: a crashed inline slot vanishes, a\n * crashed pane says so with a retry — neither takes the chat down.\n *\n * The props below ARE the contract: each owning unit's component takes\n * exactly its slot's props, as a NAMED export (`export function BranchBar`).\n *\n * Resolution uses `import.meta.glob` with literal paths — the same \"absent\n * file is an absent key\" mechanism VerseApp uses for sections.\n */\nimport { Component, Suspense, lazy, useState, type ComponentType, type ErrorInfo, type ReactNode } from 'react';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { EmptyState } from '../../../components/primitives/EmptyState.js';\nimport type { VerseReviewScope, VerseTerminalLaunchVia } from '../../../../core/verse/workbench-types.js';\n\n// ===========================================================================\n// Contracts\n// ===========================================================================\n\n/** Open the Review pane on a root, at a scope (and optionally one file). */\nexport interface DiffPaneRequest {\n root: string;\n scope: VerseReviewScope;\n file?: string;\n}\n\n/** A file the chat's latest turn touched — the Review pane's \"This turn\" scope (C2 derives it from events). */\nexport interface TurnFileChange {\n root: string;\n /** Relative to `root`. */\n path: string;\n}\n\n/** Open the Terminal pane: a tab at `root`, optionally pasting (never running) a command. */\nexport interface TerminalOpenRequest {\n /** Changes on every request, so the same request twice is two opens. */\n nonce: number;\n root?: string;\n /** Force a new tab instead of focusing the root's existing one (⌃⇧`). */\n newTab?: boolean;\n /** \"Run in terminal\": pasted at the prompt, NEVER executed — the operator presses Enter. */\n paste?: string;\n /** Apps [Launch ▸]: the catalog app to launch in the new tab. */\n appId?: string;\n /**\n * With `appId`: HOW to launch it — the app's own CLI (`native`) or through\n * Ollama (`ollama`, with `model` naming the local tag). These mirror\n * VerseTerminalCreateRequest; the page only names the choice, the server\n * resolves the argv from the catalog and the installed binaries\n * (`resolveAppLaunch`) and refuses via/model without an appId.\n */\n via?: VerseTerminalLaunchVia;\n /** With `via: 'ollama'`: the local model tag to launch the app on. */\n model?: string;\n /** Preview's dev-server Start: the server to run in the new tab. */\n devServerId?: string;\n}\n\n/** Open the Preview pane on a loopback URL, a chat artifact, or a dev server. */\nexport interface PreviewOpenRequest {\n nonce: number;\n url?: string;\n artifactPath?: string;\n devServerId?: string;\n}\n\n/** C5 `git/BranchBar.tsx` → `export function BranchBar(props: BranchBarProps)` — above the composer. */\nexport interface BranchBarProps {\n sessionId: string;\n /** The chat's roots in priority order; the bar shows one row per root with changes, then \"Show N more\". */\n roots: readonly string[];\n /** The ± counts open the branch diff: C2 opens the dock's Review pane with this. */\n onOpenDiff: (request: DiffPaneRequest) => void;\n}\n\n/** C5 `git/DiffPane.tsx` → `export function DiffPane(props: DiffPaneProps)` — the dock's Review pane. */\nexport interface DiffPaneProps {\n sessionId: string;\n roots: readonly string[];\n /** Latest open request; null = the pane chooses (Uncommitted, first root with changes). */\n request: (DiffPaneRequest & { nonce: number }) | null;\n turnFiles: readonly TurnFileChange[];\n /** \"Add to message\": drafts `path:line: note` into the composer (⌘Enter sends). */\n onAddToMessage: (text: string) => void;\n /** False while the pane is a background tab — stop timers, skip work. */\n visible: boolean;\n}\n\n/** C4 `dock/terminal/TerminalPane.tsx` → `export function TerminalPane(props: TerminalPaneProps)`. */\nexport interface TerminalPaneProps {\n sessionId: string;\n roots: readonly string[];\n request: TerminalOpenRequest | null;\n /** \"Send selection to chat\": the text, already fenced as a code block. */\n onSendToChat: (text: string) => void;\n visible: boolean;\n}\n\n/** C4 `dock/preview/PreviewPane.tsx` → `export function PreviewPane(props: PreviewPaneProps)`. */\nexport interface PreviewPaneProps {\n sessionId: string;\n roots: readonly string[];\n request: PreviewOpenRequest | null;\n /** Dev-server Start runs the server in a terminal tab — through the dock, never directly. */\n onOpenTerminal: (request: Omit<TerminalOpenRequest, 'nonce'>) => void;\n visible: boolean;\n}\n\n/** C7 `mind/SessionInsightChip.tsx` → `export function SessionInsightChip(props)` — the chat header chip. */\nexport interface SessionInsightChipProps {\n sessionId: string;\n}\n\nexport interface SlotPropsMap {\n 'branch-bar': BranchBarProps;\n 'diff-pane': DiffPaneProps;\n 'terminal-pane': TerminalPaneProps;\n 'preview-pane': PreviewPaneProps;\n 'session-insight-chip': SessionInsightChipProps;\n}\n\nexport type SlotId = keyof SlotPropsMap;\n\n/**\n * Each slot's fixed file (relative to routes/verse), its named export, its\n * owner, and how a crash is shown: an INLINE slot vanishes; a PANE fills the\n * dock, so it says it failed and offers a retry.\n */\nexport const SLOTS = {\n 'branch-bar': { path: 'git/BranchBar.tsx', exportName: 'BranchBar', owner: 'C5', kind: 'inline', label: 'Branch bar' },\n 'diff-pane': { path: 'git/DiffPane.tsx', exportName: 'DiffPane', owner: 'C5', kind: 'pane', label: 'Review' },\n 'terminal-pane': { path: 'dock/terminal/TerminalPane.tsx', exportName: 'TerminalPane', owner: 'C4', kind: 'pane', label: 'Terminal' },\n 'preview-pane': { path: 'dock/preview/PreviewPane.tsx', exportName: 'PreviewPane', owner: 'C4', kind: 'pane', label: 'Preview' },\n 'session-insight-chip': { path: 'mind/SessionInsightChip.tsx', exportName: 'SessionInsightChip', owner: 'C7', kind: 'inline', label: 'Insight' },\n} as const satisfies Record<SlotId, { path: string; exportName: string; owner: string; kind: 'inline' | 'pane'; label: string }>;\n\nexport const SLOT_IDS = Object.keys(SLOTS) as SlotId[];\n\n// ===========================================================================\n// Resolution\n// ===========================================================================\n\ntype Importer = () => Promise<unknown>;\n\n/**\n * Every slot file that exists at build time, keyed `../<path>`. Literal\n * patterns (no wildcards): a slot may only ever load its owner's one file.\n * EXPORTED for the slot test, which checks it against SLOTS.\n */\nexport const SLOT_MODULES: Record<string, Importer> = import.meta.glob([\n '../git/BranchBar.tsx',\n '../git/DiffPane.tsx',\n '../dock/terminal/TerminalPane.tsx',\n '../dock/preview/PreviewPane.tsx',\n '../mind/SessionInsightChip.tsx',\n]);\n\nfunction importerFor(id: SlotId, modules: Record<string, Importer>): Importer | undefined {\n return modules[`../${SLOTS[id].path}`];\n}\n\n/** True once the slot's file has landed in this build. */\nexport function isSlotAvailable(id: SlotId, modules: Record<string, Importer> = SLOT_MODULES): boolean {\n return importerFor(id, modules) !== undefined;\n}\n\ntype AnyComponent = ComponentType<Record<string, unknown>>;\n\n/**\n * Build the lazy component for one slot. Absent → renders nothing. Present\n * but exporting no component of the contract name → throws on load, so the\n * boundary shows it (a slot that silently renders nothing because of a typo\n * would look exactly like \"not landed yet\").\n */\nexport function createSlotComponent(id: SlotId, modules: Record<string, Importer> = SLOT_MODULES): AnyComponent | null {\n const importer = importerFor(id, modules);\n if (!importer) return null;\n const { exportName } = SLOTS[id];\n return lazy(async () => {\n const mod = (await importer()) as Record<string, unknown>;\n const exported = mod[exportName];\n if (typeof exported !== 'function' && (typeof exported !== 'object' || exported === null)) {\n throw new Error(`${SLOTS[id].path} exports no ${exportName}`);\n }\n return { default: exported as AnyComponent };\n });\n}\n\n// One lazy component per slot for the life of the page: re-creating it per\n// render would remount the pane (and drop a terminal's scrollback) each time.\nconst RESOLVED = new Map<SlotId, AnyComponent | null>();\nfunction slotComponent(id: SlotId): AnyComponent | null {\n if (!RESOLVED.has(id)) RESOLVED.set(id, createSlotComponent(id));\n return RESOLVED.get(id)!;\n}\n\n// ===========================================================================\n// Rendering\n// ===========================================================================\n\ninterface BoundaryProps {\n kind: 'inline' | 'pane';\n label: string;\n /** Drop the cached module and mount a fresh boundary (a failed lazy import stays failed otherwise). */\n onRetry: () => void;\n children: ReactNode;\n}\n\nclass SlotBoundary extends Component<BoundaryProps, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo): void {\n // The console, not the page: operator copy never carries a stack or a path.\n console.error(`[verse] ${this.props.label} failed`, error, info.componentStack);\n }\n\n override render(): ReactNode {\n if (!this.state.failed) return this.props.children;\n if (this.props.kind === 'inline') return null;\n return <PaneFailed label={this.props.label} onRetry={this.props.onRetry} />;\n }\n}\n\nfunction PaneFailed({ label, onRetry }: { label: string; onRetry: () => void }) {\n return (\n <EmptyState\n compact\n tone=\"error\"\n title={`${label} could not load`}\n body=\"The rest of the chat still works.\"\n action={\n <Button variant=\"subtle\" size=\"sm\" onClick={onRetry}>\n Try again\n </Button>\n }\n />\n );\n}\n\nfunction SlotHost<K extends SlotId>({\n id,\n props,\n resolve = slotComponent,\n forget = (slot: SlotId) => RESOLVED.delete(slot),\n}: {\n id: K;\n props: SlotPropsMap[K];\n resolve?: (id: SlotId) => AnyComponent | null;\n forget?: (id: SlotId) => void;\n}) {\n const [attempt, setAttempt] = useState(0);\n const Resolved = resolve(id);\n if (!Resolved) return null;\n const { kind, label } = SLOTS[id];\n const retry = () => {\n forget(id);\n setAttempt((n) => n + 1);\n };\n return (\n // A new key per attempt: a fresh boundary AND a fresh lazy component.\n <SlotBoundary key={attempt} kind={kind} label={label} onRetry={retry}>\n <Suspense fallback={null}>\n <Resolved {...(props as unknown as Record<string, unknown>)} />\n </Suspense>\n </SlotBoundary>\n );\n}\n\n/** Test seam: render a slot against an injected module map (fake landed / absent / broken files). */\nexport function SlotForTest<K extends SlotId>({ id, props, modules }: { id: K; props: SlotPropsMap[K]; modules: Record<string, Importer> }) {\n const [cache] = useState(() => new Map<SlotId, AnyComponent | null>());\n const resolve = (slot: SlotId) => {\n if (!cache.has(slot)) cache.set(slot, createSlotComponent(slot, modules));\n return cache.get(slot)!;\n };\n return <SlotHost id={id} props={props} resolve={resolve} forget={(slot) => cache.delete(slot)} />;\n}\n\nexport function BranchBarSlot(props: BranchBarProps) {\n return <SlotHost id=\"branch-bar\" props={props} />;\n}\n\nexport function DiffPaneSlot(props: DiffPaneProps) {\n return <SlotHost id=\"diff-pane\" props={props} />;\n}\n\nexport function TerminalPaneSlot(props: TerminalPaneProps) {\n return <SlotHost id=\"terminal-pane\" props={props} />;\n}\n\nexport function PreviewPaneSlot(props: PreviewPaneProps) {\n return <SlotHost id=\"preview-pane\" props={props} />;\n}\n\nexport function SessionInsightChipSlot(props: SessionInsightChipProps) {\n return <SlotHost id=\"session-insight-chip\" props={props} />;\n}\n"],"file":"slots-BL_J5mmV.js"}
1
+ {"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../../../../../src/web-ui/routes/verse/shell/slots.tsx"],"sourcesContent":["/**\n * routes/verse/shell/slots.tsx — where Chat mounts other units' UI (unit C0;\n * SPEC-310C §7 \"Slots\").\n *\n * C2 owns the chat, the dock and the header; C4, C5 and C7 own things that\n * render INSIDE them. Rather than C2 importing their files — which would not\n * compile until every one of them landed, and would drag each into C2's\n * chunk — C2 renders these slots. Each resolves ONE fixed file lazily and:\n * - renders nothing until that file lands (and `isSlotAvailable` says so,\n * so C2 can hide the toggle for a pane that does not exist yet);\n * - loads in its own chunk (xterm and the diff viewer stay off the chat's\n * critical path — SPEC-310C budgets: chat critical JS ≤ 350 KB);\n * - is fenced by an error boundary: a crashed inline slot vanishes, a\n * crashed pane says so with a retry — neither takes the chat down.\n *\n * The props below ARE the contract: each owning unit's component takes\n * exactly its slot's props, as a NAMED export (`export function BranchBar`).\n *\n * Resolution uses `import.meta.glob` with literal paths — the same \"absent\n * file is an absent key\" mechanism VerseApp uses for sections.\n */\nimport { Component, Suspense, lazy, useState, type ComponentType, type ErrorInfo, type ReactNode } from 'react';\nimport { Button } from '../../../components/primitives/Button.js';\nimport { EmptyState } from '../../../components/primitives/EmptyState.js';\nimport type { VerseReviewScope, VerseTerminalLaunchVia } from '../../../../core/verse/workbench-types.js';\n\n// ===========================================================================\n// Contracts\n// ===========================================================================\n\n/** Open the Review pane on a root, at a scope (and optionally one file). */\nexport interface DiffPaneRequest {\n root: string;\n scope: VerseReviewScope;\n file?: string;\n}\n\n/** A file the chat's latest turn touched — the Review pane's \"This turn\" scope (C2 derives it from events). */\nexport interface TurnFileChange {\n root: string;\n /** Relative to `root`. */\n path: string;\n}\n\n/** Open the Terminal pane: a tab at `root`, optionally pasting (never running) a command. */\nexport interface TerminalOpenRequest {\n /** Changes on every request, so the same request twice is two opens. */\n nonce: number;\n root?: string;\n /** Force a new tab instead of focusing the root's existing one (⌃⇧`). */\n newTab?: boolean;\n /** \"Run in terminal\": pasted at the prompt, NEVER executed — the operator presses Enter. */\n paste?: string;\n /** Apps [Launch ▸]: the catalog app to launch in the new tab. */\n appId?: string;\n /**\n * With `appId`: HOW to launch it — the app's own CLI (`native`) or through\n * Ollama (`ollama`, with `model` naming the local tag). These mirror\n * VerseTerminalCreateRequest; the page only names the choice, the server\n * resolves the argv from the catalog and the installed binaries\n * (`resolveAppLaunch`) and refuses via/model without an appId.\n */\n via?: VerseTerminalLaunchVia;\n /** With `via: 'ollama'`: the local model tag to launch the app on. */\n model?: string;\n /** Preview's dev-server Start: the server to run in the new tab. */\n devServerId?: string;\n}\n\n/** Open the Preview pane on a loopback URL, a chat artifact, or a dev server. */\nexport interface PreviewOpenRequest {\n nonce: number;\n url?: string;\n artifactPath?: string;\n devServerId?: string;\n}\n\n/** C5 `git/BranchBar.tsx` → `export function BranchBar(props: BranchBarProps)` — above the composer. */\nexport interface BranchBarProps {\n sessionId: string;\n /** The chat's roots in priority order; the bar shows one row per root with changes, then \"Show N more\". */\n roots: readonly string[];\n /** The ± counts open the branch diff: C2 opens the dock's Review pane with this. */\n onOpenDiff: (request: DiffPaneRequest) => void;\n}\n\n/** C5 `git/DiffPane.tsx` → `export function DiffPane(props: DiffPaneProps)` — the dock's Review pane. */\nexport interface DiffPaneProps {\n sessionId: string;\n roots: readonly string[];\n /** Latest open request; null = the pane chooses (Uncommitted, first root with changes). */\n request: (DiffPaneRequest & { nonce: number }) | null;\n turnFiles: readonly TurnFileChange[];\n /** \"Add to message\": drafts `path:line: note` into the composer (⌘Enter sends). */\n onAddToMessage: (text: string) => void;\n /** False while the pane is a background tab — stop timers, skip work. */\n visible: boolean;\n}\n\n/** C4 `dock/terminal/TerminalPane.tsx` → `export function TerminalPane(props: TerminalPaneProps)`. */\nexport interface TerminalPaneProps {\n sessionId: string;\n roots: readonly string[];\n request: TerminalOpenRequest | null;\n /** \"Send selection to chat\": the text, already fenced as a code block. */\n onSendToChat: (text: string) => void;\n visible: boolean;\n}\n\n/** C4 `dock/preview/PreviewPane.tsx` → `export function PreviewPane(props: PreviewPaneProps)`. */\nexport interface PreviewPaneProps {\n sessionId: string;\n roots: readonly string[];\n request: PreviewOpenRequest | null;\n /** Dev-server Start runs the server in a terminal tab — through the dock, never directly. */\n onOpenTerminal: (request: Omit<TerminalOpenRequest, 'nonce'>) => void;\n visible: boolean;\n}\n\n/** C7 `mind/SessionInsightChip.tsx` → `export function SessionInsightChip(props)` — the chat header chip. */\nexport interface SessionInsightChipProps {\n sessionId: string;\n}\n\nexport interface SlotPropsMap {\n 'branch-bar': BranchBarProps;\n 'diff-pane': DiffPaneProps;\n 'terminal-pane': TerminalPaneProps;\n 'preview-pane': PreviewPaneProps;\n 'session-insight-chip': SessionInsightChipProps;\n}\n\nexport type SlotId = keyof SlotPropsMap;\n\n/**\n * Each slot's fixed file (relative to routes/verse), its named export, its\n * owner, and how a crash is shown: an INLINE slot vanishes; a PANE fills the\n * dock, so it says it failed and offers a retry.\n */\nexport const SLOTS = {\n 'branch-bar': { path: 'git/BranchBar.tsx', exportName: 'BranchBar', owner: 'C5', kind: 'inline', label: 'Branch bar' },\n 'diff-pane': { path: 'git/DiffPane.tsx', exportName: 'DiffPane', owner: 'C5', kind: 'pane', label: 'Review' },\n 'terminal-pane': { path: 'dock/terminal/TerminalPane.tsx', exportName: 'TerminalPane', owner: 'C4', kind: 'pane', label: 'Terminal' },\n 'preview-pane': { path: 'dock/preview/PreviewPane.tsx', exportName: 'PreviewPane', owner: 'C4', kind: 'pane', label: 'Preview' },\n 'session-insight-chip': { path: 'mind/SessionInsightChip.tsx', exportName: 'SessionInsightChip', owner: 'C7', kind: 'inline', label: 'Insight' },\n} as const satisfies Record<SlotId, { path: string; exportName: string; owner: string; kind: 'inline' | 'pane'; label: string }>;\n\nexport const SLOT_IDS = Object.keys(SLOTS) as SlotId[];\n\n// ===========================================================================\n// Resolution\n// ===========================================================================\n\ntype Importer = () => Promise<unknown>;\n\n/**\n * Every slot file that exists at build time, keyed `../<path>`. Literal\n * patterns (no wildcards): a slot may only ever load its owner's one file.\n * EXPORTED for the slot test, which checks it against SLOTS.\n */\nexport const SLOT_MODULES: Record<string, Importer> = import.meta.glob([\n '../git/BranchBar.tsx',\n '../git/DiffPane.tsx',\n '../dock/terminal/TerminalPane.tsx',\n '../dock/preview/PreviewPane.tsx',\n '../mind/SessionInsightChip.tsx',\n]);\n\nfunction importerFor(id: SlotId, modules: Record<string, Importer>): Importer | undefined {\n return modules[`../${SLOTS[id].path}`];\n}\n\n/** True once the slot's file has landed in this build. */\nexport function isSlotAvailable(id: SlotId, modules: Record<string, Importer> = SLOT_MODULES): boolean {\n return importerFor(id, modules) !== undefined;\n}\n\ntype AnyComponent = ComponentType<Record<string, unknown>>;\n\n/**\n * Build the lazy component for one slot. Absent → renders nothing. Present\n * but exporting no component of the contract name → throws on load, so the\n * boundary shows it (a slot that silently renders nothing because of a typo\n * would look exactly like \"not landed yet\").\n */\nexport function createSlotComponent(id: SlotId, modules: Record<string, Importer> = SLOT_MODULES): AnyComponent | null {\n const importer = importerFor(id, modules);\n if (!importer) return null;\n const { exportName } = SLOTS[id];\n return lazy(async () => {\n const mod = (await importer()) as Record<string, unknown>;\n const exported = mod[exportName];\n if (typeof exported !== 'function' && (typeof exported !== 'object' || exported === null)) {\n throw new Error(`${SLOTS[id].path} exports no ${exportName}`);\n }\n return { default: exported as AnyComponent };\n });\n}\n\n// One lazy component per slot for the life of the page: re-creating it per\n// render would remount the pane (and drop a terminal's scrollback) each time.\nconst RESOLVED = new Map<SlotId, AnyComponent | null>();\nfunction slotComponent(id: SlotId): AnyComponent | null {\n if (!RESOLVED.has(id)) RESOLVED.set(id, createSlotComponent(id));\n return RESOLVED.get(id)!;\n}\n\n// ===========================================================================\n// Rendering\n// ===========================================================================\n\ninterface BoundaryProps {\n kind: 'inline' | 'pane';\n label: string;\n /** Drop the cached module and mount a fresh boundary (a failed lazy import stays failed otherwise). */\n onRetry: () => void;\n children: ReactNode;\n}\n\nclass SlotBoundary extends Component<BoundaryProps, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo): void {\n // The console, not the page: operator copy never carries a stack or a path.\n console.error(`[verse] ${this.props.label} failed`, error, info.componentStack);\n }\n\n override render(): ReactNode {\n if (!this.state.failed) return this.props.children;\n if (this.props.kind === 'inline') return null;\n return <PaneFailed label={this.props.label} onRetry={this.props.onRetry} />;\n }\n}\n\nfunction PaneFailed({ label, onRetry }: { label: string; onRetry: () => void }) {\n return (\n <EmptyState\n compact\n tone=\"error\"\n title={`${label} could not load`}\n body=\"The rest of the chat still works.\"\n action={\n <Button variant=\"subtle\" size=\"sm\" onClick={onRetry}>\n Try again\n </Button>\n }\n />\n );\n}\n\nfunction SlotHost<K extends SlotId>({\n id,\n props,\n resolve = slotComponent,\n forget = (slot: SlotId) => RESOLVED.delete(slot),\n}: {\n id: K;\n props: SlotPropsMap[K];\n resolve?: (id: SlotId) => AnyComponent | null;\n forget?: (id: SlotId) => void;\n}) {\n const [attempt, setAttempt] = useState(0);\n const Resolved = resolve(id);\n if (!Resolved) return null;\n const { kind, label } = SLOTS[id];\n const retry = () => {\n forget(id);\n setAttempt((n) => n + 1);\n };\n return (\n // A new key per attempt: a fresh boundary AND a fresh lazy component.\n <SlotBoundary key={attempt} kind={kind} label={label} onRetry={retry}>\n <Suspense fallback={null}>\n <Resolved {...(props as unknown as Record<string, unknown>)} />\n </Suspense>\n </SlotBoundary>\n );\n}\n\n/** Test seam: render a slot against an injected module map (fake landed / absent / broken files). */\nexport function SlotForTest<K extends SlotId>({ id, props, modules }: { id: K; props: SlotPropsMap[K]; modules: Record<string, Importer> }) {\n const [cache] = useState(() => new Map<SlotId, AnyComponent | null>());\n const resolve = (slot: SlotId) => {\n if (!cache.has(slot)) cache.set(slot, createSlotComponent(slot, modules));\n return cache.get(slot)!;\n };\n return <SlotHost id={id} props={props} resolve={resolve} forget={(slot) => cache.delete(slot)} />;\n}\n\nexport function BranchBarSlot(props: BranchBarProps) {\n return <SlotHost id=\"branch-bar\" props={props} />;\n}\n\nexport function DiffPaneSlot(props: DiffPaneProps) {\n return <SlotHost id=\"diff-pane\" props={props} />;\n}\n\nexport function TerminalPaneSlot(props: TerminalPaneProps) {\n return <SlotHost id=\"terminal-pane\" props={props} />;\n}\n\nexport function PreviewPaneSlot(props: PreviewPaneProps) {\n return <SlotHost id=\"preview-pane\" props={props} />;\n}\n\nexport function SessionInsightChipSlot(props: SessionInsightChipProps) {\n return <SlotHost id=\"session-insight-chip\" props={props} />;\n}\n"],"file":"slots-C-qBeu-8.js"}