@schlessera/brain-ui-react 0.34.1 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (763) hide show
  1. package/README.md +89 -4
  2. package/dist/components/activity/activity-page.d.ts +17 -5
  3. package/dist/components/activity/activity-page.d.ts.map +1 -1
  4. package/dist/components/activity/activity-page.js +144 -50
  5. package/dist/components/activity/activity-page.js.map +1 -1
  6. package/dist/components/activity/activity-run-detail.d.ts +16 -1
  7. package/dist/components/activity/activity-run-detail.d.ts.map +1 -1
  8. package/dist/components/activity/activity-run-detail.js +47 -4
  9. package/dist/components/activity/activity-run-detail.js.map +1 -1
  10. package/dist/components/activity/activity-run-list.d.ts +7 -1
  11. package/dist/components/activity/activity-run-list.d.ts.map +1 -1
  12. package/dist/components/activity/activity-run-list.js +16 -8
  13. package/dist/components/activity/activity-run-list.js.map +1 -1
  14. package/dist/components/activity/activity-views.d.ts +63 -0
  15. package/dist/components/activity/activity-views.d.ts.map +1 -0
  16. package/dist/components/activity/activity-views.js +52 -0
  17. package/dist/components/activity/activity-views.js.map +1 -0
  18. package/dist/components/activity/approval-card.d.ts +11 -0
  19. package/dist/components/activity/approval-card.d.ts.map +1 -0
  20. package/dist/components/activity/approval-card.js +46 -0
  21. package/dist/components/activity/approval-card.js.map +1 -0
  22. package/dist/components/activity/digest-card.d.ts +3 -0
  23. package/dist/components/activity/digest-card.d.ts.map +1 -1
  24. package/dist/components/activity/digest-card.js +20 -16
  25. package/dist/components/activity/digest-card.js.map +1 -1
  26. package/dist/components/activity/digest-summary.d.ts +19 -0
  27. package/dist/components/activity/digest-summary.d.ts.map +1 -0
  28. package/dist/components/activity/digest-summary.js +20 -0
  29. package/dist/components/activity/digest-summary.js.map +1 -0
  30. package/dist/components/activity/push-switch.d.ts +25 -0
  31. package/dist/components/activity/push-switch.d.ts.map +1 -0
  32. package/dist/components/activity/push-switch.js +14 -0
  33. package/dist/components/activity/push-switch.js.map +1 -0
  34. package/dist/components/activity/push-toggle.d.ts +7 -0
  35. package/dist/components/activity/push-toggle.d.ts.map +1 -1
  36. package/dist/components/activity/push-toggle.js +72 -47
  37. package/dist/components/activity/push-toggle.js.map +1 -1
  38. package/dist/components/activity/span-bits.d.ts.map +1 -1
  39. package/dist/components/activity/span-bits.js +9 -7
  40. package/dist/components/activity/span-bits.js.map +1 -1
  41. package/dist/components/chat/ask-user-card.d.ts +76 -3
  42. package/dist/components/chat/ask-user-card.d.ts.map +1 -1
  43. package/dist/components/chat/ask-user-card.js +208 -149
  44. package/dist/components/chat/ask-user-card.js.map +1 -1
  45. package/dist/components/chat/ask-user-typed.d.ts +42 -0
  46. package/dist/components/chat/ask-user-typed.d.ts.map +1 -0
  47. package/dist/components/chat/ask-user-typed.js +60 -0
  48. package/dist/components/chat/ask-user-typed.js.map +1 -0
  49. package/dist/components/chat/brain-markdown-links.d.ts +2 -1
  50. package/dist/components/chat/brain-markdown-links.d.ts.map +1 -1
  51. package/dist/components/chat/brain-markdown-links.js +3 -4
  52. package/dist/components/chat/brain-markdown-links.js.map +1 -1
  53. package/dist/components/chat/brain-markdown.d.ts.map +1 -1
  54. package/dist/components/chat/brain-markdown.js +4 -2
  55. package/dist/components/chat/brain-markdown.js.map +1 -1
  56. package/dist/components/chat/chat-page.d.ts.map +1 -1
  57. package/dist/components/chat/chat-page.js +24 -9
  58. package/dist/components/chat/chat-page.js.map +1 -1
  59. package/dist/components/chat/composer-view.d.ts +75 -0
  60. package/dist/components/chat/composer-view.d.ts.map +1 -0
  61. package/dist/components/chat/composer-view.js +31 -0
  62. package/dist/components/chat/composer-view.js.map +1 -0
  63. package/dist/components/chat/composer.d.ts +4 -0
  64. package/dist/components/chat/composer.d.ts.map +1 -1
  65. package/dist/components/chat/composer.js +76 -59
  66. package/dist/components/chat/composer.js.map +1 -1
  67. package/dist/components/chat/markdown-content.d.ts +16 -1
  68. package/dist/components/chat/markdown-content.d.ts.map +1 -1
  69. package/dist/components/chat/markdown-content.js +47 -3
  70. package/dist/components/chat/markdown-content.js.map +1 -1
  71. package/dist/components/chat/mermaid-block.d.ts +4 -0
  72. package/dist/components/chat/mermaid-block.d.ts.map +1 -1
  73. package/dist/components/chat/mermaid-block.js +13 -5
  74. package/dist/components/chat/mermaid-block.js.map +1 -1
  75. package/dist/components/chat/mermaid-share.d.ts +2 -1
  76. package/dist/components/chat/mermaid-share.d.ts.map +1 -1
  77. package/dist/components/chat/mermaid-share.js +7 -8
  78. package/dist/components/chat/mermaid-share.js.map +1 -1
  79. package/dist/components/chat/mermaid-viewer.d.ts.map +1 -1
  80. package/dist/components/chat/mermaid-viewer.js +3 -1
  81. package/dist/components/chat/mermaid-viewer.js.map +1 -1
  82. package/dist/components/chat/message-bubble.d.ts +8 -1
  83. package/dist/components/chat/message-bubble.d.ts.map +1 -1
  84. package/dist/components/chat/message-bubble.js +53 -24
  85. package/dist/components/chat/message-bubble.js.map +1 -1
  86. package/dist/components/chat/message-share.d.ts +2 -1
  87. package/dist/components/chat/message-share.d.ts.map +1 -1
  88. package/dist/components/chat/message-share.js +6 -7
  89. package/dist/components/chat/message-share.js.map +1 -1
  90. package/dist/components/chat/renderers/bind.d.ts +39 -0
  91. package/dist/components/chat/renderers/bind.d.ts.map +1 -0
  92. package/dist/components/chat/renderers/bind.js +43 -0
  93. package/dist/components/chat/renderers/bind.js.map +1 -0
  94. package/dist/components/chat/renderers/brain-ui-tools.d.ts +3 -0
  95. package/dist/components/chat/renderers/brain-ui-tools.d.ts.map +1 -0
  96. package/dist/components/chat/renderers/brain-ui-tools.js +41 -0
  97. package/dist/components/chat/renderers/brain-ui-tools.js.map +1 -0
  98. package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -1
  99. package/dist/components/chat/renderers/claude-tools.js +3 -2
  100. package/dist/components/chat/renderers/claude-tools.js.map +1 -1
  101. package/dist/components/chat/renderers/index.d.ts +10 -2
  102. package/dist/components/chat/renderers/index.d.ts.map +1 -1
  103. package/dist/components/chat/renderers/index.js +15 -10
  104. package/dist/components/chat/renderers/index.js.map +1 -1
  105. package/dist/components/chat/session-drawer.d.ts +4 -0
  106. package/dist/components/chat/session-drawer.d.ts.map +1 -1
  107. package/dist/components/chat/session-drawer.js +55 -40
  108. package/dist/components/chat/session-drawer.js.map +1 -1
  109. package/dist/components/chat/session-list.d.ts +41 -0
  110. package/dist/components/chat/session-list.d.ts.map +1 -0
  111. package/dist/components/chat/session-list.js +10 -0
  112. package/dist/components/chat/session-list.js.map +1 -0
  113. package/dist/components/chat/share-block.d.ts.map +1 -1
  114. package/dist/components/chat/share-block.js +12 -11
  115. package/dist/components/chat/share-block.js.map +1 -1
  116. package/dist/components/chat/share-card.js +2 -2
  117. package/dist/components/chat/share-card.js.map +1 -1
  118. package/dist/components/chat/subagent-view.js +1 -1
  119. package/dist/components/chat/subagent-view.js.map +1 -1
  120. package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
  121. package/dist/components/chat/tool-call-timeline.js +37 -12
  122. package/dist/components/chat/tool-call-timeline.js.map +1 -1
  123. package/dist/components/chat/tool-cards/block-card.d.ts +28 -0
  124. package/dist/components/chat/tool-cards/block-card.d.ts.map +1 -0
  125. package/dist/components/chat/tool-cards/block-card.js +103 -0
  126. package/dist/components/chat/tool-cards/block-card.js.map +1 -0
  127. package/dist/components/chat/tool-cards/image-mask-card.d.ts +70 -0
  128. package/dist/components/chat/tool-cards/image-mask-card.d.ts.map +1 -0
  129. package/dist/components/chat/tool-cards/image-mask-card.js +142 -0
  130. package/dist/components/chat/tool-cards/image-mask-card.js.map +1 -0
  131. package/dist/components/chat/tool-cards/location-card.d.ts +45 -0
  132. package/dist/components/chat/tool-cards/location-card.d.ts.map +1 -0
  133. package/dist/components/chat/tool-cards/location-card.js +128 -0
  134. package/dist/components/chat/tool-cards/location-card.js.map +1 -0
  135. package/dist/components/chat/tool-views.d.ts +15 -4
  136. package/dist/components/chat/tool-views.d.ts.map +1 -1
  137. package/dist/components/chat/tool-views.js +22 -38
  138. package/dist/components/chat/tool-views.js.map +1 -1
  139. package/dist/components/chat/transcript-turn.d.ts +45 -0
  140. package/dist/components/chat/transcript-turn.d.ts.map +1 -0
  141. package/dist/components/chat/transcript-turn.js +25 -0
  142. package/dist/components/chat/transcript-turn.js.map +1 -0
  143. package/dist/components/chat/use-chat-commands.d.ts.map +1 -1
  144. package/dist/components/chat/use-chat-commands.js +13 -16
  145. package/dist/components/chat/use-chat-commands.js.map +1 -1
  146. package/dist/components/chat/welcome-state.d.ts +7 -0
  147. package/dist/components/chat/welcome-state.d.ts.map +1 -1
  148. package/dist/components/chat/welcome-state.js +13 -5
  149. package/dist/components/chat/welcome-state.js.map +1 -1
  150. package/dist/components/connectivity/connection-gate.d.ts.map +1 -1
  151. package/dist/components/connectivity/connection-gate.js +64 -6
  152. package/dist/components/connectivity/connection-gate.js.map +1 -1
  153. package/dist/components/connectivity/login-form.d.ts +31 -0
  154. package/dist/components/connectivity/login-form.d.ts.map +1 -0
  155. package/dist/components/connectivity/login-form.js +19 -0
  156. package/dist/components/connectivity/login-form.js.map +1 -0
  157. package/dist/components/connectivity/login-screen.d.ts +5 -2
  158. package/dist/components/connectivity/login-screen.d.ts.map +1 -1
  159. package/dist/components/connectivity/login-screen.js +41 -31
  160. package/dist/components/connectivity/login-screen.js.map +1 -1
  161. package/dist/components/dev/share-harness.js +1 -1
  162. package/dist/components/dev/share-harness.js.map +1 -1
  163. package/dist/components/files/file-panel.d.ts +1 -1
  164. package/dist/components/files/file-panel.d.ts.map +1 -1
  165. package/dist/components/files/file-panel.js +74 -0
  166. package/dist/components/files/file-panel.js.map +1 -1
  167. package/dist/components/files/file-tree-view.d.ts +45 -0
  168. package/dist/components/files/file-tree-view.d.ts.map +1 -0
  169. package/dist/components/files/file-tree-view.js +51 -0
  170. package/dist/components/files/file-tree-view.js.map +1 -0
  171. package/dist/components/files/file-tree.d.ts +6 -0
  172. package/dist/components/files/file-tree.d.ts.map +1 -1
  173. package/dist/components/files/file-tree.js +39 -43
  174. package/dist/components/files/file-tree.js.map +1 -1
  175. package/dist/components/files/file-viewer-binary.d.ts.map +1 -1
  176. package/dist/components/files/file-viewer-binary.js +3 -2
  177. package/dist/components/files/file-viewer-binary.js.map +1 -1
  178. package/dist/components/files/file-viewer-frame.d.ts +36 -0
  179. package/dist/components/files/file-viewer-frame.d.ts.map +1 -0
  180. package/dist/components/files/file-viewer-frame.js +26 -0
  181. package/dist/components/files/file-viewer-frame.js.map +1 -0
  182. package/dist/components/files/file-viewer.d.ts +5 -0
  183. package/dist/components/files/file-viewer.d.ts.map +1 -1
  184. package/dist/components/files/file-viewer.js +26 -32
  185. package/dist/components/files/file-viewer.js.map +1 -1
  186. package/dist/components/files/frontmatter-chips.d.ts +18 -0
  187. package/dist/components/files/frontmatter-chips.d.ts.map +1 -0
  188. package/dist/components/files/frontmatter-chips.js +11 -0
  189. package/dist/components/files/frontmatter-chips.js.map +1 -0
  190. package/dist/components/files/frontmatter-panel.d.ts +5 -1
  191. package/dist/components/files/frontmatter-panel.d.ts.map +1 -1
  192. package/dist/components/files/frontmatter-panel.js +7 -6
  193. package/dist/components/files/frontmatter-panel.js.map +1 -1
  194. package/dist/components/files/staleness.d.ts +18 -0
  195. package/dist/components/files/staleness.d.ts.map +1 -0
  196. package/dist/components/files/staleness.js +27 -0
  197. package/dist/components/files/staleness.js.map +1 -0
  198. package/dist/components/graph/graph-canvas.d.ts.map +1 -1
  199. package/dist/components/graph/graph-canvas.js +24 -1
  200. package/dist/components/graph/graph-canvas.js.map +1 -1
  201. package/dist/components/graph/graph-controls-column.d.ts +14 -0
  202. package/dist/components/graph/graph-controls-column.d.ts.map +1 -0
  203. package/dist/components/graph/graph-controls-column.js +44 -0
  204. package/dist/components/graph/graph-controls-column.js.map +1 -0
  205. package/dist/components/graph/graph-controls.d.ts +20 -5
  206. package/dist/components/graph/graph-controls.d.ts.map +1 -1
  207. package/dist/components/graph/graph-controls.js +58 -37
  208. package/dist/components/graph/graph-controls.js.map +1 -1
  209. package/dist/components/graph/graph-form.d.ts +82 -0
  210. package/dist/components/graph/graph-form.d.ts.map +1 -0
  211. package/dist/components/graph/graph-form.js +69 -0
  212. package/dist/components/graph/graph-form.js.map +1 -0
  213. package/dist/components/graph/graph-maintenance.d.ts.map +1 -1
  214. package/dist/components/graph/graph-maintenance.js +6 -10
  215. package/dist/components/graph/graph-maintenance.js.map +1 -1
  216. package/dist/components/graph/graph-node-rail.d.ts +13 -0
  217. package/dist/components/graph/graph-node-rail.d.ts.map +1 -0
  218. package/dist/components/graph/graph-node-rail.js +92 -0
  219. package/dist/components/graph/graph-node-rail.js.map +1 -0
  220. package/dist/components/graph/graph-page.d.ts +7 -0
  221. package/dist/components/graph/graph-page.d.ts.map +1 -1
  222. package/dist/components/graph/graph-page.js +102 -12
  223. package/dist/components/graph/graph-page.js.map +1 -1
  224. package/dist/components/graph/graph-scene.d.ts.map +1 -1
  225. package/dist/components/graph/graph-scene.js +100 -24
  226. package/dist/components/graph/graph-scene.js.map +1 -1
  227. package/dist/components/graph/lib/graph-helpers.d.ts +42 -12
  228. package/dist/components/graph/lib/graph-helpers.d.ts.map +1 -1
  229. package/dist/components/graph/lib/graph-helpers.js +33 -41
  230. package/dist/components/graph/lib/graph-helpers.js.map +1 -1
  231. package/dist/components/graph/node-card.d.ts +28 -0
  232. package/dist/components/graph/node-card.d.ts.map +1 -0
  233. package/dist/components/graph/node-card.js +7 -0
  234. package/dist/components/graph/node-card.js.map +1 -0
  235. package/dist/components/graph/node-popover.d.ts +6 -2
  236. package/dist/components/graph/node-popover.d.ts.map +1 -1
  237. package/dist/components/graph/node-popover.js +13 -31
  238. package/dist/components/graph/node-popover.js.map +1 -1
  239. package/dist/components/graph/use-graph-theme.d.ts +32 -4
  240. package/dist/components/graph/use-graph-theme.d.ts.map +1 -1
  241. package/dist/components/graph/use-graph-theme.js +44 -32
  242. package/dist/components/graph/use-graph-theme.js.map +1 -1
  243. package/dist/components/graph/use-node-actions.d.ts +26 -0
  244. package/dist/components/graph/use-node-actions.d.ts.map +1 -0
  245. package/dist/components/graph/use-node-actions.js +54 -0
  246. package/dist/components/graph/use-node-actions.js.map +1 -0
  247. package/dist/components/images/image-share.d.ts +2 -1
  248. package/dist/components/images/image-share.d.ts.map +1 -1
  249. package/dist/components/images/image-share.js +3 -3
  250. package/dist/components/images/image-share.js.map +1 -1
  251. package/dist/components/images/image-viewer.d.ts.map +1 -1
  252. package/dist/components/images/image-viewer.js +3 -1
  253. package/dist/components/images/image-viewer.js.map +1 -1
  254. package/dist/components/images/mask-editor.d.ts.map +1 -1
  255. package/dist/components/images/mask-editor.js +7 -5
  256. package/dist/components/images/mask-editor.js.map +1 -1
  257. package/dist/components/layout/app-shell.d.ts.map +1 -1
  258. package/dist/components/layout/app-shell.js +5 -1
  259. package/dist/components/layout/app-shell.js.map +1 -1
  260. package/dist/components/layout/desktop-palette.d.ts +23 -0
  261. package/dist/components/layout/desktop-palette.d.ts.map +1 -0
  262. package/dist/components/layout/desktop-palette.js +132 -0
  263. package/dist/components/layout/desktop-palette.js.map +1 -0
  264. package/dist/components/layout/key-cap.d.ts +9 -0
  265. package/dist/components/layout/key-cap.d.ts.map +1 -0
  266. package/dist/components/layout/key-cap.js +10 -0
  267. package/dist/components/layout/key-cap.js.map +1 -0
  268. package/dist/components/layout/mobile-tab-bar.d.ts +13 -0
  269. package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
  270. package/dist/components/layout/mobile-tab-bar.js +58 -47
  271. package/dist/components/layout/mobile-tab-bar.js.map +1 -1
  272. package/dist/components/layout/shortcut-switch.d.ts +13 -0
  273. package/dist/components/layout/shortcut-switch.d.ts.map +1 -0
  274. package/dist/components/layout/shortcut-switch.js +22 -0
  275. package/dist/components/layout/shortcut-switch.js.map +1 -0
  276. package/dist/components/layout/side-rail.d.ts +24 -0
  277. package/dist/components/layout/side-rail.d.ts.map +1 -1
  278. package/dist/components/layout/side-rail.js +65 -27
  279. package/dist/components/layout/side-rail.js.map +1 -1
  280. package/dist/components/layout/slide-panel.d.ts +12 -2
  281. package/dist/components/layout/slide-panel.d.ts.map +1 -1
  282. package/dist/components/layout/slide-panel.js +11 -2
  283. package/dist/components/layout/slide-panel.js.map +1 -1
  284. package/dist/components/layout/theme.d.ts +22 -0
  285. package/dist/components/layout/theme.d.ts.map +1 -0
  286. package/dist/components/layout/theme.js +44 -0
  287. package/dist/components/layout/theme.js.map +1 -0
  288. package/dist/components/quick-actions/add-form.d.ts +44 -0
  289. package/dist/components/quick-actions/add-form.d.ts.map +1 -0
  290. package/dist/components/quick-actions/add-form.js +30 -0
  291. package/dist/components/quick-actions/add-form.js.map +1 -0
  292. package/dist/components/quick-actions/add-modal.d.ts +7 -0
  293. package/dist/components/quick-actions/add-modal.d.ts.map +1 -1
  294. package/dist/components/quick-actions/add-modal.js +66 -20
  295. package/dist/components/quick-actions/add-modal.js.map +1 -1
  296. package/dist/components/quick-actions/search-modal.d.ts.map +1 -1
  297. package/dist/components/quick-actions/search-modal.js +48 -19
  298. package/dist/components/quick-actions/search-modal.js.map +1 -1
  299. package/dist/components/quick-actions/streaming-modal.d.ts +6 -0
  300. package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -1
  301. package/dist/components/quick-actions/streaming-modal.js +42 -17
  302. package/dist/components/quick-actions/streaming-modal.js.map +1 -1
  303. package/dist/components/quick-actions/streaming-output.d.ts +38 -0
  304. package/dist/components/quick-actions/streaming-output.d.ts.map +1 -0
  305. package/dist/components/quick-actions/streaming-output.js +22 -0
  306. package/dist/components/quick-actions/streaming-output.js.map +1 -0
  307. package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
  308. package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -1
  309. package/dist/components/quick-actions/whatsup-modal.js +36 -10
  310. package/dist/components/quick-actions/whatsup-modal.js.map +1 -1
  311. package/dist/components/settings/devices-agents-tab.d.ts +10 -0
  312. package/dist/components/settings/devices-agents-tab.d.ts.map +1 -0
  313. package/dist/components/settings/devices-agents-tab.js +131 -0
  314. package/dist/components/settings/devices-agents-tab.js.map +1 -0
  315. package/dist/components/settings/models-list.d.ts +39 -0
  316. package/dist/components/settings/models-list.d.ts.map +1 -0
  317. package/dist/components/settings/models-list.js +72 -0
  318. package/dist/components/settings/models-list.js.map +1 -0
  319. package/dist/components/settings/models-tab.d.ts +4 -0
  320. package/dist/components/settings/models-tab.d.ts.map +1 -1
  321. package/dist/components/settings/models-tab.js +52 -102
  322. package/dist/components/settings/models-tab.js.map +1 -1
  323. package/dist/components/settings/one-time-agent-credential.d.ts +3 -0
  324. package/dist/components/settings/one-time-agent-credential.d.ts.map +1 -0
  325. package/dist/components/settings/one-time-agent-credential.js +55 -0
  326. package/dist/components/settings/one-time-agent-credential.js.map +1 -0
  327. package/dist/components/settings/passkey-list.d.ts +35 -0
  328. package/dist/components/settings/passkey-list.d.ts.map +1 -0
  329. package/dist/components/settings/passkey-list.js +34 -0
  330. package/dist/components/settings/passkey-list.js.map +1 -0
  331. package/dist/components/settings/passkey-tab.d.ts +3 -0
  332. package/dist/components/settings/passkey-tab.d.ts.map +1 -1
  333. package/dist/components/settings/passkey-tab.js +53 -45
  334. package/dist/components/settings/passkey-tab.js.map +1 -1
  335. package/dist/components/settings/pi-accounts-list.d.ts +27 -0
  336. package/dist/components/settings/pi-accounts-list.d.ts.map +1 -0
  337. package/dist/components/settings/pi-accounts-list.js +15 -0
  338. package/dist/components/settings/pi-accounts-list.js.map +1 -0
  339. package/dist/components/settings/pi-accounts.d.ts +3 -0
  340. package/dist/components/settings/pi-accounts.d.ts.map +1 -1
  341. package/dist/components/settings/pi-accounts.js +73 -55
  342. package/dist/components/settings/pi-accounts.js.map +1 -1
  343. package/dist/components/settings/principal-list.d.ts +37 -0
  344. package/dist/components/settings/principal-list.d.ts.map +1 -0
  345. package/dist/components/settings/principal-list.js +18 -0
  346. package/dist/components/settings/principal-list.js.map +1 -0
  347. package/dist/components/settings/settings-panel.d.ts +10 -3
  348. package/dist/components/settings/settings-panel.d.ts.map +1 -1
  349. package/dist/components/settings/settings-panel.js +80 -6
  350. package/dist/components/settings/settings-panel.js.map +1 -1
  351. package/dist/components/settings/skills-list.d.ts +53 -0
  352. package/dist/components/settings/skills-list.d.ts.map +1 -0
  353. package/dist/components/settings/skills-list.js +28 -0
  354. package/dist/components/settings/skills-list.js.map +1 -0
  355. package/dist/components/settings/skills-tab.d.ts.map +1 -1
  356. package/dist/components/settings/skills-tab.js +65 -38
  357. package/dist/components/settings/skills-tab.js.map +1 -1
  358. package/dist/components/settings/tool-permissions-list.d.ts +18 -0
  359. package/dist/components/settings/tool-permissions-list.d.ts.map +1 -0
  360. package/dist/components/settings/tool-permissions-list.js +6 -0
  361. package/dist/components/settings/tool-permissions-list.js.map +1 -0
  362. package/dist/components/settings/tool-permissions.d.ts +2 -1
  363. package/dist/components/settings/tool-permissions.d.ts.map +1 -1
  364. package/dist/components/settings/tool-permissions.js +33 -16
  365. package/dist/components/settings/tool-permissions.js.map +1 -1
  366. package/dist/components/settings/web-search-chain.d.ts +41 -0
  367. package/dist/components/settings/web-search-chain.d.ts.map +1 -0
  368. package/dist/components/settings/web-search-chain.js +47 -0
  369. package/dist/components/settings/web-search-chain.js.map +1 -0
  370. package/dist/components/settings/web-search-settings.d.ts +4 -7
  371. package/dist/components/settings/web-search-settings.d.ts.map +1 -1
  372. package/dist/components/settings/web-search-settings.js +54 -76
  373. package/dist/components/settings/web-search-settings.js.map +1 -1
  374. package/dist/components/share/share-menu.d.ts.map +1 -1
  375. package/dist/components/share/share-menu.js +24 -4
  376. package/dist/components/share/share-menu.js.map +1 -1
  377. package/dist/components/voice/dictation-sheet.js +3 -3
  378. package/dist/components/voice/dictation-sheet.js.map +1 -1
  379. package/dist/components/voice/mic-button.js +1 -1
  380. package/dist/components/voice/mic-button.js.map +1 -1
  381. package/dist/components/voice/review-card.js +1 -1
  382. package/dist/components/voice/review-card.js.map +1 -1
  383. package/dist/config.d.ts +5 -2
  384. package/dist/config.d.ts.map +1 -1
  385. package/dist/config.js +15 -5
  386. package/dist/config.js.map +1 -1
  387. package/dist/connection.d.ts +12 -0
  388. package/dist/connection.d.ts.map +1 -0
  389. package/dist/connection.js +421 -0
  390. package/dist/connection.js.map +1 -0
  391. package/dist/default-root.d.ts +3 -0
  392. package/dist/default-root.d.ts.map +1 -0
  393. package/dist/default-root.js +16 -0
  394. package/dist/default-root.js.map +1 -0
  395. package/dist/hooks/use-color-scheme.d.ts +14 -0
  396. package/dist/hooks/use-color-scheme.d.ts.map +1 -0
  397. package/dist/hooks/use-color-scheme.js +37 -0
  398. package/dist/hooks/use-color-scheme.js.map +1 -0
  399. package/dist/hooks/use-hash-routes.d.ts.map +1 -1
  400. package/dist/hooks/use-hash-routes.js +4 -2
  401. package/dist/hooks/use-hash-routes.js.map +1 -1
  402. package/dist/hooks/use-media-query.d.ts +7 -0
  403. package/dist/hooks/use-media-query.d.ts.map +1 -0
  404. package/dist/hooks/use-media-query.js +34 -0
  405. package/dist/hooks/use-media-query.js.map +1 -0
  406. package/dist/hooks/use-share-intake.d.ts.map +1 -1
  407. package/dist/hooks/use-share-intake.js +37 -12
  408. package/dist/hooks/use-share-intake.js.map +1 -1
  409. package/dist/hooks/use-vpn-status.d.ts +1 -1
  410. package/dist/hooks/use-vpn-status.d.ts.map +1 -1
  411. package/dist/hooks/use-vpn-status.js +20 -16
  412. package/dist/hooks/use-vpn-status.js.map +1 -1
  413. package/dist/hooks/use-websocket.d.ts +5 -24
  414. package/dist/hooks/use-websocket.d.ts.map +1 -1
  415. package/dist/hooks/use-websocket.js +11 -382
  416. package/dist/hooks/use-websocket.js.map +1 -1
  417. package/dist/hooks/websocket-handlers/activity.d.ts +2 -2
  418. package/dist/hooks/websocket-handlers/activity.d.ts.map +1 -1
  419. package/dist/hooks/websocket-handlers/activity.js +4 -5
  420. package/dist/hooks/websocket-handlers/activity.js.map +1 -1
  421. package/dist/hooks/websocket-handlers/chat.d.ts +1 -0
  422. package/dist/hooks/websocket-handlers/chat.d.ts.map +1 -1
  423. package/dist/hooks/websocket-handlers/chat.js +27 -5
  424. package/dist/hooks/websocket-handlers/chat.js.map +1 -1
  425. package/dist/hooks/websocket-handlers/connection.d.ts.map +1 -1
  426. package/dist/hooks/websocket-handlers/connection.js +4 -6
  427. package/dist/hooks/websocket-handlers/connection.js.map +1 -1
  428. package/dist/hooks/websocket-handlers/mask.d.ts +1 -1
  429. package/dist/hooks/websocket-handlers/mask.d.ts.map +1 -1
  430. package/dist/hooks/websocket-handlers/mask.js +2 -3
  431. package/dist/hooks/websocket-handlers/mask.js.map +1 -1
  432. package/dist/hooks/websocket-handlers/provider.d.ts.map +1 -1
  433. package/dist/hooks/websocket-handlers/provider.js +4 -6
  434. package/dist/hooks/websocket-handlers/provider.js.map +1 -1
  435. package/dist/hooks/websocket-handlers/types.d.ts +6 -2
  436. package/dist/hooks/websocket-handlers/types.d.ts.map +1 -1
  437. package/dist/index.d.ts +5 -3
  438. package/dist/index.d.ts.map +1 -1
  439. package/dist/index.js +6 -3
  440. package/dist/index.js.map +1 -1
  441. package/dist/lib/api-client.d.ts +321 -0
  442. package/dist/lib/api-client.d.ts.map +1 -1
  443. package/dist/lib/api-client.js +243 -213
  444. package/dist/lib/api-client.js.map +1 -1
  445. package/dist/lib/backend.d.ts +19 -2
  446. package/dist/lib/backend.d.ts.map +1 -1
  447. package/dist/lib/backend.js +15 -9
  448. package/dist/lib/backend.js.map +1 -1
  449. package/dist/lib/diff.d.ts +8 -10
  450. package/dist/lib/diff.d.ts.map +1 -1
  451. package/dist/lib/diff.js +26 -53
  452. package/dist/lib/diff.js.map +1 -1
  453. package/dist/lib/format-time.d.ts +3 -0
  454. package/dist/lib/format-time.d.ts.map +1 -0
  455. package/dist/lib/format-time.js +25 -0
  456. package/dist/lib/format-time.js.map +1 -0
  457. package/dist/lib/light-dark.d.ts +37 -0
  458. package/dist/lib/light-dark.d.ts.map +1 -0
  459. package/dist/lib/light-dark.js +83 -0
  460. package/dist/lib/light-dark.js.map +1 -0
  461. package/dist/lib/mermaid-theme.d.ts +7 -2
  462. package/dist/lib/mermaid-theme.d.ts.map +1 -1
  463. package/dist/lib/mermaid-theme.js +125 -203
  464. package/dist/lib/mermaid-theme.js.map +1 -1
  465. package/dist/lib/passkeys.d.ts +6 -3
  466. package/dist/lib/passkeys.d.ts.map +1 -1
  467. package/dist/lib/passkeys.js +10 -4
  468. package/dist/lib/passkeys.js.map +1 -1
  469. package/dist/lib/push-registration.d.ts +10 -0
  470. package/dist/lib/push-registration.d.ts.map +1 -0
  471. package/dist/lib/push-registration.js +44 -0
  472. package/dist/lib/push-registration.js.map +1 -0
  473. package/dist/lib/share-intake.d.ts +2 -1
  474. package/dist/lib/share-intake.d.ts.map +1 -1
  475. package/dist/lib/share-intake.js +3 -3
  476. package/dist/lib/share-intake.js.map +1 -1
  477. package/dist/lib/share.d.ts +4 -3
  478. package/dist/lib/share.d.ts.map +1 -1
  479. package/dist/lib/share.js +6 -7
  480. package/dist/lib/share.js.map +1 -1
  481. package/dist/lib/single-key.d.ts +30 -0
  482. package/dist/lib/single-key.d.ts.map +1 -0
  483. package/dist/lib/single-key.js +45 -0
  484. package/dist/lib/single-key.js.map +1 -0
  485. package/dist/lib/tool-names.d.ts +8 -6
  486. package/dist/lib/tool-names.d.ts.map +1 -1
  487. package/dist/lib/tool-names.js +17 -7
  488. package/dist/lib/tool-names.js.map +1 -1
  489. package/dist/root-context.d.ts +229 -0
  490. package/dist/root-context.d.ts.map +1 -0
  491. package/dist/root-context.js +33 -0
  492. package/dist/root-context.js.map +1 -0
  493. package/dist/root.d.ts +38 -0
  494. package/dist/root.d.ts.map +1 -0
  495. package/dist/root.js +47 -0
  496. package/dist/root.js.map +1 -0
  497. package/dist/stores/activity-state.d.ts +29 -0
  498. package/dist/stores/activity-state.d.ts.map +1 -0
  499. package/dist/stores/activity-state.js +282 -0
  500. package/dist/stores/activity-state.js.map +1 -0
  501. package/dist/stores/activity-store.d.ts +10 -41
  502. package/dist/stores/activity-store.d.ts.map +1 -1
  503. package/dist/stores/activity-store.js +9 -271
  504. package/dist/stores/activity-store.js.map +1 -1
  505. package/dist/stores/chat-state.d.ts +212 -0
  506. package/dist/stores/chat-state.d.ts.map +1 -0
  507. package/dist/stores/chat-state.js +466 -0
  508. package/dist/stores/chat-state.js.map +1 -0
  509. package/dist/stores/chat-store.d.ts +4 -162
  510. package/dist/stores/chat-store.d.ts.map +1 -1
  511. package/dist/stores/chat-store.js +7 -418
  512. package/dist/stores/chat-store.js.map +1 -1
  513. package/dist/stores/connection-state.d.ts +40 -0
  514. package/dist/stores/connection-state.d.ts.map +1 -0
  515. package/dist/stores/connection-state.js +30 -0
  516. package/dist/stores/connection-state.js.map +1 -0
  517. package/dist/stores/connection-store.d.ts +4 -40
  518. package/dist/stores/connection-store.d.ts.map +1 -1
  519. package/dist/stores/connection-store.js +7 -27
  520. package/dist/stores/connection-store.js.map +1 -1
  521. package/dist/stores/create-stores.d.ts +23 -0
  522. package/dist/stores/create-stores.d.ts.map +1 -0
  523. package/dist/stores/create-stores.js +28 -0
  524. package/dist/stores/create-stores.js.map +1 -0
  525. package/dist/stores/file-state.d.ts +53 -0
  526. package/dist/stores/file-state.d.ts.map +1 -0
  527. package/dist/stores/file-state.js +341 -0
  528. package/dist/stores/file-state.js.map +1 -0
  529. package/dist/stores/file-store.d.ts +4 -52
  530. package/dist/stores/file-store.d.ts.map +1 -1
  531. package/dist/stores/file-store.js +7 -300
  532. package/dist/stores/file-store.js.map +1 -1
  533. package/dist/stores/graph-state.d.ts +95 -0
  534. package/dist/stores/graph-state.d.ts.map +1 -0
  535. package/dist/stores/graph-state.js +252 -0
  536. package/dist/stores/graph-state.js.map +1 -0
  537. package/dist/stores/graph-store.d.ts +7 -83
  538. package/dist/stores/graph-store.d.ts.map +1 -1
  539. package/dist/stores/graph-store.js +8 -249
  540. package/dist/stores/graph-store.js.map +1 -1
  541. package/dist/stores/mask-state.d.ts +21 -0
  542. package/dist/stores/mask-state.d.ts.map +1 -0
  543. package/dist/stores/mask-state.js +9 -0
  544. package/dist/stores/mask-state.js.map +1 -0
  545. package/dist/stores/mask-store.d.ts +4 -21
  546. package/dist/stores/mask-store.d.ts.map +1 -1
  547. package/dist/stores/mask-store.js +7 -6
  548. package/dist/stores/mask-store.js.map +1 -1
  549. package/dist/stores/principal-state.d.ts +16 -0
  550. package/dist/stores/principal-state.d.ts.map +1 -0
  551. package/dist/stores/principal-state.js +31 -0
  552. package/dist/stores/principal-state.js.map +1 -0
  553. package/dist/stores/principal-store.d.ts +5 -0
  554. package/dist/stores/principal-store.d.ts.map +1 -0
  555. package/dist/stores/principal-store.js +8 -0
  556. package/dist/stores/principal-store.js.map +1 -0
  557. package/dist/stores/provider-state.d.ts +24 -0
  558. package/dist/stores/provider-state.d.ts.map +1 -0
  559. package/dist/stores/provider-state.js +68 -0
  560. package/dist/stores/provider-state.js.map +1 -0
  561. package/dist/stores/provider-store.d.ts +4 -23
  562. package/dist/stores/provider-store.d.ts.map +1 -1
  563. package/dist/stores/provider-store.js +7 -64
  564. package/dist/stores/provider-store.js.map +1 -1
  565. package/dist/stores/share-state.d.ts +29 -0
  566. package/dist/stores/share-state.d.ts.map +1 -0
  567. package/dist/stores/share-state.js +21 -0
  568. package/dist/stores/share-state.js.map +1 -0
  569. package/dist/stores/share-store.d.ts +4 -28
  570. package/dist/stores/share-store.d.ts.map +1 -1
  571. package/dist/stores/share-store.js +7 -18
  572. package/dist/stores/share-store.js.map +1 -1
  573. package/dist/stores/store-environment.d.ts +10 -0
  574. package/dist/stores/store-environment.d.ts.map +1 -0
  575. package/dist/stores/store-environment.js +2 -0
  576. package/dist/stores/store-environment.js.map +1 -0
  577. package/dist/stores/ui-state.d.ts +71 -0
  578. package/dist/stores/ui-state.d.ts.map +1 -0
  579. package/dist/stores/ui-state.js +58 -0
  580. package/dist/stores/ui-state.js.map +1 -0
  581. package/dist/stores/ui-store.d.ts +4 -45
  582. package/dist/stores/ui-store.d.ts.map +1 -1
  583. package/dist/stores/ui-store.js +7 -36
  584. package/dist/stores/ui-store.js.map +1 -1
  585. package/dist/styles.css +1 -1
  586. package/dist/theme.css +150 -97
  587. package/dist/voice/asr-clients.d.ts +2 -1
  588. package/dist/voice/asr-clients.d.ts.map +1 -1
  589. package/dist/voice/asr-clients.js +16 -17
  590. package/dist/voice/asr-clients.js.map +1 -1
  591. package/dist/voice/use-dictation.d.ts.map +1 -1
  592. package/dist/voice/use-dictation.js +12 -8
  593. package/dist/voice/use-dictation.js.map +1 -1
  594. package/dist/voice/voice-state.d.ts +25 -0
  595. package/dist/voice/voice-state.d.ts.map +1 -0
  596. package/dist/voice/voice-state.js +29 -0
  597. package/dist/voice/voice-state.js.map +1 -0
  598. package/dist/voice/voice-store.d.ts +4 -25
  599. package/dist/voice/voice-store.d.ts.map +1 -1
  600. package/dist/voice/voice-store.js +7 -26
  601. package/dist/voice/voice-store.js.map +1 -1
  602. package/package.json +3 -2
  603. package/src/components/activity/activity-page.tsx +334 -160
  604. package/src/components/activity/activity-run-detail.tsx +81 -47
  605. package/src/components/activity/activity-run-list.tsx +27 -59
  606. package/src/components/activity/activity-views.tsx +155 -0
  607. package/src/components/activity/approval-card.tsx +80 -0
  608. package/src/components/activity/digest-card.tsx +25 -61
  609. package/src/components/activity/digest-summary.tsx +52 -0
  610. package/src/components/activity/push-switch.tsx +62 -0
  611. package/src/components/activity/push-toggle.tsx +51 -81
  612. package/src/components/activity/span-bits.tsx +8 -7
  613. package/src/components/chat/ask-user-card.tsx +292 -356
  614. package/src/components/chat/ask-user-typed.ts +77 -0
  615. package/src/components/chat/brain-markdown-links.tsx +4 -4
  616. package/src/components/chat/brain-markdown.tsx +4 -2
  617. package/src/components/chat/chat-page.tsx +38 -9
  618. package/src/components/chat/composer-view.tsx +194 -0
  619. package/src/components/chat/composer.tsx +117 -296
  620. package/src/components/chat/markdown-content.tsx +53 -2
  621. package/src/components/chat/mermaid-block.tsx +13 -5
  622. package/src/components/chat/mermaid-share.ts +8 -7
  623. package/src/components/chat/mermaid-viewer.tsx +3 -1
  624. package/src/components/chat/message-bubble.tsx +78 -94
  625. package/src/components/chat/message-share.ts +7 -7
  626. package/src/components/chat/renderers/bind.tsx +94 -0
  627. package/src/components/chat/renderers/brain-ui-tools.tsx +56 -0
  628. package/src/components/chat/renderers/claude-tools.tsx +3 -2
  629. package/src/components/chat/renderers/index.ts +15 -10
  630. package/src/components/chat/session-drawer.tsx +60 -138
  631. package/src/components/chat/session-list.tsx +113 -0
  632. package/src/components/chat/share-block.tsx +16 -12
  633. package/src/components/chat/share-card.tsx +2 -2
  634. package/src/components/chat/subagent-view.tsx +4 -4
  635. package/src/components/chat/tool-call-timeline.tsx +59 -22
  636. package/src/components/chat/tool-cards/block-card.tsx +145 -0
  637. package/src/components/chat/tool-cards/image-mask-card.tsx +214 -0
  638. package/src/components/chat/tool-cards/location-card.tsx +159 -0
  639. package/src/components/chat/tool-views.tsx +23 -73
  640. package/src/components/chat/transcript-turn.tsx +108 -0
  641. package/src/components/chat/use-chat-commands.ts +14 -16
  642. package/src/components/chat/welcome-state.tsx +36 -91
  643. package/src/components/connectivity/connection-gate.tsx +80 -9
  644. package/src/components/connectivity/login-form.tsx +122 -0
  645. package/src/components/connectivity/login-screen.tsx +45 -100
  646. package/src/components/dev/share-harness.tsx +2 -2
  647. package/src/components/files/file-panel.tsx +168 -0
  648. package/src/components/files/file-tree-view.tsx +127 -0
  649. package/src/components/files/file-tree.tsx +55 -109
  650. package/src/components/files/file-viewer-binary.tsx +3 -2
  651. package/src/components/files/file-viewer-frame.tsx +113 -0
  652. package/src/components/files/file-viewer.tsx +40 -95
  653. package/src/components/files/frontmatter-chips.tsx +42 -0
  654. package/src/components/files/frontmatter-panel.tsx +6 -71
  655. package/src/components/files/staleness.ts +29 -0
  656. package/src/components/graph/graph-canvas.tsx +24 -1
  657. package/src/components/graph/graph-controls-column.tsx +92 -0
  658. package/src/components/graph/graph-controls.tsx +83 -127
  659. package/src/components/graph/graph-form.tsx +183 -0
  660. package/src/components/graph/graph-maintenance.tsx +9 -14
  661. package/src/components/graph/graph-node-rail.tsx +147 -0
  662. package/src/components/graph/graph-page.tsx +189 -49
  663. package/src/components/graph/graph-scene.tsx +200 -30
  664. package/src/components/graph/lib/graph-helpers.ts +65 -43
  665. package/src/components/graph/node-card.tsx +64 -0
  666. package/src/components/graph/node-popover.tsx +28 -117
  667. package/src/components/graph/use-graph-theme.ts +69 -32
  668. package/src/components/graph/use-node-actions.ts +56 -0
  669. package/src/components/images/image-share.ts +4 -2
  670. package/src/components/images/image-viewer.tsx +3 -1
  671. package/src/components/images/mask-editor.tsx +7 -4
  672. package/src/components/layout/app-shell.tsx +7 -1
  673. package/src/components/layout/desktop-palette.tsx +151 -0
  674. package/src/components/layout/key-cap.tsx +15 -0
  675. package/src/components/layout/mobile-tab-bar.tsx +80 -157
  676. package/src/components/layout/shortcut-switch.tsx +32 -0
  677. package/src/components/layout/side-rail.tsx +70 -150
  678. package/src/components/layout/slide-panel.tsx +29 -2
  679. package/src/components/layout/theme.tsx +67 -0
  680. package/src/components/quick-actions/add-form.tsx +188 -0
  681. package/src/components/quick-actions/add-modal.tsx +68 -144
  682. package/src/components/quick-actions/search-modal.tsx +49 -19
  683. package/src/components/quick-actions/streaming-modal.tsx +44 -71
  684. package/src/components/quick-actions/streaming-output.tsx +112 -0
  685. package/src/components/quick-actions/whatsup-modal.tsx +38 -60
  686. package/src/components/settings/devices-agents-tab.tsx +139 -0
  687. package/src/components/settings/models-list.tsx +299 -0
  688. package/src/components/settings/models-tab.tsx +63 -337
  689. package/src/components/settings/one-time-agent-credential.tsx +131 -0
  690. package/src/components/settings/passkey-list.tsx +201 -0
  691. package/src/components/settings/passkey-tab.tsx +53 -197
  692. package/src/components/settings/pi-accounts-list.tsx +128 -0
  693. package/src/components/settings/pi-accounts.tsx +71 -170
  694. package/src/components/settings/principal-list.tsx +172 -0
  695. package/src/components/settings/settings-panel.tsx +245 -19
  696. package/src/components/settings/skills-list.tsx +276 -0
  697. package/src/components/settings/skills-tab.tsx +82 -269
  698. package/src/components/settings/tool-permissions-list.tsx +54 -0
  699. package/src/components/settings/tool-permissions.tsx +27 -46
  700. package/src/components/settings/web-search-chain.tsx +300 -0
  701. package/src/components/settings/web-search-settings.tsx +58 -328
  702. package/src/components/share/share-menu.tsx +19 -4
  703. package/src/components/voice/dictation-sheet.tsx +5 -5
  704. package/src/components/voice/mic-button.tsx +1 -1
  705. package/src/components/voice/review-card.tsx +1 -1
  706. package/src/config.ts +21 -7
  707. package/src/connection.ts +443 -0
  708. package/src/default-root.ts +16 -0
  709. package/src/hooks/use-color-scheme.ts +36 -0
  710. package/src/hooks/use-hash-routes.ts +4 -2
  711. package/src/hooks/use-media-query.ts +32 -0
  712. package/src/hooks/use-share-intake.ts +32 -12
  713. package/src/hooks/use-vpn-status.ts +23 -15
  714. package/src/hooks/use-websocket.ts +12 -426
  715. package/src/hooks/websocket-handlers/activity.ts +4 -5
  716. package/src/hooks/websocket-handlers/chat.ts +26 -5
  717. package/src/hooks/websocket-handlers/connection.ts +4 -6
  718. package/src/hooks/websocket-handlers/mask.ts +2 -3
  719. package/src/hooks/websocket-handlers/provider.ts +4 -6
  720. package/src/hooks/websocket-handlers/types.ts +6 -2
  721. package/src/index.ts +7 -3
  722. package/src/lib/api-client.ts +446 -365
  723. package/src/lib/backend.ts +20 -10
  724. package/src/lib/diff.ts +28 -62
  725. package/src/lib/format-time.ts +20 -0
  726. package/src/lib/light-dark.ts +83 -0
  727. package/src/lib/mermaid-theme.ts +183 -214
  728. package/src/lib/passkeys.ts +12 -4
  729. package/src/lib/push-registration.ts +46 -0
  730. package/src/lib/share-intake.ts +6 -3
  731. package/src/lib/share.ts +7 -4
  732. package/src/lib/single-key.ts +47 -0
  733. package/src/lib/tool-names.ts +31 -8
  734. package/src/root-context.tsx +40 -0
  735. package/src/root.ts +83 -0
  736. package/src/stores/activity-state.ts +295 -0
  737. package/src/stores/activity-store.ts +11 -285
  738. package/src/stores/chat-state.ts +795 -0
  739. package/src/stores/chat-store.ts +11 -705
  740. package/src/stores/connection-state.ts +78 -0
  741. package/src/stores/connection-store.ts +11 -76
  742. package/src/stores/create-stores.ts +31 -0
  743. package/src/stores/file-state.ts +399 -0
  744. package/src/stores/file-store.ts +9 -360
  745. package/src/stores/graph-state.ts +368 -0
  746. package/src/stores/graph-store.ts +10 -355
  747. package/src/stores/mask-state.ts +30 -0
  748. package/src/stores/mask-store.ts +10 -27
  749. package/src/stores/principal-state.ts +42 -0
  750. package/src/stores/principal-store.ts +11 -0
  751. package/src/stores/provider-state.ts +103 -0
  752. package/src/stores/provider-store.ts +10 -95
  753. package/src/stores/share-state.ts +56 -0
  754. package/src/stores/share-store.ts +11 -54
  755. package/src/stores/store-environment.ts +10 -0
  756. package/src/stores/ui-state.ts +143 -0
  757. package/src/stores/ui-store.ts +11 -93
  758. package/src/styles.css +4 -1
  759. package/src/theme.css +150 -97
  760. package/src/voice/asr-clients.ts +17 -17
  761. package/src/voice/use-dictation.ts +11 -8
  762. package/src/voice/voice-state.ts +57 -0
  763. package/src/voice/voice-store.ts +11 -55
@@ -1,14 +1,17 @@
1
- import { X, FileText, Crosshair, Expand } from "lucide-react";
2
1
  import type { GraphNodePayload } from "@schlessera/brain-ui-sdk/protocol";
3
- import { useFileStore } from "../../stores/file-store.js";
4
- import { useUIStore } from "../../stores/ui-store.js";
5
- import { useGraphStore } from "../../stores/graph-store.js";
6
2
  import { communityColor } from "./lib/graph-helpers.js";
3
+ import { NodeCard } from "./node-card.js";
4
+ import { useGraphTheme } from "./use-graph-theme.js";
5
+ import { useNodeActions } from "./use-node-actions.js";
7
6
 
8
7
  /**
9
8
  * Detail card for the selected node, docked to the bottom-left of the canvas
10
- * (bottom sheet width on phones). "Open note" hands over to the file viewer
11
- * panel the same hand-off the search modal uses.
9
+ * (bottom sheet width on phones). From `wide:` the D6 right rail draws the
10
+ * node instead and `SceneBody` does not mount this.
11
+ *
12
+ * This is the container (S7): the store reads and the "which actions
13
+ * apply" rules (`useNodeActions`) live here; `NodeCard` draws the card on
14
+ * the kit.
12
15
  */
13
16
  export function NodePopover({
14
17
  node,
@@ -17,119 +20,27 @@ export function NodePopover({
17
20
  node: GraphNodePayload;
18
21
  communityLabel?: string | null;
19
22
  }) {
20
- const openFile = useFileStore((s) => s.openFile);
21
- const setFilePanelOpen = useUIStore((s) => s.setFilePanelOpen);
22
- const mode = useGraphStore((s) => s.mode);
23
- const select = useGraphStore((s) => s.select);
24
- const setMode = useGraphStore((s) => s.setMode);
25
- const setLocalParams = useGraphStore((s) => s.setLocalParams);
26
- const expandNode = useGraphStore((s) => s.expandNode);
27
-
23
+ const actions = useNodeActions(node);
24
+ const theme = useGraphTheme();
28
25
  const isVirtual = node.virtual === true;
29
26
 
30
- function handleOpen() {
31
- setFilePanelOpen(true);
32
- void openFile(node.path);
33
- }
34
-
35
- function handleFocus() {
36
- // Re-center the local view on this node (switching mode when needed).
37
- if (mode !== "local") setMode("local");
38
- setLocalParams({ center: node.path });
39
- select(null);
40
- }
41
-
42
- return (
43
- <div className="pointer-events-auto absolute inset-x-2 bottom-2 z-10 rounded-xl border border-border bg-surface-overlay/95 p-4 shadow-2xl backdrop-blur md:inset-x-auto md:left-4 md:bottom-4 md:w-80">
44
- <div className="flex items-start justify-between gap-2">
45
- <div className="min-w-0">
46
- <div className="flex items-center gap-2">
47
- <span className="shrink-0 rounded bg-surface-raised px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-muted-foreground">
48
- {isVirtual ? "root" : node.type}
49
- </span>
50
- {communityLabel && (
51
- <span
52
- title="Topic cluster inferred from this note's links"
53
- className="flex min-w-0 items-center gap-1 rounded bg-surface-raised px-1.5 py-0.5 text-[10px] text-muted-foreground"
54
- >
55
- {node.community !== undefined && (
56
- <span
57
- aria-hidden="true"
58
- className="h-1.5 w-1.5 shrink-0 rounded-full"
59
- style={{ backgroundColor: communityColor(node.community) }}
60
- />
61
- )}
62
- <span className="truncate">Topic: {communityLabel}</span>
63
- </span>
64
- )}
65
- </div>
66
- <h3 className="mt-1 truncate text-sm font-medium text-foreground">
67
- {node.title || node.path}
68
- </h3>
69
- <p className="truncate font-mono text-[10px] text-muted-foreground/60">
70
- {node.path}
71
- </p>
72
- </div>
73
- <button
74
- onClick={() => select(null)}
75
- className="shrink-0 rounded p-1 text-muted-foreground transition-colors hover:text-foreground"
76
- title="Close"
77
- >
78
- <X className="h-3.5 w-3.5" />
79
- </button>
80
- </div>
81
-
82
- <div className="mt-2 flex gap-4 text-[11px] text-muted-foreground">
83
- <span>{node.inDegree} in</span>
84
- <span>{node.outDegree} out</span>
85
- {node.distance !== undefined && node.distance > 0 && (
86
- <span>
87
- {node.distance} hop{node.distance === 1 ? "" : "s"}
88
- </span>
89
- )}
90
- </div>
91
-
92
- <div className="mt-3 flex flex-wrap gap-2">
93
- {!isVirtual && (
94
- <ActionButton icon={FileText} label="Open note" onClick={handleOpen} primary />
95
- )}
96
- {!isVirtual && (mode !== "local" || node.distance !== 0) && (
97
- <ActionButton icon={Crosshair} label="Focus here" onClick={handleFocus} />
98
- )}
99
- {mode === "local" && !isVirtual && node.distance !== 0 && (
100
- <ActionButton
101
- icon={Expand}
102
- label="Expand"
103
- onClick={() => void expandNode(node.path)}
104
- />
105
- )}
106
- </div>
107
- </div>
108
- );
109
- }
110
-
111
- function ActionButton({
112
- icon: Icon,
113
- label,
114
- onClick,
115
- primary,
116
- }: {
117
- icon: typeof X;
118
- label: string;
119
- onClick: () => void;
120
- primary?: boolean;
121
- }) {
122
27
  return (
123
- <button
124
- onClick={onClick}
125
- className={
126
- primary
127
- ? "flex min-h-9 items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90"
128
- : "flex min-h-9 items-center gap-1.5 rounded-lg bg-surface-raised px-3 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-surface-overlay"
129
- }
130
- >
131
- <Icon className="h-3.5 w-3.5" />
132
- {label}
133
- </button>
28
+ <NodeCard
29
+ kind={isVirtual ? "root" : node.type}
30
+ title={node.title || node.path}
31
+ path={node.path}
32
+ topic={communityLabel}
33
+ topicColor={node.community !== undefined ? communityColor(node.community, theme.palette) : undefined}
34
+ inDegree={node.inDegree}
35
+ outDegree={node.outDegree}
36
+ distance={node.distance}
37
+ canOpen={actions.canOpen}
38
+ canFocus={actions.canFocus}
39
+ canExpand={actions.canExpand}
40
+ onOpen={actions.open}
41
+ onFocus={actions.focus}
42
+ onExpand={actions.expand}
43
+ onClose={actions.close}
44
+ />
134
45
  );
135
46
  }
@@ -1,51 +1,88 @@
1
1
  import { useMemo } from "react";
2
+ import type { TokenName } from "@schlessera/brain-ui-kit";
3
+
4
+ import { useColorScheme } from "../../hooks/use-color-scheme.js";
5
+ import { readToken, type ColorScheme } from "../../lib/light-dark.js";
6
+ import type { CanvasPalette } from "./lib/graph-helpers.js";
2
7
 
3
8
  export interface GraphTheme {
4
9
  background: string;
5
10
  /** Raised surface used for the hover-label plate (sigma's default is #FFF,
6
- * unreadable under our near-white label text). */
11
+ * unreadable under the dark theme's near-white label text). */
7
12
  surfaceOverlay: string;
8
13
  node: string;
9
14
  nodeSelected: string;
10
15
  edge: string;
11
16
  edgeHighlight: string;
17
+ /** Every label is drawn in the ink — never in its node's colour, which is
18
+ * a value tuned for a 7px mark, not for the one thing you must read. */
12
19
  label: string;
13
20
  labelMuted: string;
21
+ /**
22
+ * The kit's entity colours (its `GraphView`, `PathRef` and inline
23
+ * mentions): teal a person, blue a company, purple a project, amber the
24
+ * focus node, and the neutral for any other document type. The three kinds
25
+ * take the MARK weight, which is the fill in the dark and a darkened step
26
+ * on paper, where a fill sits under 3:1 against the canvas.
27
+ */
28
+ entity: EntityColors;
29
+ /** The categorical slots, the distance ramp and the fixed roles, resolved
30
+ * for the scheme in force. See `CanvasPalette`. */
31
+ palette: CanvasPalette;
14
32
  }
15
33
 
16
- const FALLBACK: GraphTheme = {
17
- background: "#0c0e12",
18
- surfaceOverlay: "#1e2128",
19
- node: "#8a8691",
20
- nodeSelected: "#e09f3e",
21
- edge: "#2a2d35",
22
- edgeHighlight: "#5bb5a2",
23
- label: "#e8e4df",
24
- labelMuted: "#8a8691",
25
- };
34
+ export interface EntityColors {
35
+ person: string;
36
+ company: string;
37
+ project: string;
38
+ focus: string;
39
+ other: string;
40
+ }
26
41
 
27
42
  /**
28
- * Resolve the Tailwind theme tokens into concrete colors for the canvas —
29
- * WebGL cannot read CSS custom properties itself. Read once per mount; the
30
- * app is dark-only, so tokens do not change at runtime.
43
+ * Resolve the kit's tokens into concrete colours for the canvas — WebGL and
44
+ * `fillStyle` cannot read a CSS custom property, and since the kit's light
45
+ * theme every token is a `light-dark()` pair that `getComputedStyle` returns
46
+ * verbatim, so each is split on the scheme the page is drawing in.
47
+ *
48
+ * Re-resolves when the theme preference or, under `system`, the OS scheme
49
+ * changes; the canvas re-applies it in place (`graph-canvas.tsx`).
31
50
  */
32
51
  export function useGraphTheme(): GraphTheme {
33
- return useMemo(() => {
34
- if (typeof window === "undefined") return FALLBACK;
35
- const style = getComputedStyle(document.documentElement);
36
- const token = (name: string, fallback: string) => {
37
- const value = style.getPropertyValue(name).trim();
38
- return value || fallback;
39
- };
40
- return {
41
- background: token("--color-background", FALLBACK.background),
42
- surfaceOverlay: token("--color-surface-overlay", FALLBACK.surfaceOverlay),
43
- node: token("--color-muted-foreground", FALLBACK.node),
44
- nodeSelected: token("--color-primary", FALLBACK.nodeSelected),
45
- edge: token("--color-border", FALLBACK.edge),
46
- edgeHighlight: token("--color-accent", FALLBACK.edgeHighlight),
47
- label: token("--color-foreground", FALLBACK.label),
48
- labelMuted: token("--color-muted-foreground", FALLBACK.labelMuted),
49
- };
50
- }, []);
52
+ const scheme = useColorScheme();
53
+ return useMemo(() => graphTheme(scheme), [scheme]);
54
+ }
55
+
56
+ /** The theme for one scheme, from the tokens. Exported for tests. */
57
+ export function graphTheme(scheme: ColorScheme): GraphTheme {
58
+ const token = (name: TokenName) => readToken(name, scheme);
59
+ return {
60
+ background: token("color-canvas"),
61
+ surfaceOverlay: token("color-raised"),
62
+ node: token("color-ink-mute"),
63
+ nodeSelected: token("canvas-root"),
64
+ edge: token("color-edge"),
65
+ edgeHighlight: token("color-teal"),
66
+ label: token("color-ink"),
67
+ labelMuted: token("color-ink-mute"),
68
+ entity: {
69
+ person: token("teal-mark"),
70
+ company: token("blue-mark"),
71
+ project: token("purple-mark"),
72
+ focus: token("canvas-root"),
73
+ other: token("canvas-other"),
74
+ },
75
+ palette: {
76
+ slots: [1, 2, 3, 4, 5, 6, 7, 8].map((n) => token(`canvas-slot-${n}` as TokenName)),
77
+ ramp: [1, 2, 3, 4, 5].map((n) => token(`canvas-ramp-${n}` as TokenName)),
78
+ root: token("canvas-root"),
79
+ other: token("canvas-other"),
80
+ lens: {
81
+ orphan: token("canvas-lens-orphan"),
82
+ unreachable: token("canvas-lens-unreachable"),
83
+ broken: token("canvas-lens-broken"),
84
+ stale: token("canvas-lens-stale"),
85
+ },
86
+ },
87
+ };
51
88
  }
@@ -0,0 +1,56 @@
1
+ import type { GraphNodePayload } from "@schlessera/brain-ui-sdk/protocol";
2
+ import { useFileStore } from "../../stores/file-store.js";
3
+ import { useUIStore } from "../../stores/ui-store.js";
4
+ import { useGraphStore } from "../../stores/graph-store.js";
5
+
6
+ /**
7
+ * The "which actions apply to the selected node" rules, shared by the
8
+ * floating `NodePopover` (below `laptop:`) and the D6 right rail (from
9
+ * `wide:`). Both draw the same node; only the surface differs, so the rules
10
+ * live once.
11
+ *
12
+ * - Open note hands over to the file viewer panel — the same hand-off the
13
+ * search modal uses. Never for a virtual root (no file behind it).
14
+ * - Focus here re-centres the Local view on the node, switching mode when
15
+ * needed; pointless on the node that already is the centre.
16
+ * - Expand pulls the node's depth-1 ego into the scene — Local only, and
17
+ * not for the centre (its ego is the scene).
18
+ */
19
+ export function useNodeActions(node: GraphNodePayload) {
20
+ const openFile = useFileStore((s) => s.openFile);
21
+ const setFilePanelOpen = useUIStore((s) => s.setFilePanelOpen);
22
+ const mode = useGraphStore((s) => s.mode);
23
+ const select = useGraphStore((s) => s.select);
24
+ const setMode = useGraphStore((s) => s.setMode);
25
+ const setLocalParams = useGraphStore((s) => s.setLocalParams);
26
+ const expandNode = useGraphStore((s) => s.expandNode);
27
+
28
+ const isVirtual = node.virtual === true;
29
+
30
+ return {
31
+ canOpen: !isVirtual,
32
+ canFocus: !isVirtual && (mode !== "local" || node.distance !== 0),
33
+ canExpand: mode === "local" && !isVirtual && node.distance !== 0,
34
+ open() {
35
+ setFilePanelOpen(true);
36
+ void openFile(node.path);
37
+ },
38
+ focus() {
39
+ if (mode !== "local") setMode("local");
40
+ setLocalParams({ center: node.path });
41
+ select(null);
42
+ },
43
+ expand() {
44
+ void expandNode(node.path);
45
+ },
46
+ close() {
47
+ select(null);
48
+ },
49
+ };
50
+ }
51
+
52
+ /** `${n} hop`/`${n} hops`, or null at the centre (0) and where unknown. */
53
+ export function hopsLabel(distance: number | undefined): string | null {
54
+ if (distance === undefined || distance <= 0) return null;
55
+ return `${distance} hop${distance === 1 ? "" : "s"}`;
56
+ }
@@ -1,3 +1,4 @@
1
+ import type { BrainUiRoot } from "../../root.js";
1
2
  import { fetchAsFile, shareFile } from "../../lib/share.js";
2
3
  import {
3
4
  SHARE_OPTIMIZED,
@@ -20,12 +21,13 @@ import type { ShareOption } from "../share/share-menu.js";
20
21
  * falls back to the original rather than being recompressed for show.
21
22
  */
22
23
  export function buildImageShareOptions(
24
+ root: BrainUiRoot,
23
25
  url: string,
24
26
  filename: string,
25
27
  opts: { mime?: string; bytes?: number } = {}
26
28
  ): ShareOption[] {
27
29
  const shareOriginal = async (): Promise<boolean> => {
28
- const file = await fetchAsFile(url, filename, opts.mime);
30
+ const file = await fetchAsFile(root, url, filename, opts.mime);
29
31
  return shareFile(file, { title: filename });
30
32
  };
31
33
 
@@ -41,7 +43,7 @@ export function buildImageShareOptions(
41
43
  label: "Share optimized",
42
44
  hint: `JPEG, up to ${SHARE_OPTIMIZED.maxEdge}px · under ${formatBytes(SHARE_OPTIMIZED.maxBytes)}`,
43
45
  run: async () => {
44
- const original = await fetchAsFile(url, filename, opts.mime);
46
+ const original = await fetchAsFile(root, url, filename, opts.mime);
45
47
  const result = await optimizeImage(original, SHARE_OPTIMIZED);
46
48
  // null means "nothing to gain" (already small enough) or "could not be
47
49
  // decoded". Either way the original is the right thing to send, and
@@ -1,3 +1,4 @@
1
+ import { useBrainUiRoot } from "../../root-context.js";
1
2
  import { useState } from "react";
2
3
  import { ShareMenu } from "../share/share-menu.js";
3
4
  import { ZoomViewer } from "../viewer/zoom-viewer.js";
@@ -26,6 +27,7 @@ export function ImageViewer({
26
27
  bytes?: number;
27
28
  onClose: () => void;
28
29
  }) {
30
+ const root = useBrainUiRoot();
29
31
  // The natural size is unknown until the decode finishes, and `fit()` measures
30
32
  // the DOM — so the load event is what tells the viewer to fit.
31
33
  const [loaded, setLoaded] = useState(false);
@@ -38,7 +40,7 @@ export function ImageViewer({
38
40
  label={`Image viewer: ${filename}`}
39
41
  actions={
40
42
  <ShareMenu
41
- options={buildImageShareOptions(src, filename, { mime, bytes })}
43
+ options={buildImageShareOptions(root, src, filename, { mime, bytes })}
42
44
  title="Share image"
43
45
  />
44
46
  }
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { Eraser, RotateCcw, X } from "lucide-react";
3
3
 
4
- import { apiBase } from "../../lib/backend.js";
4
+ import { useBrainUiRoot } from "../../root-context.js";
5
5
  import { useMaskStore } from "../../stores/mask-store.js";
6
6
 
7
7
  /**
@@ -31,6 +31,7 @@ export function MaskEditor({
31
31
  onSubmit: (requestId: string, maskPngBase64: string) => void;
32
32
  onCancel: (requestId: string, message: string) => void;
33
33
  }) {
34
+ const root = useBrainUiRoot();
34
35
  const request = useMaskStore((s) => s.request);
35
36
  const close = useMaskStore((s) => s.close);
36
37
 
@@ -43,16 +44,17 @@ export function MaskEditor({
43
44
  const [error, setError] = useState<string | null>(null);
44
45
 
45
46
  const rawUrl = request
46
- ? `${apiBase()}/files/content?path=${encodeURIComponent(request.imagePath)}&raw=1`
47
+ ? `${root.apiBase()}/files/content?path=${encodeURIComponent(request.imagePath)}&raw=1`
47
48
  : null;
48
49
 
49
50
  // Reset per request: a second mask on a different image must not inherit the
50
51
  // first one's strokes.
51
52
  useEffect(() => {
52
53
  setStrokes([]);
54
+ setDrawing(false);
53
55
  setLoaded(false);
54
56
  setError(null);
55
- }, [request?.requestId]);
57
+ }, [root, request?.requestId, rawUrl]);
56
58
 
57
59
  const redraw = useCallback(() => {
58
60
  const canvas = canvasRef.current;
@@ -165,6 +167,7 @@ export function MaskEditor({
165
167
  <div className="flex min-h-0 flex-1 items-center justify-center p-3">
166
168
  {rawUrl && (
167
169
  <img
170
+ key={rawUrl}
168
171
  ref={imageRef}
169
172
  src={rawUrl}
170
173
  alt=""
@@ -207,7 +210,7 @@ export function MaskEditor({
207
210
  />
208
211
  </div>
209
212
 
210
- {error && <div className="px-3 pb-1 text-center text-sm text-red-300">{error}</div>}
213
+ {error && <div className="px-3 pb-1 text-center text-sm text-destructive-fill">{error}</div>}
211
214
 
212
215
  <div className="flex items-center gap-3 p-3">
213
216
  <label className="flex flex-1 items-center gap-2 text-xs text-white/80">
@@ -1,11 +1,15 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { SideRail } from "./side-rail.js";
3
3
  import { MobileTabBar } from "./mobile-tab-bar.js";
4
+ import { DesktopPalette } from "./desktop-palette.js";
4
5
  import { useChatStore, activeChat } from "../../stores/chat-store.js";
5
6
  import { cn } from "../../lib/utils.js";
7
+ import { OneTimeAgentCredentialDialog } from "../settings/one-time-agent-credential.js";
8
+ import { useApplyTheme } from "./theme.js";
6
9
 
7
10
  export function AppShell({ children }: { children: ReactNode }) {
8
11
  const isStreaming = useChatStore((s) => activeChat(s).isStreaming);
12
+ useApplyTheme();
9
13
 
10
14
  return (
11
15
  <div className="flex h-[100dvh] bg-background text-foreground">
@@ -15,11 +19,13 @@ export function AppShell({ children }: { children: ReactNode }) {
15
19
  <div
16
20
  className={cn("filament", isStreaming && "filament--active")}
17
21
  />
18
- <main className="flex flex-1 flex-col overflow-hidden pb-16 md:pb-0">
22
+ <main className="flex flex-1 flex-col overflow-hidden pb-16 tablet:pb-0">
19
23
  {children}
20
24
  </main>
21
25
  </div>
22
26
  <MobileTabBar />
27
+ <DesktopPalette />
28
+ <OneTimeAgentCredentialDialog />
23
29
  </div>
24
30
  );
25
31
  }
@@ -0,0 +1,151 @@
1
+ import { CommandPalette, type PaletteGroup, type PaletteItem } from "@schlessera/brain-ui-kit";
2
+ import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent } from "react";
3
+ import { useUIStore } from "../../stores/ui-store.js";
4
+ import { useChatStore, activeChat } from "../../stores/chat-store.js";
5
+ import { useConnectionStore } from "../../stores/connection-store.js";
6
+ import { useChatCommands } from "../chat/use-chat-commands.js";
7
+
8
+ /**
9
+ * The ⌘K palette, on the kit's `CommandPalette` (D22: "SideRail + ⌘K
10
+ * palette" is the desktop's navigation). The kit draws the box, the real
11
+ * query input, the groups, the selected row and its key, and owns ↑↓,
12
+ * Home/End, ⏎ and esc on the rows; this file owns opening it, the query,
13
+ * and what the rows do.
14
+ *
15
+ * Groups are what ⏎ DOES (D37), not the app's feature areas. **Jump to**:
16
+ * the five destinations with their ⌘ keys printed, New chat and Sessions —
17
+ * they move you. **Ask**: Search the brain and Brain statistics — they
18
+ * answer something. **Run**: Sync (`effect: sync`, it writes the
19
+ * repository), the Daily briefing (a cost chip: spending is an effect even
20
+ * when nothing is written) and Add a note (bare — opening a form is not an
21
+ * effect; its submit carries the write). A command the host cannot serve
22
+ * right now is shown DISABLED with its reason, never omitted: dropping rows
23
+ * while the socket is down would teach that the palette's contents are a
24
+ * guess.
25
+ *
26
+ * The app has no cost estimate for the briefing, so its chip says `spends`
27
+ * rather than an invented figure — the design's `~$0.12` is an example.
28
+ */
29
+ export function DesktopPalette() {
30
+ const [open, setOpen] = useState(false);
31
+ const [query, setQuery] = useState("");
32
+ const [selected, setSelected] = useState(0);
33
+ const boxRef = useRef<HTMLDivElement>(null);
34
+
35
+ const setActiveView = useUIStore((s) => s.setActiveView);
36
+ const toggleFilePanel = useUIStore((s) => s.toggleFilePanel);
37
+ const toggleSettingsPanel = useUIStore((s) => s.toggleSettingsPanel);
38
+ const setSessionPanelOpen = useUIStore((s) => s.setSessionPanelOpen);
39
+ const clearMessages = useChatStore((s) => s.clearMessages);
40
+ const isStreaming = useChatStore((s) => activeChat(s).isStreaming);
41
+ const connected = useConnectionStore((s) => s.wsStatus === "connected");
42
+ const runCommand = useChatCommands();
43
+
44
+ useEffect(() => {
45
+ if (typeof window === "undefined") return;
46
+ function onKey(e: KeyboardEvent) {
47
+ if ((e.metaKey || e.ctrlKey) && !e.altKey && !e.shiftKey && e.key.toLowerCase() === "k") {
48
+ e.preventDefault();
49
+ setOpen((v) => !v);
50
+ }
51
+ }
52
+ window.addEventListener("keydown", onKey);
53
+ return () => window.removeEventListener("keydown", onKey);
54
+ }, []);
55
+
56
+ function close() {
57
+ setOpen(false);
58
+ setQuery("");
59
+ setSelected(0);
60
+ }
61
+ function run(fn: () => void) {
62
+ return () => {
63
+ close();
64
+ fn();
65
+ };
66
+ }
67
+ function inChat(fn: () => void) {
68
+ return run(() => {
69
+ setActiveView("chat");
70
+ fn();
71
+ });
72
+ }
73
+
74
+ // The reason a row cannot run right now, printed in the row rather than
75
+ // hiding it. Sync, the briefing and stats talk to the agent over the socket
76
+ // and need a quiet turn; search and add go over REST and always work.
77
+ const why = !connected ? "needs the host" : isStreaming ? "a turn is running" : undefined;
78
+ const jumpTo: PaletteItem[] = [
79
+ { icon: "brain", label: "Chat", tone: "amber", shortcut: "⌘1", onClick: run(() => setActiveView("chat")) },
80
+ { icon: "resolved", label: "Actions", tone: "amber", shortcut: "⌘2", onClick: run(() => setActiveView("activity")) },
81
+ { icon: "files", label: "Files", tone: "teal", shortcut: "⌘3", onClick: run(toggleFilePanel) },
82
+ { icon: "graph", label: "Graph", tone: "purple", shortcut: "⌘4", onClick: run(() => setActiveView("graph")) },
83
+ { icon: "settings", label: "Settings", tone: "neutral", shortcut: "⌘5", onClick: run(toggleSettingsPanel) },
84
+ { icon: "compose", label: "New chat", tone: "amber", onClick: inChat(clearMessages) },
85
+ { icon: "history", label: "Sessions", tone: "blue", onClick: inChat(() => setSessionPanelOpen(true)) },
86
+ ];
87
+ const ask: PaletteItem[] = [
88
+ { icon: "search", label: "Search the brain", tone: "teal", onClick: inChat(() => runCommand("search")) },
89
+ { icon: "ledger", label: "Brain statistics", tone: "neutral", why, onClick: inChat(() => runCommand("stats")) },
90
+ ];
91
+ const runGroup: PaletteItem[] = [
92
+ { icon: "repeat", label: "Sync the brain", tone: "amber", effect: "sync", why, onClick: inChat(() => runCommand("sync")) },
93
+ { icon: "sunrise", label: "Daily briefing", tone: "gold", cost: "spends", why, onClick: inChat(() => runCommand("whatsup")) },
94
+ { icon: "add", label: "Add a note", tone: "teal", onClick: inChat(() => runCommand("add")) },
95
+ ];
96
+ const q = query.trim().toLowerCase();
97
+ const groups: PaletteGroup[] = [
98
+ { label: "Jump to", items: jumpTo },
99
+ { label: "Ask", items: ask },
100
+ { label: "Run", items: runGroup },
101
+ ]
102
+ .map((g) => ({ ...g, items: q ? g.items.filter((it) => it.label.toLowerCase().includes(q)) : g.items }))
103
+ .filter((g) => g.items.length > 0);
104
+ const count = groups.reduce((n, g) => n + g.items.length, 0);
105
+
106
+ // The query input takes focus when the palette opens; ↓ from it lands on
107
+ // the selected row, where the kit's own keys take over.
108
+ useEffect(() => {
109
+ if (!open) return;
110
+ boxRef.current?.querySelector<HTMLInputElement>("input")?.focus();
111
+ }, [open]);
112
+
113
+ if (!open) return null;
114
+
115
+ function onKeyDown(e: ReactKeyboardEvent) {
116
+ const target = e.target as HTMLElement;
117
+ if (target.tagName !== "INPUT") return;
118
+ if (e.key === "ArrowDown") {
119
+ e.preventDefault();
120
+ boxRef.current?.querySelector<HTMLElement>('[role="option"][tabindex="0"]')?.focus();
121
+ } else if (e.key === "Enter") {
122
+ e.preventDefault();
123
+ boxRef.current?.querySelector<HTMLElement>('[role="option"][tabindex="0"]')?.click();
124
+ }
125
+ }
126
+
127
+ return (
128
+ <div
129
+ className="fixed inset-0 z-50 hidden tablet:block bg-black/60"
130
+ onMouseDown={(e) => {
131
+ if (e.target === e.currentTarget) close();
132
+ }}
133
+ >
134
+ <div ref={boxRef} className="mx-auto mt-[110px] w-[560px] max-w-[calc(100vw-2rem)]" onKeyDown={onKeyDown}>
135
+ <CommandPalette
136
+ query={query}
137
+ onQueryChange={(value) => {
138
+ setQuery(value);
139
+ setSelected(0);
140
+ }}
141
+ groups={groups}
142
+ selected={Math.min(selected, Math.max(0, count - 1))}
143
+ footHint="↑↓ move · ⏎ run · esc close"
144
+ footMeta={count === 1 ? "1 command" : `${count} commands`}
145
+ onSelect={setSelected}
146
+ onClose={close}
147
+ />
148
+ </div>
149
+ </div>
150
+ );
151
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The printed key on the button it belongs to — "every shortcut is printed
3
+ * where it applies, never hidden in help" (D36). Decorative to assistive
4
+ * tech: the key is a sighted shortcut, the button's name is the action.
5
+ */
6
+ export function KeyCap({ children }: { children: string }) {
7
+ return (
8
+ <span
9
+ aria-hidden="true"
10
+ className="ml-0.5 rounded border border-current/30 px-1 font-[family-name:var(--font-mono)] text-[9.5px] leading-[1.4] opacity-70"
11
+ >
12
+ {children}
13
+ </span>
14
+ );
15
+ }