@schlessera/brain-ui-react 0.35.0 → 0.37.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 (761) 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 +148 -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 +29 -0
  19. package/dist/components/activity/approval-card.d.ts.map +1 -0
  20. package/dist/components/activity/approval-card.js +73 -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 +11 -0
  39. package/dist/components/activity/span-bits.d.ts.map +1 -1
  40. package/dist/components/activity/span-bits.js +50 -7
  41. package/dist/components/activity/span-bits.js.map +1 -1
  42. package/dist/components/chat/ask-user-card.d.ts +76 -3
  43. package/dist/components/chat/ask-user-card.d.ts.map +1 -1
  44. package/dist/components/chat/ask-user-card.js +208 -149
  45. package/dist/components/chat/ask-user-card.js.map +1 -1
  46. package/dist/components/chat/ask-user-typed.d.ts +42 -0
  47. package/dist/components/chat/ask-user-typed.d.ts.map +1 -0
  48. package/dist/components/chat/ask-user-typed.js +60 -0
  49. package/dist/components/chat/ask-user-typed.js.map +1 -0
  50. package/dist/components/chat/brain-markdown-links.d.ts +2 -1
  51. package/dist/components/chat/brain-markdown-links.d.ts.map +1 -1
  52. package/dist/components/chat/brain-markdown-links.js +3 -4
  53. package/dist/components/chat/brain-markdown-links.js.map +1 -1
  54. package/dist/components/chat/brain-markdown.d.ts.map +1 -1
  55. package/dist/components/chat/brain-markdown.js +4 -2
  56. package/dist/components/chat/brain-markdown.js.map +1 -1
  57. package/dist/components/chat/chat-page.d.ts.map +1 -1
  58. package/dist/components/chat/chat-page.js +27 -11
  59. package/dist/components/chat/chat-page.js.map +1 -1
  60. package/dist/components/chat/composer-view.d.ts +75 -0
  61. package/dist/components/chat/composer-view.d.ts.map +1 -0
  62. package/dist/components/chat/composer-view.js +31 -0
  63. package/dist/components/chat/composer-view.js.map +1 -0
  64. package/dist/components/chat/composer.d.ts +4 -0
  65. package/dist/components/chat/composer.d.ts.map +1 -1
  66. package/dist/components/chat/composer.js +76 -59
  67. package/dist/components/chat/composer.js.map +1 -1
  68. package/dist/components/chat/markdown-content.d.ts +16 -1
  69. package/dist/components/chat/markdown-content.d.ts.map +1 -1
  70. package/dist/components/chat/markdown-content.js +47 -3
  71. package/dist/components/chat/markdown-content.js.map +1 -1
  72. package/dist/components/chat/mermaid-block.d.ts +4 -0
  73. package/dist/components/chat/mermaid-block.d.ts.map +1 -1
  74. package/dist/components/chat/mermaid-block.js +13 -5
  75. package/dist/components/chat/mermaid-block.js.map +1 -1
  76. package/dist/components/chat/mermaid-share.d.ts +2 -1
  77. package/dist/components/chat/mermaid-share.d.ts.map +1 -1
  78. package/dist/components/chat/mermaid-share.js +7 -8
  79. package/dist/components/chat/mermaid-share.js.map +1 -1
  80. package/dist/components/chat/mermaid-viewer.d.ts.map +1 -1
  81. package/dist/components/chat/mermaid-viewer.js +3 -1
  82. package/dist/components/chat/mermaid-viewer.js.map +1 -1
  83. package/dist/components/chat/message-bubble.d.ts +8 -1
  84. package/dist/components/chat/message-bubble.d.ts.map +1 -1
  85. package/dist/components/chat/message-bubble.js +53 -24
  86. package/dist/components/chat/message-bubble.js.map +1 -1
  87. package/dist/components/chat/message-share.d.ts +2 -1
  88. package/dist/components/chat/message-share.d.ts.map +1 -1
  89. package/dist/components/chat/message-share.js +6 -7
  90. package/dist/components/chat/message-share.js.map +1 -1
  91. package/dist/components/chat/renderers/bind.d.ts +39 -0
  92. package/dist/components/chat/renderers/bind.d.ts.map +1 -0
  93. package/dist/components/chat/renderers/bind.js +43 -0
  94. package/dist/components/chat/renderers/bind.js.map +1 -0
  95. package/dist/components/chat/renderers/brain-ui-tools.d.ts +3 -0
  96. package/dist/components/chat/renderers/brain-ui-tools.d.ts.map +1 -0
  97. package/dist/components/chat/renderers/brain-ui-tools.js +41 -0
  98. package/dist/components/chat/renderers/brain-ui-tools.js.map +1 -0
  99. package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -1
  100. package/dist/components/chat/renderers/claude-tools.js +3 -2
  101. package/dist/components/chat/renderers/claude-tools.js.map +1 -1
  102. package/dist/components/chat/renderers/index.d.ts +10 -2
  103. package/dist/components/chat/renderers/index.d.ts.map +1 -1
  104. package/dist/components/chat/renderers/index.js +15 -10
  105. package/dist/components/chat/renderers/index.js.map +1 -1
  106. package/dist/components/chat/session-drawer.d.ts +4 -0
  107. package/dist/components/chat/session-drawer.d.ts.map +1 -1
  108. package/dist/components/chat/session-drawer.js +32 -32
  109. package/dist/components/chat/session-drawer.js.map +1 -1
  110. package/dist/components/chat/session-list.d.ts +41 -0
  111. package/dist/components/chat/session-list.d.ts.map +1 -0
  112. package/dist/components/chat/session-list.js +10 -0
  113. package/dist/components/chat/session-list.js.map +1 -0
  114. package/dist/components/chat/share-block.d.ts.map +1 -1
  115. package/dist/components/chat/share-block.js +12 -11
  116. package/dist/components/chat/share-block.js.map +1 -1
  117. package/dist/components/chat/share-card.js +2 -2
  118. package/dist/components/chat/share-card.js.map +1 -1
  119. package/dist/components/chat/subagent-view.js +1 -1
  120. package/dist/components/chat/subagent-view.js.map +1 -1
  121. package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
  122. package/dist/components/chat/tool-call-timeline.js +45 -14
  123. package/dist/components/chat/tool-call-timeline.js.map +1 -1
  124. package/dist/components/chat/tool-cards/block-card.d.ts +28 -0
  125. package/dist/components/chat/tool-cards/block-card.d.ts.map +1 -0
  126. package/dist/components/chat/tool-cards/block-card.js +103 -0
  127. package/dist/components/chat/tool-cards/block-card.js.map +1 -0
  128. package/dist/components/chat/tool-cards/image-mask-card.d.ts +70 -0
  129. package/dist/components/chat/tool-cards/image-mask-card.d.ts.map +1 -0
  130. package/dist/components/chat/tool-cards/image-mask-card.js +142 -0
  131. package/dist/components/chat/tool-cards/image-mask-card.js.map +1 -0
  132. package/dist/components/chat/tool-cards/location-card.d.ts +45 -0
  133. package/dist/components/chat/tool-cards/location-card.d.ts.map +1 -0
  134. package/dist/components/chat/tool-cards/location-card.js +128 -0
  135. package/dist/components/chat/tool-cards/location-card.js.map +1 -0
  136. package/dist/components/chat/tool-views.d.ts +19 -2
  137. package/dist/components/chat/tool-views.d.ts.map +1 -1
  138. package/dist/components/chat/tool-views.js +28 -22
  139. package/dist/components/chat/tool-views.js.map +1 -1
  140. package/dist/components/chat/transcript-turn.d.ts +45 -0
  141. package/dist/components/chat/transcript-turn.d.ts.map +1 -0
  142. package/dist/components/chat/transcript-turn.js +25 -0
  143. package/dist/components/chat/transcript-turn.js.map +1 -0
  144. package/dist/components/chat/use-chat-commands.d.ts.map +1 -1
  145. package/dist/components/chat/use-chat-commands.js +13 -16
  146. package/dist/components/chat/use-chat-commands.js.map +1 -1
  147. package/dist/components/chat/welcome-state.d.ts +7 -0
  148. package/dist/components/chat/welcome-state.d.ts.map +1 -1
  149. package/dist/components/chat/welcome-state.js +13 -5
  150. package/dist/components/chat/welcome-state.js.map +1 -1
  151. package/dist/components/connectivity/connection-gate.d.ts.map +1 -1
  152. package/dist/components/connectivity/connection-gate.js +27 -21
  153. package/dist/components/connectivity/connection-gate.js.map +1 -1
  154. package/dist/components/connectivity/login-form.d.ts +31 -0
  155. package/dist/components/connectivity/login-form.d.ts.map +1 -0
  156. package/dist/components/connectivity/login-form.js +19 -0
  157. package/dist/components/connectivity/login-form.js.map +1 -0
  158. package/dist/components/connectivity/login-screen.d.ts +5 -2
  159. package/dist/components/connectivity/login-screen.d.ts.map +1 -1
  160. package/dist/components/connectivity/login-screen.js +41 -31
  161. package/dist/components/connectivity/login-screen.js.map +1 -1
  162. package/dist/components/dev/share-harness.js +1 -1
  163. package/dist/components/dev/share-harness.js.map +1 -1
  164. package/dist/components/files/file-panel.d.ts +1 -1
  165. package/dist/components/files/file-panel.d.ts.map +1 -1
  166. package/dist/components/files/file-panel.js +74 -0
  167. package/dist/components/files/file-panel.js.map +1 -1
  168. package/dist/components/files/file-tree-view.d.ts +45 -0
  169. package/dist/components/files/file-tree-view.d.ts.map +1 -0
  170. package/dist/components/files/file-tree-view.js +51 -0
  171. package/dist/components/files/file-tree-view.js.map +1 -0
  172. package/dist/components/files/file-tree.d.ts +6 -0
  173. package/dist/components/files/file-tree.d.ts.map +1 -1
  174. package/dist/components/files/file-tree.js +39 -43
  175. package/dist/components/files/file-tree.js.map +1 -1
  176. package/dist/components/files/file-viewer-binary.d.ts.map +1 -1
  177. package/dist/components/files/file-viewer-binary.js +3 -2
  178. package/dist/components/files/file-viewer-binary.js.map +1 -1
  179. package/dist/components/files/file-viewer-frame.d.ts +36 -0
  180. package/dist/components/files/file-viewer-frame.d.ts.map +1 -0
  181. package/dist/components/files/file-viewer-frame.js +26 -0
  182. package/dist/components/files/file-viewer-frame.js.map +1 -0
  183. package/dist/components/files/file-viewer.d.ts +5 -0
  184. package/dist/components/files/file-viewer.d.ts.map +1 -1
  185. package/dist/components/files/file-viewer.js +26 -32
  186. package/dist/components/files/file-viewer.js.map +1 -1
  187. package/dist/components/files/frontmatter-chips.d.ts +18 -0
  188. package/dist/components/files/frontmatter-chips.d.ts.map +1 -0
  189. package/dist/components/files/frontmatter-chips.js +11 -0
  190. package/dist/components/files/frontmatter-chips.js.map +1 -0
  191. package/dist/components/files/frontmatter-panel.d.ts +5 -1
  192. package/dist/components/files/frontmatter-panel.d.ts.map +1 -1
  193. package/dist/components/files/frontmatter-panel.js +7 -6
  194. package/dist/components/files/frontmatter-panel.js.map +1 -1
  195. package/dist/components/files/staleness.d.ts +18 -0
  196. package/dist/components/files/staleness.d.ts.map +1 -0
  197. package/dist/components/files/staleness.js +27 -0
  198. package/dist/components/files/staleness.js.map +1 -0
  199. package/dist/components/graph/graph-canvas.d.ts.map +1 -1
  200. package/dist/components/graph/graph-canvas.js +24 -1
  201. package/dist/components/graph/graph-canvas.js.map +1 -1
  202. package/dist/components/graph/graph-controls-column.d.ts +14 -0
  203. package/dist/components/graph/graph-controls-column.d.ts.map +1 -0
  204. package/dist/components/graph/graph-controls-column.js +44 -0
  205. package/dist/components/graph/graph-controls-column.js.map +1 -0
  206. package/dist/components/graph/graph-controls.d.ts +20 -5
  207. package/dist/components/graph/graph-controls.d.ts.map +1 -1
  208. package/dist/components/graph/graph-controls.js +58 -37
  209. package/dist/components/graph/graph-controls.js.map +1 -1
  210. package/dist/components/graph/graph-form.d.ts +82 -0
  211. package/dist/components/graph/graph-form.d.ts.map +1 -0
  212. package/dist/components/graph/graph-form.js +69 -0
  213. package/dist/components/graph/graph-form.js.map +1 -0
  214. package/dist/components/graph/graph-maintenance.d.ts.map +1 -1
  215. package/dist/components/graph/graph-maintenance.js +6 -10
  216. package/dist/components/graph/graph-maintenance.js.map +1 -1
  217. package/dist/components/graph/graph-node-rail.d.ts +13 -0
  218. package/dist/components/graph/graph-node-rail.d.ts.map +1 -0
  219. package/dist/components/graph/graph-node-rail.js +92 -0
  220. package/dist/components/graph/graph-node-rail.js.map +1 -0
  221. package/dist/components/graph/graph-page.d.ts +7 -0
  222. package/dist/components/graph/graph-page.d.ts.map +1 -1
  223. package/dist/components/graph/graph-page.js +102 -12
  224. package/dist/components/graph/graph-page.js.map +1 -1
  225. package/dist/components/graph/graph-scene.d.ts.map +1 -1
  226. package/dist/components/graph/graph-scene.js +100 -24
  227. package/dist/components/graph/graph-scene.js.map +1 -1
  228. package/dist/components/graph/lib/graph-helpers.d.ts +42 -12
  229. package/dist/components/graph/lib/graph-helpers.d.ts.map +1 -1
  230. package/dist/components/graph/lib/graph-helpers.js +33 -41
  231. package/dist/components/graph/lib/graph-helpers.js.map +1 -1
  232. package/dist/components/graph/node-card.d.ts +28 -0
  233. package/dist/components/graph/node-card.d.ts.map +1 -0
  234. package/dist/components/graph/node-card.js +7 -0
  235. package/dist/components/graph/node-card.js.map +1 -0
  236. package/dist/components/graph/node-popover.d.ts +6 -2
  237. package/dist/components/graph/node-popover.d.ts.map +1 -1
  238. package/dist/components/graph/node-popover.js +13 -31
  239. package/dist/components/graph/node-popover.js.map +1 -1
  240. package/dist/components/graph/use-graph-theme.d.ts +32 -4
  241. package/dist/components/graph/use-graph-theme.d.ts.map +1 -1
  242. package/dist/components/graph/use-graph-theme.js +44 -32
  243. package/dist/components/graph/use-graph-theme.js.map +1 -1
  244. package/dist/components/graph/use-node-actions.d.ts +26 -0
  245. package/dist/components/graph/use-node-actions.d.ts.map +1 -0
  246. package/dist/components/graph/use-node-actions.js +54 -0
  247. package/dist/components/graph/use-node-actions.js.map +1 -0
  248. package/dist/components/images/image-share.d.ts +2 -1
  249. package/dist/components/images/image-share.d.ts.map +1 -1
  250. package/dist/components/images/image-share.js +3 -3
  251. package/dist/components/images/image-share.js.map +1 -1
  252. package/dist/components/images/image-viewer.d.ts.map +1 -1
  253. package/dist/components/images/image-viewer.js +3 -1
  254. package/dist/components/images/image-viewer.js.map +1 -1
  255. package/dist/components/images/mask-editor.d.ts.map +1 -1
  256. package/dist/components/images/mask-editor.js +7 -5
  257. package/dist/components/images/mask-editor.js.map +1 -1
  258. package/dist/components/layout/app-shell.d.ts.map +1 -1
  259. package/dist/components/layout/app-shell.js +4 -1
  260. package/dist/components/layout/app-shell.js.map +1 -1
  261. package/dist/components/layout/desktop-palette.d.ts +23 -0
  262. package/dist/components/layout/desktop-palette.d.ts.map +1 -0
  263. package/dist/components/layout/desktop-palette.js +132 -0
  264. package/dist/components/layout/desktop-palette.js.map +1 -0
  265. package/dist/components/layout/key-cap.d.ts +9 -0
  266. package/dist/components/layout/key-cap.d.ts.map +1 -0
  267. package/dist/components/layout/key-cap.js +10 -0
  268. package/dist/components/layout/key-cap.js.map +1 -0
  269. package/dist/components/layout/mobile-tab-bar.d.ts +13 -0
  270. package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
  271. package/dist/components/layout/mobile-tab-bar.js +58 -47
  272. package/dist/components/layout/mobile-tab-bar.js.map +1 -1
  273. package/dist/components/layout/shortcut-switch.d.ts +13 -0
  274. package/dist/components/layout/shortcut-switch.d.ts.map +1 -0
  275. package/dist/components/layout/shortcut-switch.js +22 -0
  276. package/dist/components/layout/shortcut-switch.js.map +1 -0
  277. package/dist/components/layout/side-rail.d.ts +28 -0
  278. package/dist/components/layout/side-rail.d.ts.map +1 -1
  279. package/dist/components/layout/side-rail.js +72 -27
  280. package/dist/components/layout/side-rail.js.map +1 -1
  281. package/dist/components/layout/slide-panel.d.ts +25 -2
  282. package/dist/components/layout/slide-panel.d.ts.map +1 -1
  283. package/dist/components/layout/slide-panel.js +13 -4
  284. package/dist/components/layout/slide-panel.js.map +1 -1
  285. package/dist/components/layout/theme.d.ts +22 -0
  286. package/dist/components/layout/theme.d.ts.map +1 -0
  287. package/dist/components/layout/theme.js +44 -0
  288. package/dist/components/layout/theme.js.map +1 -0
  289. package/dist/components/quick-actions/add-form.d.ts +44 -0
  290. package/dist/components/quick-actions/add-form.d.ts.map +1 -0
  291. package/dist/components/quick-actions/add-form.js +32 -0
  292. package/dist/components/quick-actions/add-form.js.map +1 -0
  293. package/dist/components/quick-actions/add-modal.d.ts +7 -0
  294. package/dist/components/quick-actions/add-modal.d.ts.map +1 -1
  295. package/dist/components/quick-actions/add-modal.js +23 -20
  296. package/dist/components/quick-actions/add-modal.js.map +1 -1
  297. package/dist/components/quick-actions/search-modal.d.ts.map +1 -1
  298. package/dist/components/quick-actions/search-modal.js +8 -5
  299. package/dist/components/quick-actions/search-modal.js.map +1 -1
  300. package/dist/components/quick-actions/streaming-modal.d.ts +6 -0
  301. package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -1
  302. package/dist/components/quick-actions/streaming-modal.js +53 -18
  303. package/dist/components/quick-actions/streaming-modal.js.map +1 -1
  304. package/dist/components/quick-actions/streaming-output.d.ts +38 -0
  305. package/dist/components/quick-actions/streaming-output.d.ts.map +1 -0
  306. package/dist/components/quick-actions/streaming-output.js +22 -0
  307. package/dist/components/quick-actions/streaming-output.js.map +1 -0
  308. package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
  309. package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -1
  310. package/dist/components/quick-actions/whatsup-modal.js +51 -10
  311. package/dist/components/quick-actions/whatsup-modal.js.map +1 -1
  312. package/dist/components/settings/devices-agents-tab.d.ts +6 -1
  313. package/dist/components/settings/devices-agents-tab.d.ts.map +1 -1
  314. package/dist/components/settings/devices-agents-tab.js +55 -20
  315. package/dist/components/settings/devices-agents-tab.js.map +1 -1
  316. package/dist/components/settings/models-list.d.ts +39 -0
  317. package/dist/components/settings/models-list.d.ts.map +1 -0
  318. package/dist/components/settings/models-list.js +72 -0
  319. package/dist/components/settings/models-list.js.map +1 -0
  320. package/dist/components/settings/models-tab.d.ts +4 -0
  321. package/dist/components/settings/models-tab.d.ts.map +1 -1
  322. package/dist/components/settings/models-tab.js +52 -102
  323. package/dist/components/settings/models-tab.js.map +1 -1
  324. package/dist/components/settings/one-time-agent-credential.js +1 -1
  325. package/dist/components/settings/one-time-agent-credential.js.map +1 -1
  326. package/dist/components/settings/passkey-list.d.ts +35 -0
  327. package/dist/components/settings/passkey-list.d.ts.map +1 -0
  328. package/dist/components/settings/passkey-list.js +34 -0
  329. package/dist/components/settings/passkey-list.js.map +1 -0
  330. package/dist/components/settings/passkey-tab.d.ts +3 -0
  331. package/dist/components/settings/passkey-tab.d.ts.map +1 -1
  332. package/dist/components/settings/passkey-tab.js +53 -45
  333. package/dist/components/settings/passkey-tab.js.map +1 -1
  334. package/dist/components/settings/pi-accounts-list.d.ts +27 -0
  335. package/dist/components/settings/pi-accounts-list.d.ts.map +1 -0
  336. package/dist/components/settings/pi-accounts-list.js +15 -0
  337. package/dist/components/settings/pi-accounts-list.js.map +1 -0
  338. package/dist/components/settings/pi-accounts.d.ts +3 -0
  339. package/dist/components/settings/pi-accounts.d.ts.map +1 -1
  340. package/dist/components/settings/pi-accounts.js +73 -55
  341. package/dist/components/settings/pi-accounts.js.map +1 -1
  342. package/dist/components/settings/principal-list.d.ts +37 -0
  343. package/dist/components/settings/principal-list.d.ts.map +1 -0
  344. package/dist/components/settings/principal-list.js +18 -0
  345. package/dist/components/settings/principal-list.js.map +1 -0
  346. package/dist/components/settings/settings-panel.d.ts +10 -3
  347. package/dist/components/settings/settings-panel.d.ts.map +1 -1
  348. package/dist/components/settings/settings-panel.js +71 -10
  349. package/dist/components/settings/settings-panel.js.map +1 -1
  350. package/dist/components/settings/skills-list.d.ts +53 -0
  351. package/dist/components/settings/skills-list.d.ts.map +1 -0
  352. package/dist/components/settings/skills-list.js +28 -0
  353. package/dist/components/settings/skills-list.js.map +1 -0
  354. package/dist/components/settings/skills-tab.d.ts.map +1 -1
  355. package/dist/components/settings/skills-tab.js +65 -38
  356. package/dist/components/settings/skills-tab.js.map +1 -1
  357. package/dist/components/settings/tool-permissions-list.d.ts +18 -0
  358. package/dist/components/settings/tool-permissions-list.d.ts.map +1 -0
  359. package/dist/components/settings/tool-permissions-list.js +6 -0
  360. package/dist/components/settings/tool-permissions-list.js.map +1 -0
  361. package/dist/components/settings/tool-permissions.d.ts +2 -1
  362. package/dist/components/settings/tool-permissions.d.ts.map +1 -1
  363. package/dist/components/settings/tool-permissions.js +33 -16
  364. package/dist/components/settings/tool-permissions.js.map +1 -1
  365. package/dist/components/settings/web-search-chain.d.ts +41 -0
  366. package/dist/components/settings/web-search-chain.d.ts.map +1 -0
  367. package/dist/components/settings/web-search-chain.js +47 -0
  368. package/dist/components/settings/web-search-chain.js.map +1 -0
  369. package/dist/components/settings/web-search-settings.d.ts +4 -7
  370. package/dist/components/settings/web-search-settings.d.ts.map +1 -1
  371. package/dist/components/settings/web-search-settings.js +54 -76
  372. package/dist/components/settings/web-search-settings.js.map +1 -1
  373. package/dist/components/share/share-menu.d.ts.map +1 -1
  374. package/dist/components/share/share-menu.js +24 -4
  375. package/dist/components/share/share-menu.js.map +1 -1
  376. package/dist/components/voice/dictation-sheet.js +3 -3
  377. package/dist/components/voice/dictation-sheet.js.map +1 -1
  378. package/dist/components/voice/mic-button.js +1 -1
  379. package/dist/components/voice/mic-button.js.map +1 -1
  380. package/dist/components/voice/review-card.js +1 -1
  381. package/dist/components/voice/review-card.js.map +1 -1
  382. package/dist/config.d.ts +5 -2
  383. package/dist/config.d.ts.map +1 -1
  384. package/dist/config.js +15 -5
  385. package/dist/config.js.map +1 -1
  386. package/dist/connection.d.ts +12 -0
  387. package/dist/connection.d.ts.map +1 -0
  388. package/dist/connection.js +421 -0
  389. package/dist/connection.js.map +1 -0
  390. package/dist/default-root.d.ts +3 -0
  391. package/dist/default-root.d.ts.map +1 -0
  392. package/dist/default-root.js +16 -0
  393. package/dist/default-root.js.map +1 -0
  394. package/dist/hooks/use-color-scheme.d.ts +14 -0
  395. package/dist/hooks/use-color-scheme.d.ts.map +1 -0
  396. package/dist/hooks/use-color-scheme.js +37 -0
  397. package/dist/hooks/use-color-scheme.js.map +1 -0
  398. package/dist/hooks/use-fine-pointer.d.ts +12 -0
  399. package/dist/hooks/use-fine-pointer.d.ts.map +1 -0
  400. package/dist/hooks/use-fine-pointer.js +15 -0
  401. package/dist/hooks/use-fine-pointer.js.map +1 -0
  402. package/dist/hooks/use-hash-routes.d.ts.map +1 -1
  403. package/dist/hooks/use-hash-routes.js +4 -2
  404. package/dist/hooks/use-hash-routes.js.map +1 -1
  405. package/dist/hooks/use-media-query.d.ts +9 -0
  406. package/dist/hooks/use-media-query.d.ts.map +1 -0
  407. package/dist/hooks/use-media-query.js +38 -0
  408. package/dist/hooks/use-media-query.js.map +1 -0
  409. package/dist/hooks/use-share-intake.d.ts.map +1 -1
  410. package/dist/hooks/use-share-intake.js +37 -12
  411. package/dist/hooks/use-share-intake.js.map +1 -1
  412. package/dist/hooks/use-vpn-status.d.ts.map +1 -1
  413. package/dist/hooks/use-vpn-status.js +17 -18
  414. package/dist/hooks/use-vpn-status.js.map +1 -1
  415. package/dist/hooks/use-websocket.d.ts +5 -24
  416. package/dist/hooks/use-websocket.d.ts.map +1 -1
  417. package/dist/hooks/use-websocket.js +11 -384
  418. package/dist/hooks/use-websocket.js.map +1 -1
  419. package/dist/hooks/websocket-handlers/activity.d.ts +2 -2
  420. package/dist/hooks/websocket-handlers/activity.d.ts.map +1 -1
  421. package/dist/hooks/websocket-handlers/activity.js +4 -5
  422. package/dist/hooks/websocket-handlers/activity.js.map +1 -1
  423. package/dist/hooks/websocket-handlers/chat.d.ts +1 -0
  424. package/dist/hooks/websocket-handlers/chat.d.ts.map +1 -1
  425. package/dist/hooks/websocket-handlers/chat.js +28 -6
  426. package/dist/hooks/websocket-handlers/chat.js.map +1 -1
  427. package/dist/hooks/websocket-handlers/connection.d.ts.map +1 -1
  428. package/dist/hooks/websocket-handlers/connection.js +4 -6
  429. package/dist/hooks/websocket-handlers/connection.js.map +1 -1
  430. package/dist/hooks/websocket-handlers/mask.d.ts +1 -1
  431. package/dist/hooks/websocket-handlers/mask.d.ts.map +1 -1
  432. package/dist/hooks/websocket-handlers/mask.js +2 -3
  433. package/dist/hooks/websocket-handlers/mask.js.map +1 -1
  434. package/dist/hooks/websocket-handlers/provider.d.ts.map +1 -1
  435. package/dist/hooks/websocket-handlers/provider.js +4 -6
  436. package/dist/hooks/websocket-handlers/provider.js.map +1 -1
  437. package/dist/hooks/websocket-handlers/types.d.ts +6 -2
  438. package/dist/hooks/websocket-handlers/types.d.ts.map +1 -1
  439. package/dist/index.d.ts +5 -3
  440. package/dist/index.d.ts.map +1 -1
  441. package/dist/index.js +6 -3
  442. package/dist/index.js.map +1 -1
  443. package/dist/lib/api-client.d.ts +289 -0
  444. package/dist/lib/api-client.d.ts.map +1 -1
  445. package/dist/lib/api-client.js +243 -224
  446. package/dist/lib/api-client.js.map +1 -1
  447. package/dist/lib/backend.d.ts +19 -2
  448. package/dist/lib/backend.d.ts.map +1 -1
  449. package/dist/lib/backend.js +15 -9
  450. package/dist/lib/backend.js.map +1 -1
  451. package/dist/lib/diff.d.ts +8 -10
  452. package/dist/lib/diff.d.ts.map +1 -1
  453. package/dist/lib/diff.js +26 -53
  454. package/dist/lib/diff.js.map +1 -1
  455. package/dist/lib/light-dark.d.ts +37 -0
  456. package/dist/lib/light-dark.d.ts.map +1 -0
  457. package/dist/lib/light-dark.js +83 -0
  458. package/dist/lib/light-dark.js.map +1 -0
  459. package/dist/lib/mermaid-theme.d.ts +7 -2
  460. package/dist/lib/mermaid-theme.d.ts.map +1 -1
  461. package/dist/lib/mermaid-theme.js +125 -203
  462. package/dist/lib/mermaid-theme.js.map +1 -1
  463. package/dist/lib/passkeys.d.ts +6 -3
  464. package/dist/lib/passkeys.d.ts.map +1 -1
  465. package/dist/lib/passkeys.js +10 -4
  466. package/dist/lib/passkeys.js.map +1 -1
  467. package/dist/lib/push-registration.d.ts +4 -1
  468. package/dist/lib/push-registration.d.ts.map +1 -1
  469. package/dist/lib/push-registration.js +20 -2
  470. package/dist/lib/push-registration.js.map +1 -1
  471. package/dist/lib/share-intake.d.ts +2 -1
  472. package/dist/lib/share-intake.d.ts.map +1 -1
  473. package/dist/lib/share-intake.js +3 -3
  474. package/dist/lib/share-intake.js.map +1 -1
  475. package/dist/lib/share.d.ts +4 -3
  476. package/dist/lib/share.d.ts.map +1 -1
  477. package/dist/lib/share.js +6 -7
  478. package/dist/lib/share.js.map +1 -1
  479. package/dist/lib/single-key.d.ts +30 -0
  480. package/dist/lib/single-key.d.ts.map +1 -0
  481. package/dist/lib/single-key.js +45 -0
  482. package/dist/lib/single-key.js.map +1 -0
  483. package/dist/lib/tool-names.d.ts +8 -6
  484. package/dist/lib/tool-names.d.ts.map +1 -1
  485. package/dist/lib/tool-names.js +17 -7
  486. package/dist/lib/tool-names.js.map +1 -1
  487. package/dist/root-context.d.ts +229 -0
  488. package/dist/root-context.d.ts.map +1 -0
  489. package/dist/root-context.js +33 -0
  490. package/dist/root-context.js.map +1 -0
  491. package/dist/root.d.ts +38 -0
  492. package/dist/root.d.ts.map +1 -0
  493. package/dist/root.js +47 -0
  494. package/dist/root.js.map +1 -0
  495. package/dist/stores/activity-state.d.ts +29 -0
  496. package/dist/stores/activity-state.d.ts.map +1 -0
  497. package/dist/stores/activity-state.js +282 -0
  498. package/dist/stores/activity-state.js.map +1 -0
  499. package/dist/stores/activity-store.d.ts +10 -41
  500. package/dist/stores/activity-store.d.ts.map +1 -1
  501. package/dist/stores/activity-store.js +9 -271
  502. package/dist/stores/activity-store.js.map +1 -1
  503. package/dist/stores/chat-state.d.ts +233 -0
  504. package/dist/stores/chat-state.d.ts.map +1 -0
  505. package/dist/stores/chat-state.js +477 -0
  506. package/dist/stores/chat-state.js.map +1 -0
  507. package/dist/stores/chat-store.d.ts +4 -162
  508. package/dist/stores/chat-store.d.ts.map +1 -1
  509. package/dist/stores/chat-store.js +7 -418
  510. package/dist/stores/chat-store.js.map +1 -1
  511. package/dist/stores/connection-state.d.ts +40 -0
  512. package/dist/stores/connection-state.d.ts.map +1 -0
  513. package/dist/stores/connection-state.js +30 -0
  514. package/dist/stores/connection-state.js.map +1 -0
  515. package/dist/stores/connection-store.d.ts +4 -40
  516. package/dist/stores/connection-store.d.ts.map +1 -1
  517. package/dist/stores/connection-store.js +7 -27
  518. package/dist/stores/connection-store.js.map +1 -1
  519. package/dist/stores/create-stores.d.ts +23 -0
  520. package/dist/stores/create-stores.d.ts.map +1 -0
  521. package/dist/stores/create-stores.js +28 -0
  522. package/dist/stores/create-stores.js.map +1 -0
  523. package/dist/stores/file-state.d.ts +53 -0
  524. package/dist/stores/file-state.d.ts.map +1 -0
  525. package/dist/stores/file-state.js +341 -0
  526. package/dist/stores/file-state.js.map +1 -0
  527. package/dist/stores/file-store.d.ts +4 -52
  528. package/dist/stores/file-store.d.ts.map +1 -1
  529. package/dist/stores/file-store.js +7 -336
  530. package/dist/stores/file-store.js.map +1 -1
  531. package/dist/stores/graph-state.d.ts +95 -0
  532. package/dist/stores/graph-state.d.ts.map +1 -0
  533. package/dist/stores/graph-state.js +252 -0
  534. package/dist/stores/graph-state.js.map +1 -0
  535. package/dist/stores/graph-store.d.ts +7 -83
  536. package/dist/stores/graph-store.d.ts.map +1 -1
  537. package/dist/stores/graph-store.js +8 -249
  538. package/dist/stores/graph-store.js.map +1 -1
  539. package/dist/stores/mask-state.d.ts +21 -0
  540. package/dist/stores/mask-state.d.ts.map +1 -0
  541. package/dist/stores/mask-state.js +9 -0
  542. package/dist/stores/mask-state.js.map +1 -0
  543. package/dist/stores/mask-store.d.ts +4 -21
  544. package/dist/stores/mask-store.d.ts.map +1 -1
  545. package/dist/stores/mask-store.js +7 -6
  546. package/dist/stores/mask-store.js.map +1 -1
  547. package/dist/stores/principal-state.d.ts +16 -0
  548. package/dist/stores/principal-state.d.ts.map +1 -0
  549. package/dist/stores/principal-state.js +31 -0
  550. package/dist/stores/principal-state.js.map +1 -0
  551. package/dist/stores/principal-store.d.ts +4 -15
  552. package/dist/stores/principal-store.d.ts.map +1 -1
  553. package/dist/stores/principal-store.js +7 -28
  554. package/dist/stores/principal-store.js.map +1 -1
  555. package/dist/stores/provider-state.d.ts +24 -0
  556. package/dist/stores/provider-state.d.ts.map +1 -0
  557. package/dist/stores/provider-state.js +68 -0
  558. package/dist/stores/provider-state.js.map +1 -0
  559. package/dist/stores/provider-store.d.ts +4 -23
  560. package/dist/stores/provider-store.d.ts.map +1 -1
  561. package/dist/stores/provider-store.js +7 -64
  562. package/dist/stores/provider-store.js.map +1 -1
  563. package/dist/stores/share-state.d.ts +29 -0
  564. package/dist/stores/share-state.d.ts.map +1 -0
  565. package/dist/stores/share-state.js +21 -0
  566. package/dist/stores/share-state.js.map +1 -0
  567. package/dist/stores/share-store.d.ts +4 -28
  568. package/dist/stores/share-store.d.ts.map +1 -1
  569. package/dist/stores/share-store.js +7 -18
  570. package/dist/stores/share-store.js.map +1 -1
  571. package/dist/stores/store-environment.d.ts +10 -0
  572. package/dist/stores/store-environment.d.ts.map +1 -0
  573. package/dist/stores/store-environment.js +2 -0
  574. package/dist/stores/store-environment.js.map +1 -0
  575. package/dist/stores/ui-state.d.ts +71 -0
  576. package/dist/stores/ui-state.d.ts.map +1 -0
  577. package/dist/stores/ui-state.js +58 -0
  578. package/dist/stores/ui-state.js.map +1 -0
  579. package/dist/stores/ui-store.d.ts +4 -45
  580. package/dist/stores/ui-store.d.ts.map +1 -1
  581. package/dist/stores/ui-store.js +7 -36
  582. package/dist/stores/ui-store.js.map +1 -1
  583. package/dist/styles.css +1 -1
  584. package/dist/theme.css +150 -97
  585. package/dist/voice/asr-clients.d.ts +2 -1
  586. package/dist/voice/asr-clients.d.ts.map +1 -1
  587. package/dist/voice/asr-clients.js +16 -17
  588. package/dist/voice/asr-clients.js.map +1 -1
  589. package/dist/voice/use-dictation.d.ts.map +1 -1
  590. package/dist/voice/use-dictation.js +12 -8
  591. package/dist/voice/use-dictation.js.map +1 -1
  592. package/dist/voice/voice-state.d.ts +25 -0
  593. package/dist/voice/voice-state.d.ts.map +1 -0
  594. package/dist/voice/voice-state.js +29 -0
  595. package/dist/voice/voice-state.js.map +1 -0
  596. package/dist/voice/voice-store.d.ts +4 -25
  597. package/dist/voice/voice-store.d.ts.map +1 -1
  598. package/dist/voice/voice-store.js +7 -26
  599. package/dist/voice/voice-store.js.map +1 -1
  600. package/package.json +3 -2
  601. package/src/components/activity/activity-page.tsx +341 -160
  602. package/src/components/activity/activity-run-detail.tsx +81 -47
  603. package/src/components/activity/activity-run-list.tsx +27 -59
  604. package/src/components/activity/activity-views.tsx +155 -0
  605. package/src/components/activity/approval-card.tsx +117 -0
  606. package/src/components/activity/digest-card.tsx +25 -61
  607. package/src/components/activity/digest-summary.tsx +52 -0
  608. package/src/components/activity/push-switch.tsx +62 -0
  609. package/src/components/activity/push-toggle.tsx +51 -81
  610. package/src/components/activity/span-bits.tsx +60 -7
  611. package/src/components/chat/ask-user-card.tsx +292 -356
  612. package/src/components/chat/ask-user-typed.ts +77 -0
  613. package/src/components/chat/brain-markdown-links.tsx +4 -4
  614. package/src/components/chat/brain-markdown.tsx +4 -2
  615. package/src/components/chat/chat-page.tsx +41 -11
  616. package/src/components/chat/composer-view.tsx +194 -0
  617. package/src/components/chat/composer.tsx +117 -296
  618. package/src/components/chat/markdown-content.tsx +53 -2
  619. package/src/components/chat/mermaid-block.tsx +13 -5
  620. package/src/components/chat/mermaid-share.ts +8 -7
  621. package/src/components/chat/mermaid-viewer.tsx +3 -1
  622. package/src/components/chat/message-bubble.tsx +78 -94
  623. package/src/components/chat/message-share.ts +7 -7
  624. package/src/components/chat/renderers/bind.tsx +94 -0
  625. package/src/components/chat/renderers/brain-ui-tools.tsx +56 -0
  626. package/src/components/chat/renderers/claude-tools.tsx +3 -2
  627. package/src/components/chat/renderers/index.ts +15 -10
  628. package/src/components/chat/session-drawer.tsx +41 -138
  629. package/src/components/chat/session-list.tsx +113 -0
  630. package/src/components/chat/share-block.tsx +16 -12
  631. package/src/components/chat/share-card.tsx +2 -2
  632. package/src/components/chat/subagent-view.tsx +4 -4
  633. package/src/components/chat/tool-call-timeline.tsx +75 -26
  634. package/src/components/chat/tool-cards/block-card.tsx +145 -0
  635. package/src/components/chat/tool-cards/image-mask-card.tsx +214 -0
  636. package/src/components/chat/tool-cards/location-card.tsx +159 -0
  637. package/src/components/chat/tool-views.tsx +30 -60
  638. package/src/components/chat/transcript-turn.tsx +108 -0
  639. package/src/components/chat/use-chat-commands.ts +14 -16
  640. package/src/components/chat/welcome-state.tsx +36 -91
  641. package/src/components/connectivity/connection-gate.tsx +32 -24
  642. package/src/components/connectivity/login-form.tsx +122 -0
  643. package/src/components/connectivity/login-screen.tsx +45 -100
  644. package/src/components/dev/share-harness.tsx +2 -2
  645. package/src/components/files/file-panel.tsx +168 -0
  646. package/src/components/files/file-tree-view.tsx +127 -0
  647. package/src/components/files/file-tree.tsx +55 -109
  648. package/src/components/files/file-viewer-binary.tsx +3 -2
  649. package/src/components/files/file-viewer-frame.tsx +113 -0
  650. package/src/components/files/file-viewer.tsx +40 -95
  651. package/src/components/files/frontmatter-chips.tsx +42 -0
  652. package/src/components/files/frontmatter-panel.tsx +6 -71
  653. package/src/components/files/staleness.ts +29 -0
  654. package/src/components/graph/graph-canvas.tsx +24 -1
  655. package/src/components/graph/graph-controls-column.tsx +92 -0
  656. package/src/components/graph/graph-controls.tsx +83 -127
  657. package/src/components/graph/graph-form.tsx +183 -0
  658. package/src/components/graph/graph-maintenance.tsx +9 -14
  659. package/src/components/graph/graph-node-rail.tsx +147 -0
  660. package/src/components/graph/graph-page.tsx +189 -49
  661. package/src/components/graph/graph-scene.tsx +200 -30
  662. package/src/components/graph/lib/graph-helpers.ts +65 -43
  663. package/src/components/graph/node-card.tsx +64 -0
  664. package/src/components/graph/node-popover.tsx +28 -117
  665. package/src/components/graph/use-graph-theme.ts +69 -32
  666. package/src/components/graph/use-node-actions.ts +56 -0
  667. package/src/components/images/image-share.ts +4 -2
  668. package/src/components/images/image-viewer.tsx +3 -1
  669. package/src/components/images/mask-editor.tsx +7 -4
  670. package/src/components/layout/app-shell.tsx +5 -1
  671. package/src/components/layout/desktop-palette.tsx +151 -0
  672. package/src/components/layout/key-cap.tsx +15 -0
  673. package/src/components/layout/mobile-tab-bar.tsx +80 -157
  674. package/src/components/layout/shortcut-switch.tsx +32 -0
  675. package/src/components/layout/side-rail.tsx +77 -150
  676. package/src/components/layout/slide-panel.tsx +49 -6
  677. package/src/components/layout/theme.tsx +67 -0
  678. package/src/components/quick-actions/add-form.tsx +196 -0
  679. package/src/components/quick-actions/add-modal.tsx +32 -153
  680. package/src/components/quick-actions/search-modal.tsx +15 -5
  681. package/src/components/quick-actions/streaming-modal.tsx +57 -72
  682. package/src/components/quick-actions/streaming-output.tsx +112 -0
  683. package/src/components/quick-actions/whatsup-modal.tsx +53 -59
  684. package/src/components/settings/devices-agents-tab.tsx +60 -152
  685. package/src/components/settings/models-list.tsx +299 -0
  686. package/src/components/settings/models-tab.tsx +63 -337
  687. package/src/components/settings/one-time-agent-credential.tsx +1 -1
  688. package/src/components/settings/passkey-list.tsx +201 -0
  689. package/src/components/settings/passkey-tab.tsx +53 -197
  690. package/src/components/settings/pi-accounts-list.tsx +128 -0
  691. package/src/components/settings/pi-accounts.tsx +71 -170
  692. package/src/components/settings/principal-list.tsx +172 -0
  693. package/src/components/settings/settings-panel.tsx +239 -25
  694. package/src/components/settings/skills-list.tsx +276 -0
  695. package/src/components/settings/skills-tab.tsx +82 -269
  696. package/src/components/settings/tool-permissions-list.tsx +54 -0
  697. package/src/components/settings/tool-permissions.tsx +27 -46
  698. package/src/components/settings/web-search-chain.tsx +300 -0
  699. package/src/components/settings/web-search-settings.tsx +58 -328
  700. package/src/components/share/share-menu.tsx +19 -4
  701. package/src/components/voice/dictation-sheet.tsx +5 -5
  702. package/src/components/voice/mic-button.tsx +1 -1
  703. package/src/components/voice/review-card.tsx +1 -1
  704. package/src/config.ts +21 -7
  705. package/src/connection.ts +443 -0
  706. package/src/default-root.ts +16 -0
  707. package/src/hooks/use-color-scheme.ts +36 -0
  708. package/src/hooks/use-fine-pointer.ts +15 -0
  709. package/src/hooks/use-hash-routes.ts +4 -2
  710. package/src/hooks/use-media-query.ts +35 -0
  711. package/src/hooks/use-share-intake.ts +32 -12
  712. package/src/hooks/use-vpn-status.ts +18 -17
  713. package/src/hooks/use-websocket.ts +12 -428
  714. package/src/hooks/websocket-handlers/activity.ts +4 -5
  715. package/src/hooks/websocket-handlers/chat.ts +28 -6
  716. package/src/hooks/websocket-handlers/connection.ts +4 -6
  717. package/src/hooks/websocket-handlers/mask.ts +2 -3
  718. package/src/hooks/websocket-handlers/provider.ts +4 -6
  719. package/src/hooks/websocket-handlers/types.ts +6 -2
  720. package/src/index.ts +7 -3
  721. package/src/lib/api-client.ts +426 -384
  722. package/src/lib/backend.ts +20 -10
  723. package/src/lib/diff.ts +28 -62
  724. package/src/lib/light-dark.ts +83 -0
  725. package/src/lib/mermaid-theme.ts +183 -214
  726. package/src/lib/passkeys.ts +12 -4
  727. package/src/lib/push-registration.ts +19 -2
  728. package/src/lib/share-intake.ts +6 -3
  729. package/src/lib/share.ts +7 -4
  730. package/src/lib/single-key.ts +47 -0
  731. package/src/lib/tool-names.ts +31 -8
  732. package/src/root-context.tsx +40 -0
  733. package/src/root.ts +83 -0
  734. package/src/stores/activity-state.ts +295 -0
  735. package/src/stores/activity-store.ts +11 -285
  736. package/src/stores/chat-state.ts +822 -0
  737. package/src/stores/chat-store.ts +11 -705
  738. package/src/stores/connection-state.ts +78 -0
  739. package/src/stores/connection-store.ts +11 -76
  740. package/src/stores/create-stores.ts +31 -0
  741. package/src/stores/file-state.ts +399 -0
  742. package/src/stores/file-store.ts +9 -390
  743. package/src/stores/graph-state.ts +368 -0
  744. package/src/stores/graph-store.ts +10 -355
  745. package/src/stores/mask-state.ts +30 -0
  746. package/src/stores/mask-store.ts +10 -27
  747. package/src/stores/principal-state.ts +42 -0
  748. package/src/stores/principal-store.ts +10 -37
  749. package/src/stores/provider-state.ts +103 -0
  750. package/src/stores/provider-store.ts +10 -95
  751. package/src/stores/share-state.ts +56 -0
  752. package/src/stores/share-store.ts +11 -54
  753. package/src/stores/store-environment.ts +10 -0
  754. package/src/stores/ui-state.ts +143 -0
  755. package/src/stores/ui-store.ts +11 -93
  756. package/src/styles.css +4 -1
  757. package/src/theme.css +150 -97
  758. package/src/voice/asr-clients.ts +17 -17
  759. package/src/voice/use-dictation.ts +11 -8
  760. package/src/voice/voice-state.ts +57 -0
  761. package/src/voice/voice-store.ts +11 -55
@@ -1,4 +1,5 @@
1
- import { useState, useEffect, useRef } from "react";
1
+ import { useBrainUiRoot } from "../../root-context.js";
2
+ import { useState, useEffect, useRef, type KeyboardEvent } from "react";
2
3
  import {
3
4
  Check,
4
5
  X,
@@ -9,17 +10,20 @@ import {
9
10
  AlertTriangle,
10
11
  FileText,
11
12
  } from "lucide-react";
12
- import { resolveToolRenderer, type ToolSemantics } from "@schlessera/brain-ui-sdk/client";
13
- import { useChatStore, type ToolCall } from "../../stores/chat-store.js";
13
+ import { type ToolSemantics } from "@schlessera/brain-ui-sdk/client";
14
+ import { offersAlwaysAllow, useChatStore, type ToolCall } from "../../stores/chat-store.js";
14
15
  import { cn } from "../../lib/utils.js";
15
16
  import { motion, AnimatePresence } from "framer-motion";
16
- import { getToolLabel, getTouchedFile, formatDuration, formatTokenCount } from "./tool-views.js";
17
+ import { effectOf, getToolLabel, getTouchedFile, formatDuration, formatTokenCount } from "./tool-views.js";
17
18
  import { registerBuiltinRenderers, GENERIC_RENDERER } from "./renderers/index.js";
18
19
  import { riskHints } from "./risk-hints.js";
19
20
  import { useShallow } from "zustand/react/shallow";
21
+ import { focusAfterDecision, singleKey } from "../../lib/single-key.js";
22
+ import { KeyCap } from "../layout/key-cap.js";
20
23
  import { useActivityStore, spanForTool, childSpans } from "../../stores/activity-store.js";
21
24
  import { useUIStore } from "../../stores/ui-store.js";
22
25
  import { useNow } from "../../hooks/use-now.js";
26
+ import { useFinePointer } from "../../hooks/use-fine-pointer.js";
23
27
  import { SpanStatusDot } from "../activity/span-bits.js";
24
28
 
25
29
  // Sessions that predate backend stamping (old servers, cleared stores) scope
@@ -46,7 +50,8 @@ export function ToolCallTimeline({
46
50
  live?: boolean;
47
51
  }) {
48
52
  // Resolution happens below during this render, before effects can run.
49
- registerBuiltinRenderers();
53
+ const root = useBrainUiRoot();
54
+ registerBuiltinRenderers(root.renderers);
50
55
 
51
56
  // Collapse the whole run to a summary row once the turn is over. History
52
57
  // messages mount collapsed; a live timeline collapses when streaming ends.
@@ -108,12 +113,13 @@ function TimelineSummaryRow({
108
113
  backendId: string;
109
114
  onExpand: () => void;
110
115
  }) {
116
+ const root = useBrainUiRoot();
111
117
  const steps = toolCalls.length;
112
118
  const files = new Set(
113
119
  toolCalls
114
120
  .map(
115
121
  (t) =>
116
- resolveToolRenderer(t, backendId)?.touchedFile?.(t) ?? getTouchedFile(t)
122
+ root.renderers.resolve(t, backendId)?.touchedFile?.(t) ?? getTouchedFile(t)
117
123
  )
118
124
  .filter(Boolean)
119
125
  ).size;
@@ -156,6 +162,7 @@ function ToolCallEntry({
156
162
  backendId: string;
157
163
  onApproval: (toolUseId: string, approved: boolean, always?: boolean) => void;
158
164
  }) {
165
+ const root = useBrainUiRoot();
159
166
  const [expanded, setExpanded] = useState(
160
167
  toolCall.status === "pending_approval"
161
168
  );
@@ -175,13 +182,35 @@ function ToolCallEntry({
175
182
  : toolCall;
176
183
  // Resolve the renderer for this tool (backend-scoped exact -> global exact ->
177
184
  // shape-sniffing predicate). Falls back to the generic renderer.
178
- const renderer = resolveToolRenderer(toolCall, backendId) ?? GENERIC_RENDERER;
185
+ const renderer = root.renderers.resolve(toolCall, backendId) ?? GENERIC_RENDERER;
179
186
  const Icon = renderer.icon ?? FileText;
180
187
  const label =
181
188
  typeof renderer.label === "function"
182
189
  ? renderer.label(toolCall)
183
190
  : renderer.label ?? getToolLabel(toolCall.name);
184
191
  const isPending = toolCall.status === "pending_approval";
192
+ const keys = useUIStore((s) => s.singleKeyShortcuts);
193
+ // The caps are printed only while a fine pointer is present (#86); the letters
194
+ // themselves follow the Settings switch alone, so a paired keyboard works
195
+ // even if the pointer query stays coarse.
196
+ const finePointer = useFinePointer();
197
+ const printKeys = keys && finePointer;
198
+ /**
199
+ * A decision hands focus on before the card goes (D36): the next pending
200
+ * approval in the transcript, else the composer — the thing the reader
201
+ * continues with, since a chat has no empty-state heading to land on.
202
+ */
203
+ function decide(card: HTMLElement | null, approved: boolean, always?: boolean) {
204
+ if (card) focusAfterDecision(card, "[data-approval-card]", "textarea[data-composer]");
205
+ onApproval(toolCall.id, approved, always);
206
+ }
207
+ function onCardKeyDown(event: KeyboardEvent<HTMLDivElement>) {
208
+ if (!keys) return;
209
+ const key = singleKey(event);
210
+ if (key !== "a" && key !== "d") return;
211
+ event.preventDefault();
212
+ decide(event.currentTarget, key === "a");
213
+ }
185
214
  const summary = renderer.summary?.(timed) ?? null;
186
215
  const meta = renderer.meta?.(timed) ?? null;
187
216
  const Input = renderer.Input;
@@ -204,17 +233,18 @@ function ToolCallEntry({
204
233
 
205
234
  return (
206
235
  <div className="relative">
207
- {/* Timeline dot */}
236
+ {/* Timeline dot: a bare mark with no content, so it takes the MARK
237
+ weight — a fill sits at 1.3-1.8:1 on paper at any diameter. */}
208
238
  <div
209
239
  className={cn(
210
240
  "absolute -left-[21px] top-2 h-2.5 w-2.5 rounded-full border-2 border-background",
211
- toolCall.status === "streaming" && "bg-primary animate-pulse",
241
+ toolCall.status === "streaming" && "bg-primary-mark animate-pulse",
212
242
  toolCall.status === "pending_approval" &&
213
- "bg-primary",
214
- toolCall.status === "approved" && "bg-accent",
215
- toolCall.status === "denied" && "bg-destructive",
243
+ "bg-primary-mark",
244
+ toolCall.status === "approved" && "bg-accent-mark",
245
+ toolCall.status === "denied" && "bg-destructive-mark",
216
246
  toolCall.status === "complete" &&
217
- (toolCall.isError ? "bg-destructive" : "bg-accent"),
247
+ (toolCall.isError ? "bg-destructive-mark" : "bg-accent-mark"),
218
248
  !["streaming", "pending_approval", "approved", "denied", "complete"].includes(toolCall.status) && "bg-muted-foreground"
219
249
  )}
220
250
  style={
@@ -275,13 +305,18 @@ function ToolCallEntry({
275
305
  className={cn(
276
306
  "mt-1 rounded-lg p-3 space-y-2",
277
307
  isPending
278
- ? "border-2 border-primary/40 bg-primary/5"
308
+ ? "border-2 border-primary/40 bg-primary-fill/5"
279
309
  : "border border-border-subtle bg-surface"
280
310
  )}
281
311
  >
282
312
  {/* Tool input */}
283
313
  {Input && <Input tool={toolCall} />}
284
314
 
315
+ {/* What a confirmed command will do, in words (#112) */}
316
+ {isPending && effectOf(toolCall) && (
317
+ <p className="text-[11px] text-muted-foreground">{effectOf(toolCall)}</p>
318
+ )}
319
+
285
320
  {/* Risk hints — advisory only, never blocks approval */}
286
321
  {isPending && (
287
322
  <RiskHints toolCall={toolCall} semantics={renderer.semantics} />
@@ -289,32 +324,45 @@ function ToolCallEntry({
289
324
 
290
325
  {/* Approval buttons. "Always allow" only for grantable tool
291
326
  requests — a destructive-command confirmation (kind
292
- "command") stays per-use. */}
327
+ "command") stays per-use, and a grant the host said it
328
+ will not keep (#147) is not offered. */}
293
329
  {isPending && (
294
- <div className="flex flex-wrap gap-2">
330
+ // The card is the focus scope for `a` / `d` (D36): the keys
331
+ // act only while it, or a button inside it, holds focus, and
332
+ // they are printed on the buttons they belong to.
333
+ <div
334
+ data-approval-card=""
335
+ role="group"
336
+ aria-label={`Approval: ${label}`}
337
+ tabIndex={0}
338
+ onKeyDown={onCardKeyDown}
339
+ className="flex flex-wrap gap-2 rounded-md outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
340
+ >
295
341
  <button
296
- onClick={() => onApproval(toolCall.id, true)}
297
- className="flex items-center gap-1.5 rounded-lg bg-primary px-4 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110"
342
+ onClick={(e) => decide(e.currentTarget.closest("[data-approval-card]"), true)}
343
+ className="flex items-center gap-1.5 rounded-lg bg-primary-fill px-4 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110"
298
344
  >
299
345
  <Check className="h-3 w-3" />
300
346
  Allow
347
+ {printKeys && <KeyCap>a</KeyCap>}
301
348
  </button>
302
- {toolCall.approvalKind !== "command" && (
349
+ {offersAlwaysAllow(toolCall) && (
303
350
  <button
304
- onClick={() => onApproval(toolCall.id, true, true)}
351
+ onClick={(e) => decide(e.currentTarget.closest("[data-approval-card]"), true, true)}
305
352
  title={`Allow ${toolCall.name} without asking from now on (revocable in Settings → Models)`}
306
- className="flex items-center gap-1.5 rounded-lg border border-primary/40 px-4 py-1.5 text-xs font-medium text-primary transition-colors hover:bg-primary/10"
353
+ className="flex items-center gap-1.5 rounded-lg border border-primary/40 px-4 py-1.5 text-xs font-medium text-primary transition-colors hover:bg-primary-fill/10"
307
354
  >
308
355
  <Check className="h-3 w-3" />
309
356
  Always allow
310
357
  </button>
311
358
  )}
312
359
  <button
313
- onClick={() => onApproval(toolCall.id, false)}
314
- className="flex items-center gap-1.5 rounded-lg border border-destructive/30 px-4 py-1.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10"
360
+ onClick={(e) => decide(e.currentTarget.closest("[data-approval-card]"), false)}
361
+ className="flex items-center gap-1.5 rounded-lg border border-destructive/30 px-4 py-1.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive-fill/10"
315
362
  >
316
363
  <X className="h-3 w-3" />
317
364
  Deny
365
+ {printKeys && <KeyCap>d</KeyCap>}
318
366
  </button>
319
367
  </div>
320
368
  )}
@@ -389,7 +437,7 @@ function RiskHints({
389
437
  const hints = riskHints(toolCall, semantics);
390
438
  if (hints.length === 0) return null;
391
439
  return (
392
- <div className="space-y-0.5 text-[11px] text-amber-400">
440
+ <div className="space-y-0.5 text-[11px] text-primary">
393
441
  {hints.map((hint) => (
394
442
  <div key={hint} className="flex items-center gap-1.5">
395
443
  <AlertTriangle className="h-3 w-3 shrink-0" />
@@ -410,11 +458,11 @@ function StatusIndicator({
410
458
  switch (status) {
411
459
  case "streaming":
412
460
  return (
413
- <span className="inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-primary" />
461
+ <span className="inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-primary-mark" />
414
462
  );
415
463
  case "pending_approval":
416
464
  return (
417
- <span className="rounded bg-primary/20 px-1.5 py-0.5 text-[10px] font-medium text-primary">
465
+ <span className="rounded bg-primary-fill/20 px-1.5 py-0.5 text-[10px] font-medium text-primary">
418
466
  Approval needed
419
467
  </span>
420
468
  );
@@ -430,3 +478,4 @@ function StatusIndicator({
430
478
  );
431
479
  }
432
480
  }
481
+
@@ -0,0 +1,145 @@
1
+ /**
2
+ * The `show_block` result: one of the kit's answer blocks, drawn inline (D41).
3
+ *
4
+ * A switch typed by the contract's payload, handing each variant to its kit
5
+ * component. That typing is the drift check the contract promised: a schema
6
+ * field the kit does not accept fails here, and the kit's own tone unions are
7
+ * asserted equal to the schema's lists in `tests/block-contract.test-d.ts`.
8
+ *
9
+ * Icons come from the model as strings; the kit's `Icon` renders an empty
10
+ * box for a key it does not know, so unknown keys are dropped before the
11
+ * prop is handed on. Optional TEXT props are the other translation: the kit
12
+ * ports the design's demo defaults, so a `QuoteCard` with no `source` names
13
+ * a forecast from the Odysseus fixture world and a `ContactCard` with no
14
+ * `label` is Penelope, and omitted `facts` or `ticks` draw a demo list. Each
15
+ * of those components honours an empty string or an empty array as
16
+ * "cleared", so an omitted field is handed on as `""` or `[]` rather than
17
+ * `undefined`. Everything else is passed through untouched: the schema
18
+ * already rejected what the kit cannot draw.
19
+ */
20
+
21
+ import {
22
+ BarList,
23
+ ComparisonTable,
24
+ ContactCard,
25
+ DataTable,
26
+ ICONS,
27
+ QuoteCard,
28
+ Receipt,
29
+ ScheduleList,
30
+ StatTiles,
31
+ StepList,
32
+ TimelineList,
33
+ TrendChart,
34
+ type IconName,
35
+ } from "@schlessera/brain-ui-kit";
36
+ import type { Block, ShowBlockPayload } from "@schlessera/brain-ui-sdk/client";
37
+
38
+ /** A kit icon key, or nothing when the model named one the kit lacks. */
39
+ export function kitIcon(name: string | undefined): IconName | undefined {
40
+ // An own-property check: `"constructor" in ICONS` is true through the
41
+ // prototype, and the kit would then try to render a function that is not
42
+ // a component.
43
+ return name !== undefined && Object.hasOwn(ICONS, name) ? (name as IconName) : undefined;
44
+ }
45
+
46
+ /** An omitted optional text prop, cleared rather than left to the kit's demo default. */
47
+ const text = (value: string | undefined): string => value ?? "";
48
+
49
+ /** The collapsed one-liner for the trace: `comparison · 3 columns · 4 rows`. */
50
+ export function blockSummary({ block }: ShowBlockPayload): string {
51
+ const count = (n: number, noun: string) => `${n} ${noun}${n === 1 ? "" : "s"}`;
52
+ switch (block.kind) {
53
+ case "comparison":
54
+ return `comparison · ${count(block.columns.length, "column")} · ${count(block.rows.length, "row")}`;
55
+ case "stats":
56
+ return `stats · ${count(block.tiles.length, "tile")}`;
57
+ case "trend":
58
+ return `trend · ${block.label ?? block.value ?? count(block.values.length, "point")}`;
59
+ case "table":
60
+ return `table · ${count(block.columns.length, "column")} · ${count(block.rows.length, "row")}`;
61
+ case "bars":
62
+ return `bars · ${count(block.rows.length, "row")}`;
63
+ case "receipt":
64
+ return `receipt · ${block.title ?? count(block.rows.length, "row")}`;
65
+ case "steps":
66
+ return `steps · ${count(block.steps.length, "step")}`;
67
+ case "timeline":
68
+ return `timeline · ${count(block.items.length, "event")}`;
69
+ case "schedule":
70
+ return `schedule · ${count(block.groups.length, "day")}`;
71
+ case "quote":
72
+ return `quote · ${block.source ?? "unattributed"}`;
73
+ case "contact":
74
+ return `contact · ${block.label}`;
75
+ }
76
+ }
77
+
78
+ function BlockView({ block }: { block: Block }) {
79
+ switch (block.kind) {
80
+ case "comparison": {
81
+ const { kind: _kind, footnote, ...props } = block;
82
+ return <ComparisonTable {...props} footnote={text(footnote)} />;
83
+ }
84
+ case "stats":
85
+ return (
86
+ <StatTiles
87
+ tiles={block.tiles.map((tile) => ({ ...tile, icon: kitIcon(tile.icon) }))}
88
+ />
89
+ );
90
+ case "trend": {
91
+ const { kind: _kind, label, value, ticks, ...props } = block;
92
+ return <TrendChart {...props} label={text(label)} value={text(value)} ticks={ticks ?? []} />;
93
+ }
94
+ case "table": {
95
+ const { kind: _kind, ...props } = block;
96
+ return <DataTable {...props} />;
97
+ }
98
+ case "bars":
99
+ return <BarList rows={block.rows} />;
100
+ case "receipt": {
101
+ const { kind: _kind, title, titleIcon, footnote, ...props } = block;
102
+ return (
103
+ <Receipt
104
+ {...props}
105
+ title={text(title)}
106
+ titleIcon={kitIcon(titleIcon)}
107
+ footnote={text(footnote)}
108
+ />
109
+ );
110
+ }
111
+ case "steps": {
112
+ const { kind: _kind, ...props } = block;
113
+ return <StepList {...props} />;
114
+ }
115
+ case "timeline":
116
+ return <TimelineList items={block.items} />;
117
+ case "schedule":
118
+ return <ScheduleList groups={block.groups} />;
119
+ case "quote": {
120
+ const { kind: _kind, icon, source, locator, note, ...props } = block;
121
+ return (
122
+ <QuoteCard
123
+ {...props}
124
+ source={text(source)}
125
+ locator={text(locator)}
126
+ note={text(note)}
127
+ icon={kitIcon(icon)}
128
+ />
129
+ );
130
+ }
131
+ case "contact": {
132
+ const { kind: _kind, contactKind, role, facts, ...props } = block;
133
+ return <ContactCard {...props} kind={contactKind} role={text(role)} facts={facts ?? []} />;
134
+ }
135
+ }
136
+ }
137
+
138
+ /** Bound to `SHOW_BLOCK_CONTRACT`; receives the parsed payload as props. */
139
+ export function BlockCard({ block }: ShowBlockPayload) {
140
+ return (
141
+ <div data-block={block.kind}>
142
+ <BlockView block={block} />
143
+ </div>
144
+ );
145
+ }
@@ -0,0 +1,214 @@
1
+ /**
2
+ * The `request_image_mask` result: a receipt, not a path (D38 §2).
3
+ *
4
+ * The source thumb — hatched, as everywhere: no remote image loads inline for
5
+ * the source — stacked ABOVE a kit `Receipt` (the truncation rule: a receipt
6
+ * value column under ~160px means change the layout, not the break rule).
7
+ *
8
+ * Typed `ImageMaskPayload`, so the rows are the fields the handler actually
9
+ * sends: `imagePath`, `maskPath`, `bytes`. The design also draws a region and
10
+ * a coverage row; the payload carries neither. The seventh drop's ruling 8
11
+ * settles what happens then: **state the absence**. The receipt's `region`
12
+ * row reads "region not recorded", in gold, rather than disappearing — a
13
+ * load-bearing fact that vanishes cannot be told apart from a whole-image
14
+ * mask, and a later answer citing that receipt would be citing a gap. A
15
+ * caller that does supply a region (the view test) gets the figures.
16
+ *
17
+ * And the mask itself is DRAWN over the thumb whenever its bytes exist: the
18
+ * PNG the handler wrote is fetched from the files API and laid over the
19
+ * hatch, with the teal region fill beneath it so the transparent (editable)
20
+ * pixels show as the user's answer. When the bytes do not exist the thumb
21
+ * shows the source alone with a mono line saying the mask was not rendered.
22
+ *
23
+ * Failure is a fact about the evidence, not a dialog: a declined or failed
24
+ * mask comes back as a tool error with a message, and `ImageMaskFallback`
25
+ * states it in a red boxed mono `Callout` from the result's own words.
26
+ */
27
+
28
+ import { useState, type CSSProperties } from "react";
29
+ import { Callout, Receipt, Surface, color, font, type ReceiptRow } from "@schlessera/brain-ui-kit";
30
+ import type { ImageMaskPayload, ToolCallView } from "@schlessera/brain-ui-sdk/client";
31
+ import { useBrainUiRoot } from "../../../root-context.js";
32
+ import { ClampedPre } from "../tool-views.js";
33
+
34
+ /** A normalised rectangle over the source image: every value in 0..1. */
35
+ export interface MaskRegion {
36
+ x: number;
37
+ y: number;
38
+ w: number;
39
+ h: number;
40
+ }
41
+
42
+ const THUMB_W = 160;
43
+ const THUMB_H = 100;
44
+
45
+ export const REGION_NOT_RECORDED = "region not recorded";
46
+ export const MASK_NOT_RENDERED = "mask not rendered";
47
+
48
+ /** The kit's image placeholder: raised stripes on the surface, no pixels. */
49
+ const HATCH = `repeating-linear-gradient(135deg,${color.raised} 0 6px,var(--bk-hatch-stripe) 6px 12px)`;
50
+
51
+ function bytesLabel(bytes: number): string {
52
+ if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
53
+ if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`;
54
+ return `${bytes} B`;
55
+ }
56
+
57
+ /** The mask file exists with content: the handler reports the PNG's byte length. */
58
+ export function hasMaskBytes(payload: Pick<ImageMaskPayload, "bytes">): boolean {
59
+ return typeof payload.bytes === "number" && payload.bytes > 0;
60
+ }
61
+
62
+ /**
63
+ * The thumb: the hatched source, the drawn region when a caller has one, and
64
+ * the mask image over both when `maskUrl` is given. Exported for the view
65
+ * test; the bound card computes `maskUrl` from the payload.
66
+ */
67
+ export function MaskThumb({
68
+ region,
69
+ label,
70
+ maskUrl,
71
+ maskShown,
72
+ onMaskLoad,
73
+ onMaskError,
74
+ }: {
75
+ region?: MaskRegion;
76
+ label: string;
77
+ maskUrl?: string;
78
+ /** The teal fill sits under the mask only once the PNG has loaded: until
79
+ * then, or after a failure, a full teal frame would read as a whole-image
80
+ * mask that was never drawn. */
81
+ maskShown?: boolean;
82
+ onMaskLoad?: () => void;
83
+ onMaskError?: () => void;
84
+ }) {
85
+ const frame: CSSProperties = {
86
+ position: "relative",
87
+ width: "100%",
88
+ maxWidth: THUMB_W * 2,
89
+ aspectRatio: `${THUMB_W} / ${THUMB_H}`,
90
+ borderRadius: 9,
91
+ border: `1px solid ${color.edge}`,
92
+ background: HATCH,
93
+ overflow: "hidden",
94
+ };
95
+ const drawn: CSSProperties | undefined = region
96
+ ? {
97
+ position: "absolute",
98
+ left: `${region.x * 100}%`,
99
+ top: `${region.y * 100}%`,
100
+ width: `${region.w * 100}%`,
101
+ height: `${region.h * 100}%`,
102
+ border: "1.5px dashed var(--bk-teal-ink)",
103
+ background: "var(--bk-mask-region-fill)",
104
+ borderRadius: 3,
105
+ boxSizing: "border-box",
106
+ }
107
+ : undefined;
108
+ // The teal fill sits under the mask: where the PNG is transparent — the
109
+ // editable region, the user's own answer — the teal shows through.
110
+ const fill: CSSProperties = { position: "absolute", inset: 0, background: "var(--bk-mask-region-fill)" };
111
+ const overlay: CSSProperties = {
112
+ position: "absolute",
113
+ inset: 0,
114
+ width: "100%",
115
+ height: "100%",
116
+ objectFit: "contain",
117
+ };
118
+ return (
119
+ <div role="img" aria-label={label} style={frame} data-mask-thumb>
120
+ {drawn ? <div style={drawn} data-mask-region /> : null}
121
+ {maskUrl ? (
122
+ <>
123
+ {maskShown ? <div style={fill} aria-hidden="true" /> : null}
124
+ <img
125
+ src={maskUrl}
126
+ alt=""
127
+ style={{ ...overlay, visibility: maskShown ? "visible" : "hidden" }}
128
+ data-mask-overlay
129
+ data-mask-shown={maskShown ? "" : undefined}
130
+ onLoad={onMaskLoad}
131
+ onError={onMaskError}
132
+ />
133
+ </>
134
+ ) : null}
135
+ </div>
136
+ );
137
+ }
138
+
139
+ /** The rows the receipt prints. The region row is always there: figures when
140
+ * a caller has them, the stated absence when the payload carries none. */
141
+ export function maskReceiptRows(payload: ImageMaskPayload, region?: MaskRegion): ReceiptRow[] {
142
+ const rows: ReceiptRow[] = [];
143
+ if (region) {
144
+ rows.push({
145
+ k: "region",
146
+ v: `${pct(region.x)},${pct(region.y)} → ${pct(region.x + region.w)},${pct(region.y + region.h)}`,
147
+ tone: "teal",
148
+ });
149
+ rows.push({ k: "covers", v: `${pct(region.w * region.h)} of the image`, tone: "teal" });
150
+ } else {
151
+ rows.push({ k: "region", v: REGION_NOT_RECORDED, tone: "gold" });
152
+ }
153
+ rows.push({ k: "source", v: payload.imagePath });
154
+ rows.push({ k: "mask", v: `${payload.maskPath} · ${bytesLabel(payload.bytes)}` });
155
+ return rows;
156
+ }
157
+
158
+ function pct(fraction: number): string {
159
+ return `${Math.round(fraction * 100)}%`;
160
+ }
161
+
162
+ export function ImageMaskResultCard(payload: ImageMaskPayload & { region?: MaskRegion }) {
163
+ const root = useBrainUiRoot();
164
+ const region = payload.region;
165
+ const hasBytes = hasMaskBytes(payload);
166
+ const maskUrl = hasBytes
167
+ ? `${root.apiBase()}/files/content?path=${encodeURIComponent(payload.maskPath)}&raw=1`
168
+ : undefined;
169
+ // The bytes say a mask was written; only the browser can say it loaded.
170
+ // A file gone since, or a path the raw route refuses, must not leave a
171
+ // full teal frame standing in for a mask nobody can see.
172
+ const [maskState, setMaskState] = useState<"loading" | "shown" | "failed">("loading");
173
+ const rendered = hasBytes && maskState === "shown";
174
+ const note: CSSProperties = { font: `400 10.5px/1.5 ${font.mono}`, color: color.inkMute };
175
+ return (
176
+ <Surface tone="teal" label="Mask drawn" labelIcon="confirm" meta="by you" pad={12}>
177
+ <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
178
+ <MaskThumb
179
+ region={region}
180
+ maskUrl={maskUrl}
181
+ maskShown={rendered}
182
+ onMaskLoad={() => setMaskState("shown")}
183
+ onMaskError={() => setMaskState("failed")}
184
+ label={
185
+ rendered
186
+ ? `Mask ${payload.maskPath} over the source ${payload.imagePath}`
187
+ : `Source ${payload.imagePath}; the mask is in ${payload.maskPath}`
188
+ }
189
+ />
190
+ {!hasBytes || maskState === "failed" ? <div style={note}>{MASK_NOT_RENDERED}</div> : null}
191
+ <Receipt keyWidth={58} rows={maskReceiptRows(payload, region)} />
192
+ </div>
193
+ </Surface>
194
+ );
195
+ }
196
+
197
+ /**
198
+ * No payload: the user declined, the editor failed, or an older server
199
+ * answered with a sentence. An error is stated as a fact in red; anything
200
+ * else is shown as the text it is.
201
+ */
202
+ export function ImageMaskFallback({ tool }: { tool: ToolCallView }) {
203
+ if (!tool.output) return null;
204
+ if (!tool.isError) return <ClampedPre text={tool.output} />;
205
+ const source = typeof tool.input.imagePath === "string" ? tool.input.imagePath : null;
206
+ return (
207
+ <Callout
208
+ tone="red"
209
+ variant="boxed"
210
+ mono
211
+ text={`no mask drawn${source ? ` on ${source}` : ""} · ${tool.output.trim()}`}
212
+ />
213
+ );
214
+ }