@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,4 +1,4 @@
1
- import { uiConfig } from "../../config.js";
1
+ import type { BrainUiRoot } from "../../root.js";
2
2
  import { renderMermaidSvg, sizeSvgForExport } from "../../lib/mermaid.js";
3
3
  import { renderAndShare, shareFile, shareText } from "../../lib/share.js";
4
4
  import type { ShareOption } from "../share/share-menu.js";
@@ -41,6 +41,7 @@ async function exportHtml(source: string, tight: boolean): Promise<string> {
41
41
  }
42
42
 
43
43
  export function buildDiagramShareOptions(
44
+ root: BrainUiRoot,
44
45
  source: string,
45
46
  opts: { filename?: string } = {}
46
47
  ): ShareOption[] {
@@ -51,12 +52,12 @@ export function buildDiagramShareOptions(
51
52
  label: "Image (PNG)",
52
53
  hint: "Cropped to the diagram",
53
54
  run: async () =>
54
- renderAndShare({
55
+ renderAndShare(root, {
55
56
  content: await exportHtml(source, true),
56
57
  contentType: "html",
57
58
  format: "png",
58
59
  filename,
59
- title: uiConfig.shareTitle,
60
+ title: root.config.shareTitle,
60
61
  }),
61
62
  },
62
63
  {
@@ -64,12 +65,12 @@ export function buildDiagramShareOptions(
64
65
  label: "PDF",
65
66
  hint: "Vector PDF, A4",
66
67
  run: async () =>
67
- renderAndShare({
68
+ renderAndShare(root, {
68
69
  content: await exportHtml(source, false),
69
70
  contentType: "html",
70
71
  format: "pdf",
71
72
  filename,
72
- title: uiConfig.shareTitle,
73
+ title: root.config.shareTitle,
73
74
  }),
74
75
  },
75
76
  {
@@ -78,14 +79,14 @@ export function buildDiagramShareOptions(
78
79
  hint: "Scales to any size",
79
80
  run: async () =>
80
81
  shareFile(new File([await exportSvg(source)], `${filename}.svg`, { type: "image/svg+xml" }), {
81
- title: uiConfig.shareTitle,
82
+ title: root.config.shareTitle,
82
83
  }),
83
84
  },
84
85
  {
85
86
  id: "source",
86
87
  label: "Mermaid source",
87
88
  hint: "Paste into another tool",
88
- run: () => shareText({ text: source, title: uiConfig.shareTitle }),
89
+ run: () => shareText({ text: source, title: root.config.shareTitle }),
89
90
  },
90
91
  ];
91
92
  }
@@ -1,3 +1,4 @@
1
+ import { useBrainUiRoot } from "../../root-context.js";
1
2
  import { useMemo } from "react";
2
3
  import { sizeSvgForExport } from "../../lib/mermaid.js";
3
4
  import { ShareMenu } from "../share/share-menu.js";
@@ -23,6 +24,7 @@ export function MermaidViewer({
23
24
  source: string;
24
25
  onClose: () => void;
25
26
  }) {
27
+ const root = useBrainUiRoot();
26
28
  // Mermaid ships `width: 100%` + `max-width` on the svg, which has no
27
29
  // intrinsic size to measure or to scale from. Reuse the export sizer to pin
28
30
  // it to its viewBox pixels; the viewer's transform does all the scaling.
@@ -33,7 +35,7 @@ export function MermaidViewer({
33
35
  onClose={onClose}
34
36
  refitKey={sizedSvg}
35
37
  label="Diagram viewer"
36
- actions={<ShareMenu options={buildDiagramShareOptions(source)} title="Share diagram" />}
38
+ actions={<ShareMenu options={buildDiagramShareOptions(root, source)} title="Share diagram" />}
37
39
  >
38
40
  <div dangerouslySetInnerHTML={{ __html: sizedSvg }} />
39
41
  </ZoomViewer>
@@ -1,6 +1,5 @@
1
- import { uiConfig } from "../../config.js";
1
+ import { useBrainUiRoot } from "../../root-context.js";
2
2
  import { memo, useEffect, useRef, useState } from "react";
3
- import { ChevronDown, Sparkles, Mic, Image as ImageIcon } from "lucide-react";
4
3
  import type {
5
4
  ChatMessage,
6
5
  ToolCall,
@@ -12,11 +11,14 @@ import { ToolCallTimeline } from "./tool-call-timeline.js";
12
11
  import { MarkdownContent } from "./markdown-content.js";
13
12
  import { linkifyPaths } from "./brain-markdown.js";
14
13
  import { AskUserCard } from "./ask-user-card.js";
15
- import { isAskUserTool } from "../../lib/tool-names.js";
14
+ import { isAskUserTool, isShowBlockTool } from "../../lib/tool-names.js";
15
+ import { BlockCard } from "./tool-cards/block-card.js";
16
+ import { SHOW_BLOCK_CONTRACT, parseToolPayload, type ShowBlockPayload } from "@schlessera/brain-ui-sdk/client";
16
17
  import { motion } from "framer-motion";
17
18
  import { buildMessageShareOptions } from "./message-share.js";
18
19
  import { ShareMenu } from "../share/share-menu.js";
19
20
  import { ZoomableImage } from "../images/zoomable-image.js";
21
+ import { AttachmentCount, ThinkingBlock, ThinkingIndicator, TurnHeader, UserTurn } from "./transcript-turn.js";
20
22
 
21
23
  /**
22
24
  * One message in the transcript.
@@ -28,12 +30,18 @@ import { ZoomableImage } from "../images/zoomable-image.js";
28
30
  *
29
31
  * The contract that keeps it working: every callback prop must be stable.
30
32
  * ChatPage wraps all three in useCallback for exactly this reason.
33
+ *
34
+ * This is the container (S7): it reads the message, groups its parts and
35
+ * routes the tool timelines, ask cards and markdown; the frame — header,
36
+ * user bubble, thinking disclosure, the streaming dot — is
37
+ * `transcript-turn.tsx`, on the kit.
31
38
  */
32
39
  export const MessageBubble = memo(function MessageBubble({
33
40
  message,
34
41
  onToolApproval,
35
42
  onAskUserSubmit,
36
43
  onAskUserCancel,
44
+ onAskUserReask,
37
45
  }: {
38
46
  message: ChatMessage;
39
47
  onToolApproval: (toolUseId: string, approved: boolean) => void;
@@ -43,7 +51,10 @@ export const MessageBubble = memo(function MessageBubble({
43
51
  annotations?: Record<string, AskUserAnnotation>
44
52
  ) => void;
45
53
  onAskUserCancel: (requestId: string) => void;
54
+ /** A dismissed question asked again answers by composer message. */
55
+ onAskUserReask?: (text: string) => void;
46
56
  }) {
57
+ const root = useBrainUiRoot();
47
58
  const isUser = message.role === "user";
48
59
 
49
60
  return (
@@ -53,53 +64,30 @@ export const MessageBubble = memo(function MessageBubble({
53
64
  transition={{ duration: 0.2, ease: "easeOut" }}
54
65
  className="py-4"
55
66
  >
56
- {/* Label row */}
57
- <div className="mb-2 flex items-center gap-3">
58
- <span
59
- className={
60
- isUser
61
- ? "select-none font-[family-name:var(--font-mono)] text-xs font-semibold uppercase tracking-widest text-primary/80"
62
- : "select-none font-[family-name:var(--font-mono)] text-xs font-semibold uppercase tracking-widest text-accent/80"
63
- }
64
- >
65
- {isUser ? "You" : uiConfig.assistantName}
66
- </span>
67
- <div className="h-px flex-1 bg-border/40" />
68
- {isUser && message.source && message.source !== "typed" && (
69
- <Mic
70
- className={
71
- message.source === "voice-conversation"
72
- ? "h-3 w-3 text-primary/70"
73
- : "h-3 w-3 text-primary/50"
74
- }
75
- aria-label={
76
- message.source === "voice-conversation"
77
- ? "Voice conversation"
78
- : "Voice dictation"
79
- }
80
- />
81
- )}
82
- <span className="font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground/40">
83
- {formatTime(message.timestamp)}
84
- </span>
85
- </div>
67
+ <TurnHeader
68
+ who={isUser ? "You" : root.config.assistantName}
69
+ when={formatTime(message.timestamp)}
70
+ voice={isUser && message.source && message.source !== "typed" ? message.source : undefined}
71
+ tone={isUser ? "user" : "brain"}
72
+ />
86
73
 
87
74
  {/* Content */}
88
75
  {isUser ? (
89
- <div className="space-y-2">
76
+ <UserTurn>
90
77
  <UserAttachments message={message} />
91
78
  {message.content && (
92
79
  <div className="chat-message-body text-sm leading-relaxed text-foreground whitespace-pre-wrap">
93
80
  {linkifyPaths(message.content)}
94
81
  </div>
95
82
  )}
96
- </div>
83
+ </UserTurn>
97
84
  ) : (
98
85
  <AssistantContent
99
86
  message={message}
100
87
  onToolApproval={onToolApproval}
101
88
  onAskUserSubmit={onAskUserSubmit}
102
89
  onAskUserCancel={onAskUserCancel}
90
+ onAskUserReask={onAskUserReask}
103
91
  />
104
92
  )}
105
93
  </motion.div>
@@ -131,12 +119,7 @@ function UserAttachments({ message }: { message: ChatMessage }) {
131
119
  }
132
120
 
133
121
  if (message.attachmentCount && message.attachmentCount > 0) {
134
- return (
135
- <div className="inline-flex items-center gap-1.5 rounded-lg border border-border/40 bg-surface/50 px-2.5 py-1 text-xs text-muted-foreground">
136
- <ImageIcon className="h-3.5 w-3.5" />
137
- {message.attachmentCount} image{message.attachmentCount === 1 ? "" : "s"}
138
- </div>
139
- );
122
+ return <AttachmentCount count={message.attachmentCount} />;
140
123
  }
141
124
 
142
125
  return null;
@@ -149,9 +132,10 @@ function UserAttachments({ message }: { message: ChatMessage }) {
149
132
  */
150
133
  type PartGroup =
151
134
  | { kind: "thinking"; text: string; isLast: boolean }
152
- | { kind: "text"; text: string; isLast: boolean; isLastText: boolean }
135
+ | { kind: "text"; text: string; isLast: boolean; isLastText: boolean; textIndex: number }
153
136
  | { kind: "tools"; toolCalls: ToolCall[]; isLast: boolean }
154
- | { kind: "askUser"; exchange: AskUserExchange; isLast: boolean };
137
+ | { kind: "askUser"; exchange: AskUserExchange; isLast: boolean }
138
+ | { kind: "block"; payload: ShowBlockPayload; isLast: boolean };
155
139
 
156
140
  function groupParts(
157
141
  parts: MessagePart[],
@@ -163,6 +147,8 @@ function groupParts(
163
147
  // to its exchange and renders as its own AskUserCard at that chronological
164
148
  // spot, so it collapses and scrolls away like the surrounding events.
165
149
  let askUserSeen = 0;
150
+ // Ordinal among TEXT parts: classified blocks (D42) are anchored to it.
151
+ let textSeen = 0;
166
152
  for (const part of parts) {
167
153
  if (part.kind === "tool") {
168
154
  const tool = toolCalls[part.toolIndex];
@@ -176,6 +162,17 @@ function groupParts(
176
162
  }
177
163
  continue;
178
164
  }
165
+ if (isShowBlockTool(tool.name)) {
166
+ // A block is part of the answer, not a step in the trace (D41): it
167
+ // renders inline where it was called. Until the echo arrives, and
168
+ // when it does not parse (a rejected call, an older server), the
169
+ // call stays in the timeline, where its bound fallback states why.
170
+ const payload = parseToolPayload(SHOW_BLOCK_CONTRACT, tool.output);
171
+ if (payload) {
172
+ groups.push({ kind: "block", payload, isLast: false });
173
+ continue;
174
+ }
175
+ }
179
176
  const last = groups[groups.length - 1];
180
177
  if (last?.kind === "tools") {
181
178
  last.toolCalls.push(tool);
@@ -183,7 +180,14 @@ function groupParts(
183
180
  groups.push({ kind: "tools", toolCalls: [tool], isLast: false });
184
181
  }
185
182
  } else if (part.text.trim()) {
186
- groups.push({ kind: part.kind, text: part.text, isLast: false, isLastText: false });
183
+ if (part.kind === "text") {
184
+ groups.push({ kind: "text", text: part.text, isLast: false, isLastText: false, textIndex: textSeen++ });
185
+ } else {
186
+ groups.push({ kind: "thinking", text: part.text, isLast: false });
187
+ }
188
+ } else if (part.kind === "text") {
189
+ // An all-whitespace text part still counts toward the ordinal.
190
+ textSeen++;
187
191
  }
188
192
  }
189
193
  const last = groups[groups.length - 1];
@@ -198,11 +202,19 @@ function groupParts(
198
202
  return groups;
199
203
  }
200
204
 
205
+ /** The classified blocks anchored to the n-th text part, or nothing. */
206
+ function blocksFor(message: ChatMessage, textIndex: number) {
207
+ if (!message.blocks || message.blocks.length === 0) return undefined;
208
+ const own = message.blocks.filter((b) => b.partIndex === textIndex);
209
+ return own.length ? own : undefined;
210
+ }
211
+
201
212
  function AssistantContent({
202
213
  message,
203
214
  onToolApproval,
204
215
  onAskUserSubmit,
205
216
  onAskUserCancel,
217
+ onAskUserReask,
206
218
  }: {
207
219
  message: ChatMessage;
208
220
  onToolApproval: (toolUseId: string, approved: boolean) => void;
@@ -212,12 +224,15 @@ function AssistantContent({
212
224
  annotations?: Record<string, AskUserAnnotation>
213
225
  ) => void;
214
226
  onAskUserCancel: (requestId: string) => void;
227
+ /** A dismissed question asked again answers by composer message. */
228
+ onAskUserReask?: (text: string) => void;
215
229
  }) {
230
+ const root = useBrainUiRoot();
216
231
  const contentRef = useRef<HTMLDivElement>(null);
217
232
  const showShare =
218
233
  !message.isStreaming && !!message.content && message.content.trim().length > 0;
219
234
  const shareOptions = showShare
220
- ? buildMessageShareOptions({
235
+ ? buildMessageShareOptions(root, {
221
236
  content: message.content,
222
237
  renderedRef: contentRef,
223
238
  })
@@ -263,6 +278,8 @@ function AssistantContent({
263
278
  live={message.isStreaming}
264
279
  />
265
280
  );
281
+ case "block":
282
+ return <BlockCard key={i} {...group.payload} />;
266
283
  case "askUser":
267
284
  return (
268
285
  <AskUserCard
@@ -271,9 +288,11 @@ function AssistantContent({
271
288
  questions={group.exchange.questions}
272
289
  answered={group.exchange.answers}
273
290
  cancelled={group.exchange.cancelled}
274
- live={message.isStreaming}
291
+ typed={group.exchange.typed}
292
+ answeredAt={group.exchange.answeredAt}
275
293
  onSubmit={onAskUserSubmit}
276
294
  onCancel={onAskUserCancel}
295
+ onReask={onAskUserReask}
277
296
  />
278
297
  );
279
298
  case "text":
@@ -285,7 +304,7 @@ function AssistantContent({
285
304
  wrapper: content-visibility implies paint containment,
286
305
  which would clip a dropdown that opens past the box. */}
287
306
  <div className="chat-message-body">
288
- <MarkdownContent content={group.text} />
307
+ <MarkdownContent content={group.text} blocks={blocksFor(message, group.textIndex)} />
289
308
  </div>
290
309
  {showShare && shareOptions.length > 0 && (
291
310
  <div className="mt-1 flex justify-end opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100">
@@ -295,7 +314,7 @@ function AssistantContent({
295
314
  </div>
296
315
  ) : (
297
316
  <div key={i} className="chat-message-body">
298
- <MarkdownContent content={group.text} />
317
+ <MarkdownContent content={group.text} blocks={blocksFor(message, group.textIndex)} />
299
318
  </div>
300
319
  );
301
320
  }
@@ -308,21 +327,15 @@ function AssistantContent({
308
327
  questions={ex.questions}
309
328
  answered={ex.answers}
310
329
  cancelled={ex.cancelled}
311
- live={message.isStreaming}
330
+ typed={ex.typed}
331
+ answeredAt={ex.answeredAt}
312
332
  onSubmit={onAskUserSubmit}
313
333
  onCancel={onAskUserCancel}
334
+ onReask={onAskUserReask}
314
335
  />
315
336
  ))}
316
337
 
317
- {message.isStreaming && groups.length === 0 && unmatchedExchanges.length === 0 && (
318
- <div className="flex items-center gap-2 text-xs text-muted-foreground">
319
- <span
320
- className="inline-block h-1.5 w-1.5 rounded-full bg-primary"
321
- style={{ animation: "breathe 2s ease-in-out infinite" }}
322
- />
323
- Thinking...
324
- </div>
325
- )}
338
+ {message.isStreaming && groups.length === 0 && unmatchedExchanges.length === 0 && <ThinkingIndicator />}
326
339
  </div>
327
340
  );
328
341
  }
@@ -344,43 +357,14 @@ function ThinkingSection({
344
357
  prevStreaming.current = isStreaming;
345
358
  }, [isStreaming]);
346
359
 
347
- if (!isStreaming && !expanded) {
348
- // Collapsed: minimal clickable text
349
- const estimatedTokens = Math.round(content.length / 4);
350
- return (
351
- <button
352
- onClick={() => setExpanded(true)}
353
- className="flex items-center gap-1.5 text-xs text-muted-foreground/50 transition-colors hover:text-muted-foreground"
354
- >
355
- <Sparkles className="h-3 w-3" />
356
- <span className="font-[family-name:var(--font-mono)]">
357
- Thought for ~{estimatedTokens} tokens
358
- </span>
359
- <ChevronDown className="h-3 w-3" />
360
- </button>
361
- );
362
- }
363
-
364
360
  return (
365
- <div className="rounded-lg bg-surface/50 px-4 py-3">
366
- {!isStreaming && (
367
- <button
368
- onClick={() => setExpanded(false)}
369
- className="mb-2 text-[11px] font-medium text-muted-foreground/50 transition-colors hover:text-muted-foreground"
370
- >
371
- Hide thinking
372
- </button>
373
- )}
374
- <div className="font-[family-name:var(--font-mono)] text-xs leading-relaxed text-muted-foreground/60 italic whitespace-pre-wrap">
375
- {linkifyPaths(content)}
376
- {isStreaming && (
377
- <span
378
- className="inline-block h-1.5 w-1.5 rounded-full bg-primary ml-1"
379
- style={{ animation: "breathe 2s ease-in-out infinite" }}
380
- />
381
- )}
382
- </div>
383
- </div>
361
+ <ThinkingBlock
362
+ content={linkifyPaths(content)}
363
+ chars={content.length}
364
+ streaming={isStreaming}
365
+ open={expanded}
366
+ onOpenChange={setExpanded}
367
+ />
384
368
  );
385
369
  }
386
370
 
@@ -1,4 +1,4 @@
1
- import { uiConfig } from "../../config.js";
1
+ import type { BrainUiRoot } from "../../root.js";
2
2
  import type { RefObject } from "react";
3
3
  import { renderAndShare, shareFile, shareText, copyRichText } from "../../lib/share.js";
4
4
  import { stripMarkdown } from "../../lib/strip-markdown.js";
@@ -11,7 +11,7 @@ interface BuildOpts {
11
11
  renderedRef: RefObject<HTMLElement | null>;
12
12
  }
13
13
 
14
- export function buildMessageShareOptions({ content, renderedRef }: BuildOpts): ShareOption[] {
14
+ export function buildMessageShareOptions(root: BrainUiRoot, { content, renderedRef }: BuildOpts): ShareOption[] {
15
15
  const plain = () => stripMarkdown(content);
16
16
 
17
17
  return [
@@ -20,14 +20,14 @@ export function buildMessageShareOptions({ content, renderedRef }: BuildOpts): S
20
20
  label: "Image (PNG)",
21
21
  hint: "Rendered snapshot",
22
22
  run: async () =>
23
- renderAndShare({
23
+ renderAndShare(root, {
24
24
  // The render page runs without JavaScript, so mermaid fences are
25
25
  // pre-rendered to inline SVG here on the client.
26
26
  content: await inlineMermaidDiagrams(content),
27
27
  contentType: "markdown",
28
28
  format: "png",
29
29
  filename: "message",
30
- title: uiConfig.shareTitle,
30
+ title: root.config.shareTitle,
31
31
  }),
32
32
  },
33
33
  {
@@ -35,12 +35,12 @@ export function buildMessageShareOptions({ content, renderedRef }: BuildOpts): S
35
35
  label: "PDF",
36
36
  hint: "Vector PDF, A4",
37
37
  run: async () =>
38
- renderAndShare({
38
+ renderAndShare(root, {
39
39
  content: await inlineMermaidDiagrams(content),
40
40
  contentType: "markdown",
41
41
  format: "pdf",
42
42
  filename: "message",
43
- title: uiConfig.shareTitle,
43
+ title: root.config.shareTitle,
44
44
  }),
45
45
  },
46
46
  {
@@ -55,7 +55,7 @@ export function buildMessageShareOptions({ content, renderedRef }: BuildOpts): S
55
55
  hint: "Raw markdown verbatim",
56
56
  run: () =>
57
57
  shareFile(new File([content], "message.md", { type: "text/markdown" }), {
58
- title: uiConfig.shareTitle,
58
+ title: root.config.shareTitle,
59
59
  }),
60
60
  },
61
61
  {
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `bind(contract, Component)` — the client half of D3.
3
+ *
4
+ * The contract owns the payload schema; the component is typed
5
+ * `ToolPayload<contract>`, so a component that reads a field the tool stopped
6
+ * sending is a `tsc` error rather than an empty line in a chat log. At runtime
7
+ * the payload is parsed through the same schema, and a result that does not
8
+ * parse falls through to the caller's fallback view instead of throwing: the
9
+ * work already happened and the reader still wants to see it.
10
+ *
11
+ * One contract produces several renderers, because the same tool has a
12
+ * different name on each backend — `mcp__brain-ui__x` on Claude, bare `x` on
13
+ * pi, plus the pre-rename `mcp__brain_ui__x` that old transcripts carry. The
14
+ * timeline resolves on the raw streamed name, so all three are registered
15
+ * globally rather than scoped to one backend.
16
+ */
17
+
18
+ import type { ComponentType } from "react";
19
+ import {
20
+ parseToolPayload,
21
+ visibleToolName,
22
+ type ToolCallView,
23
+ type ToolComponentContract,
24
+ type ToolPayload,
25
+ type ToolRenderer,
26
+ } from "@schlessera/brain-ui-sdk/client";
27
+
28
+ /** Pre-rename MCP server prefix, still present in resumed transcripts. */
29
+ const LEGACY_MCP_PREFIX = "mcp__brain_ui__";
30
+
31
+ /** Every spelling of a contract's tool name that can arrive in the stream. */
32
+ export function boundToolNames(contract: ToolComponentContract): string[] {
33
+ return [
34
+ visibleToolName(contract.name, "pi"),
35
+ visibleToolName(contract.name, "claude"),
36
+ `${LEGACY_MCP_PREFIX}${contract.name}`,
37
+ ];
38
+ }
39
+
40
+ export interface BindOptions<Contract extends ToolComponentContract> {
41
+ icon?: ToolRenderer["icon"];
42
+ label?: string;
43
+ /** Collapsed one-liner, from the parsed payload. */
44
+ summary?: (payload: ToolPayload<Contract>, tool: ToolCallView) => string | null;
45
+ /** Secondary metadata line, from the parsed payload. */
46
+ meta?: (payload: ToolPayload<Contract>, tool: ToolCallView) => string | null;
47
+ /** Input view; the contract does not type this, the tool's own input does. */
48
+ Input?: ToolRenderer["Input"];
49
+ /**
50
+ * Rendered when the output is absent, is prose, or fails the payload schema
51
+ * — an errored call, an older server, a tool that answered with a message.
52
+ */
53
+ Fallback?: ComponentType<{ tool: ToolCallView }>;
54
+ }
55
+
56
+ export function bind<Contract extends ToolComponentContract>(
57
+ contract: Contract,
58
+ Component: ComponentType<ToolPayload<Contract>>,
59
+ options: BindOptions<Contract> = {}
60
+ ): ToolRenderer[] {
61
+ const { Fallback } = options;
62
+
63
+ // TS cannot spread an unresolved generic into JSX, so the spread — and only
64
+ // the spread — goes through an untyped alias. The public parameter above is
65
+ // what carries the guarantee: `Component` must accept the contract's payload.
66
+ const Spread = Component as ComponentType<Record<string, unknown>>;
67
+
68
+ function Output({ tool }: { tool: ToolCallView }) {
69
+ const payload = parseToolPayload(contract, tool.output);
70
+ if (payload === null) return Fallback ? <Fallback tool={tool} /> : null;
71
+ return <Spread {...(payload as Record<string, unknown>)} />;
72
+ }
73
+
74
+ function fromPayload(
75
+ read: ((payload: ToolPayload<Contract>, tool: ToolCallView) => string | null) | undefined
76
+ ): ((tool: ToolCallView) => string | null) | undefined {
77
+ if (!read) return undefined;
78
+ return (tool: ToolCallView) => {
79
+ const payload = parseToolPayload(contract, tool.output);
80
+ return payload === null ? null : read(payload, tool);
81
+ };
82
+ }
83
+
84
+ const renderer: Omit<ToolRenderer, "match"> = {
85
+ ...(options.icon ? { icon: options.icon } : {}),
86
+ ...(options.label ? { label: options.label } : {}),
87
+ ...(options.summary ? { summary: fromPayload(options.summary)! } : {}),
88
+ ...(options.meta ? { meta: fromPayload(options.meta)! } : {}),
89
+ ...(options.Input ? { Input: options.Input } : {}),
90
+ Output,
91
+ };
92
+
93
+ return boundToolNames(contract).map((match) => ({ match, ...renderer }));
94
+ }
@@ -0,0 +1,56 @@
1
+ // The chat UI's own in-process tools, rendered from their contracts.
2
+ //
3
+ // Unlike the per-backend packs, this one is GLOBAL: the same contract is
4
+ // exposed by every backend under that backend's spelling of the name, so
5
+ // `bind()` registers each spelling and resolution does not depend on which
6
+ // backend owns the session. That also fixes a real gap — the location result
7
+ // only ever had a renderer under Claude's MCP-prefixed name, so the identical
8
+ // tool on pi fell through to the generic JSON view.
9
+
10
+ import type { RendererPack } from "@schlessera/brain-ui-sdk/client";
11
+ import {
12
+ GET_CURRENT_LOCATION_CONTRACT,
13
+ REQUEST_IMAGE_MASK_CONTRACT,
14
+ SHOW_BLOCK_CONTRACT,
15
+ } from "@schlessera/brain-ui-sdk/client";
16
+ import { LayoutGrid, MapPin, Scissors } from "lucide-react";
17
+ import { BlockCard, blockSummary } from "../tool-cards/block-card.js";
18
+ import { LocationResultCard } from "../tool-cards/location-card.js";
19
+ import { ImageMaskResultCard, ImageMaskFallback } from "../tool-cards/image-mask-card.js";
20
+ import { ClampedPre } from "../tool-views.js";
21
+ import { bind } from "./bind.js";
22
+
23
+ export const brainUiToolPack: RendererPack = {
24
+ renderers: [
25
+ ...bind(GET_CURRENT_LOCATION_CONTRACT, LocationResultCard, {
26
+ icon: MapPin,
27
+ label: "Location",
28
+ summary: (payload) => payload.place ?? payload.address ?? null,
29
+ meta: (payload) => `±${Math.round(payload.accuracyMeters)} m`,
30
+ // A denial, a timeout or a browser without geolocation answers with a
31
+ // message, not a payload — the reader needs to see WHY there is no fix.
32
+ Fallback: ({ tool }) =>
33
+ tool.output ? <ClampedPre text={tool.output} isError={tool.isError} /> : null,
34
+ }),
35
+ ...bind(REQUEST_IMAGE_MASK_CONTRACT, ImageMaskResultCard, {
36
+ icon: Scissors,
37
+ label: "Mask",
38
+ summary: (payload) => payload.imagePath,
39
+ meta: (payload) => `mask ${payload.maskPath}`,
40
+ // A declined mask is an error with a message, not a payload. The fact
41
+ // belongs in the transcript in red, from the result's own words.
42
+ Fallback: ImageMaskFallback,
43
+ }),
44
+ // Rendered inline at the call's position by the transcript, not in the
45
+ // timeline; this binding is what the timeline uses when the payload does
46
+ // not parse (a rejected call, an older server), so the fact reaches the
47
+ // reader in the result's own words rather than as a blank.
48
+ ...bind(SHOW_BLOCK_CONTRACT, BlockCard, {
49
+ icon: LayoutGrid,
50
+ label: "Block",
51
+ summary: (payload) => blockSummary(payload),
52
+ Fallback: ({ tool }) =>
53
+ tool.output ? <ClampedPre text={tool.output} isError={tool.isError} /> : null,
54
+ }),
55
+ ],
56
+ };
@@ -10,7 +10,6 @@ import type {
10
10
  ToolSemantics,
11
11
  } from "@schlessera/brain-ui-sdk/client";
12
12
  import type { ToolCall } from "../../../stores/chat-store.js";
13
- import { GET_LOCATION_TOOL_NAME } from "../../../lib/tool-names.js";
14
13
  import {
15
14
  getToolIcon,
16
15
  getToolSummary,
@@ -34,7 +33,9 @@ const CLAUDE_TOOL_NAMES = [
34
33
  "Skill",
35
34
  "NotebookEdit",
36
35
  "LSP",
37
- GET_LOCATION_TOOL_NAME,
36
+ // `mcp__brain-ui__get_current_location` is deliberately NOT here: it is one
37
+ // of the chat UI's own contract-bound tools (`brain-ui-tools.tsx`), and a
38
+ // backend-scoped entry would beat that global renderer.
38
39
  ];
39
40
 
40
41
  // The shared views read brain-ui's richer ToolCall (status, inputJson, timing).