@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,13 +1,13 @@
1
- import { Loader2, AlertCircle, Eye, Code, Copy, Check, FolderOpen } from "lucide-react";
1
+ import type { BrainUiRoot } from "../../root.js";
2
+ import type { FileState } from "../../stores/file-state.js";
2
3
  import { useState } from "react";
3
4
  import { useFileStore } from "../../stores/file-store.js";
4
- import { cn } from "../../lib/utils.js";
5
5
  import { FileViewerMarkdown } from "./file-viewer-markdown.js";
6
6
  import { FileViewerHtml } from "./file-viewer-html.js";
7
7
  import { FileViewerRaw } from "./file-viewer-raw.js";
8
8
  import { FileViewerBinary } from "./file-viewer-binary.js";
9
9
  import { ShareMenu, type ShareOption } from "../share/share-menu.js";
10
- import { apiBase } from "../../lib/backend.js";
10
+ import { useBrainUiRoot } from "../../root-context.js";
11
11
  import { fetchAsFile, shareFile, renderAndShare } from "../../lib/share.js";
12
12
  import { splitFrontmatter } from "../../lib/frontmatter.js";
13
13
  import { stripMarkdown } from "../../lib/strip-markdown.js";
@@ -16,7 +16,13 @@ import { MermaidBlock } from "../chat/mermaid-block.js";
16
16
  import { buildDiagramShareOptions } from "../chat/mermaid-share.js";
17
17
  import { buildImageShareOptions } from "../images/image-share.js";
18
18
  import type { FileContentResponse } from "@schlessera/brain-ui-sdk/protocol";
19
+ import { ViewerEmpty, ViewerError, ViewerLoading, ViewerToolbar } from "./file-viewer-frame.js";
19
20
 
21
+ /**
22
+ * The container (S7): reads the file store, builds the share options (they
23
+ * need the root) and picks the body renderer; the frame around it is
24
+ * `file-viewer-frame.tsx`, rendered from props.
25
+ */
20
26
  export function FileViewer() {
21
27
  const currentPath = useFileStore((s) => s.currentPath);
22
28
  const content = useFileStore((s) => s.currentContent);
@@ -26,14 +32,7 @@ export function FileViewer() {
26
32
  const setViewMode = useFileStore((s) => s.setViewMode);
27
33
  const setTreeExpanded = useFileStore((s) => s.setTreeExpanded);
28
34
 
29
- if (!currentPath) {
30
- return (
31
- <div className="flex h-full flex-col items-center justify-center gap-2 px-6 text-center text-sm text-muted-foreground">
32
- <FolderOpen className="h-8 w-8 text-muted-foreground/40" />
33
- <span>Select a file from the tree to view it.</span>
34
- </div>
35
- );
36
- }
35
+ if (!currentPath) return <ViewerEmpty />;
37
36
 
38
37
  const fileName = currentPath.split("/").pop() ?? currentPath;
39
38
  const previewAvailable =
@@ -55,25 +54,15 @@ export function FileViewer() {
55
54
  />
56
55
 
57
56
  <div className="flex-1 overflow-auto">
58
- {loading && (
59
- <div className="flex items-center justify-center gap-2 py-8 text-sm text-muted-foreground">
60
- <Loader2 className="h-4 w-4 animate-spin" />
61
- Loading file...
62
- </div>
63
- )}
64
- {error && (
65
- <div className="m-4 flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive">
66
- <AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
67
- <span>{error}</span>
68
- </div>
69
- )}
57
+ {loading && <ViewerLoading />}
58
+ {error && <ViewerError message={error} />}
70
59
  {!loading && !error && content && <ViewerBody content={content} viewMode={viewMode} />}
71
60
  </div>
72
61
  </div>
73
62
  );
74
63
  }
75
64
 
76
- function ViewerBody({ content, viewMode }: { content: NonNullable<ReturnType<typeof useFileStore.getState>["currentContent"]>; viewMode: "preview" | "raw" }) {
65
+ function ViewerBody({ content, viewMode }: { content: NonNullable<FileState["currentContent"]>; viewMode: "preview" | "raw" }) {
77
66
  if (content.kind === "binary") {
78
67
  return <FileViewerBinary content={content} />;
79
68
  }
@@ -113,81 +102,37 @@ function Toolbar({
113
102
  content: FileContentResponse | null;
114
103
  onRevealInTree: () => void;
115
104
  }) {
105
+ const root = useBrainUiRoot();
116
106
  const [copied, setCopied] = useState(false);
117
- const shareOptions = content ? buildFileShareOptions(content, fileName) : [];
118
- return (
119
- <div className="flex items-center gap-2 border-b border-border bg-surface px-4 py-2">
120
- <button
121
- onClick={onRevealInTree}
122
- title="Reveal in tree"
123
- className="rounded p-1 text-muted-foreground transition-colors hover:bg-surface-raised hover:text-foreground"
124
- >
125
- <FolderOpen className="h-3.5 w-3.5" />
126
- </button>
127
- <div className="min-w-0 flex-1">
128
- <div className="truncate text-sm font-medium text-foreground" title={fullPath}>
129
- {fileName}
130
- </div>
131
- <div className="truncate text-[10px] text-muted-foreground" title={fullPath}>
132
- {fullPath}
133
- {size !== undefined && <span className="ml-2">· {formatSize(size)}</span>}
134
- </div>
135
- </div>
136
- <button
137
- onClick={() => {
138
- navigator.clipboard.writeText(fullPath);
139
- setCopied(true);
140
- setTimeout(() => setCopied(false), 1500);
141
- }}
142
- title="Copy path"
143
- className="rounded p-1.5 text-muted-foreground transition-colors hover:bg-surface-raised hover:text-foreground"
144
- >
145
- {copied ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />}
146
- </button>
147
- {shareOptions.length > 0 && <ShareMenu options={shareOptions} title="Share" />}
148
- {previewAvailable && (
149
- <div className="flex items-center rounded-md border border-border bg-background">
150
- <ModeButton active={viewMode === "preview"} onClick={() => setViewMode("preview")} title="Preview">
151
- <Eye className="h-3.5 w-3.5" />
152
- </ModeButton>
153
- <ModeButton active={viewMode === "raw"} onClick={() => setViewMode("raw")} title="Raw">
154
- <Code className="h-3.5 w-3.5" />
155
- </ModeButton>
156
- </div>
157
- )}
158
- </div>
159
- );
160
- }
161
-
162
- function ModeButton({ active, onClick, title, children }: { active: boolean; onClick: () => void; title: string; children: React.ReactNode }) {
107
+ const shareOptions = content ? buildFileShareOptions(root, content, fileName) : [];
163
108
  return (
164
- <button
165
- onClick={onClick}
166
- title={title}
167
- className={cn(
168
- "flex h-7 w-7 items-center justify-center transition-colors",
169
- active ? "bg-surface-raised text-primary" : "text-muted-foreground hover:text-foreground"
170
- )}
171
- >
172
- {children}
173
- </button>
109
+ <ViewerToolbar
110
+ fileName={fileName}
111
+ fullPath={fullPath}
112
+ size={size}
113
+ mode={viewMode}
114
+ previewAvailable={previewAvailable}
115
+ copied={copied}
116
+ share={shareOptions.length > 0 ? <ShareMenu options={shareOptions} title="Share" /> : null}
117
+ onMode={setViewMode}
118
+ onCopyPath={() => {
119
+ navigator.clipboard.writeText(fullPath);
120
+ setCopied(true);
121
+ setTimeout(() => setCopied(false), 1500);
122
+ }}
123
+ onReveal={onRevealInTree}
124
+ />
174
125
  );
175
126
  }
176
127
 
177
- function formatSize(bytes: number): string {
178
- if (bytes < 1024) return `${bytes} B`;
179
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
180
- return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
181
- }
182
-
183
- function buildFileShareOptions(content: FileContentResponse, fileName: string): ShareOption[] {
184
- const rawUrl = `${apiBase()}/files/content?path=${encodeURIComponent(content.path)}&raw=1`;
128
+ function buildFileShareOptions(root: BrainUiRoot, content: FileContentResponse, fileName: string): ShareOption[] {
129
+ const rawUrl = `${root.apiBase()}/files/content?path=${encodeURIComponent(content.path)}&raw=1`;
185
130
 
186
131
  if (content.kind === "binary") {
187
132
  // An image gets both: the original bytes, and a lighter re-encode for
188
133
  // messaging. The original is first, and nothing is downgraded unasked.
189
134
  if (content.mime?.startsWith("image/")) {
190
- return buildImageShareOptions(rawUrl, fileName, {
135
+ return buildImageShareOptions(root, rawUrl, fileName, {
191
136
  mime: content.mime,
192
137
  bytes: content.size,
193
138
  });
@@ -199,7 +144,7 @@ function buildFileShareOptions(content: FileContentResponse, fileName: string):
199
144
  id: "file",
200
145
  label: "Share file",
201
146
  run: async () => {
202
- const file = await fetchAsFile(rawUrl, fileName, content.mime);
147
+ const file = await fetchAsFile(root, rawUrl, fileName, content.mime);
203
148
  return shareFile(file, { title: fileName });
204
149
  },
205
150
  },
@@ -240,7 +185,7 @@ function buildFileShareOptions(content: FileContentResponse, fileName: string):
240
185
  label: "Share as image",
241
186
  hint: "Rendered PNG snapshot",
242
187
  run: async () =>
243
- renderAndShare({
188
+ renderAndShare(root, {
244
189
  // The render page runs without JavaScript — mermaid fences are
245
190
  // pre-rendered to inline SVG on the client.
246
191
  content: await inlineMermaidDiagrams(body),
@@ -255,7 +200,7 @@ function buildFileShareOptions(content: FileContentResponse, fileName: string):
255
200
  label: "Share as PDF",
256
201
  hint: "Vector PDF, A4",
257
202
  run: async () =>
258
- renderAndShare({
203
+ renderAndShare(root, {
259
204
  content: await inlineMermaidDiagrams(body),
260
205
  contentType: "markdown",
261
206
  format: "pdf",
@@ -283,7 +228,7 @@ function buildFileShareOptions(content: FileContentResponse, fileName: string):
283
228
  id: "html-png",
284
229
  label: "Share as image",
285
230
  run: () =>
286
- renderAndShare({
231
+ renderAndShare(root, {
287
232
  content: html,
288
233
  contentType: "html",
289
234
  format: "png",
@@ -295,7 +240,7 @@ function buildFileShareOptions(content: FileContentResponse, fileName: string):
295
240
  id: "html-pdf",
296
241
  label: "Share as PDF",
297
242
  run: () =>
298
- renderAndShare({
243
+ renderAndShare(root, {
299
244
  content: html,
300
245
  contentType: "html",
301
246
  format: "pdf",
@@ -311,7 +256,7 @@ function buildFileShareOptions(content: FileContentResponse, fileName: string):
311
256
  if (content.kind === "text" && isMermaidPath(content.path)) {
312
257
  const source = content.content ?? "";
313
258
  return [
314
- ...buildDiagramShareOptions(source, { filename: baseName(fileName) }),
259
+ ...buildDiagramShareOptions(root, source, { filename: baseName(fileName) }),
315
260
  {
316
261
  id: "mmd-file",
317
262
  label: "Share source file",
@@ -0,0 +1,42 @@
1
+ import { Chip, Disclosure } from "@schlessera/brain-ui-kit";
2
+ import type { FrontmatterField } from "../../lib/frontmatter.js";
3
+
4
+ /**
5
+ * A file's frontmatter as the design's `1f` screen draws it: key/value
6
+ * chips (`type: talk`, `status: active`) behind a `Disclosure` whose summary
7
+ * says how much is hidden. Rendered from props (S7); `FrontmatterPanel` is
8
+ * the container that keeps the collapsed choice in the file store so it
9
+ * survives moving between files.
10
+ *
11
+ * A list-valued field is one chip per element, keyed by the field; an empty
12
+ * value is an explicit em dash, because a blank chip reads as nothing.
13
+ */
14
+ export interface FrontmatterChipsProps {
15
+ fields: FrontmatterField[];
16
+ open: boolean;
17
+ onOpenChange: (open: boolean) => void;
18
+ }
19
+
20
+ export function FrontmatterChips(p: FrontmatterChipsProps) {
21
+ if (p.fields.length === 0) return null;
22
+ const summary = p.fields.slice(0, 3).map((f) => f.key).join(", ") + (p.fields.length > 3 ? "…" : "");
23
+ return (
24
+ <div className="mb-4">
25
+ <Disclosure
26
+ label={`frontmatter · ${p.fields.length} ${p.fields.length === 1 ? "field" : "fields"}`}
27
+ meta={p.open ? undefined : summary}
28
+ icon="file"
29
+ open={p.open}
30
+ onOpenChange={p.onOpenChange}
31
+ >
32
+ <div className="flex flex-wrap gap-1.5">
33
+ {p.fields.flatMap((f) =>
34
+ f.list
35
+ ? f.list.map((item, i) => <Chip key={`${f.key}-${i}`} label={`${f.key}: ${item}`} variant="kv" tone="neutral" />)
36
+ : [<Chip key={f.key} label={`${f.key}: ${f.value || "—"}`} variant="kv" tone="neutral" />],
37
+ )}
38
+ </div>
39
+ </Disclosure>
40
+ </div>
41
+ );
42
+ }
@@ -1,78 +1,13 @@
1
- import { ChevronRight } from "lucide-react";
2
1
  import type { FrontmatterField } from "../../lib/frontmatter.js";
3
2
  import { useFileStore } from "../../stores/file-store.js";
4
- import { cn } from "../../lib/utils.js";
3
+ import { FrontmatterChips } from "./frontmatter-chips.js";
5
4
 
5
+ /**
6
+ * The container (S7): the collapsed choice lives in the file store so it
7
+ * carries from one file to the next; `FrontmatterChips` draws from props.
8
+ */
6
9
  export function FrontmatterPanel({ fields }: { fields: FrontmatterField[] }) {
7
10
  const collapsed = useFileStore((s) => s.frontmatterCollapsed);
8
11
  const toggle = useFileStore((s) => s.toggleFrontmatter);
9
-
10
- if (fields.length === 0) return null;
11
-
12
- return (
13
- <div className="mb-4 overflow-hidden rounded-md border border-border/60 bg-surface/50">
14
- <button
15
- type="button"
16
- onClick={toggle}
17
- aria-expanded={!collapsed}
18
- className="flex w-full items-center gap-2 px-3 py-1.5 text-left font-[family-name:var(--font-mono)] text-[11px] uppercase tracking-wider text-muted-foreground transition-colors hover:bg-surface-raised"
19
- >
20
- <ChevronRight
21
- className={cn(
22
- "h-3 w-3 transition-transform",
23
- !collapsed && "rotate-90"
24
- )}
25
- />
26
- <span>frontmatter</span>
27
- <span className="text-muted-foreground/50">·</span>
28
- <span>{fields.length} {fields.length === 1 ? "field" : "fields"}</span>
29
- {collapsed && (
30
- <span className="ml-auto truncate text-muted-foreground/40">
31
- {fields.slice(0, 3).map((f) => f.key).join(", ")}
32
- {fields.length > 3 ? "…" : ""}
33
- </span>
34
- )}
35
- </button>
36
-
37
- {!collapsed && (
38
- <table className="w-full border-collapse text-xs">
39
- <tbody>
40
- {fields.map((f) => (
41
- <tr
42
- key={f.key}
43
- className="border-t border-border/30 align-top first:border-t-0"
44
- >
45
- <th
46
- scope="row"
47
- className="w-32 max-w-[40%] whitespace-nowrap px-3 py-1.5 text-right font-[family-name:var(--font-mono)] font-normal text-muted-foreground"
48
- >
49
- {f.key}
50
- </th>
51
- <td className="px-3 py-1.5 text-foreground/90">
52
- {f.list ? (
53
- <div className="flex flex-wrap gap-1">
54
- {f.list.map((item, i) => (
55
- <span
56
- key={`${item}-${i}`}
57
- className="rounded border border-border bg-background px-1.5 py-[1px] font-[family-name:var(--font-mono)] text-[11px] text-muted-foreground"
58
- >
59
- {item}
60
- </span>
61
- ))}
62
- </div>
63
- ) : (
64
- <span className="font-[family-name:var(--font-mono)] text-[11px] leading-relaxed">
65
- {f.value || (
66
- <span className="text-muted-foreground/40">—</span>
67
- )}
68
- </span>
69
- )}
70
- </td>
71
- </tr>
72
- ))}
73
- </tbody>
74
- </table>
75
- )}
76
- </div>
77
- );
12
+ return <FrontmatterChips fields={fields} open={!collapsed} onOpenChange={() => toggle()} />;
78
13
  }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Staleness from `mtime` (design README, sixth pass §3b): "Stale needs only
3
+ * `mtime` and a threshold, which every file already has — build it."
4
+ *
5
+ * The threshold is this app's, not the design's: the design gives no number
6
+ * (D3's tree draws `stale 38d`, D6's switch says "untouched over 30 days",
7
+ * and neither is a rule). 30 days is the D6 subtitle's own figure and the
8
+ * shortest one the maintenance mode's stale slider offers, so a file the
9
+ * Files rail calls stale is one the graph would too. Change it here and
10
+ * both the rail and the tree's dots follow.
11
+ */
12
+ export const STALE_AFTER_DAYS = 30;
13
+
14
+ const DAY_MS = 24 * 60 * 60 * 1000;
15
+
16
+ /** Whole days since `mtime` (milliseconds since the epoch, as the server sends). */
17
+ export function ageInDays(mtime: number, now = Date.now()): number {
18
+ return Math.max(0, Math.floor((now - mtime) / DAY_MS));
19
+ }
20
+
21
+ export function isStale(mtime: number, now = Date.now()): boolean {
22
+ return ageInDays(mtime, now) >= STALE_AFTER_DAYS;
23
+ }
24
+
25
+ /** "today" · "1 day ago" · "24 days ago" — the rail's mono line. */
26
+ export function formatAge(days: number): string {
27
+ if (days === 0) return "today";
28
+ return `${days} ${days === 1 ? "day" : "days"} ago`;
29
+ }
@@ -143,6 +143,11 @@ export default function GraphCanvas({
143
143
  const ringCanvasRef = useRef<HTMLCanvasElement>(null);
144
144
  const sigmaRef = useRef<Sigma | null>(null);
145
145
  const theme = useGraphTheme();
146
+ // The reducers are registered once at mount and read the theme through this
147
+ // ref, so a theme switch recolours the fade and the selection without
148
+ // re-instantiating sigma.
149
+ const themeRef = useRef(theme);
150
+ themeRef.current = theme;
146
151
  const ringCount = layout === "radial" ? rings : 0;
147
152
 
148
153
  // State the reducers read without re-instantiating sigma.
@@ -179,6 +184,7 @@ export default function GraphCanvas({
179
184
  nodeReducer: (node, attrs) => {
180
185
  const id = Number(node);
181
186
  const s = interactionRef.current;
187
+ const theme = themeRef.current;
182
188
  const active = s.hoveredId ?? s.selectedId;
183
189
  const out = { ...attrs } as typeof attrs & {
184
190
  forceLabel?: boolean;
@@ -207,6 +213,7 @@ export default function GraphCanvas({
207
213
  },
208
214
  edgeReducer: (edge, attrs) => {
209
215
  const s = interactionRef.current;
216
+ const theme = themeRef.current;
210
217
  const active = s.hoveredId ?? s.selectedId;
211
218
  const out = { ...attrs } as typeof attrs & { hidden?: boolean };
212
219
  if (active !== null) {
@@ -264,10 +271,26 @@ export default function GraphCanvas({
264
271
  renderer.kill();
265
272
  sigmaRef.current = null;
266
273
  };
267
- // Theme is read once per mount (dark-only app).
274
+ // The theme the settings above close over is the mount-time one; the
275
+ // effect below swaps them when it changes.
268
276
  // eslint-disable-next-line react-hooks/exhaustive-deps
269
277
  }, []);
270
278
 
279
+ // A theme switch re-applies the colours sigma was configured with — the
280
+ // label ink and the two label drawers — in place. Node and edge colours
281
+ // follow through the restyle effect, whose `nodeColor` and `theme` change
282
+ // with it; the reducers read `themeRef`.
283
+ useEffect(() => {
284
+ const renderer = sigmaRef.current;
285
+ if (!renderer) return;
286
+ renderer.setSettings({
287
+ labelColor: { color: theme.label },
288
+ defaultDrawNodeLabel: makeDrawNodeLabel(theme),
289
+ defaultDrawNodeHover: makeDrawNodeHover(theme),
290
+ });
291
+ renderer.refresh({ skipIndexation: true });
292
+ }, [theme]);
293
+
271
294
  // (Re)build the graph when the scene changes.
272
295
  useEffect(() => {
273
296
  const renderer = sigmaRef.current;
@@ -0,0 +1,92 @@
1
+ import { useGraphStore, type GraphMode } from "../../stores/graph-store.js";
2
+ import { ControlsBody } from "./graph-controls.js";
3
+ import { DisabledToggleRow, Field, Rows, Segmented } from "./graph-form.js";
4
+
5
+ export const MODES: { value: GraphMode; label: string }[] = [
6
+ { value: "clusters", label: "Clusters" },
7
+ { value: "discovery", label: "Discovery" },
8
+ { value: "local", label: "Local" },
9
+ { value: "maintenance", label: "Maintenance" },
10
+ ];
11
+
12
+ /**
13
+ * D6's 264px controls column, from `laptop:` up: the serif "Graph" title,
14
+ * `Label "Mode"` + `FilterRow`, the per-mode form (`ControlsBody` — the
15
+ * same one the phone sheet shows), and a mono footer with the counts the
16
+ * store already has. The footer is silent until a scene has landed; it
17
+ * never estimates.
18
+ */
19
+ export function GraphControlsColumn() {
20
+ const mode = useGraphStore((s) => s.mode);
21
+ const setMode = useGraphStore((s) => s.setMode);
22
+
23
+ return (
24
+ <aside
25
+ aria-label="Graph controls"
26
+ className="flex w-[264px] shrink-0 flex-col border-r border-border bg-surface"
27
+ >
28
+ <div className="px-4 pb-3 pt-4">
29
+ <h1 className="font-display text-lg text-foreground">Graph</h1>
30
+ </div>
31
+ <div className="flex flex-1 flex-col gap-4 overflow-y-auto px-4 pb-4">
32
+ <Field label="Mode">
33
+ <Segmented
34
+ options={MODES}
35
+ value={mode}
36
+ onChange={(v) => setMode(v as GraphMode)}
37
+ />
38
+ </Field>
39
+ <ControlsBody />
40
+ {/* D6's switches, drawn but disabled with their reasons (sixth pass
41
+ §3b, the palette's rule). A scene node carries no `mtime` and no
42
+ provenance record — `GraphNodePayload` has type, degrees,
43
+ community, distance — so neither switch can fire here yet; the
44
+ footer's gold line says the same thing. */}
45
+ {mode !== "maintenance" && (
46
+ <Rows>
47
+ <DisabledToggleRow label="Mark stale" reason="needs mtime" tone="amber" />
48
+ <DisabledToggleRow label="Untrusted only" reason="needs provenance" tone="purple" last />
49
+ </Rows>
50
+ )}
51
+ </div>
52
+ <ColumnFooter />
53
+ </aside>
54
+ );
55
+ }
56
+
57
+ function ColumnFooter() {
58
+ const mode = useGraphStore((s) => s.mode);
59
+ const subgraph = useGraphStore((s) => s.subgraph);
60
+ const total = useGraphStore((s) => s.meta?.nodeCount);
61
+ const local = useGraphStore((s) => s.local);
62
+
63
+ if (!subgraph) return null;
64
+ const drawn = subgraph.nodes.length.toLocaleString();
65
+ const first =
66
+ total !== undefined
67
+ ? `${drawn} of ${total.toLocaleString()} nodes drawn`
68
+ : `${drawn} nodes drawn`;
69
+ const second =
70
+ mode === "local"
71
+ ? `${local.depth}-hop · ${DIRECTION_LABEL[local.direction]}`
72
+ : `${subgraph.edges.length.toLocaleString()} edges${subgraph.truncated ? " · truncated" : ""}`;
73
+
74
+ return (
75
+ <div className="flex flex-col gap-0.5 border-t border-border px-4 py-3 font-mono text-[10px] text-muted-foreground">
76
+ <span>{first}</span>
77
+ <span>{second}</span>
78
+ {/* True of every scene the API serves today: nodes carry no mtime and
79
+ no provenance. Printed in gold, as D6 draws it, and only while it
80
+ is true — the switches above are disabled for the same reasons. */}
81
+ {mode !== "maintenance" && (
82
+ <span className="text-[var(--bk-gold-ink)]">stale needs mtime · untrusted needs provenance</span>
83
+ )}
84
+ </div>
85
+ );
86
+ }
87
+
88
+ const DIRECTION_LABEL = {
89
+ in: "inbound only",
90
+ out: "outbound only",
91
+ both: "both directions",
92
+ } as const;