@schlessera/brain-ui-react 0.34.1 → 0.36.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 (763) hide show
  1. package/README.md +89 -4
  2. package/dist/components/activity/activity-page.d.ts +17 -5
  3. package/dist/components/activity/activity-page.d.ts.map +1 -1
  4. package/dist/components/activity/activity-page.js +144 -50
  5. package/dist/components/activity/activity-page.js.map +1 -1
  6. package/dist/components/activity/activity-run-detail.d.ts +16 -1
  7. package/dist/components/activity/activity-run-detail.d.ts.map +1 -1
  8. package/dist/components/activity/activity-run-detail.js +47 -4
  9. package/dist/components/activity/activity-run-detail.js.map +1 -1
  10. package/dist/components/activity/activity-run-list.d.ts +7 -1
  11. package/dist/components/activity/activity-run-list.d.ts.map +1 -1
  12. package/dist/components/activity/activity-run-list.js +16 -8
  13. package/dist/components/activity/activity-run-list.js.map +1 -1
  14. package/dist/components/activity/activity-views.d.ts +63 -0
  15. package/dist/components/activity/activity-views.d.ts.map +1 -0
  16. package/dist/components/activity/activity-views.js +52 -0
  17. package/dist/components/activity/activity-views.js.map +1 -0
  18. package/dist/components/activity/approval-card.d.ts +11 -0
  19. package/dist/components/activity/approval-card.d.ts.map +1 -0
  20. package/dist/components/activity/approval-card.js +46 -0
  21. package/dist/components/activity/approval-card.js.map +1 -0
  22. package/dist/components/activity/digest-card.d.ts +3 -0
  23. package/dist/components/activity/digest-card.d.ts.map +1 -1
  24. package/dist/components/activity/digest-card.js +20 -16
  25. package/dist/components/activity/digest-card.js.map +1 -1
  26. package/dist/components/activity/digest-summary.d.ts +19 -0
  27. package/dist/components/activity/digest-summary.d.ts.map +1 -0
  28. package/dist/components/activity/digest-summary.js +20 -0
  29. package/dist/components/activity/digest-summary.js.map +1 -0
  30. package/dist/components/activity/push-switch.d.ts +25 -0
  31. package/dist/components/activity/push-switch.d.ts.map +1 -0
  32. package/dist/components/activity/push-switch.js +14 -0
  33. package/dist/components/activity/push-switch.js.map +1 -0
  34. package/dist/components/activity/push-toggle.d.ts +7 -0
  35. package/dist/components/activity/push-toggle.d.ts.map +1 -1
  36. package/dist/components/activity/push-toggle.js +72 -47
  37. package/dist/components/activity/push-toggle.js.map +1 -1
  38. package/dist/components/activity/span-bits.d.ts.map +1 -1
  39. package/dist/components/activity/span-bits.js +9 -7
  40. package/dist/components/activity/span-bits.js.map +1 -1
  41. package/dist/components/chat/ask-user-card.d.ts +76 -3
  42. package/dist/components/chat/ask-user-card.d.ts.map +1 -1
  43. package/dist/components/chat/ask-user-card.js +208 -149
  44. package/dist/components/chat/ask-user-card.js.map +1 -1
  45. package/dist/components/chat/ask-user-typed.d.ts +42 -0
  46. package/dist/components/chat/ask-user-typed.d.ts.map +1 -0
  47. package/dist/components/chat/ask-user-typed.js +60 -0
  48. package/dist/components/chat/ask-user-typed.js.map +1 -0
  49. package/dist/components/chat/brain-markdown-links.d.ts +2 -1
  50. package/dist/components/chat/brain-markdown-links.d.ts.map +1 -1
  51. package/dist/components/chat/brain-markdown-links.js +3 -4
  52. package/dist/components/chat/brain-markdown-links.js.map +1 -1
  53. package/dist/components/chat/brain-markdown.d.ts.map +1 -1
  54. package/dist/components/chat/brain-markdown.js +4 -2
  55. package/dist/components/chat/brain-markdown.js.map +1 -1
  56. package/dist/components/chat/chat-page.d.ts.map +1 -1
  57. package/dist/components/chat/chat-page.js +24 -9
  58. package/dist/components/chat/chat-page.js.map +1 -1
  59. package/dist/components/chat/composer-view.d.ts +75 -0
  60. package/dist/components/chat/composer-view.d.ts.map +1 -0
  61. package/dist/components/chat/composer-view.js +31 -0
  62. package/dist/components/chat/composer-view.js.map +1 -0
  63. package/dist/components/chat/composer.d.ts +4 -0
  64. package/dist/components/chat/composer.d.ts.map +1 -1
  65. package/dist/components/chat/composer.js +76 -59
  66. package/dist/components/chat/composer.js.map +1 -1
  67. package/dist/components/chat/markdown-content.d.ts +16 -1
  68. package/dist/components/chat/markdown-content.d.ts.map +1 -1
  69. package/dist/components/chat/markdown-content.js +47 -3
  70. package/dist/components/chat/markdown-content.js.map +1 -1
  71. package/dist/components/chat/mermaid-block.d.ts +4 -0
  72. package/dist/components/chat/mermaid-block.d.ts.map +1 -1
  73. package/dist/components/chat/mermaid-block.js +13 -5
  74. package/dist/components/chat/mermaid-block.js.map +1 -1
  75. package/dist/components/chat/mermaid-share.d.ts +2 -1
  76. package/dist/components/chat/mermaid-share.d.ts.map +1 -1
  77. package/dist/components/chat/mermaid-share.js +7 -8
  78. package/dist/components/chat/mermaid-share.js.map +1 -1
  79. package/dist/components/chat/mermaid-viewer.d.ts.map +1 -1
  80. package/dist/components/chat/mermaid-viewer.js +3 -1
  81. package/dist/components/chat/mermaid-viewer.js.map +1 -1
  82. package/dist/components/chat/message-bubble.d.ts +8 -1
  83. package/dist/components/chat/message-bubble.d.ts.map +1 -1
  84. package/dist/components/chat/message-bubble.js +53 -24
  85. package/dist/components/chat/message-bubble.js.map +1 -1
  86. package/dist/components/chat/message-share.d.ts +2 -1
  87. package/dist/components/chat/message-share.d.ts.map +1 -1
  88. package/dist/components/chat/message-share.js +6 -7
  89. package/dist/components/chat/message-share.js.map +1 -1
  90. package/dist/components/chat/renderers/bind.d.ts +39 -0
  91. package/dist/components/chat/renderers/bind.d.ts.map +1 -0
  92. package/dist/components/chat/renderers/bind.js +43 -0
  93. package/dist/components/chat/renderers/bind.js.map +1 -0
  94. package/dist/components/chat/renderers/brain-ui-tools.d.ts +3 -0
  95. package/dist/components/chat/renderers/brain-ui-tools.d.ts.map +1 -0
  96. package/dist/components/chat/renderers/brain-ui-tools.js +41 -0
  97. package/dist/components/chat/renderers/brain-ui-tools.js.map +1 -0
  98. package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -1
  99. package/dist/components/chat/renderers/claude-tools.js +3 -2
  100. package/dist/components/chat/renderers/claude-tools.js.map +1 -1
  101. package/dist/components/chat/renderers/index.d.ts +10 -2
  102. package/dist/components/chat/renderers/index.d.ts.map +1 -1
  103. package/dist/components/chat/renderers/index.js +15 -10
  104. package/dist/components/chat/renderers/index.js.map +1 -1
  105. package/dist/components/chat/session-drawer.d.ts +4 -0
  106. package/dist/components/chat/session-drawer.d.ts.map +1 -1
  107. package/dist/components/chat/session-drawer.js +55 -40
  108. package/dist/components/chat/session-drawer.js.map +1 -1
  109. package/dist/components/chat/session-list.d.ts +41 -0
  110. package/dist/components/chat/session-list.d.ts.map +1 -0
  111. package/dist/components/chat/session-list.js +10 -0
  112. package/dist/components/chat/session-list.js.map +1 -0
  113. package/dist/components/chat/share-block.d.ts.map +1 -1
  114. package/dist/components/chat/share-block.js +12 -11
  115. package/dist/components/chat/share-block.js.map +1 -1
  116. package/dist/components/chat/share-card.js +2 -2
  117. package/dist/components/chat/share-card.js.map +1 -1
  118. package/dist/components/chat/subagent-view.js +1 -1
  119. package/dist/components/chat/subagent-view.js.map +1 -1
  120. package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
  121. package/dist/components/chat/tool-call-timeline.js +37 -12
  122. package/dist/components/chat/tool-call-timeline.js.map +1 -1
  123. package/dist/components/chat/tool-cards/block-card.d.ts +28 -0
  124. package/dist/components/chat/tool-cards/block-card.d.ts.map +1 -0
  125. package/dist/components/chat/tool-cards/block-card.js +103 -0
  126. package/dist/components/chat/tool-cards/block-card.js.map +1 -0
  127. package/dist/components/chat/tool-cards/image-mask-card.d.ts +70 -0
  128. package/dist/components/chat/tool-cards/image-mask-card.d.ts.map +1 -0
  129. package/dist/components/chat/tool-cards/image-mask-card.js +142 -0
  130. package/dist/components/chat/tool-cards/image-mask-card.js.map +1 -0
  131. package/dist/components/chat/tool-cards/location-card.d.ts +45 -0
  132. package/dist/components/chat/tool-cards/location-card.d.ts.map +1 -0
  133. package/dist/components/chat/tool-cards/location-card.js +128 -0
  134. package/dist/components/chat/tool-cards/location-card.js.map +1 -0
  135. package/dist/components/chat/tool-views.d.ts +15 -4
  136. package/dist/components/chat/tool-views.d.ts.map +1 -1
  137. package/dist/components/chat/tool-views.js +22 -38
  138. package/dist/components/chat/tool-views.js.map +1 -1
  139. package/dist/components/chat/transcript-turn.d.ts +45 -0
  140. package/dist/components/chat/transcript-turn.d.ts.map +1 -0
  141. package/dist/components/chat/transcript-turn.js +25 -0
  142. package/dist/components/chat/transcript-turn.js.map +1 -0
  143. package/dist/components/chat/use-chat-commands.d.ts.map +1 -1
  144. package/dist/components/chat/use-chat-commands.js +13 -16
  145. package/dist/components/chat/use-chat-commands.js.map +1 -1
  146. package/dist/components/chat/welcome-state.d.ts +7 -0
  147. package/dist/components/chat/welcome-state.d.ts.map +1 -1
  148. package/dist/components/chat/welcome-state.js +13 -5
  149. package/dist/components/chat/welcome-state.js.map +1 -1
  150. package/dist/components/connectivity/connection-gate.d.ts.map +1 -1
  151. package/dist/components/connectivity/connection-gate.js +64 -6
  152. package/dist/components/connectivity/connection-gate.js.map +1 -1
  153. package/dist/components/connectivity/login-form.d.ts +31 -0
  154. package/dist/components/connectivity/login-form.d.ts.map +1 -0
  155. package/dist/components/connectivity/login-form.js +19 -0
  156. package/dist/components/connectivity/login-form.js.map +1 -0
  157. package/dist/components/connectivity/login-screen.d.ts +5 -2
  158. package/dist/components/connectivity/login-screen.d.ts.map +1 -1
  159. package/dist/components/connectivity/login-screen.js +41 -31
  160. package/dist/components/connectivity/login-screen.js.map +1 -1
  161. package/dist/components/dev/share-harness.js +1 -1
  162. package/dist/components/dev/share-harness.js.map +1 -1
  163. package/dist/components/files/file-panel.d.ts +1 -1
  164. package/dist/components/files/file-panel.d.ts.map +1 -1
  165. package/dist/components/files/file-panel.js +74 -0
  166. package/dist/components/files/file-panel.js.map +1 -1
  167. package/dist/components/files/file-tree-view.d.ts +45 -0
  168. package/dist/components/files/file-tree-view.d.ts.map +1 -0
  169. package/dist/components/files/file-tree-view.js +51 -0
  170. package/dist/components/files/file-tree-view.js.map +1 -0
  171. package/dist/components/files/file-tree.d.ts +6 -0
  172. package/dist/components/files/file-tree.d.ts.map +1 -1
  173. package/dist/components/files/file-tree.js +39 -43
  174. package/dist/components/files/file-tree.js.map +1 -1
  175. package/dist/components/files/file-viewer-binary.d.ts.map +1 -1
  176. package/dist/components/files/file-viewer-binary.js +3 -2
  177. package/dist/components/files/file-viewer-binary.js.map +1 -1
  178. package/dist/components/files/file-viewer-frame.d.ts +36 -0
  179. package/dist/components/files/file-viewer-frame.d.ts.map +1 -0
  180. package/dist/components/files/file-viewer-frame.js +26 -0
  181. package/dist/components/files/file-viewer-frame.js.map +1 -0
  182. package/dist/components/files/file-viewer.d.ts +5 -0
  183. package/dist/components/files/file-viewer.d.ts.map +1 -1
  184. package/dist/components/files/file-viewer.js +26 -32
  185. package/dist/components/files/file-viewer.js.map +1 -1
  186. package/dist/components/files/frontmatter-chips.d.ts +18 -0
  187. package/dist/components/files/frontmatter-chips.d.ts.map +1 -0
  188. package/dist/components/files/frontmatter-chips.js +11 -0
  189. package/dist/components/files/frontmatter-chips.js.map +1 -0
  190. package/dist/components/files/frontmatter-panel.d.ts +5 -1
  191. package/dist/components/files/frontmatter-panel.d.ts.map +1 -1
  192. package/dist/components/files/frontmatter-panel.js +7 -6
  193. package/dist/components/files/frontmatter-panel.js.map +1 -1
  194. package/dist/components/files/staleness.d.ts +18 -0
  195. package/dist/components/files/staleness.d.ts.map +1 -0
  196. package/dist/components/files/staleness.js +27 -0
  197. package/dist/components/files/staleness.js.map +1 -0
  198. package/dist/components/graph/graph-canvas.d.ts.map +1 -1
  199. package/dist/components/graph/graph-canvas.js +24 -1
  200. package/dist/components/graph/graph-canvas.js.map +1 -1
  201. package/dist/components/graph/graph-controls-column.d.ts +14 -0
  202. package/dist/components/graph/graph-controls-column.d.ts.map +1 -0
  203. package/dist/components/graph/graph-controls-column.js +44 -0
  204. package/dist/components/graph/graph-controls-column.js.map +1 -0
  205. package/dist/components/graph/graph-controls.d.ts +20 -5
  206. package/dist/components/graph/graph-controls.d.ts.map +1 -1
  207. package/dist/components/graph/graph-controls.js +58 -37
  208. package/dist/components/graph/graph-controls.js.map +1 -1
  209. package/dist/components/graph/graph-form.d.ts +82 -0
  210. package/dist/components/graph/graph-form.d.ts.map +1 -0
  211. package/dist/components/graph/graph-form.js +69 -0
  212. package/dist/components/graph/graph-form.js.map +1 -0
  213. package/dist/components/graph/graph-maintenance.d.ts.map +1 -1
  214. package/dist/components/graph/graph-maintenance.js +6 -10
  215. package/dist/components/graph/graph-maintenance.js.map +1 -1
  216. package/dist/components/graph/graph-node-rail.d.ts +13 -0
  217. package/dist/components/graph/graph-node-rail.d.ts.map +1 -0
  218. package/dist/components/graph/graph-node-rail.js +92 -0
  219. package/dist/components/graph/graph-node-rail.js.map +1 -0
  220. package/dist/components/graph/graph-page.d.ts +7 -0
  221. package/dist/components/graph/graph-page.d.ts.map +1 -1
  222. package/dist/components/graph/graph-page.js +102 -12
  223. package/dist/components/graph/graph-page.js.map +1 -1
  224. package/dist/components/graph/graph-scene.d.ts.map +1 -1
  225. package/dist/components/graph/graph-scene.js +100 -24
  226. package/dist/components/graph/graph-scene.js.map +1 -1
  227. package/dist/components/graph/lib/graph-helpers.d.ts +42 -12
  228. package/dist/components/graph/lib/graph-helpers.d.ts.map +1 -1
  229. package/dist/components/graph/lib/graph-helpers.js +33 -41
  230. package/dist/components/graph/lib/graph-helpers.js.map +1 -1
  231. package/dist/components/graph/node-card.d.ts +28 -0
  232. package/dist/components/graph/node-card.d.ts.map +1 -0
  233. package/dist/components/graph/node-card.js +7 -0
  234. package/dist/components/graph/node-card.js.map +1 -0
  235. package/dist/components/graph/node-popover.d.ts +6 -2
  236. package/dist/components/graph/node-popover.d.ts.map +1 -1
  237. package/dist/components/graph/node-popover.js +13 -31
  238. package/dist/components/graph/node-popover.js.map +1 -1
  239. package/dist/components/graph/use-graph-theme.d.ts +32 -4
  240. package/dist/components/graph/use-graph-theme.d.ts.map +1 -1
  241. package/dist/components/graph/use-graph-theme.js +44 -32
  242. package/dist/components/graph/use-graph-theme.js.map +1 -1
  243. package/dist/components/graph/use-node-actions.d.ts +26 -0
  244. package/dist/components/graph/use-node-actions.d.ts.map +1 -0
  245. package/dist/components/graph/use-node-actions.js +54 -0
  246. package/dist/components/graph/use-node-actions.js.map +1 -0
  247. package/dist/components/images/image-share.d.ts +2 -1
  248. package/dist/components/images/image-share.d.ts.map +1 -1
  249. package/dist/components/images/image-share.js +3 -3
  250. package/dist/components/images/image-share.js.map +1 -1
  251. package/dist/components/images/image-viewer.d.ts.map +1 -1
  252. package/dist/components/images/image-viewer.js +3 -1
  253. package/dist/components/images/image-viewer.js.map +1 -1
  254. package/dist/components/images/mask-editor.d.ts.map +1 -1
  255. package/dist/components/images/mask-editor.js +7 -5
  256. package/dist/components/images/mask-editor.js.map +1 -1
  257. package/dist/components/layout/app-shell.d.ts.map +1 -1
  258. package/dist/components/layout/app-shell.js +5 -1
  259. package/dist/components/layout/app-shell.js.map +1 -1
  260. package/dist/components/layout/desktop-palette.d.ts +23 -0
  261. package/dist/components/layout/desktop-palette.d.ts.map +1 -0
  262. package/dist/components/layout/desktop-palette.js +132 -0
  263. package/dist/components/layout/desktop-palette.js.map +1 -0
  264. package/dist/components/layout/key-cap.d.ts +9 -0
  265. package/dist/components/layout/key-cap.d.ts.map +1 -0
  266. package/dist/components/layout/key-cap.js +10 -0
  267. package/dist/components/layout/key-cap.js.map +1 -0
  268. package/dist/components/layout/mobile-tab-bar.d.ts +13 -0
  269. package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
  270. package/dist/components/layout/mobile-tab-bar.js +58 -47
  271. package/dist/components/layout/mobile-tab-bar.js.map +1 -1
  272. package/dist/components/layout/shortcut-switch.d.ts +13 -0
  273. package/dist/components/layout/shortcut-switch.d.ts.map +1 -0
  274. package/dist/components/layout/shortcut-switch.js +22 -0
  275. package/dist/components/layout/shortcut-switch.js.map +1 -0
  276. package/dist/components/layout/side-rail.d.ts +24 -0
  277. package/dist/components/layout/side-rail.d.ts.map +1 -1
  278. package/dist/components/layout/side-rail.js +65 -27
  279. package/dist/components/layout/side-rail.js.map +1 -1
  280. package/dist/components/layout/slide-panel.d.ts +12 -2
  281. package/dist/components/layout/slide-panel.d.ts.map +1 -1
  282. package/dist/components/layout/slide-panel.js +11 -2
  283. package/dist/components/layout/slide-panel.js.map +1 -1
  284. package/dist/components/layout/theme.d.ts +22 -0
  285. package/dist/components/layout/theme.d.ts.map +1 -0
  286. package/dist/components/layout/theme.js +44 -0
  287. package/dist/components/layout/theme.js.map +1 -0
  288. package/dist/components/quick-actions/add-form.d.ts +44 -0
  289. package/dist/components/quick-actions/add-form.d.ts.map +1 -0
  290. package/dist/components/quick-actions/add-form.js +30 -0
  291. package/dist/components/quick-actions/add-form.js.map +1 -0
  292. package/dist/components/quick-actions/add-modal.d.ts +7 -0
  293. package/dist/components/quick-actions/add-modal.d.ts.map +1 -1
  294. package/dist/components/quick-actions/add-modal.js +66 -20
  295. package/dist/components/quick-actions/add-modal.js.map +1 -1
  296. package/dist/components/quick-actions/search-modal.d.ts.map +1 -1
  297. package/dist/components/quick-actions/search-modal.js +48 -19
  298. package/dist/components/quick-actions/search-modal.js.map +1 -1
  299. package/dist/components/quick-actions/streaming-modal.d.ts +6 -0
  300. package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -1
  301. package/dist/components/quick-actions/streaming-modal.js +42 -17
  302. package/dist/components/quick-actions/streaming-modal.js.map +1 -1
  303. package/dist/components/quick-actions/streaming-output.d.ts +38 -0
  304. package/dist/components/quick-actions/streaming-output.d.ts.map +1 -0
  305. package/dist/components/quick-actions/streaming-output.js +22 -0
  306. package/dist/components/quick-actions/streaming-output.js.map +1 -0
  307. package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
  308. package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -1
  309. package/dist/components/quick-actions/whatsup-modal.js +36 -10
  310. package/dist/components/quick-actions/whatsup-modal.js.map +1 -1
  311. package/dist/components/settings/devices-agents-tab.d.ts +10 -0
  312. package/dist/components/settings/devices-agents-tab.d.ts.map +1 -0
  313. package/dist/components/settings/devices-agents-tab.js +131 -0
  314. package/dist/components/settings/devices-agents-tab.js.map +1 -0
  315. package/dist/components/settings/models-list.d.ts +39 -0
  316. package/dist/components/settings/models-list.d.ts.map +1 -0
  317. package/dist/components/settings/models-list.js +72 -0
  318. package/dist/components/settings/models-list.js.map +1 -0
  319. package/dist/components/settings/models-tab.d.ts +4 -0
  320. package/dist/components/settings/models-tab.d.ts.map +1 -1
  321. package/dist/components/settings/models-tab.js +52 -102
  322. package/dist/components/settings/models-tab.js.map +1 -1
  323. package/dist/components/settings/one-time-agent-credential.d.ts +3 -0
  324. package/dist/components/settings/one-time-agent-credential.d.ts.map +1 -0
  325. package/dist/components/settings/one-time-agent-credential.js +55 -0
  326. package/dist/components/settings/one-time-agent-credential.js.map +1 -0
  327. package/dist/components/settings/passkey-list.d.ts +35 -0
  328. package/dist/components/settings/passkey-list.d.ts.map +1 -0
  329. package/dist/components/settings/passkey-list.js +34 -0
  330. package/dist/components/settings/passkey-list.js.map +1 -0
  331. package/dist/components/settings/passkey-tab.d.ts +3 -0
  332. package/dist/components/settings/passkey-tab.d.ts.map +1 -1
  333. package/dist/components/settings/passkey-tab.js +53 -45
  334. package/dist/components/settings/passkey-tab.js.map +1 -1
  335. package/dist/components/settings/pi-accounts-list.d.ts +27 -0
  336. package/dist/components/settings/pi-accounts-list.d.ts.map +1 -0
  337. package/dist/components/settings/pi-accounts-list.js +15 -0
  338. package/dist/components/settings/pi-accounts-list.js.map +1 -0
  339. package/dist/components/settings/pi-accounts.d.ts +3 -0
  340. package/dist/components/settings/pi-accounts.d.ts.map +1 -1
  341. package/dist/components/settings/pi-accounts.js +73 -55
  342. package/dist/components/settings/pi-accounts.js.map +1 -1
  343. package/dist/components/settings/principal-list.d.ts +37 -0
  344. package/dist/components/settings/principal-list.d.ts.map +1 -0
  345. package/dist/components/settings/principal-list.js +18 -0
  346. package/dist/components/settings/principal-list.js.map +1 -0
  347. package/dist/components/settings/settings-panel.d.ts +10 -3
  348. package/dist/components/settings/settings-panel.d.ts.map +1 -1
  349. package/dist/components/settings/settings-panel.js +80 -6
  350. package/dist/components/settings/settings-panel.js.map +1 -1
  351. package/dist/components/settings/skills-list.d.ts +53 -0
  352. package/dist/components/settings/skills-list.d.ts.map +1 -0
  353. package/dist/components/settings/skills-list.js +28 -0
  354. package/dist/components/settings/skills-list.js.map +1 -0
  355. package/dist/components/settings/skills-tab.d.ts.map +1 -1
  356. package/dist/components/settings/skills-tab.js +65 -38
  357. package/dist/components/settings/skills-tab.js.map +1 -1
  358. package/dist/components/settings/tool-permissions-list.d.ts +18 -0
  359. package/dist/components/settings/tool-permissions-list.d.ts.map +1 -0
  360. package/dist/components/settings/tool-permissions-list.js +6 -0
  361. package/dist/components/settings/tool-permissions-list.js.map +1 -0
  362. package/dist/components/settings/tool-permissions.d.ts +2 -1
  363. package/dist/components/settings/tool-permissions.d.ts.map +1 -1
  364. package/dist/components/settings/tool-permissions.js +33 -16
  365. package/dist/components/settings/tool-permissions.js.map +1 -1
  366. package/dist/components/settings/web-search-chain.d.ts +41 -0
  367. package/dist/components/settings/web-search-chain.d.ts.map +1 -0
  368. package/dist/components/settings/web-search-chain.js +47 -0
  369. package/dist/components/settings/web-search-chain.js.map +1 -0
  370. package/dist/components/settings/web-search-settings.d.ts +4 -7
  371. package/dist/components/settings/web-search-settings.d.ts.map +1 -1
  372. package/dist/components/settings/web-search-settings.js +54 -76
  373. package/dist/components/settings/web-search-settings.js.map +1 -1
  374. package/dist/components/share/share-menu.d.ts.map +1 -1
  375. package/dist/components/share/share-menu.js +24 -4
  376. package/dist/components/share/share-menu.js.map +1 -1
  377. package/dist/components/voice/dictation-sheet.js +3 -3
  378. package/dist/components/voice/dictation-sheet.js.map +1 -1
  379. package/dist/components/voice/mic-button.js +1 -1
  380. package/dist/components/voice/mic-button.js.map +1 -1
  381. package/dist/components/voice/review-card.js +1 -1
  382. package/dist/components/voice/review-card.js.map +1 -1
  383. package/dist/config.d.ts +5 -2
  384. package/dist/config.d.ts.map +1 -1
  385. package/dist/config.js +15 -5
  386. package/dist/config.js.map +1 -1
  387. package/dist/connection.d.ts +12 -0
  388. package/dist/connection.d.ts.map +1 -0
  389. package/dist/connection.js +421 -0
  390. package/dist/connection.js.map +1 -0
  391. package/dist/default-root.d.ts +3 -0
  392. package/dist/default-root.d.ts.map +1 -0
  393. package/dist/default-root.js +16 -0
  394. package/dist/default-root.js.map +1 -0
  395. package/dist/hooks/use-color-scheme.d.ts +14 -0
  396. package/dist/hooks/use-color-scheme.d.ts.map +1 -0
  397. package/dist/hooks/use-color-scheme.js +37 -0
  398. package/dist/hooks/use-color-scheme.js.map +1 -0
  399. package/dist/hooks/use-hash-routes.d.ts.map +1 -1
  400. package/dist/hooks/use-hash-routes.js +4 -2
  401. package/dist/hooks/use-hash-routes.js.map +1 -1
  402. package/dist/hooks/use-media-query.d.ts +7 -0
  403. package/dist/hooks/use-media-query.d.ts.map +1 -0
  404. package/dist/hooks/use-media-query.js +34 -0
  405. package/dist/hooks/use-media-query.js.map +1 -0
  406. package/dist/hooks/use-share-intake.d.ts.map +1 -1
  407. package/dist/hooks/use-share-intake.js +37 -12
  408. package/dist/hooks/use-share-intake.js.map +1 -1
  409. package/dist/hooks/use-vpn-status.d.ts +1 -1
  410. package/dist/hooks/use-vpn-status.d.ts.map +1 -1
  411. package/dist/hooks/use-vpn-status.js +20 -16
  412. package/dist/hooks/use-vpn-status.js.map +1 -1
  413. package/dist/hooks/use-websocket.d.ts +5 -24
  414. package/dist/hooks/use-websocket.d.ts.map +1 -1
  415. package/dist/hooks/use-websocket.js +11 -382
  416. package/dist/hooks/use-websocket.js.map +1 -1
  417. package/dist/hooks/websocket-handlers/activity.d.ts +2 -2
  418. package/dist/hooks/websocket-handlers/activity.d.ts.map +1 -1
  419. package/dist/hooks/websocket-handlers/activity.js +4 -5
  420. package/dist/hooks/websocket-handlers/activity.js.map +1 -1
  421. package/dist/hooks/websocket-handlers/chat.d.ts +1 -0
  422. package/dist/hooks/websocket-handlers/chat.d.ts.map +1 -1
  423. package/dist/hooks/websocket-handlers/chat.js +27 -5
  424. package/dist/hooks/websocket-handlers/chat.js.map +1 -1
  425. package/dist/hooks/websocket-handlers/connection.d.ts.map +1 -1
  426. package/dist/hooks/websocket-handlers/connection.js +4 -6
  427. package/dist/hooks/websocket-handlers/connection.js.map +1 -1
  428. package/dist/hooks/websocket-handlers/mask.d.ts +1 -1
  429. package/dist/hooks/websocket-handlers/mask.d.ts.map +1 -1
  430. package/dist/hooks/websocket-handlers/mask.js +2 -3
  431. package/dist/hooks/websocket-handlers/mask.js.map +1 -1
  432. package/dist/hooks/websocket-handlers/provider.d.ts.map +1 -1
  433. package/dist/hooks/websocket-handlers/provider.js +4 -6
  434. package/dist/hooks/websocket-handlers/provider.js.map +1 -1
  435. package/dist/hooks/websocket-handlers/types.d.ts +6 -2
  436. package/dist/hooks/websocket-handlers/types.d.ts.map +1 -1
  437. package/dist/index.d.ts +5 -3
  438. package/dist/index.d.ts.map +1 -1
  439. package/dist/index.js +6 -3
  440. package/dist/index.js.map +1 -1
  441. package/dist/lib/api-client.d.ts +321 -0
  442. package/dist/lib/api-client.d.ts.map +1 -1
  443. package/dist/lib/api-client.js +243 -213
  444. package/dist/lib/api-client.js.map +1 -1
  445. package/dist/lib/backend.d.ts +19 -2
  446. package/dist/lib/backend.d.ts.map +1 -1
  447. package/dist/lib/backend.js +15 -9
  448. package/dist/lib/backend.js.map +1 -1
  449. package/dist/lib/diff.d.ts +8 -10
  450. package/dist/lib/diff.d.ts.map +1 -1
  451. package/dist/lib/diff.js +26 -53
  452. package/dist/lib/diff.js.map +1 -1
  453. package/dist/lib/format-time.d.ts +3 -0
  454. package/dist/lib/format-time.d.ts.map +1 -0
  455. package/dist/lib/format-time.js +25 -0
  456. package/dist/lib/format-time.js.map +1 -0
  457. package/dist/lib/light-dark.d.ts +37 -0
  458. package/dist/lib/light-dark.d.ts.map +1 -0
  459. package/dist/lib/light-dark.js +83 -0
  460. package/dist/lib/light-dark.js.map +1 -0
  461. package/dist/lib/mermaid-theme.d.ts +7 -2
  462. package/dist/lib/mermaid-theme.d.ts.map +1 -1
  463. package/dist/lib/mermaid-theme.js +125 -203
  464. package/dist/lib/mermaid-theme.js.map +1 -1
  465. package/dist/lib/passkeys.d.ts +6 -3
  466. package/dist/lib/passkeys.d.ts.map +1 -1
  467. package/dist/lib/passkeys.js +10 -4
  468. package/dist/lib/passkeys.js.map +1 -1
  469. package/dist/lib/push-registration.d.ts +10 -0
  470. package/dist/lib/push-registration.d.ts.map +1 -0
  471. package/dist/lib/push-registration.js +44 -0
  472. package/dist/lib/push-registration.js.map +1 -0
  473. package/dist/lib/share-intake.d.ts +2 -1
  474. package/dist/lib/share-intake.d.ts.map +1 -1
  475. package/dist/lib/share-intake.js +3 -3
  476. package/dist/lib/share-intake.js.map +1 -1
  477. package/dist/lib/share.d.ts +4 -3
  478. package/dist/lib/share.d.ts.map +1 -1
  479. package/dist/lib/share.js +6 -7
  480. package/dist/lib/share.js.map +1 -1
  481. package/dist/lib/single-key.d.ts +30 -0
  482. package/dist/lib/single-key.d.ts.map +1 -0
  483. package/dist/lib/single-key.js +45 -0
  484. package/dist/lib/single-key.js.map +1 -0
  485. package/dist/lib/tool-names.d.ts +8 -6
  486. package/dist/lib/tool-names.d.ts.map +1 -1
  487. package/dist/lib/tool-names.js +17 -7
  488. package/dist/lib/tool-names.js.map +1 -1
  489. package/dist/root-context.d.ts +229 -0
  490. package/dist/root-context.d.ts.map +1 -0
  491. package/dist/root-context.js +33 -0
  492. package/dist/root-context.js.map +1 -0
  493. package/dist/root.d.ts +38 -0
  494. package/dist/root.d.ts.map +1 -0
  495. package/dist/root.js +47 -0
  496. package/dist/root.js.map +1 -0
  497. package/dist/stores/activity-state.d.ts +29 -0
  498. package/dist/stores/activity-state.d.ts.map +1 -0
  499. package/dist/stores/activity-state.js +282 -0
  500. package/dist/stores/activity-state.js.map +1 -0
  501. package/dist/stores/activity-store.d.ts +10 -41
  502. package/dist/stores/activity-store.d.ts.map +1 -1
  503. package/dist/stores/activity-store.js +9 -271
  504. package/dist/stores/activity-store.js.map +1 -1
  505. package/dist/stores/chat-state.d.ts +212 -0
  506. package/dist/stores/chat-state.d.ts.map +1 -0
  507. package/dist/stores/chat-state.js +466 -0
  508. package/dist/stores/chat-state.js.map +1 -0
  509. package/dist/stores/chat-store.d.ts +4 -162
  510. package/dist/stores/chat-store.d.ts.map +1 -1
  511. package/dist/stores/chat-store.js +7 -418
  512. package/dist/stores/chat-store.js.map +1 -1
  513. package/dist/stores/connection-state.d.ts +40 -0
  514. package/dist/stores/connection-state.d.ts.map +1 -0
  515. package/dist/stores/connection-state.js +30 -0
  516. package/dist/stores/connection-state.js.map +1 -0
  517. package/dist/stores/connection-store.d.ts +4 -40
  518. package/dist/stores/connection-store.d.ts.map +1 -1
  519. package/dist/stores/connection-store.js +7 -27
  520. package/dist/stores/connection-store.js.map +1 -1
  521. package/dist/stores/create-stores.d.ts +23 -0
  522. package/dist/stores/create-stores.d.ts.map +1 -0
  523. package/dist/stores/create-stores.js +28 -0
  524. package/dist/stores/create-stores.js.map +1 -0
  525. package/dist/stores/file-state.d.ts +53 -0
  526. package/dist/stores/file-state.d.ts.map +1 -0
  527. package/dist/stores/file-state.js +341 -0
  528. package/dist/stores/file-state.js.map +1 -0
  529. package/dist/stores/file-store.d.ts +4 -52
  530. package/dist/stores/file-store.d.ts.map +1 -1
  531. package/dist/stores/file-store.js +7 -300
  532. package/dist/stores/file-store.js.map +1 -1
  533. package/dist/stores/graph-state.d.ts +95 -0
  534. package/dist/stores/graph-state.d.ts.map +1 -0
  535. package/dist/stores/graph-state.js +252 -0
  536. package/dist/stores/graph-state.js.map +1 -0
  537. package/dist/stores/graph-store.d.ts +7 -83
  538. package/dist/stores/graph-store.d.ts.map +1 -1
  539. package/dist/stores/graph-store.js +8 -249
  540. package/dist/stores/graph-store.js.map +1 -1
  541. package/dist/stores/mask-state.d.ts +21 -0
  542. package/dist/stores/mask-state.d.ts.map +1 -0
  543. package/dist/stores/mask-state.js +9 -0
  544. package/dist/stores/mask-state.js.map +1 -0
  545. package/dist/stores/mask-store.d.ts +4 -21
  546. package/dist/stores/mask-store.d.ts.map +1 -1
  547. package/dist/stores/mask-store.js +7 -6
  548. package/dist/stores/mask-store.js.map +1 -1
  549. package/dist/stores/principal-state.d.ts +16 -0
  550. package/dist/stores/principal-state.d.ts.map +1 -0
  551. package/dist/stores/principal-state.js +31 -0
  552. package/dist/stores/principal-state.js.map +1 -0
  553. package/dist/stores/principal-store.d.ts +5 -0
  554. package/dist/stores/principal-store.d.ts.map +1 -0
  555. package/dist/stores/principal-store.js +8 -0
  556. package/dist/stores/principal-store.js.map +1 -0
  557. package/dist/stores/provider-state.d.ts +24 -0
  558. package/dist/stores/provider-state.d.ts.map +1 -0
  559. package/dist/stores/provider-state.js +68 -0
  560. package/dist/stores/provider-state.js.map +1 -0
  561. package/dist/stores/provider-store.d.ts +4 -23
  562. package/dist/stores/provider-store.d.ts.map +1 -1
  563. package/dist/stores/provider-store.js +7 -64
  564. package/dist/stores/provider-store.js.map +1 -1
  565. package/dist/stores/share-state.d.ts +29 -0
  566. package/dist/stores/share-state.d.ts.map +1 -0
  567. package/dist/stores/share-state.js +21 -0
  568. package/dist/stores/share-state.js.map +1 -0
  569. package/dist/stores/share-store.d.ts +4 -28
  570. package/dist/stores/share-store.d.ts.map +1 -1
  571. package/dist/stores/share-store.js +7 -18
  572. package/dist/stores/share-store.js.map +1 -1
  573. package/dist/stores/store-environment.d.ts +10 -0
  574. package/dist/stores/store-environment.d.ts.map +1 -0
  575. package/dist/stores/store-environment.js +2 -0
  576. package/dist/stores/store-environment.js.map +1 -0
  577. package/dist/stores/ui-state.d.ts +71 -0
  578. package/dist/stores/ui-state.d.ts.map +1 -0
  579. package/dist/stores/ui-state.js +58 -0
  580. package/dist/stores/ui-state.js.map +1 -0
  581. package/dist/stores/ui-store.d.ts +4 -45
  582. package/dist/stores/ui-store.d.ts.map +1 -1
  583. package/dist/stores/ui-store.js +7 -36
  584. package/dist/stores/ui-store.js.map +1 -1
  585. package/dist/styles.css +1 -1
  586. package/dist/theme.css +150 -97
  587. package/dist/voice/asr-clients.d.ts +2 -1
  588. package/dist/voice/asr-clients.d.ts.map +1 -1
  589. package/dist/voice/asr-clients.js +16 -17
  590. package/dist/voice/asr-clients.js.map +1 -1
  591. package/dist/voice/use-dictation.d.ts.map +1 -1
  592. package/dist/voice/use-dictation.js +12 -8
  593. package/dist/voice/use-dictation.js.map +1 -1
  594. package/dist/voice/voice-state.d.ts +25 -0
  595. package/dist/voice/voice-state.d.ts.map +1 -0
  596. package/dist/voice/voice-state.js +29 -0
  597. package/dist/voice/voice-state.js.map +1 -0
  598. package/dist/voice/voice-store.d.ts +4 -25
  599. package/dist/voice/voice-store.d.ts.map +1 -1
  600. package/dist/voice/voice-store.js +7 -26
  601. package/dist/voice/voice-store.js.map +1 -1
  602. package/package.json +3 -2
  603. package/src/components/activity/activity-page.tsx +334 -160
  604. package/src/components/activity/activity-run-detail.tsx +81 -47
  605. package/src/components/activity/activity-run-list.tsx +27 -59
  606. package/src/components/activity/activity-views.tsx +155 -0
  607. package/src/components/activity/approval-card.tsx +80 -0
  608. package/src/components/activity/digest-card.tsx +25 -61
  609. package/src/components/activity/digest-summary.tsx +52 -0
  610. package/src/components/activity/push-switch.tsx +62 -0
  611. package/src/components/activity/push-toggle.tsx +51 -81
  612. package/src/components/activity/span-bits.tsx +8 -7
  613. package/src/components/chat/ask-user-card.tsx +292 -356
  614. package/src/components/chat/ask-user-typed.ts +77 -0
  615. package/src/components/chat/brain-markdown-links.tsx +4 -4
  616. package/src/components/chat/brain-markdown.tsx +4 -2
  617. package/src/components/chat/chat-page.tsx +38 -9
  618. package/src/components/chat/composer-view.tsx +194 -0
  619. package/src/components/chat/composer.tsx +117 -296
  620. package/src/components/chat/markdown-content.tsx +53 -2
  621. package/src/components/chat/mermaid-block.tsx +13 -5
  622. package/src/components/chat/mermaid-share.ts +8 -7
  623. package/src/components/chat/mermaid-viewer.tsx +3 -1
  624. package/src/components/chat/message-bubble.tsx +78 -94
  625. package/src/components/chat/message-share.ts +7 -7
  626. package/src/components/chat/renderers/bind.tsx +94 -0
  627. package/src/components/chat/renderers/brain-ui-tools.tsx +56 -0
  628. package/src/components/chat/renderers/claude-tools.tsx +3 -2
  629. package/src/components/chat/renderers/index.ts +15 -10
  630. package/src/components/chat/session-drawer.tsx +60 -138
  631. package/src/components/chat/session-list.tsx +113 -0
  632. package/src/components/chat/share-block.tsx +16 -12
  633. package/src/components/chat/share-card.tsx +2 -2
  634. package/src/components/chat/subagent-view.tsx +4 -4
  635. package/src/components/chat/tool-call-timeline.tsx +59 -22
  636. package/src/components/chat/tool-cards/block-card.tsx +145 -0
  637. package/src/components/chat/tool-cards/image-mask-card.tsx +214 -0
  638. package/src/components/chat/tool-cards/location-card.tsx +159 -0
  639. package/src/components/chat/tool-views.tsx +23 -73
  640. package/src/components/chat/transcript-turn.tsx +108 -0
  641. package/src/components/chat/use-chat-commands.ts +14 -16
  642. package/src/components/chat/welcome-state.tsx +36 -91
  643. package/src/components/connectivity/connection-gate.tsx +80 -9
  644. package/src/components/connectivity/login-form.tsx +122 -0
  645. package/src/components/connectivity/login-screen.tsx +45 -100
  646. package/src/components/dev/share-harness.tsx +2 -2
  647. package/src/components/files/file-panel.tsx +168 -0
  648. package/src/components/files/file-tree-view.tsx +127 -0
  649. package/src/components/files/file-tree.tsx +55 -109
  650. package/src/components/files/file-viewer-binary.tsx +3 -2
  651. package/src/components/files/file-viewer-frame.tsx +113 -0
  652. package/src/components/files/file-viewer.tsx +40 -95
  653. package/src/components/files/frontmatter-chips.tsx +42 -0
  654. package/src/components/files/frontmatter-panel.tsx +6 -71
  655. package/src/components/files/staleness.ts +29 -0
  656. package/src/components/graph/graph-canvas.tsx +24 -1
  657. package/src/components/graph/graph-controls-column.tsx +92 -0
  658. package/src/components/graph/graph-controls.tsx +83 -127
  659. package/src/components/graph/graph-form.tsx +183 -0
  660. package/src/components/graph/graph-maintenance.tsx +9 -14
  661. package/src/components/graph/graph-node-rail.tsx +147 -0
  662. package/src/components/graph/graph-page.tsx +189 -49
  663. package/src/components/graph/graph-scene.tsx +200 -30
  664. package/src/components/graph/lib/graph-helpers.ts +65 -43
  665. package/src/components/graph/node-card.tsx +64 -0
  666. package/src/components/graph/node-popover.tsx +28 -117
  667. package/src/components/graph/use-graph-theme.ts +69 -32
  668. package/src/components/graph/use-node-actions.ts +56 -0
  669. package/src/components/images/image-share.ts +4 -2
  670. package/src/components/images/image-viewer.tsx +3 -1
  671. package/src/components/images/mask-editor.tsx +7 -4
  672. package/src/components/layout/app-shell.tsx +7 -1
  673. package/src/components/layout/desktop-palette.tsx +151 -0
  674. package/src/components/layout/key-cap.tsx +15 -0
  675. package/src/components/layout/mobile-tab-bar.tsx +80 -157
  676. package/src/components/layout/shortcut-switch.tsx +32 -0
  677. package/src/components/layout/side-rail.tsx +70 -150
  678. package/src/components/layout/slide-panel.tsx +29 -2
  679. package/src/components/layout/theme.tsx +67 -0
  680. package/src/components/quick-actions/add-form.tsx +188 -0
  681. package/src/components/quick-actions/add-modal.tsx +68 -144
  682. package/src/components/quick-actions/search-modal.tsx +49 -19
  683. package/src/components/quick-actions/streaming-modal.tsx +44 -71
  684. package/src/components/quick-actions/streaming-output.tsx +112 -0
  685. package/src/components/quick-actions/whatsup-modal.tsx +38 -60
  686. package/src/components/settings/devices-agents-tab.tsx +139 -0
  687. package/src/components/settings/models-list.tsx +299 -0
  688. package/src/components/settings/models-tab.tsx +63 -337
  689. package/src/components/settings/one-time-agent-credential.tsx +131 -0
  690. package/src/components/settings/passkey-list.tsx +201 -0
  691. package/src/components/settings/passkey-tab.tsx +53 -197
  692. package/src/components/settings/pi-accounts-list.tsx +128 -0
  693. package/src/components/settings/pi-accounts.tsx +71 -170
  694. package/src/components/settings/principal-list.tsx +172 -0
  695. package/src/components/settings/settings-panel.tsx +245 -19
  696. package/src/components/settings/skills-list.tsx +276 -0
  697. package/src/components/settings/skills-tab.tsx +82 -269
  698. package/src/components/settings/tool-permissions-list.tsx +54 -0
  699. package/src/components/settings/tool-permissions.tsx +27 -46
  700. package/src/components/settings/web-search-chain.tsx +300 -0
  701. package/src/components/settings/web-search-settings.tsx +58 -328
  702. package/src/components/share/share-menu.tsx +19 -4
  703. package/src/components/voice/dictation-sheet.tsx +5 -5
  704. package/src/components/voice/mic-button.tsx +1 -1
  705. package/src/components/voice/review-card.tsx +1 -1
  706. package/src/config.ts +21 -7
  707. package/src/connection.ts +443 -0
  708. package/src/default-root.ts +16 -0
  709. package/src/hooks/use-color-scheme.ts +36 -0
  710. package/src/hooks/use-hash-routes.ts +4 -2
  711. package/src/hooks/use-media-query.ts +32 -0
  712. package/src/hooks/use-share-intake.ts +32 -12
  713. package/src/hooks/use-vpn-status.ts +23 -15
  714. package/src/hooks/use-websocket.ts +12 -426
  715. package/src/hooks/websocket-handlers/activity.ts +4 -5
  716. package/src/hooks/websocket-handlers/chat.ts +26 -5
  717. package/src/hooks/websocket-handlers/connection.ts +4 -6
  718. package/src/hooks/websocket-handlers/mask.ts +2 -3
  719. package/src/hooks/websocket-handlers/provider.ts +4 -6
  720. package/src/hooks/websocket-handlers/types.ts +6 -2
  721. package/src/index.ts +7 -3
  722. package/src/lib/api-client.ts +446 -365
  723. package/src/lib/backend.ts +20 -10
  724. package/src/lib/diff.ts +28 -62
  725. package/src/lib/format-time.ts +20 -0
  726. package/src/lib/light-dark.ts +83 -0
  727. package/src/lib/mermaid-theme.ts +183 -214
  728. package/src/lib/passkeys.ts +12 -4
  729. package/src/lib/push-registration.ts +46 -0
  730. package/src/lib/share-intake.ts +6 -3
  731. package/src/lib/share.ts +7 -4
  732. package/src/lib/single-key.ts +47 -0
  733. package/src/lib/tool-names.ts +31 -8
  734. package/src/root-context.tsx +40 -0
  735. package/src/root.ts +83 -0
  736. package/src/stores/activity-state.ts +295 -0
  737. package/src/stores/activity-store.ts +11 -285
  738. package/src/stores/chat-state.ts +795 -0
  739. package/src/stores/chat-store.ts +11 -705
  740. package/src/stores/connection-state.ts +78 -0
  741. package/src/stores/connection-store.ts +11 -76
  742. package/src/stores/create-stores.ts +31 -0
  743. package/src/stores/file-state.ts +399 -0
  744. package/src/stores/file-store.ts +9 -360
  745. package/src/stores/graph-state.ts +368 -0
  746. package/src/stores/graph-store.ts +10 -355
  747. package/src/stores/mask-state.ts +30 -0
  748. package/src/stores/mask-store.ts +10 -27
  749. package/src/stores/principal-state.ts +42 -0
  750. package/src/stores/principal-store.ts +11 -0
  751. package/src/stores/provider-state.ts +103 -0
  752. package/src/stores/provider-store.ts +10 -95
  753. package/src/stores/share-state.ts +56 -0
  754. package/src/stores/share-store.ts +11 -54
  755. package/src/stores/store-environment.ts +10 -0
  756. package/src/stores/ui-state.ts +143 -0
  757. package/src/stores/ui-store.ts +11 -93
  758. package/src/styles.css +4 -1
  759. package/src/theme.css +150 -97
  760. package/src/voice/asr-clients.ts +17 -17
  761. package/src/voice/use-dictation.ts +11 -8
  762. package/src/voice/voice-state.ts +57 -0
  763. package/src/voice/voice-store.ts +11 -55
@@ -1,21 +1,21 @@
1
- import { useEffect } from "react";
1
+ import { defaultRoot } from "../default-root.js";
2
+ import { useBrainUiRoot } from "../root-context.js";
3
+ import type { BrainUiRoot } from "../root.js";
4
+ import { useEffect, useState } from "react";
2
5
  import {
3
- useConnectionStore,
4
6
  type VpnStatus,
5
7
  } from "../stores/connection-store.js";
6
- import { getBackendUrl } from "../lib/backend.js";
7
8
 
8
9
  const POLL_INTERVAL = 15_000;
9
10
  // Tighter cadence while offline so recovery is near-immediate
10
11
  const OFFLINE_POLL_INTERVAL = 3_000;
11
12
  const TIMEOUT_MS = 5_000;
12
- let activeRecheck: (() => void) | null = null;
13
13
 
14
- async function fetchVpnStatus(): Promise<VpnStatus> {
14
+ async function fetchVpnStatus(root: BrainUiRoot): Promise<VpnStatus> {
15
15
  const controller = new AbortController();
16
16
  const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);
17
17
  try {
18
- const res = await fetch(getBackendUrl("/api/vpn-check"), {
18
+ const res = await root.request(root.backendUrl("/api/vpn-check"), {
19
19
  signal: controller.signal,
20
20
  });
21
21
 
@@ -35,10 +35,13 @@ async function fetchVpnStatus(): Promise<VpnStatus> {
35
35
  * the only writer of vpnStatus and serializes this with its scheduled checks.
36
36
  */
37
37
  export function recheckVpnStatus(): void {
38
- activeRecheck?.();
38
+ defaultRoot.recheckVpn?.();
39
39
  }
40
40
 
41
41
  export function useVpnStatus() {
42
+ const root = useBrainUiRoot();
43
+ const [successfulProbe, setSuccessfulProbe] = useState({ root, count: 0 });
44
+
42
45
  useEffect(() => {
43
46
  let timer: ReturnType<typeof setTimeout> | undefined;
44
47
  let inFlight = false;
@@ -52,18 +55,21 @@ export function useVpnStatus() {
52
55
  return;
53
56
  }
54
57
  inFlight = true;
55
- const opensAtStart = useConnectionStore.getState().socketOpens;
58
+ const opensAtStart = root.stores.connection.getState().socketOpens;
56
59
  try {
57
- const status = await fetchVpnStatus();
60
+ const status = await fetchVpnStatus(root);
58
61
  // A socket that reached `open` while this probe was in flight is newer
59
62
  // reachability evidence than a failure the probe was started for.
60
63
  // Counting opens rather than sampling wsStatus twice also catches a
61
64
  // drop and a replacement open inside one probe, where both samples
62
65
  // read "connected".
63
66
  const socketOpenedDuringCheck =
64
- useConnectionStore.getState().socketOpens !== opensAtStart;
67
+ root.stores.connection.getState().socketOpens !== opensAtStart;
65
68
  if (!disposed && !(socketOpenedDuringCheck && status !== "connected")) {
66
- useConnectionStore.getState().setVpnStatus(status);
69
+ root.stores.connection.getState().setVpnStatus(status);
70
+ if (status === "connected") {
71
+ setSuccessfulProbe((previous) => ({ root, count: previous.root === root ? previous.count + 1 : 1 }));
72
+ }
67
73
  }
68
74
  } finally {
69
75
  inFlight = false;
@@ -73,7 +79,7 @@ export function useVpnStatus() {
73
79
  recheckRequested = false;
74
80
  void check();
75
81
  } else {
76
- const status = useConnectionStore.getState().vpnStatus;
82
+ const status = root.stores.connection.getState().vpnStatus;
77
83
  // Auth required but no valid session is still a reachable server.
78
84
  const reachable = status === "connected" || status === "unauthorized";
79
85
  timer = setTimeout(
@@ -88,7 +94,7 @@ export function useVpnStatus() {
88
94
  // Re-check immediately when the network returns or the PWA is foregrounded
89
95
  // instead of waiting out the poll interval.
90
96
  const recheckNow = () => void check();
91
- activeRecheck = recheckNow;
97
+ const removeRecheck = root.registerVpnRecheck(recheckNow);
92
98
  const onVisible = () => {
93
99
  if (document.visibilityState === "visible") void check();
94
100
  };
@@ -100,9 +106,11 @@ export function useVpnStatus() {
100
106
  return () => {
101
107
  disposed = true;
102
108
  clearTimeout(timer);
103
- if (activeRecheck === recheckNow) activeRecheck = null;
109
+ removeRecheck();
104
110
  window.removeEventListener("online", recheckNow);
105
111
  document.removeEventListener("visibilitychange", onVisible);
106
112
  };
107
- }, []);
113
+ }, [root]);
114
+
115
+ return successfulProbe.root === root ? successfulProbe.count : 0;
108
116
  }
@@ -1,432 +1,18 @@
1
- import { useEffect, useRef, useCallback } from "react";
2
- import {
3
- BrainUiClient,
4
- type WebSocketClose,
5
- } from "@schlessera/brain-ui-sdk/client";
6
- import { useConnectionStore } from "../stores/connection-store.js";
7
- import { useChatStore, activeChat, type ChatKey } from "../stores/chat-store.js";
8
- import { useActivityStore, loadSessionActivityHistory } from "../stores/activity-store.js";
9
- import { getWsUrl } from "../lib/backend.js";
10
- import type {
11
- ServerMessage,
12
- ClientMessage,
13
- ServerLocationRequest,
14
- } from "@schlessera/brain-ui-sdk/protocol";
15
- import { dispatchServerMessage } from "./websocket-handlers/index.js";
16
- import { runStateForFrame } from "./websocket-handlers/chat.js";
17
- import { recheckVpnStatus } from "./use-vpn-status.js";
18
- import { REFUSAL_ATTEMPTS } from "../components/connectivity/connection-state.js";
19
-
1
+ import { useEffect, useCallback } from "react";
2
+ import type { ClientMessage, ServerMessage } from "@schlessera/brain-ui-sdk/protocol";
3
+ import { defaultRoot } from "../default-root.js";
4
+ import { useBrainUiRoot } from "../root-context.js";
20
5
  export { runStateForFrame } from "./websocket-handlers/chat.js";
21
6
 
22
- /**
23
- * Does this frame announce the identity of the conversation THIS client just
24
- * started?
25
- *
26
- * The old test was `session_info || result` for any unknown session, which
27
- * adopted whichever arrived first — an older background turn finishing, or
28
- * another client's new session, would capture the user's draft and bind it to
29
- * a transcript they never wrote. `draftId` is minted per draft turn and echoed
30
- * on `session_info`, so a match is proof.
31
- *
32
- * A server too old to echo it sends no `draftId`, and the pre-existing
33
- * behaviour applies rather than the draft never binding at all: correctness
34
- * where the information exists, compatibility where it does not.
35
- */
36
- function isOurDraftAnnouncement(
37
- state: ReturnType<typeof useChatStore.getState>,
38
- msg: ServerMessage
39
- ): boolean {
40
- if (msg.type !== "session_info" && msg.type !== "result") return false;
41
- const pending = state.pendingDraftId;
42
- if (msg.type === "session_info" && msg.draftId) return msg.draftId === pending;
43
- // No echo to compare against.
44
- return true;
45
- }
46
-
47
- /**
48
- * Lazily open a session-scoped activity subscription (live subagent rows,
49
- * server-stamped tool timing). Idempotent per connection; the subscribed set
50
- * resets when a new socket's server_hello arrives.
51
- */
52
- function ensureActivitySubscription(sessionId: string | null | undefined): void {
53
- if (!sessionId) return;
54
- const activity = useActivityStore.getState();
55
- if (!activity.supported || activity.subscribed[sessionId]) return;
56
- activity.markSubscribed(sessionId);
57
- wsClient?.send({ type: "activity_subscribe", view: "session", sessionId });
58
- // The subscription snapshot carries OPEN runs; finished runs (history
59
- // timing, past fan-outs) come from the REST side.
60
- void loadSessionActivityHistory(sessionId);
61
- }
62
-
63
- /**
64
- * Text and thinking deltas waiting to be applied, per buffer.
65
- *
66
- * A model streams tokens far faster than the display refreshes, and each socket
67
- * frame arrives in its own macrotask, so React cannot batch them: one token was
68
- * one store write, one render and one markdown re-parse of the growing message.
69
- * Coalescing a frame's worth of tokens into a single write costs nothing
70
- * visually — the screen could not have shown the intermediate states anyway.
71
- *
72
- * Consecutive same-kind chunks merge, so a burst of text becomes ONE appendText
73
- * rather than one per token. Kind changes start a new chunk, which is what keeps
74
- * interleaved thinking and text in their true chronological order.
75
- */
76
- type PendingDelta = { kind: "text" | "thinking"; text: string };
77
- const pendingDeltas = new Map<ChatKey, PendingDelta[]>();
78
- let flushScheduled = false;
79
-
80
- /**
81
- * Apply every buffered delta, in arrival order, and clear the buffer.
82
- *
83
- * Exported so tests can force the frame rather than wait for one; production
84
- * code never needs to call it, because every path that reads the transcript
85
- * flushes first.
86
- */
87
- export function flushChatDeltas(): void {
88
- flushDeltas();
89
- }
90
-
91
- function flushDeltas(): void {
92
- flushScheduled = false;
93
- if (pendingDeltas.size === 0) return;
94
- const batches = [...pendingDeltas.entries()];
95
- pendingDeltas.clear();
96
- const state = useChatStore.getState();
97
- for (const [key, chunks] of batches) {
98
- for (const chunk of chunks) {
99
- if (chunk.kind === "text") state.appendText(key, chunk.text);
100
- else state.appendThinking(key, chunk.text);
101
- }
102
- }
103
- }
104
-
105
- function enqueueDelta(key: ChatKey, kind: PendingDelta["kind"], text: string): void {
106
- const chunks = pendingDeltas.get(key);
107
- if (!chunks) {
108
- pendingDeltas.set(key, [{ kind, text }]);
109
- } else {
110
- const last = chunks[chunks.length - 1];
111
- if (last.kind === kind) last.text += text;
112
- else chunks.push({ kind, text });
113
- }
114
- // Outside a browser (unit tests, SSR) there is no frame to wait for, so apply
115
- // straight away and keep the handler's behaviour synchronous.
116
- if (typeof requestAnimationFrame !== "function") {
117
- flushDeltas();
118
- return;
119
- }
120
- if (!flushScheduled) {
121
- flushScheduled = true;
122
- requestAnimationFrame(flushDeltas);
123
- }
124
- }
125
-
126
- export function handleServerMessage(msg: ServerMessage) {
127
- // Every frame that is not itself a delta must see the transcript fully
128
- // applied: the demux below reads buffer state, and the store records parts in
129
- // arrival order, so a tool call landing ahead of buffered text would reorder
130
- // the message.
131
- if (msg.type !== "text_delta" && msg.type !== "thinking_delta") flushDeltas();
132
-
133
- const state = useChatStore.getState();
134
-
135
- // Activity stream frames feed their own store and never touch chat state.
136
- if (
137
- msg.type === "server_hello" ||
138
- msg.type === "activity_snapshot" ||
139
- msg.type === "activity_delta"
140
- ) {
141
- const key = state.activeSessionId;
142
- dispatchServerMessage(msg, {
143
- state,
144
- frameSessionId: undefined,
145
- key,
146
- buffer: () => (key === null ? state.draft : state.buffers[key]),
147
- enqueueDelta,
148
- ensureActivitySubscription,
149
- requestBrowserLocation,
150
- resyncIfNeeded,
151
- coldResumeIfNeeded,
152
- markHistoryReplaced,
153
- });
154
- return;
155
- }
156
-
157
- // Parallel-session demux (per-session buffers). Every frame is scoped by
158
- // sessionId; a scoped frame lands in ITS session's buffer, so a background
159
- // session's transcript keeps accumulating while another one is in view.
160
- // Frames without a sessionId (legacy single-session servers, or a new
161
- // session's pre-binding frames) apply to the buffer in view.
162
- const frameSessionId = (msg as { sessionId?: string }).sessionId;
163
- if (frameSessionId) {
164
- // `detail` on a queued status is the host's queue-pressure note; it rides
165
- // along so the session's badge can show WHY it is queued deep.
166
- const queueNote =
167
- msg.type === "status" && msg.status === "queued" ? msg.detail : undefined;
168
- state.setRunState(frameSessionId, runStateForFrame(msg), queueNote);
169
- }
170
-
171
- // Resolve the target buffer key for this frame.
172
- let key: ChatKey;
173
- if (!frameSessionId) {
174
- key = state.activeSessionId; // null = the draft view
175
- } else if (state.buffers[frameSessionId]) {
176
- key = frameSessionId;
177
- } else if (state.draft && isOurDraftAnnouncement(state, msg)) {
178
- // A draft run just got its server identity: adopt the draft buffer.
179
- state.bindDraftSession(frameSessionId);
180
- key = frameSessionId;
181
- } else if (msg.type === "session_info" && frameSessionId === state.activeSessionId) {
182
- // The ACTIVE session announced itself but has no buffer yet — the cold
183
- // reattach case (PWA relaunch mid-turn; the server may skip the history
184
- // frame when a first turn has no history yet). Materialize the buffer so
185
- // this session_info and every following delta land instead of vanishing.
186
- state.setActiveSession(frameSessionId);
187
- key = frameSessionId;
188
- } else if (msg.type === "session_history") {
189
- // History replay may create a buffer (cold resume / reattach).
190
- key = frameSessionId;
191
- } else {
192
- // Scoped frame for a session with no buffer (never opened, or evicted):
193
- // the badge above is all we track. The transcript heals via
194
- // session_resume when the user opens it.
195
- return;
196
- }
197
-
198
- const buffer = () => {
199
- const s = useChatStore.getState();
200
- return key === null ? s.draft : s.buffers[key];
201
- };
202
-
203
- dispatchServerMessage(msg, {
204
- state,
205
- frameSessionId,
206
- key,
207
- buffer,
208
- enqueueDelta,
209
- ensureActivitySubscription,
210
- requestBrowserLocation,
211
- resyncIfNeeded,
212
- coldResumeIfNeeded,
213
- markHistoryReplaced,
214
- });
215
- }
216
-
217
- /**
218
- * The server asked the browser for its location (the agent called
219
- * `get_current_location`). Read `navigator.geolocation` and reply over the same
220
- * requestId. The browser shows its own permission prompt on first use; a denial,
221
- * timeout, or unavailable position comes back as a `location_error` that the
222
- * server turns into a tool error for the agent.
223
- */
224
- function requestBrowserLocation(msg: ServerLocationRequest) {
225
- const { requestId } = msg;
226
- if (typeof navigator === "undefined" || !navigator.geolocation) {
227
- wsClient?.send({
228
- type: "location_error",
229
- requestId,
230
- code: 0,
231
- message: "Geolocation is not available in this browser.",
232
- });
233
- return;
234
- }
235
- const opts = msg.options ?? {};
236
- navigator.geolocation.getCurrentPosition(
237
- (pos) => {
238
- wsClient?.send({
239
- type: "location_response",
240
- requestId,
241
- coords: {
242
- latitude: pos.coords.latitude,
243
- longitude: pos.coords.longitude,
244
- accuracy: pos.coords.accuracy,
245
- altitude: pos.coords.altitude,
246
- altitudeAccuracy: pos.coords.altitudeAccuracy,
247
- heading: pos.coords.heading,
248
- speed: pos.coords.speed,
249
- },
250
- timestamp: pos.timestamp,
251
- });
252
- },
253
- (err) => {
254
- wsClient?.send({
255
- type: "location_error",
256
- requestId,
257
- code: err.code,
258
- message: err.message || "Failed to retrieve location.",
259
- });
260
- },
261
- {
262
- enableHighAccuracy: opts.enableHighAccuracy ?? false,
263
- timeout: opts.timeoutMs ?? 15000,
264
- maximumAge: opts.maximumAgeMs ?? 60000,
265
- }
266
- );
267
- }
268
-
269
- // Reconnection bookkeeping: after a WS drop, the rendered transcript may have
270
- // gaps (deltas streamed while offline are lost). We heal by replaying the
271
- // authoritative session history — immediately if nothing is streaming, or
272
- // once the in-flight turn settles (result / idle status). The pending resync
273
- // is keyed to the session that needs healing (the one that was active at the
274
- // reconnect), so a background session settling first cannot consume it.
275
- let wasDisconnected = false;
276
- let resyncSessionId: string | null = null;
277
-
278
- function handleSocketClose(close: WebSocketClose): void {
279
- const connection = useConnectionStore.getState();
280
- connection.recordWsClose(close.opened, close.code);
281
- if (
282
- !close.opened &&
283
- useConnectionStore.getState().handshakeFailures >= REFUSAL_ATTEMPTS
284
- ) {
285
- recheckVpnStatus();
286
- }
287
- }
288
-
289
- function resyncIfNeeded(sessionId: string | null) {
290
- if (!resyncSessionId || !sessionId || sessionId !== resyncSessionId) return;
291
- resyncSessionId = null;
292
- wsClient?.send({ type: "session_resume", sessionId });
293
- }
294
-
295
- // A cold page / PWA relaunch restores only the stored session id, not the
296
- // transcript. The server pushes a snapshot on connect only while a session is
297
- // actively running; when it's idle (the common "agent finished while the phone
298
- // slept" case) nothing arrives, so the client must fetch the finished
299
- // session's history itself. Guarded to fire at most once per session id per
300
- // connection — an empty session would otherwise re-trigger on every idle
301
- // status and loop.
302
- let coldResumedSessionId: string | null = null;
303
-
304
- function markHistoryReplaced(key: ChatKey): void {
305
- if (key !== null && key === resyncSessionId) resyncSessionId = null;
306
- coldResumedSessionId = key;
307
- }
308
-
309
- function coldResumeIfNeeded(sessionId: string | null, messageCount: number) {
310
- if (!sessionId || messageCount > 0) return;
311
- if (coldResumedSessionId === sessionId) return;
312
- coldResumedSessionId = sessionId;
313
- wsClient?.send({ type: "session_resume", sessionId });
314
- }
315
-
316
- function handleStatusChange(status: "connecting" | "connected" | "disconnected") {
317
- useConnectionStore.getState().setWsStatus(status);
318
-
319
- if (status === "connected") {
320
- useConnectionStore.getState().noteSocketOpen();
321
- }
322
-
323
- // A status change can be followed by a history replay that rewrites the
324
- // buffer, so land whatever is still buffered before anything reads it. In a
325
- // hidden tab requestAnimationFrame does not run at all, which is exactly the
326
- // case where deltas could otherwise sit unapplied across a reconnect.
327
- flushDeltas();
328
-
329
- if (status === "disconnected") {
330
- wasDisconnected = true;
331
- // Allow a fresh cold-resume attempt after we reconnect.
332
- coldResumedSessionId = null;
333
- } else if (status === "connected" && wasDisconnected) {
334
- wasDisconnected = false;
335
- const chat = useChatStore.getState();
336
- const active = activeChat(chat);
337
- if (chat.activeSessionId && active.messages.length > 0) {
338
- resyncSessionId = chat.activeSessionId;
339
- // Not mid-stream: replay right away. Mid-stream: the flag holds until
340
- // the running turn finishes (result or idle status).
341
- if (!active.isStreaming) {
342
- resyncIfNeeded(chat.activeSessionId);
343
- }
344
- }
345
- }
346
- }
347
-
348
- // Singleton client - survives React re-renders
349
- let wsClient: BrainUiClient | null = null;
350
-
351
- /**
352
- * Send on the live socket from outside a component.
353
- *
354
- * `useWebSocket()` OWNS the socket — its construction guard is a per-instance
355
- * ref, so a second caller would build a second client, overwrite this
356
- * singleton, and orphan the first; unmounting either one would then close the
357
- * socket for both. Anything that needs to send but not to own (the share
358
- * intake) goes through here instead of calling the hook again.
359
- *
360
- * Returns false when there is no open socket: `send` drops silently in that
361
- * case and a caller that just staged an upload needs to know.
362
- */
363
- export function sendClientMessage(msg: ClientMessage): boolean {
364
- if (!wsClient) return false;
365
- if (useConnectionStore.getState().wsStatus !== "connected") return false;
366
- wsClient.send(msg);
367
- return true;
368
- }
369
-
370
- /** Retry the singleton socket immediately, skipping any remaining backoff. */
371
- export function reconnectWebSocketNow(): void {
372
- wsClient?.reconnectNow();
373
- }
7
+ /** Default-app entry points for callers outside React. */
8
+ export function handleServerMessage(message: ServerMessage) { defaultRoot.connection.handleServerMessage(message); }
9
+ export function flushChatDeltas() { defaultRoot.connection.flushChatDeltas(); }
10
+ export function sendClientMessage(message: ClientMessage) { return defaultRoot.connection.send(message); }
11
+ export function reconnectWebSocketNow() { defaultRoot.connection.reconnectNow(); }
374
12
 
375
13
  export function useWebSocket() {
376
- const initialized = useRef(false);
377
-
378
- useEffect(() => {
379
- if (initialized.current) return;
380
- initialized.current = true;
381
- let disposed = false;
382
- useConnectionStore.getState().noteSocketOpen();
383
-
384
- wsClient = new BrainUiClient({
385
- url: getWsUrl(),
386
- // One handler with a shared preamble, rather than sixteen copies of the
387
- // session-buffer demux — see handleServerMessage.
388
- handlers: { onAny: handleServerMessage },
389
- onStatusChange: handleStatusChange,
390
- onClose: (close) => {
391
- if (!disposed) handleSocketClose(close);
392
- },
393
- // A frame the SDK refused. Surfaced rather than logged into a console
394
- // nobody is attached to; the server-side counterpart is the
395
- // ws.frames.dropped counter.
396
- onProtocolError: (err) => {
397
- useConnectionStore
398
- .getState()
399
- .reportError(
400
- "PROTOCOL_ERROR",
401
- err.frameType
402
- ? `Dropped a ${err.frameType} frame: ${err.detail}`
403
- : `Dropped an unreadable frame: ${err.detail}`
404
- );
405
- },
406
- });
407
- wsClient.connect();
408
-
409
- // Skip the exponential backoff when the network demonstrably returns.
410
- const reconnectNow = () => wsClient?.reconnectNow();
411
- const onVisible = () => {
412
- if (document.visibilityState === "visible") wsClient?.reconnectNow();
413
- };
414
- window.addEventListener("online", reconnectNow);
415
- document.addEventListener("visibilitychange", onVisible);
416
-
417
- return () => {
418
- disposed = true;
419
- window.removeEventListener("online", reconnectNow);
420
- document.removeEventListener("visibilitychange", onVisible);
421
- wsClient?.close();
422
- wsClient = null;
423
- initialized.current = false;
424
- };
425
- }, []);
426
-
427
- const send = useCallback((msg: ClientMessage) => {
428
- wsClient?.send(msg);
429
- }, []);
430
-
14
+ const root = useBrainUiRoot();
15
+ useEffect(() => root.connection.connect(), [root]);
16
+ const send = useCallback((message: ClientMessage) => root.connection.send(message), [root]);
431
17
  return { send };
432
18
  }
@@ -1,13 +1,12 @@
1
- import { useActivityStore } from "../../stores/activity-store.js";
2
1
  import type { ServerMessageHandlerMap } from "./types.js";
3
2
 
4
3
  type ActivityFrame = "activity_snapshot" | "activity_delta";
5
4
 
6
5
  export const activityFrameHandlers = {
7
- activity_snapshot: (msg) => {
8
- useActivityStore.getState().applySnapshot(msg);
6
+ activity_snapshot: (msg, context) => {
7
+ context.stores.activity.getState().applySnapshot(msg);
9
8
  },
10
- activity_delta: (msg) => {
11
- useActivityStore.getState().applyDelta(msg);
9
+ activity_delta: (msg, context) => {
10
+ context.stores.activity.getState().applyDelta(msg);
12
11
  },
13
12
  } satisfies ServerMessageHandlerMap<ActivityFrame>;
@@ -1,4 +1,4 @@
1
- import { activeChat, useChatStore } from "../../stores/chat-store.js";
1
+ import { activeChat } from "../../stores/chat-state.js";
2
2
  import type { ChatMessage, ToolCall, AskUserExchange } from "../../stores/chat-store.js";
3
3
  import type {
4
4
  AskUserQuestion,
@@ -18,6 +18,7 @@ type ChatFrame =
18
18
  | "tool_result"
19
19
  | "ask_user_request"
20
20
  | "result"
21
+ | "message_blocks"
21
22
  | "session_history"
22
23
  | "status";
23
24
 
@@ -56,10 +57,20 @@ function convertHistoryMessage(msg: SessionHistoryMessage): ChatMessage {
56
57
  timestamp: Date.now(),
57
58
  ...(askUserExchanges ? { askUserExchanges } : {}),
58
59
  ...(msg.attachmentCount ? { attachmentCount: msg.attachmentCount } : {}),
60
+ ...(msg.blocks && msg.blocks.length > 0 ? { blocks: msg.blocks } : {}),
59
61
  };
60
62
  }
61
63
 
62
- /** Rebuild ask_user exchanges from a resumed message's tool calls. */
64
+ /**
65
+ * Rebuild ask_user exchanges from a resumed message's tool calls.
66
+ *
67
+ * The persisted tool output is `{answers, annotations}` (Claude) or the bare
68
+ * answers map (pi). Neither carries whether the answer was chosen from the
69
+ * options or typed into the composer (`AskUserExchange.typed`), nor when it
70
+ * was given, so a resumed exchange comes back as a plain `answered` one with
71
+ * no time. Carrying `typed` would mean widening the `ask_user` response —
72
+ * a `CONTRACT:` change — not guessing here.
73
+ */
63
74
  function isBareAnswersMap(v: unknown): v is Record<string, string> {
64
75
  return (
65
76
  !!v &&
@@ -117,14 +128,16 @@ export const chatFrameHandlers = {
117
128
  // Opening the bubble stays immediate — the first token should show a
118
129
  // message starting, and every later delta needs isStreaming to be true.
119
130
  if (!context.buffer()?.isStreaming) {
120
- context.state.startAssistantMessage(context.key);
131
+ context.state.startAssistantMessage(context.key, context.frameTurnId);
121
132
  }
133
+ if (context.frameTurnId) context.state.stampTurn(context.key, context.frameTurnId);
122
134
  context.enqueueDelta(context.key, "text", msg.text);
123
135
  },
124
136
  thinking_delta: (msg, context) => {
125
137
  if (!context.buffer()?.isStreaming) {
126
- context.state.startAssistantMessage(context.key);
138
+ context.state.startAssistantMessage(context.key, context.frameTurnId);
127
139
  }
140
+ if (context.frameTurnId) context.state.stampTurn(context.key, context.frameTurnId);
128
141
  context.enqueueDelta(context.key, "thinking", msg.text);
129
142
  },
130
143
  tool_use_start: (msg, context) => {
@@ -169,6 +182,14 @@ export const chatFrameHandlers = {
169
182
  context.state.finishAssistantMessage(context.key);
170
183
  context.resyncIfNeeded(msg.sessionId);
171
184
  },
185
+ message_blocks: (msg, context) => {
186
+ // Arrives after `result`, for the turn's own assistant message. An
187
+ // answer never waits on it: the markdown is already on screen, and this
188
+ // only says which spans to draw as blocks (D42). Targeted by the turn
189
+ // the frame belongs to: a queued follow-up may already have opened a
190
+ // newer assistant message by the time the pass returns.
191
+ context.state.setMessageBlocks(context.key, msg.blocks, context.frameTurnId);
192
+ },
172
193
  session_history: (msg, context) => {
173
194
  const converted = msg.messages.map(convertHistoryMessage);
174
195
  if (msg.append) {
@@ -194,7 +215,7 @@ export const chatFrameHandlers = {
194
215
  // THIS frame's session: a background session settling must not consume
195
216
  // (or trigger) the active session's pending resync.
196
217
  if (msg.status === "idle" || msg.status === "cancelled") {
197
- const current = useChatStore.getState();
218
+ const current = context.stores.chat.getState();
198
219
  context.resyncIfNeeded(context.frameSessionId ?? current.activeSessionId);
199
220
  // Cold load: we hold a stored session id but an empty transcript and
200
221
  // the server is idle (so it sent no snapshot). Fetch the history.
@@ -1,16 +1,14 @@
1
- import { useActivityStore } from "../../stores/activity-store.js";
2
- import { useConnectionStore } from "../../stores/connection-store.js";
3
1
  import type { ServerMessageHandlerMap } from "./types.js";
4
2
 
5
3
  type ConnectionFrame = "server_hello" | "location_request" | "error";
6
4
 
7
5
  export const connectionFrameHandlers = {
8
6
  server_hello: (msg, context) => {
9
- useActivityStore.getState().setSupported(msg.capabilities?.activity === true);
7
+ context.stores.activity.getState().setSupported(msg.capabilities?.activity === true);
10
8
  // A new hello means a new connection: server-side subscriptions are gone.
11
- useActivityStore.getState().resetSubscriptions();
9
+ context.stores.activity.getState().resetSubscriptions();
12
10
  // …and view-owned subscriptions (the Activity index) must re-send too.
13
- useActivityStore.getState().bumpConnectionEpoch();
11
+ context.stores.activity.getState().bumpConnectionEpoch();
14
12
  context.ensureActivitySubscription(context.state.activeSessionId);
15
13
  },
16
14
  location_request: (msg, context) => {
@@ -21,7 +19,7 @@ export const connectionFrameHandlers = {
21
19
  // message is streaming, and this used to be the whole handler — so an
22
20
  // error arriving between turns (a rejected frame, a failed resume) was
23
21
  // dropped as silently on the client as it was on the server.
24
- useConnectionStore.getState().reportError(msg.code, msg.message);
22
+ context.stores.connection.getState().reportError(msg.code, msg.message);
25
23
  if (context.buffer()?.isStreaming) {
26
24
  context.state.appendText(context.key, `\n\n**Error:** ${msg.message}`);
27
25
  context.state.finishAssistantMessage(context.key);