@schlessera/brain-ui-react 0.35.0 → 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 (755) hide show
  1. package/README.md +82 -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 +32 -32
  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 +13 -2
  136. package/dist/components/chat/tool-views.d.ts.map +1 -1
  137. package/dist/components/chat/tool-views.js +20 -22
  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 +27 -21
  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 +4 -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 +23 -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 +4 -3
  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 +39 -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 +6 -1
  312. package/dist/components/settings/devices-agents-tab.d.ts.map +1 -1
  313. package/dist/components/settings/devices-agents-tab.js +55 -20
  314. package/dist/components/settings/devices-agents-tab.js.map +1 -1
  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.js +1 -1
  324. package/dist/components/settings/one-time-agent-credential.js.map +1 -1
  325. package/dist/components/settings/passkey-list.d.ts +35 -0
  326. package/dist/components/settings/passkey-list.d.ts.map +1 -0
  327. package/dist/components/settings/passkey-list.js +34 -0
  328. package/dist/components/settings/passkey-list.js.map +1 -0
  329. package/dist/components/settings/passkey-tab.d.ts +3 -0
  330. package/dist/components/settings/passkey-tab.d.ts.map +1 -1
  331. package/dist/components/settings/passkey-tab.js +53 -45
  332. package/dist/components/settings/passkey-tab.js.map +1 -1
  333. package/dist/components/settings/pi-accounts-list.d.ts +27 -0
  334. package/dist/components/settings/pi-accounts-list.d.ts.map +1 -0
  335. package/dist/components/settings/pi-accounts-list.js +15 -0
  336. package/dist/components/settings/pi-accounts-list.js.map +1 -0
  337. package/dist/components/settings/pi-accounts.d.ts +3 -0
  338. package/dist/components/settings/pi-accounts.d.ts.map +1 -1
  339. package/dist/components/settings/pi-accounts.js +73 -55
  340. package/dist/components/settings/pi-accounts.js.map +1 -1
  341. package/dist/components/settings/principal-list.d.ts +37 -0
  342. package/dist/components/settings/principal-list.d.ts.map +1 -0
  343. package/dist/components/settings/principal-list.js +18 -0
  344. package/dist/components/settings/principal-list.js.map +1 -0
  345. package/dist/components/settings/settings-panel.d.ts +10 -3
  346. package/dist/components/settings/settings-panel.d.ts.map +1 -1
  347. package/dist/components/settings/settings-panel.js +69 -8
  348. package/dist/components/settings/settings-panel.js.map +1 -1
  349. package/dist/components/settings/skills-list.d.ts +53 -0
  350. package/dist/components/settings/skills-list.d.ts.map +1 -0
  351. package/dist/components/settings/skills-list.js +28 -0
  352. package/dist/components/settings/skills-list.js.map +1 -0
  353. package/dist/components/settings/skills-tab.d.ts.map +1 -1
  354. package/dist/components/settings/skills-tab.js +65 -38
  355. package/dist/components/settings/skills-tab.js.map +1 -1
  356. package/dist/components/settings/tool-permissions-list.d.ts +18 -0
  357. package/dist/components/settings/tool-permissions-list.d.ts.map +1 -0
  358. package/dist/components/settings/tool-permissions-list.js +6 -0
  359. package/dist/components/settings/tool-permissions-list.js.map +1 -0
  360. package/dist/components/settings/tool-permissions.d.ts +2 -1
  361. package/dist/components/settings/tool-permissions.d.ts.map +1 -1
  362. package/dist/components/settings/tool-permissions.js +33 -16
  363. package/dist/components/settings/tool-permissions.js.map +1 -1
  364. package/dist/components/settings/web-search-chain.d.ts +41 -0
  365. package/dist/components/settings/web-search-chain.d.ts.map +1 -0
  366. package/dist/components/settings/web-search-chain.js +47 -0
  367. package/dist/components/settings/web-search-chain.js.map +1 -0
  368. package/dist/components/settings/web-search-settings.d.ts +4 -7
  369. package/dist/components/settings/web-search-settings.d.ts.map +1 -1
  370. package/dist/components/settings/web-search-settings.js +54 -76
  371. package/dist/components/settings/web-search-settings.js.map +1 -1
  372. package/dist/components/share/share-menu.d.ts.map +1 -1
  373. package/dist/components/share/share-menu.js +24 -4
  374. package/dist/components/share/share-menu.js.map +1 -1
  375. package/dist/components/voice/dictation-sheet.js +3 -3
  376. package/dist/components/voice/dictation-sheet.js.map +1 -1
  377. package/dist/components/voice/mic-button.js +1 -1
  378. package/dist/components/voice/mic-button.js.map +1 -1
  379. package/dist/components/voice/review-card.js +1 -1
  380. package/dist/components/voice/review-card.js.map +1 -1
  381. package/dist/config.d.ts +5 -2
  382. package/dist/config.d.ts.map +1 -1
  383. package/dist/config.js +15 -5
  384. package/dist/config.js.map +1 -1
  385. package/dist/connection.d.ts +12 -0
  386. package/dist/connection.d.ts.map +1 -0
  387. package/dist/connection.js +421 -0
  388. package/dist/connection.js.map +1 -0
  389. package/dist/default-root.d.ts +3 -0
  390. package/dist/default-root.d.ts.map +1 -0
  391. package/dist/default-root.js +16 -0
  392. package/dist/default-root.js.map +1 -0
  393. package/dist/hooks/use-color-scheme.d.ts +14 -0
  394. package/dist/hooks/use-color-scheme.d.ts.map +1 -0
  395. package/dist/hooks/use-color-scheme.js +37 -0
  396. package/dist/hooks/use-color-scheme.js.map +1 -0
  397. package/dist/hooks/use-hash-routes.d.ts.map +1 -1
  398. package/dist/hooks/use-hash-routes.js +4 -2
  399. package/dist/hooks/use-hash-routes.js.map +1 -1
  400. package/dist/hooks/use-media-query.d.ts +7 -0
  401. package/dist/hooks/use-media-query.d.ts.map +1 -0
  402. package/dist/hooks/use-media-query.js +34 -0
  403. package/dist/hooks/use-media-query.js.map +1 -0
  404. package/dist/hooks/use-share-intake.d.ts.map +1 -1
  405. package/dist/hooks/use-share-intake.js +37 -12
  406. package/dist/hooks/use-share-intake.js.map +1 -1
  407. package/dist/hooks/use-vpn-status.d.ts.map +1 -1
  408. package/dist/hooks/use-vpn-status.js +17 -18
  409. package/dist/hooks/use-vpn-status.js.map +1 -1
  410. package/dist/hooks/use-websocket.d.ts +5 -24
  411. package/dist/hooks/use-websocket.d.ts.map +1 -1
  412. package/dist/hooks/use-websocket.js +11 -384
  413. package/dist/hooks/use-websocket.js.map +1 -1
  414. package/dist/hooks/websocket-handlers/activity.d.ts +2 -2
  415. package/dist/hooks/websocket-handlers/activity.d.ts.map +1 -1
  416. package/dist/hooks/websocket-handlers/activity.js +4 -5
  417. package/dist/hooks/websocket-handlers/activity.js.map +1 -1
  418. package/dist/hooks/websocket-handlers/chat.d.ts +1 -0
  419. package/dist/hooks/websocket-handlers/chat.d.ts.map +1 -1
  420. package/dist/hooks/websocket-handlers/chat.js +27 -5
  421. package/dist/hooks/websocket-handlers/chat.js.map +1 -1
  422. package/dist/hooks/websocket-handlers/connection.d.ts.map +1 -1
  423. package/dist/hooks/websocket-handlers/connection.js +4 -6
  424. package/dist/hooks/websocket-handlers/connection.js.map +1 -1
  425. package/dist/hooks/websocket-handlers/mask.d.ts +1 -1
  426. package/dist/hooks/websocket-handlers/mask.d.ts.map +1 -1
  427. package/dist/hooks/websocket-handlers/mask.js +2 -3
  428. package/dist/hooks/websocket-handlers/mask.js.map +1 -1
  429. package/dist/hooks/websocket-handlers/provider.d.ts.map +1 -1
  430. package/dist/hooks/websocket-handlers/provider.js +4 -6
  431. package/dist/hooks/websocket-handlers/provider.js.map +1 -1
  432. package/dist/hooks/websocket-handlers/types.d.ts +6 -2
  433. package/dist/hooks/websocket-handlers/types.d.ts.map +1 -1
  434. package/dist/index.d.ts +5 -3
  435. package/dist/index.d.ts.map +1 -1
  436. package/dist/index.js +6 -3
  437. package/dist/index.js.map +1 -1
  438. package/dist/lib/api-client.d.ts +289 -0
  439. package/dist/lib/api-client.d.ts.map +1 -1
  440. package/dist/lib/api-client.js +243 -224
  441. package/dist/lib/api-client.js.map +1 -1
  442. package/dist/lib/backend.d.ts +19 -2
  443. package/dist/lib/backend.d.ts.map +1 -1
  444. package/dist/lib/backend.js +15 -9
  445. package/dist/lib/backend.js.map +1 -1
  446. package/dist/lib/diff.d.ts +8 -10
  447. package/dist/lib/diff.d.ts.map +1 -1
  448. package/dist/lib/diff.js +26 -53
  449. package/dist/lib/diff.js.map +1 -1
  450. package/dist/lib/light-dark.d.ts +37 -0
  451. package/dist/lib/light-dark.d.ts.map +1 -0
  452. package/dist/lib/light-dark.js +83 -0
  453. package/dist/lib/light-dark.js.map +1 -0
  454. package/dist/lib/mermaid-theme.d.ts +7 -2
  455. package/dist/lib/mermaid-theme.d.ts.map +1 -1
  456. package/dist/lib/mermaid-theme.js +125 -203
  457. package/dist/lib/mermaid-theme.js.map +1 -1
  458. package/dist/lib/passkeys.d.ts +6 -3
  459. package/dist/lib/passkeys.d.ts.map +1 -1
  460. package/dist/lib/passkeys.js +10 -4
  461. package/dist/lib/passkeys.js.map +1 -1
  462. package/dist/lib/push-registration.d.ts +4 -1
  463. package/dist/lib/push-registration.d.ts.map +1 -1
  464. package/dist/lib/push-registration.js +20 -2
  465. package/dist/lib/push-registration.js.map +1 -1
  466. package/dist/lib/share-intake.d.ts +2 -1
  467. package/dist/lib/share-intake.d.ts.map +1 -1
  468. package/dist/lib/share-intake.js +3 -3
  469. package/dist/lib/share-intake.js.map +1 -1
  470. package/dist/lib/share.d.ts +4 -3
  471. package/dist/lib/share.d.ts.map +1 -1
  472. package/dist/lib/share.js +6 -7
  473. package/dist/lib/share.js.map +1 -1
  474. package/dist/lib/single-key.d.ts +30 -0
  475. package/dist/lib/single-key.d.ts.map +1 -0
  476. package/dist/lib/single-key.js +45 -0
  477. package/dist/lib/single-key.js.map +1 -0
  478. package/dist/lib/tool-names.d.ts +8 -6
  479. package/dist/lib/tool-names.d.ts.map +1 -1
  480. package/dist/lib/tool-names.js +17 -7
  481. package/dist/lib/tool-names.js.map +1 -1
  482. package/dist/root-context.d.ts +229 -0
  483. package/dist/root-context.d.ts.map +1 -0
  484. package/dist/root-context.js +33 -0
  485. package/dist/root-context.js.map +1 -0
  486. package/dist/root.d.ts +38 -0
  487. package/dist/root.d.ts.map +1 -0
  488. package/dist/root.js +47 -0
  489. package/dist/root.js.map +1 -0
  490. package/dist/stores/activity-state.d.ts +29 -0
  491. package/dist/stores/activity-state.d.ts.map +1 -0
  492. package/dist/stores/activity-state.js +282 -0
  493. package/dist/stores/activity-state.js.map +1 -0
  494. package/dist/stores/activity-store.d.ts +10 -41
  495. package/dist/stores/activity-store.d.ts.map +1 -1
  496. package/dist/stores/activity-store.js +9 -271
  497. package/dist/stores/activity-store.js.map +1 -1
  498. package/dist/stores/chat-state.d.ts +212 -0
  499. package/dist/stores/chat-state.d.ts.map +1 -0
  500. package/dist/stores/chat-state.js +466 -0
  501. package/dist/stores/chat-state.js.map +1 -0
  502. package/dist/stores/chat-store.d.ts +4 -162
  503. package/dist/stores/chat-store.d.ts.map +1 -1
  504. package/dist/stores/chat-store.js +7 -418
  505. package/dist/stores/chat-store.js.map +1 -1
  506. package/dist/stores/connection-state.d.ts +40 -0
  507. package/dist/stores/connection-state.d.ts.map +1 -0
  508. package/dist/stores/connection-state.js +30 -0
  509. package/dist/stores/connection-state.js.map +1 -0
  510. package/dist/stores/connection-store.d.ts +4 -40
  511. package/dist/stores/connection-store.d.ts.map +1 -1
  512. package/dist/stores/connection-store.js +7 -27
  513. package/dist/stores/connection-store.js.map +1 -1
  514. package/dist/stores/create-stores.d.ts +23 -0
  515. package/dist/stores/create-stores.d.ts.map +1 -0
  516. package/dist/stores/create-stores.js +28 -0
  517. package/dist/stores/create-stores.js.map +1 -0
  518. package/dist/stores/file-state.d.ts +53 -0
  519. package/dist/stores/file-state.d.ts.map +1 -0
  520. package/dist/stores/file-state.js +341 -0
  521. package/dist/stores/file-state.js.map +1 -0
  522. package/dist/stores/file-store.d.ts +4 -52
  523. package/dist/stores/file-store.d.ts.map +1 -1
  524. package/dist/stores/file-store.js +7 -336
  525. package/dist/stores/file-store.js.map +1 -1
  526. package/dist/stores/graph-state.d.ts +95 -0
  527. package/dist/stores/graph-state.d.ts.map +1 -0
  528. package/dist/stores/graph-state.js +252 -0
  529. package/dist/stores/graph-state.js.map +1 -0
  530. package/dist/stores/graph-store.d.ts +7 -83
  531. package/dist/stores/graph-store.d.ts.map +1 -1
  532. package/dist/stores/graph-store.js +8 -249
  533. package/dist/stores/graph-store.js.map +1 -1
  534. package/dist/stores/mask-state.d.ts +21 -0
  535. package/dist/stores/mask-state.d.ts.map +1 -0
  536. package/dist/stores/mask-state.js +9 -0
  537. package/dist/stores/mask-state.js.map +1 -0
  538. package/dist/stores/mask-store.d.ts +4 -21
  539. package/dist/stores/mask-store.d.ts.map +1 -1
  540. package/dist/stores/mask-store.js +7 -6
  541. package/dist/stores/mask-store.js.map +1 -1
  542. package/dist/stores/principal-state.d.ts +16 -0
  543. package/dist/stores/principal-state.d.ts.map +1 -0
  544. package/dist/stores/principal-state.js +31 -0
  545. package/dist/stores/principal-state.js.map +1 -0
  546. package/dist/stores/principal-store.d.ts +4 -15
  547. package/dist/stores/principal-store.d.ts.map +1 -1
  548. package/dist/stores/principal-store.js +7 -28
  549. package/dist/stores/principal-store.js.map +1 -1
  550. package/dist/stores/provider-state.d.ts +24 -0
  551. package/dist/stores/provider-state.d.ts.map +1 -0
  552. package/dist/stores/provider-state.js +68 -0
  553. package/dist/stores/provider-state.js.map +1 -0
  554. package/dist/stores/provider-store.d.ts +4 -23
  555. package/dist/stores/provider-store.d.ts.map +1 -1
  556. package/dist/stores/provider-store.js +7 -64
  557. package/dist/stores/provider-store.js.map +1 -1
  558. package/dist/stores/share-state.d.ts +29 -0
  559. package/dist/stores/share-state.d.ts.map +1 -0
  560. package/dist/stores/share-state.js +21 -0
  561. package/dist/stores/share-state.js.map +1 -0
  562. package/dist/stores/share-store.d.ts +4 -28
  563. package/dist/stores/share-store.d.ts.map +1 -1
  564. package/dist/stores/share-store.js +7 -18
  565. package/dist/stores/share-store.js.map +1 -1
  566. package/dist/stores/store-environment.d.ts +10 -0
  567. package/dist/stores/store-environment.d.ts.map +1 -0
  568. package/dist/stores/store-environment.js +2 -0
  569. package/dist/stores/store-environment.js.map +1 -0
  570. package/dist/stores/ui-state.d.ts +71 -0
  571. package/dist/stores/ui-state.d.ts.map +1 -0
  572. package/dist/stores/ui-state.js +58 -0
  573. package/dist/stores/ui-state.js.map +1 -0
  574. package/dist/stores/ui-store.d.ts +4 -45
  575. package/dist/stores/ui-store.d.ts.map +1 -1
  576. package/dist/stores/ui-store.js +7 -36
  577. package/dist/stores/ui-store.js.map +1 -1
  578. package/dist/styles.css +1 -1
  579. package/dist/theme.css +150 -97
  580. package/dist/voice/asr-clients.d.ts +2 -1
  581. package/dist/voice/asr-clients.d.ts.map +1 -1
  582. package/dist/voice/asr-clients.js +16 -17
  583. package/dist/voice/asr-clients.js.map +1 -1
  584. package/dist/voice/use-dictation.d.ts.map +1 -1
  585. package/dist/voice/use-dictation.js +12 -8
  586. package/dist/voice/use-dictation.js.map +1 -1
  587. package/dist/voice/voice-state.d.ts +25 -0
  588. package/dist/voice/voice-state.d.ts.map +1 -0
  589. package/dist/voice/voice-state.js +29 -0
  590. package/dist/voice/voice-state.js.map +1 -0
  591. package/dist/voice/voice-store.d.ts +4 -25
  592. package/dist/voice/voice-store.d.ts.map +1 -1
  593. package/dist/voice/voice-store.js +7 -26
  594. package/dist/voice/voice-store.js.map +1 -1
  595. package/package.json +3 -2
  596. package/src/components/activity/activity-page.tsx +334 -160
  597. package/src/components/activity/activity-run-detail.tsx +81 -47
  598. package/src/components/activity/activity-run-list.tsx +27 -59
  599. package/src/components/activity/activity-views.tsx +155 -0
  600. package/src/components/activity/approval-card.tsx +80 -0
  601. package/src/components/activity/digest-card.tsx +25 -61
  602. package/src/components/activity/digest-summary.tsx +52 -0
  603. package/src/components/activity/push-switch.tsx +62 -0
  604. package/src/components/activity/push-toggle.tsx +51 -81
  605. package/src/components/activity/span-bits.tsx +8 -7
  606. package/src/components/chat/ask-user-card.tsx +292 -356
  607. package/src/components/chat/ask-user-typed.ts +77 -0
  608. package/src/components/chat/brain-markdown-links.tsx +4 -4
  609. package/src/components/chat/brain-markdown.tsx +4 -2
  610. package/src/components/chat/chat-page.tsx +38 -9
  611. package/src/components/chat/composer-view.tsx +194 -0
  612. package/src/components/chat/composer.tsx +117 -296
  613. package/src/components/chat/markdown-content.tsx +53 -2
  614. package/src/components/chat/mermaid-block.tsx +13 -5
  615. package/src/components/chat/mermaid-share.ts +8 -7
  616. package/src/components/chat/mermaid-viewer.tsx +3 -1
  617. package/src/components/chat/message-bubble.tsx +78 -94
  618. package/src/components/chat/message-share.ts +7 -7
  619. package/src/components/chat/renderers/bind.tsx +94 -0
  620. package/src/components/chat/renderers/brain-ui-tools.tsx +56 -0
  621. package/src/components/chat/renderers/claude-tools.tsx +3 -2
  622. package/src/components/chat/renderers/index.ts +15 -10
  623. package/src/components/chat/session-drawer.tsx +41 -138
  624. package/src/components/chat/session-list.tsx +113 -0
  625. package/src/components/chat/share-block.tsx +16 -12
  626. package/src/components/chat/share-card.tsx +2 -2
  627. package/src/components/chat/subagent-view.tsx +4 -4
  628. package/src/components/chat/tool-call-timeline.tsx +59 -22
  629. package/src/components/chat/tool-cards/block-card.tsx +145 -0
  630. package/src/components/chat/tool-cards/image-mask-card.tsx +214 -0
  631. package/src/components/chat/tool-cards/location-card.tsx +159 -0
  632. package/src/components/chat/tool-views.tsx +21 -60
  633. package/src/components/chat/transcript-turn.tsx +108 -0
  634. package/src/components/chat/use-chat-commands.ts +14 -16
  635. package/src/components/chat/welcome-state.tsx +36 -91
  636. package/src/components/connectivity/connection-gate.tsx +32 -24
  637. package/src/components/connectivity/login-form.tsx +122 -0
  638. package/src/components/connectivity/login-screen.tsx +45 -100
  639. package/src/components/dev/share-harness.tsx +2 -2
  640. package/src/components/files/file-panel.tsx +168 -0
  641. package/src/components/files/file-tree-view.tsx +127 -0
  642. package/src/components/files/file-tree.tsx +55 -109
  643. package/src/components/files/file-viewer-binary.tsx +3 -2
  644. package/src/components/files/file-viewer-frame.tsx +113 -0
  645. package/src/components/files/file-viewer.tsx +40 -95
  646. package/src/components/files/frontmatter-chips.tsx +42 -0
  647. package/src/components/files/frontmatter-panel.tsx +6 -71
  648. package/src/components/files/staleness.ts +29 -0
  649. package/src/components/graph/graph-canvas.tsx +24 -1
  650. package/src/components/graph/graph-controls-column.tsx +92 -0
  651. package/src/components/graph/graph-controls.tsx +83 -127
  652. package/src/components/graph/graph-form.tsx +183 -0
  653. package/src/components/graph/graph-maintenance.tsx +9 -14
  654. package/src/components/graph/graph-node-rail.tsx +147 -0
  655. package/src/components/graph/graph-page.tsx +189 -49
  656. package/src/components/graph/graph-scene.tsx +200 -30
  657. package/src/components/graph/lib/graph-helpers.ts +65 -43
  658. package/src/components/graph/node-card.tsx +64 -0
  659. package/src/components/graph/node-popover.tsx +28 -117
  660. package/src/components/graph/use-graph-theme.ts +69 -32
  661. package/src/components/graph/use-node-actions.ts +56 -0
  662. package/src/components/images/image-share.ts +4 -2
  663. package/src/components/images/image-viewer.tsx +3 -1
  664. package/src/components/images/mask-editor.tsx +7 -4
  665. package/src/components/layout/app-shell.tsx +5 -1
  666. package/src/components/layout/desktop-palette.tsx +151 -0
  667. package/src/components/layout/key-cap.tsx +15 -0
  668. package/src/components/layout/mobile-tab-bar.tsx +80 -157
  669. package/src/components/layout/shortcut-switch.tsx +32 -0
  670. package/src/components/layout/side-rail.tsx +70 -150
  671. package/src/components/layout/slide-panel.tsx +29 -2
  672. package/src/components/layout/theme.tsx +67 -0
  673. package/src/components/quick-actions/add-form.tsx +188 -0
  674. package/src/components/quick-actions/add-modal.tsx +32 -153
  675. package/src/components/quick-actions/search-modal.tsx +5 -3
  676. package/src/components/quick-actions/streaming-modal.tsx +42 -71
  677. package/src/components/quick-actions/streaming-output.tsx +112 -0
  678. package/src/components/quick-actions/whatsup-modal.tsx +38 -60
  679. package/src/components/settings/devices-agents-tab.tsx +60 -152
  680. package/src/components/settings/models-list.tsx +299 -0
  681. package/src/components/settings/models-tab.tsx +63 -337
  682. package/src/components/settings/one-time-agent-credential.tsx +1 -1
  683. package/src/components/settings/passkey-list.tsx +201 -0
  684. package/src/components/settings/passkey-tab.tsx +53 -197
  685. package/src/components/settings/pi-accounts-list.tsx +128 -0
  686. package/src/components/settings/pi-accounts.tsx +71 -170
  687. package/src/components/settings/principal-list.tsx +172 -0
  688. package/src/components/settings/settings-panel.tsx +232 -21
  689. package/src/components/settings/skills-list.tsx +276 -0
  690. package/src/components/settings/skills-tab.tsx +82 -269
  691. package/src/components/settings/tool-permissions-list.tsx +54 -0
  692. package/src/components/settings/tool-permissions.tsx +27 -46
  693. package/src/components/settings/web-search-chain.tsx +300 -0
  694. package/src/components/settings/web-search-settings.tsx +58 -328
  695. package/src/components/share/share-menu.tsx +19 -4
  696. package/src/components/voice/dictation-sheet.tsx +5 -5
  697. package/src/components/voice/mic-button.tsx +1 -1
  698. package/src/components/voice/review-card.tsx +1 -1
  699. package/src/config.ts +21 -7
  700. package/src/connection.ts +443 -0
  701. package/src/default-root.ts +16 -0
  702. package/src/hooks/use-color-scheme.ts +36 -0
  703. package/src/hooks/use-hash-routes.ts +4 -2
  704. package/src/hooks/use-media-query.ts +32 -0
  705. package/src/hooks/use-share-intake.ts +32 -12
  706. package/src/hooks/use-vpn-status.ts +18 -17
  707. package/src/hooks/use-websocket.ts +12 -428
  708. package/src/hooks/websocket-handlers/activity.ts +4 -5
  709. package/src/hooks/websocket-handlers/chat.ts +26 -5
  710. package/src/hooks/websocket-handlers/connection.ts +4 -6
  711. package/src/hooks/websocket-handlers/mask.ts +2 -3
  712. package/src/hooks/websocket-handlers/provider.ts +4 -6
  713. package/src/hooks/websocket-handlers/types.ts +6 -2
  714. package/src/index.ts +7 -3
  715. package/src/lib/api-client.ts +426 -384
  716. package/src/lib/backend.ts +20 -10
  717. package/src/lib/diff.ts +28 -62
  718. package/src/lib/light-dark.ts +83 -0
  719. package/src/lib/mermaid-theme.ts +183 -214
  720. package/src/lib/passkeys.ts +12 -4
  721. package/src/lib/push-registration.ts +19 -2
  722. package/src/lib/share-intake.ts +6 -3
  723. package/src/lib/share.ts +7 -4
  724. package/src/lib/single-key.ts +47 -0
  725. package/src/lib/tool-names.ts +31 -8
  726. package/src/root-context.tsx +40 -0
  727. package/src/root.ts +83 -0
  728. package/src/stores/activity-state.ts +295 -0
  729. package/src/stores/activity-store.ts +11 -285
  730. package/src/stores/chat-state.ts +795 -0
  731. package/src/stores/chat-store.ts +11 -705
  732. package/src/stores/connection-state.ts +78 -0
  733. package/src/stores/connection-store.ts +11 -76
  734. package/src/stores/create-stores.ts +31 -0
  735. package/src/stores/file-state.ts +399 -0
  736. package/src/stores/file-store.ts +9 -390
  737. package/src/stores/graph-state.ts +368 -0
  738. package/src/stores/graph-store.ts +10 -355
  739. package/src/stores/mask-state.ts +30 -0
  740. package/src/stores/mask-store.ts +10 -27
  741. package/src/stores/principal-state.ts +42 -0
  742. package/src/stores/principal-store.ts +10 -37
  743. package/src/stores/provider-state.ts +103 -0
  744. package/src/stores/provider-store.ts +10 -95
  745. package/src/stores/share-state.ts +56 -0
  746. package/src/stores/share-store.ts +11 -54
  747. package/src/stores/store-environment.ts +10 -0
  748. package/src/stores/ui-state.ts +143 -0
  749. package/src/stores/ui-store.ts +11 -93
  750. package/src/styles.css +4 -1
  751. package/src/theme.css +150 -97
  752. package/src/voice/asr-clients.ts +17 -17
  753. package/src/voice/use-dictation.ts +11 -8
  754. package/src/voice/voice-state.ts +57 -0
  755. package/src/voice/voice-store.ts +11 -55
@@ -1,18 +1,7 @@
1
+ import { useBrainUiRoot } from "../../root-context.js";
1
2
  import { useState, useRef, useEffect } from "react";
2
- import {
3
- ArrowUp,
4
- Square,
5
- CornerLeftUp,
6
- Paperclip,
7
- Camera,
8
- X,
9
- Check,
10
- ChevronDown,
11
- Lock,
12
- } from "lucide-react";
13
3
  import type { ClientMessage } from "@schlessera/brain-ui-sdk/protocol";
14
4
  import { useChatStore, activeChat } from "../../stores/chat-store.js";
15
- import { uiConfig } from "../../config.js";
16
5
  import { useConnectionStore } from "../../stores/connection-store.js";
17
6
  import { deriveConnectionIssue } from "../connectivity/connection-state.js";
18
7
  import { useProviderStore } from "../../stores/provider-store.js";
@@ -23,14 +12,14 @@ import {
23
12
  } from "../../lib/image-attachments.js";
24
13
  import { ShareIntake } from "./share-card.js";
25
14
  import { CommandPalette } from "./command-palette.js";
26
- import { MicButton } from "../voice/mic-button.js";
15
+ import { ComposerView } from "./composer-view.js";
27
16
  import { DictationSheet } from "../voice/dictation-sheet.js";
28
17
  import { ReviewCard } from "../voice/review-card.js";
29
18
  import { useDictation } from "../../voice/use-dictation.js";
30
19
  import { useVoiceStore } from "../../voice/voice-store.js";
31
20
  import { detectClientEnvironment } from "../../lib/client-environment.js";
32
21
  import { useChatCommands } from "./use-chat-commands.js";
33
- import { cn } from "../../lib/utils.js";
22
+ import { takeComposerTextAsAnswer } from "./ask-user-typed.js";
34
23
 
35
24
  /**
36
25
  * The composer — everything below the transcript: draft text, attachments,
@@ -44,11 +33,19 @@ import { cn } from "../../lib/utils.js";
44
33
  *
45
34
  * The corollary is a rule for future edits: transcript-scale state does not
46
35
  * belong in this file, and draft state does not belong above it.
36
+ *
37
+ * This is the container (S7): every store read, the draft, the attachments
38
+ * and their object URLs, the provider choice and the voice review live here;
39
+ * `ComposerView` draws the field.
47
40
  */
48
41
  export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
42
+ const root = useBrainUiRoot();
49
43
  const [input, setInput] = useState("");
50
44
  const [lastPrompt, setLastPrompt] = useState("");
51
- const textareaRef = useRef<HTMLTextAreaElement>(null);
45
+ const frameRef = useRef<HTMLDivElement>(null);
46
+ const [attachMenuOpen, setAttachMenuOpen] = useState(false);
47
+ /** The kit owns the textarea; the frame finds it when a recall or a voice edit needs focus. */
48
+ const focusField = () => frameRef.current?.querySelector("textarea")?.focus();
52
49
 
53
50
  // Image attachments. `attachmentsRef` mirrors state so async add/merge logic
54
51
  // reads the current set synchronously (avoids stale closures / updater races).
@@ -111,16 +108,18 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
111
108
  void loadProviders();
112
109
  }, [loadProviders]);
113
110
 
114
- // Dismiss the provider popover on outside-click / Escape.
111
+ // Dismiss the provider popover and the attach menu on outside-click / Escape.
115
112
  useEffect(() => {
116
- if (!providerMenuOpen) return;
113
+ if (!providerMenuOpen && !attachMenuOpen) return;
117
114
  const onDocClick = (e: MouseEvent) => {
118
- if (!providerMenuRef.current?.contains(e.target as Node)) {
119
- setProviderMenuOpen(false);
120
- }
115
+ if (!providerMenuRef.current?.contains(e.target as Node)) setProviderMenuOpen(false);
116
+ if (!(e.target as HTMLElement).closest?.('[role="menu"][aria-label="Attach"], [role="dialog"][aria-label="Attach"]')) setAttachMenuOpen(false);
121
117
  };
122
118
  const onKey = (e: KeyboardEvent) => {
123
- if (e.key === "Escape") setProviderMenuOpen(false);
119
+ if (e.key === "Escape") {
120
+ setProviderMenuOpen(false);
121
+ setAttachMenuOpen(false);
122
+ }
124
123
  };
125
124
  document.addEventListener("mousedown", onDocClick);
126
125
  document.addEventListener("keydown", onKey);
@@ -128,7 +127,7 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
128
127
  document.removeEventListener("mousedown", onDocClick);
129
128
  document.removeEventListener("keydown", onKey);
130
129
  };
131
- }, [providerMenuOpen]);
130
+ }, [providerMenuOpen, attachMenuOpen]);
132
131
 
133
132
  /**
134
133
  * The draft is whatever is visible above the send button: composer text
@@ -197,12 +196,26 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
197
196
  const hasAttachments = attachments.length > 0;
198
197
  if ((!text && !hasAttachments) || wsStatus !== "connected") return;
199
198
 
199
+ // A send while a question is pending is the ANSWER to it, not a new
200
+ // message (D38 §1): the text binds to the question, the card quotes it,
201
+ // and nothing goes out as `chat_message`. Attachments are not an answer
202
+ // to a question, so a send that carries one stays a message.
203
+ if (
204
+ text &&
205
+ !hasAttachments &&
206
+ takeComposerTextAsAnswer(root.stores.chat.getState(), sessionId, text, send)
207
+ ) {
208
+ setInput("");
209
+ clearReview();
210
+ return;
211
+ }
212
+
200
213
  if (text) setLastPrompt(text);
201
214
  const messageAttachments = attachments.map((a) => ({
202
215
  previewUrl: a.previewUrl,
203
216
  mediaType: a.attachment.mediaType,
204
217
  }));
205
- const chat = useChatStore.getState();
218
+ const chat = root.stores.chat.getState();
206
219
  chat.addUserMessage(
207
220
  sessionId,
208
221
  text,
@@ -251,7 +264,7 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
251
264
  void dictation.stop(true);
252
265
  } else {
253
266
  // Defensive: blur composer so the keyboard never fights the mic sheet on Android
254
- textareaRef.current?.blur();
267
+ frameRef.current?.querySelector("textarea")?.blur();
255
268
  // Any existing review text stays put — the new capture appends to it.
256
269
  void dictation.start();
257
270
  }
@@ -269,7 +282,7 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
269
282
  function handleVoiceEdit() {
270
283
  setInput((prev) => (prev ? `${prev}\n${reviewText}` : reviewText));
271
284
  clearReview();
272
- setTimeout(() => textareaRef.current?.focus(), 50);
285
+ setTimeout(focusField, 50);
273
286
  }
274
287
 
275
288
  function handleVoiceAppend() {
@@ -280,7 +293,7 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
280
293
  function handleRecall() {
281
294
  if (lastPrompt && !input.trim()) {
282
295
  setInput(lastPrompt);
283
- setTimeout(() => textareaRef.current?.focus(), 50);
296
+ setTimeout(focusField, 50);
284
297
  }
285
298
  }
286
299
 
@@ -352,278 +365,86 @@ export function Composer({ send }: { send: (msg: ClientMessage) => void }) {
352
365
  onDiscard={clearReview}
353
366
  onAppend={handleVoiceAppend}
354
367
  />
368
+ </div>
355
369
 
356
- {/* Rejected-file errors */}
357
- {attachErrors.length > 0 && (
358
- <div className="mb-2 flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-[11px] text-destructive">
359
- <div className="flex-1 space-y-0.5">
360
- {attachErrors.map((e, i) => (
361
- <div key={i}>{e}</div>
362
- ))}
363
- </div>
364
- <button
365
- type="button"
366
- onClick={() => setAttachErrors([])}
367
- title="Dismiss"
368
- className="shrink-0 rounded p-0.5 transition-colors hover:text-foreground"
369
- >
370
- <X className="h-3.5 w-3.5" />
371
- </button>
372
- </div>
373
- )}
374
-
375
- {/* Image attachment preview strip */}
376
- {attachments.length > 0 && (
377
- <div className="mb-2 flex flex-wrap gap-2">
378
- {attachments.map((a, i) => (
379
- <div key={i} className="relative h-16 w-16 shrink-0">
380
- <img
381
- src={a.previewUrl}
382
- alt={a.name}
383
- className="h-16 w-16 rounded-lg border border-border object-cover"
384
- />
385
- <button
386
- type="button"
387
- onClick={() => removeAttachment(i)}
388
- title="Remove"
389
- className="absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-surface text-muted-foreground shadow transition-colors hover:text-destructive"
390
- >
391
- <X className="h-3 w-3" />
392
- </button>
393
- </div>
394
- ))}
395
- </div>
396
- )}
397
-
398
- <div
399
- className={cn(
400
- "relative rounded-2xl border border-border bg-surface shadow-lg transition-all duration-200",
401
- "focus-within:border-primary/40 focus-within:shadow-[0_0_20px_rgba(224,159,62,0.05)]"
402
- )}
403
- >
404
- {/* Command palette */}
405
- {showCommandPalette && (
406
- <CommandPalette
407
- filter={input.slice(1)}
408
- onSelect={handleCommand}
409
- />
410
- )}
411
-
412
- {/* Hidden file inputs for the paperclip / camera buttons */}
413
- <input
414
- ref={libraryInputRef}
415
- type="file"
416
- accept="image/*"
417
- multiple
418
- hidden
419
- onChange={onFilePick}
420
- />
421
- <input
422
- ref={cameraInputRef}
423
- type="file"
424
- accept="image/*"
425
- capture="environment"
426
- hidden
427
- onChange={onFilePick}
428
- />
429
-
430
- {/* The textarea grows by CSS, not by JavaScript: the wrapper's
431
- ::after mirrors the value and sets the row height, so the
432
- composer never reads scrollHeight. That read forced a full
433
- document layout on every keystroke, and its cost scaled with
434
- the size of the transcript behind it. */}
435
- <div className="composer-grow" data-value={input + " "}>
436
- <textarea
437
- ref={textareaRef}
438
- value={input}
439
- onChange={(e) => {
440
- setInput(e.target.value);
441
- setPaletteDismissed(false);
442
- }}
443
- onPaste={(e) => {
444
- const files = e.clipboardData?.files;
445
- if (files && files.length > 0) {
446
- const images = Array.from(files).filter((f) =>
447
- f.type.startsWith("image/")
448
- );
449
- if (images.length > 0) {
450
- e.preventDefault();
451
- void addFiles(images);
452
- }
453
- }
454
- }}
455
- onKeyDown={(e) => {
456
- if (e.key === "Enter" && !e.shiftKey) {
457
- if (showCommandPalette) return;
458
- // On desktop (>=768px), Enter sends. On mobile, Enter inserts newline.
459
- if (window.matchMedia("(min-width: 768px)").matches) {
460
- e.preventDefault();
461
- handleSubmit();
462
- }
463
- }
464
- if (e.key === "ArrowUp" && !input.trim()) {
465
- handleRecall();
466
- }
467
- if (e.key === "Escape") {
468
- setPaletteDismissed(true);
469
- }
470
- }}
471
- placeholder={
472
- wsStatus !== "connected"
473
- ? connectionIssue === "capacity"
474
- ? "Server connection limit reached"
475
- : connectionIssue === "refused"
476
- ? "Server refused the connection"
477
- : "Connecting..."
478
- : uiConfig.composerPlaceholder
370
+ {/* Hidden file inputs for the paperclip / camera buttons */}
371
+ <input ref={libraryInputRef} type="file" accept="image/*" multiple hidden onChange={onFilePick} />
372
+ <input ref={cameraInputRef} type="file" accept="image/*" capture="environment" hidden onChange={onFilePick} />
373
+
374
+ <ComposerView
375
+ value={input}
376
+ // The kit's `state` drives placeholder, hint and the trailing control
377
+ // together (D37): streaming shows the stop, reconnecting keeps send
378
+ // live, offline disables it and keeps the draft.
379
+ state={
380
+ wsStatus === "connected"
381
+ ? isStreaming
382
+ ? "streaming"
383
+ : "ready"
384
+ : wsStatus === "connecting" && connectionIssue === null
385
+ ? "reconnecting"
386
+ : "offline"
387
+ }
388
+ placeholder={
389
+ wsStatus !== "connected"
390
+ ? connectionIssue === "capacity"
391
+ ? "Server connection limit reached"
392
+ : connectionIssue === "refused"
393
+ ? "Server refused the connection"
394
+ : "Connecting..."
395
+ : root.config.composerPlaceholder
396
+ }
397
+ hint={followUpHint ? `${followUpHint} · esc or the stop button ends the run` : undefined}
398
+ blockedWhy={
399
+ wsStatus === "connected" ? undefined : `${connectionIssue === "capacity" ? "the host is full" : connectionIssue === "refused" ? "the host refused the connection" : "needs the host"} · your draft is kept`
400
+ }
401
+ paletteOpen={showCommandPalette}
402
+ palette={showCommandPalette ? <CommandPalette filter={input.slice(1)} onSelect={handleCommand} /> : null}
403
+ attachMenuOpen={attachMenuOpen}
404
+ attachments={attachments.map((a) => ({ previewUrl: a.previewUrl, name: a.name }))}
405
+ attachErrors={attachErrors}
406
+ provider={
407
+ showProviderPicker
408
+ ? {
409
+ label: displayProviderLabel,
410
+ locked: providerLocked,
411
+ menuOpen: providerMenuOpen,
412
+ options: providers.map((p) => ({ id: p.id, label: p.label })),
413
+ selectedId: selectedProviderId,
479
414
  }
480
- disabled={wsStatus !== "connected"}
481
- rows={1}
482
- className="w-full resize-none bg-transparent text-sm text-foreground placeholder:text-muted-foreground/40 focus:outline-none disabled:opacity-50"
483
- />
484
- </div>
485
-
486
- <div className="flex items-center justify-between px-4 pb-3">
487
- {/* Provider picker + hints */}
488
- <div className="flex min-w-0 items-center gap-3 text-[11px] text-muted-foreground/50">
489
- {showProviderPicker && (
490
- <div ref={providerMenuRef} className="relative">
491
- <button
492
- type="button"
493
- onClick={() =>
494
- !providerLocked && setProviderMenuOpen((v) => !v)
495
- }
496
- disabled={providerLocked}
497
- title={
498
- providerLocked
499
- ? "Provider is fixed for this conversation"
500
- : "Choose model"
501
- }
502
- className={cn(
503
- "flex max-w-[9rem] items-center gap-1 rounded-lg px-2 py-1 text-[11px] transition-colors md:max-w-[14rem]",
504
- providerLocked
505
- ? "cursor-default text-muted-foreground/60"
506
- : "text-muted-foreground hover:bg-surface-raised hover:text-foreground"
507
- )}
508
- >
509
- {providerLocked && (
510
- <Lock className="h-3 w-3 shrink-0 opacity-70" />
511
- )}
512
- <span className="truncate">
513
- {displayProviderLabel}
514
- </span>
515
- {!providerLocked && (
516
- <ChevronDown className="h-3 w-3 shrink-0 opacity-70" />
517
- )}
518
- </button>
519
- {providerMenuOpen && !providerLocked && (
520
- <div
521
- role="menu"
522
- className="absolute bottom-full left-0 z-50 mb-1 min-w-[14rem] overflow-hidden rounded-xl border border-border bg-surface-overlay py-1 shadow-2xl"
523
- >
524
- {providers.map((p) => (
525
- <button
526
- key={p.id}
527
- role="menuitem"
528
- type="button"
529
- onClick={() => {
530
- setSelectedProvider(p.id);
531
- setProviderMenuOpen(false);
532
- }}
533
- className="flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-foreground transition-colors hover:bg-surface-raised"
534
- >
535
- <Check
536
- className={cn(
537
- "h-3.5 w-3.5 shrink-0 text-primary",
538
- p.id === selectedProviderId
539
- ? "opacity-100"
540
- : "opacity-0"
541
- )}
542
- />
543
- <span className="truncate">{p.label}</span>
544
- </button>
545
- ))}
546
- </div>
547
- )}
548
- </div>
549
- )}
550
- {followUpHint ? (
551
- <span className="text-primary/70">{followUpHint}</span>
552
- ) : (
553
- <>
554
- <span className="hidden sm:inline">
555
- <span className="font-[family-name:var(--font-mono)]">/</span>{" "}
556
- for commands
557
- </span>
558
- <span className="hidden md:inline">Shift+Enter for newline</span>
559
- </>
560
- )}
561
- </div>
562
-
563
- {/* Attach + Recall + Mic + Send / Cancel */}
564
- <div className="flex items-center gap-1.5">
565
- <button
566
- type="button"
567
- onClick={() => libraryInputRef.current?.click()}
568
- disabled={isStreaming || wsStatus !== "connected"}
569
- title="Attach images"
570
- aria-label="Attach images"
571
- className="flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition-all duration-150 hover:bg-surface-raised hover:text-foreground disabled:cursor-not-allowed disabled:opacity-30"
572
- >
573
- <Paperclip className="h-4 w-4" />
574
- </button>
575
- <button
576
- type="button"
577
- onClick={() => cameraInputRef.current?.click()}
578
- disabled={isStreaming || wsStatus !== "connected"}
579
- title="Take a photo"
580
- aria-label="Take a photo"
581
- className="flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition-all duration-150 hover:bg-surface-raised hover:text-foreground disabled:cursor-not-allowed disabled:opacity-30"
582
- >
583
- <Camera className="h-4 w-4" />
584
- </button>
585
- {lastPrompt && !input.trim() && !isStreaming && (
586
- <button
587
- type="button"
588
- onClick={handleRecall}
589
- title="Recall last prompt"
590
- className="flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition-all duration-150 hover:bg-surface-raised hover:text-foreground"
591
- >
592
- <CornerLeftUp className="h-4 w-4" />
593
- </button>
594
- )}
595
- <MicButton
596
- active={voiceMode === "dictate"}
597
- disabled={isStreaming || wsStatus !== "connected"}
598
- onTap={handleMicTap}
599
- />
600
- {isStreaming && !hasDraft ? (
601
- // Streaming with nothing drafted: the primary action is cancel.
602
- <button
603
- type="button"
604
- onClick={handleCancel}
605
- title="Stop the running turn"
606
- className="flex h-8 w-8 items-center justify-center rounded-lg bg-destructive text-primary-foreground transition-all duration-150"
607
- >
608
- <Square className="h-3.5 w-3.5" />
609
- </button>
610
- ) : (
611
- // A draft always sends — as a new turn, or a follow-up when a
612
- // session is already running.
613
- <button
614
- type="button"
615
- onClick={handleSubmit}
616
- disabled={!canSend}
617
- title={followUpHint ?? "Send"}
618
- className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary text-primary-foreground transition-all duration-150 hover:brightness-110 disabled:opacity-30"
619
- >
620
- <ArrowUp className="h-4 w-4" />
621
- </button>
622
- )}
623
- </div>
624
- </div>
625
- </div>
626
- </div>
415
+ : null
416
+ }
417
+ frameRef={frameRef}
418
+ providerMenuRef={providerMenuRef}
419
+ onChange={(value) => {
420
+ setInput(value);
421
+ setPaletteDismissed(false);
422
+ }}
423
+ onSend={() => {
424
+ if (canSend) handleSubmit();
425
+ }}
426
+ onStop={handleCancel}
427
+ onMic={handleMicTap}
428
+ onAttachToggle={() => setAttachMenuOpen((v) => !v)}
429
+ onPickLibrary={() => {
430
+ setAttachMenuOpen(false);
431
+ libraryInputRef.current?.click();
432
+ }}
433
+ onPickCamera={() => {
434
+ setAttachMenuOpen(false);
435
+ cameraInputRef.current?.click();
436
+ }}
437
+ onPasteFiles={(files) => void addFiles(files)}
438
+ onRecall={handleRecall}
439
+ onEscape={() => setPaletteDismissed(true)}
440
+ onRemoveAttachment={removeAttachment}
441
+ onDismissErrors={() => setAttachErrors([])}
442
+ onProviderToggle={() => !providerLocked && setProviderMenuOpen((v) => !v)}
443
+ onProviderSelect={(id) => {
444
+ setSelectedProvider(id);
445
+ setProviderMenuOpen(false);
446
+ }}
447
+ />
627
448
  </div>
628
449
  </>
629
450
  );
@@ -1,5 +1,56 @@
1
+ import type { MessageBlock } from "@schlessera/brain-ui-sdk/protocol";
1
2
  import { BrainMarkdown } from "./brain-markdown.js";
3
+ import { BlockCard } from "./tool-cards/block-card.js";
2
4
 
3
- export function MarkdownContent({ content }: { content: string }) {
4
- return <BrainMarkdown content={content} fileLinks />;
5
+ /**
6
+ * A text part of an assistant message, with the blocks the surface
7
+ * classified out of it drawn in place (D42).
8
+ *
9
+ * The blocks are anchored by character span. The part is cut at those
10
+ * spans and each piece renders as markdown, with the kit block between —
11
+ * so a table the model typed becomes a comparison table without touching
12
+ * the markdown renderer, and a message with no blocks renders exactly as it
13
+ * did before this prop existed. A span that does not fit the text (an
14
+ * anchor from a text that has since changed) is ignored, never a blank.
15
+ */
16
+ export function MarkdownContent({
17
+ content,
18
+ blocks,
19
+ }: {
20
+ content: string;
21
+ blocks?: MessageBlock[];
22
+ }) {
23
+ const cuts = usableBlocks(content, blocks);
24
+ if (cuts.length === 0) return <BrainMarkdown content={content} fileLinks />;
25
+ const pieces: React.ReactNode[] = [];
26
+ let cursor = 0;
27
+ cuts.forEach((cut, i) => {
28
+ const before = content.slice(cursor, cut.start);
29
+ if (before.trim()) pieces.push(<BrainMarkdown key={`md-${i}`} content={before} fileLinks />);
30
+ pieces.push(
31
+ <div key={`block-${i}`} className="my-3" data-classified-block={cut.block.kind}>
32
+ <BlockCard block={cut.block} />
33
+ </div>
34
+ );
35
+ cursor = cut.end;
36
+ });
37
+ const after = content.slice(cursor);
38
+ if (after.trim()) pieces.push(<BrainMarkdown key="md-tail" content={after} fileLinks />);
39
+ return <>{pieces}</>;
40
+ }
41
+
42
+ /** The blocks whose spans fit this text, in order, non-overlapping. */
43
+ export function usableBlocks(content: string, blocks: MessageBlock[] | undefined): MessageBlock[] {
44
+ if (!blocks || blocks.length === 0) return [];
45
+ const sorted = [...blocks]
46
+ .filter((b) => b.start >= 0 && b.end > b.start && b.end <= content.length)
47
+ .sort((a, b) => a.start - b.start);
48
+ const out: MessageBlock[] = [];
49
+ let cursor = 0;
50
+ for (const block of sorted) {
51
+ if (block.start < cursor) continue;
52
+ out.push(block);
53
+ cursor = block.end;
54
+ }
55
+ return out;
5
56
  }
@@ -1,6 +1,8 @@
1
+ import { useBrainUiRoot } from "../../root-context.js";
1
2
  import { useEffect, useRef, useState } from "react";
2
3
  import { Code, ChartNetwork, Expand } from "lucide-react";
3
4
  import { peekMermaidSvg, renderMermaidSvg } from "../../lib/mermaid.js";
5
+ import { useColorScheme } from "../../hooks/use-color-scheme.js";
4
6
  import { ShareMenu } from "../share/share-menu.js";
5
7
  import { CopyButton } from "./copy-button.js";
6
8
  import { buildDiagramShareOptions } from "./mermaid-share.js";
@@ -15,9 +17,15 @@ import { MermaidViewer } from "./mermaid-viewer.js";
15
17
  * fails keeps the last good diagram instead of flashing an error. Renders
16
18
  * are cached module-wide, so the per-token re-render of a streaming message
17
19
  * costs a cache lookup, not a mermaid parse.
20
+ *
21
+ * The diagram is drawn for the scheme the page is in — mermaid's variables
22
+ * are literal colours, so a theme switch is a re-render (cached per scheme),
23
+ * not a stylesheet change.
18
24
  */
19
25
  export function MermaidBlock({ source }: { source: string }) {
20
- const [svg, setSvg] = useState<string | null>(() => peekMermaidSvg(source));
26
+ const root = useBrainUiRoot();
27
+ const scheme = useColorScheme();
28
+ const [svg, setSvg] = useState<string | null>(() => peekMermaidSvg(source, scheme));
21
29
  const [showSource, setShowSource] = useState(false);
22
30
  const [zoomed, setZoomed] = useState(false);
23
31
  const latest = useRef(0);
@@ -25,7 +33,7 @@ export function MermaidBlock({ source }: { source: string }) {
25
33
 
26
34
  useEffect(() => {
27
35
  const id = ++latest.current;
28
- const cached = peekMermaidSvg(source);
36
+ const cached = peekMermaidSvg(source, scheme);
29
37
  if (cached) {
30
38
  setSvg(cached);
31
39
  return;
@@ -37,13 +45,13 @@ export function MermaidBlock({ source }: { source: string }) {
37
45
  const wait = Date.now() - lastAttempt.current > 400 ? 0 : 150;
38
46
  const t = setTimeout(() => {
39
47
  lastAttempt.current = Date.now();
40
- void renderMermaidSvg(source).then((result) => {
48
+ void renderMermaidSvg(source, scheme).then((result) => {
41
49
  if (latest.current !== id || !result) return;
42
50
  setSvg(result);
43
51
  });
44
52
  }, wait);
45
53
  return () => clearTimeout(t);
46
- }, [source]);
54
+ }, [source, scheme]);
47
55
 
48
56
  const diagramReady = svg !== null;
49
57
  const showDiagram = diagramReady && !showSource;
@@ -77,7 +85,7 @@ export function MermaidBlock({ source }: { source: string }) {
77
85
  )}
78
86
  {diagramReady && (
79
87
  <ShareMenu
80
- options={buildDiagramShareOptions(source)}
88
+ options={buildDiagramShareOptions(root, source)}
81
89
  title="Share diagram"
82
90
  renderTrigger={({ onClick, busy, icon }) => (
83
91
  <button type="button" title="Share diagram" onClick={onClick} disabled={busy} className={iconBtn}>