@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,9 +1,9 @@
1
- import { useEffect, useState, type FormEvent } from "react";
2
- import { Bot, Laptop, Loader2, Plus, Trash2 } from "lucide-react";
3
- import { api, type PrincipalSummary } from "../../lib/api-client.js";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import type { PrincipalSummary } from "../../lib/api-client.js";
3
+ import { useBrainApi } from "../../root-context.js";
4
4
  import { formatRelativeTime } from "../../lib/format-time.js";
5
- import { cn } from "../../lib/utils.js";
6
5
  import { usePrincipalStore } from "../../stores/principal-store.js";
6
+ import { PrincipalList } from "./principal-list.js";
7
7
 
8
8
  const MAX_LABEL_LENGTH = 64;
9
9
  const NOT_ENABLED = "Principal management is not enabled";
@@ -12,8 +12,16 @@ function displayLabel(label: string): string {
12
12
  return Array.from(label).slice(0, MAX_LABEL_LENGTH).join("");
13
13
  }
14
14
 
15
- /** Active devices and delegated agents, with owner-only mint and revoke controls. */
15
+ /**
16
+ * Active devices and delegated agents, with owner-only mint and revoke
17
+ * controls. This is the container (S7): the principals request, the mint
18
+ * through the principal store and the revoke with its confirm live here;
19
+ * `PrincipalList` draws the list and the form on the kit.
20
+ */
16
21
  export function DevicesAgentsTab({ active }: { active: boolean }) {
22
+ const api = useBrainApi();
23
+ const lifetime = useRef(0);
24
+ const request = useRef(0);
17
25
  const [principals, setPrincipals] = useState<PrincipalSummary[]>([]);
18
26
  const [loading, setLoading] = useState(false);
19
27
  const [enabled, setEnabled] = useState(true);
@@ -28,15 +36,20 @@ export function DevicesAgentsTab({ active }: { active: boolean }) {
28
36
  );
29
37
  const mintAgent = usePrincipalStore((state) => state.mintAgent);
30
38
 
31
- async function refresh() {
39
+ const refresh = useCallback(async () => {
40
+ const generation = lifetime.current;
41
+ const token = ++request.current;
42
+ const current = () => generation === lifetime.current && token === request.current;
32
43
  setLoading(true);
33
44
  setLoadFailed(false);
34
45
  setError(null);
35
46
  try {
36
47
  const data = await api.principals();
48
+ if (!current()) return;
37
49
  setPrincipals(data.principals);
38
50
  setEnabled(true);
39
51
  } catch (err) {
52
+ if (!current()) return;
40
53
  setPrincipals([]);
41
54
  if (err instanceof Error && err.message === NOT_ENABLED) {
42
55
  setEnabled(false);
@@ -46,22 +59,31 @@ export function DevicesAgentsTab({ active }: { active: boolean }) {
46
59
  setError(err instanceof Error ? err.message : "Could not load devices and agents");
47
60
  }
48
61
  } finally {
49
- setLoading(false);
62
+ if (current()) setLoading(false);
50
63
  }
51
- }
64
+ }, [api]);
52
65
 
53
66
  useEffect(() => {
67
+ lifetime.current++;
68
+ setPrincipals([]);
69
+ setLoading(false);
70
+ setEnabled(true);
71
+ setLoadFailed(false);
72
+ setError(null);
73
+ setLabel("");
74
+ setTtlDays(7);
54
75
  if (active) void refresh();
55
- }, [active]);
76
+ const invalidate = () => { lifetime.current++; };
77
+ return invalidate;
78
+ }, [active, refresh]);
56
79
 
57
80
  useEffect(() => {
58
81
  if (!oneTimeCredential) return;
59
82
  setLabel("");
60
83
  if (active) void refresh();
61
- }, [active, oneTimeCredential]);
84
+ }, [active, oneTimeCredential, refresh]);
62
85
 
63
- function onMint(event: FormEvent<HTMLFormElement>) {
64
- event.preventDefault();
86
+ function onMint() {
65
87
  const trimmed = label.trim();
66
88
  if (!trimmed || busy) return;
67
89
  setError(null);
@@ -76,156 +98,42 @@ export function DevicesAgentsTab({ active }: { active: boolean }) {
76
98
  : "That device will be signed out immediately.";
77
99
  if (!window.confirm(`${consequence} You can't undo this.`)) return;
78
100
 
101
+ const generation = lifetime.current;
79
102
  setError(null);
80
103
  try {
81
104
  await api.principalRevoke(principal.id);
105
+ if (generation !== lifetime.current) return;
82
106
  setPrincipals((rows) => rows.filter((row) => row.id !== principal.id));
83
107
  if (principal.is_own) window.location.reload();
84
108
  } catch (err) {
109
+ if (generation !== lifetime.current) return;
85
110
  setError(err instanceof Error ? err.message : "Could not revoke access");
86
111
  }
87
112
  }
88
113
 
89
114
  return (
90
- <div className="h-full overflow-y-auto p-4">
91
- <h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
92
- Devices &amp; agents
93
- </h3>
94
- <p className="mt-1 text-xs text-muted-foreground">
95
- See where this brain is signed in and create time-limited access for an agent.
96
- </p>
97
-
98
- {loading ? (
99
- <div className="mt-6 flex justify-center">
100
- <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
101
- </div>
102
- ) : !enabled ? (
103
- <p className="mt-4 text-xs text-muted-foreground">
104
- Devices and agents can only be managed when password authentication is enabled.
105
- </p>
106
- ) : loadFailed ? (
107
- <p role="alert" className="mt-4 text-xs text-destructive">
108
- {error}
109
- </p>
110
- ) : (
111
- <>
112
- <ul className="mt-4 flex flex-col gap-2">
113
- {principals.map((principal) => (
114
- <PrincipalRow
115
- key={principal.id}
116
- principal={principal}
117
- onRevoke={() => void onRevoke(principal)}
118
- />
119
- ))}
120
- {principals.length === 0 ? (
121
- <li className="rounded-lg border border-dashed border-border-subtle p-4 text-center text-xs text-muted-foreground">
122
- No active devices or agents.
123
- </li>
124
- ) : null}
125
- </ul>
126
-
127
- {error || mintError ? (
128
- <p role="alert" className="mt-3 text-xs text-destructive">
129
- {error ?? mintError}
130
- </p>
131
- ) : null}
132
-
133
- <form onSubmit={onMint} className="mt-6 border-t border-border pt-4">
134
- <h4 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
135
- Agent access
136
- </h4>
137
- <p className="mt-1 text-xs text-muted-foreground">
138
- Create a credential an agent can use until it expires or you revoke it.
139
- </p>
140
- <label className="mt-3 block text-xs font-medium text-foreground" htmlFor="agent-label">
141
- Label
142
- </label>
143
- <input
144
- id="agent-label"
145
- value={label}
146
- maxLength={MAX_LABEL_LENGTH}
147
- onChange={(event) => setLabel(event.target.value)}
148
- placeholder="Build agent"
149
- className="mt-1 w-full rounded-lg border border-border-subtle bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary"
150
- />
151
- <label className="mt-3 block text-xs font-medium text-foreground" htmlFor="agent-ttl">
152
- Expires after
153
- </label>
154
- <select
155
- id="agent-ttl"
156
- value={ttlDays}
157
- onChange={(event) => setTtlDays(Number(event.target.value))}
158
- className="mt-1 w-full rounded-lg border border-border-subtle bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary"
159
- >
160
- <option value={1}>1 day</option>
161
- <option value={7}>7 days</option>
162
- <option value={30}>30 days</option>
163
- </select>
164
- <button
165
- type="submit"
166
- disabled={busy || !label.trim()}
167
- className="mt-4 flex w-full items-center justify-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:brightness-110 disabled:opacity-50"
168
- >
169
- {busy ? <Loader2 className="h-4 w-4 animate-spin" /> : <Plus className="h-4 w-4" />}
170
- Create agent credential
171
- </button>
172
- </form>
173
- </>
174
- )}
175
- </div>
176
- );
177
- }
178
-
179
- function PrincipalRow({
180
- principal,
181
- onRevoke,
182
- }: {
183
- principal: PrincipalSummary;
184
- onRevoke: () => void;
185
- }) {
186
- const agent = principal.kind === "agent";
187
- const Icon = agent ? Bot : Laptop;
188
- const kind = principal.is_own ? "This device" : agent ? "Agent" : "Device";
189
-
190
- return (
191
- <li
192
- className={cn(
193
- "rounded-lg border bg-surface p-3",
194
- principal.is_own ? "border-primary/60" : "border-border-subtle"
195
- )}
196
- >
197
- <div className="flex items-start gap-2">
198
- <Icon className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
199
- <div className="min-w-0 flex-1">
200
- <div className="flex flex-wrap items-center gap-1.5">
201
- <span className="break-words text-sm text-foreground">
202
- {displayLabel(principal.label)}
203
- </span>
204
- <span className="rounded bg-surface-raised px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
205
- {kind}
206
- </span>
207
- </div>
208
- <dl className="mt-1.5 grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5 text-[11px] text-muted-foreground">
209
- <dt>Created</dt>
210
- <dd>{formatRelativeTime(principal.created_at)}</dd>
211
- <dt>Last seen</dt>
212
- <dd>
213
- {principal.last_seen_at ? formatRelativeTime(principal.last_seen_at) : "Never"}
214
- </dd>
215
- <dt>Expires</dt>
216
- <dd>{formatRelativeTime(principal.expires_at)}</dd>
217
- </dl>
218
- </div>
219
- <button
220
- type="button"
221
- onClick={onRevoke}
222
- aria-label={`Revoke ${displayLabel(principal.label)}`}
223
- className="flex shrink-0 items-center gap-1 rounded px-1.5 py-1 text-xs text-muted-foreground transition-colors hover:text-destructive"
224
- >
225
- <Trash2 className="h-3.5 w-3.5" />
226
- Revoke
227
- </button>
228
- </div>
229
- </li>
115
+ <PrincipalList
116
+ state={loading ? "loading" : !enabled ? "unavailable" : loadFailed ? "error" : "ready"}
117
+ principals={principals.map((principal) => ({
118
+ id: principal.id,
119
+ label: displayLabel(principal.label),
120
+ kind: principal.kind,
121
+ isOwn: principal.is_own,
122
+ created: formatRelativeTime(principal.created_at),
123
+ lastSeen: principal.last_seen_at ? formatRelativeTime(principal.last_seen_at) : "Never",
124
+ expires: formatRelativeTime(principal.expires_at),
125
+ }))}
126
+ error={error ?? mintError}
127
+ label={label}
128
+ ttlDays={ttlDays}
129
+ minting={busy}
130
+ onLabel={setLabel}
131
+ onTtlDays={setTtlDays}
132
+ onMint={onMint}
133
+ onRevoke={(id) => {
134
+ const principal = principals.find((row) => row.id === id);
135
+ if (principal) void onRevoke(principal);
136
+ }}
137
+ />
230
138
  );
231
139
  }
@@ -0,0 +1,299 @@
1
+ import { Button, Callout, Chip, Placeholder } from "@schlessera/brain-ui-kit";
2
+ import { Eye, EyeOff, X } from "lucide-react";
3
+ import {
4
+ THINKING_LEVELS,
5
+ type BillingMode,
6
+ type ModelCatalogEntry,
7
+ type ModelCatalogResponse,
8
+ type ThinkingLevel,
9
+ } from "@schlessera/brain-ui-sdk/protocol";
10
+ import { useState, type ReactNode } from "react";
11
+
12
+ /**
13
+ * The Models tab's surface, rendered from props (S7, the `settings`
14
+ * directory). `ModelsTab` is the container: the catalog request, the
15
+ * optimistic commits, their ordering gate and their write queue live there;
16
+ * this draws the roster.
17
+ *
18
+ * The per-row choices stay native `<select>`s with the accessible names the
19
+ * tests read — the kit has no select — and the hide toggle stays a native,
20
+ * titled icon button. A hidden model is no longer faded (design-feedback
21
+ * §4, "no opacity de-emphasis"): it reads as hidden from its chip, at full
22
+ * contrast. Refresh, Add and the section errors are the kit's.
23
+ */
24
+ export interface ModelsCatalogViewProps {
25
+ catalog: ModelCatalogResponse | null;
26
+ loading: boolean;
27
+ refreshing: boolean;
28
+ error: string | null;
29
+ /** The sections the tab hosts below the roster, rendered by the container. */
30
+ sections: ReactNode;
31
+ onToggleHidden: (entry: ModelCatalogEntry) => void;
32
+ onBilling: (entry: ModelCatalogEntry, next: BillingMode | "auto") => void;
33
+ onThinking: (entry: ModelCatalogEntry, next: ThinkingLevel | "auto") => void;
34
+ onDefault: (next: string | null) => void;
35
+ onCustomModels: (models: string[]) => void;
36
+ onRefresh: () => void;
37
+ }
38
+
39
+ export function ModelsCatalogView(p: ModelsCatalogViewProps) {
40
+ const catalog = p.catalog;
41
+ const visibleCount = catalog?.models.filter((m) => !m.hidden).length ?? 0;
42
+ return (
43
+ <div className="flex h-full flex-col">
44
+ <div className="flex-1 overflow-y-auto p-4">
45
+ <h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
46
+ Models
47
+ </h3>
48
+ <p className="mt-1 text-xs text-muted-foreground">
49
+ The list is read from the provider and refreshes on its own. Hide the
50
+ ones you never pick — running sessions are unaffected.
51
+ </p>
52
+
53
+ {catalog && <DefaultModelSelect catalog={catalog} onChange={p.onDefault} />}
54
+
55
+ {p.loading ? (
56
+ <div className="mt-4">
57
+ <Placeholder variant="loading" lines={4} />
58
+ </div>
59
+ ) : (
60
+ <ul className="mt-4 flex flex-col gap-2">
61
+ {catalog?.models.map((entry) => (
62
+ <ModelRow
63
+ key={entry.id}
64
+ entry={entry}
65
+ onToggle={() => p.onToggleHidden(entry)}
66
+ onBilling={(next) => p.onBilling(entry, next)}
67
+ onThinking={(next) => p.onThinking(entry, next)}
68
+ />
69
+ ))}
70
+ {catalog?.models.length === 0 && (
71
+ <li>
72
+ <Placeholder variant="empty" message="No models available." icon="model" />
73
+ </li>
74
+ )}
75
+ </ul>
76
+ )}
77
+
78
+ {p.error && (
79
+ <div role="alert" className="mt-3">
80
+ <Callout tone="red" variant="banner" icon="failed" mono text={p.error} />
81
+ </div>
82
+ )}
83
+
84
+ {catalog?.discovery.error && (
85
+ <div className="mt-3">
86
+ <Callout tone="gold" variant="banner" icon="unverified" mono text={`Last refresh failed (${catalog.discovery.error}). Showing the last known list.`} />
87
+ </div>
88
+ )}
89
+ {catalog && !catalog.discovery.enabled && (
90
+ <p className="mt-3 text-xs text-muted-foreground">
91
+ Discovery is disabled (BRAIN_UI_MODEL_DISCOVERY). Only configured
92
+ profiles are listed.
93
+ </p>
94
+ )}
95
+
96
+ {catalog && <OpenRouterSection models={catalog.customModels ?? []} onChange={p.onCustomModels} />}
97
+
98
+ {p.sections}
99
+ </div>
100
+
101
+ <div className="flex items-center justify-between gap-3 border-t border-border p-4">
102
+ <span className="font-[family-name:var(--font-mono)] text-[11px] text-muted-foreground">
103
+ {visibleCount} in picker · {formatRefreshed(catalog?.refreshedAt ?? null)}
104
+ </span>
105
+ <Button label={p.refreshing ? "Refreshing…" : "Refresh"} icon="retry" tone="ghost" size="sm" block={false} disabled={p.refreshing} onClick={p.onRefresh} />
106
+ </div>
107
+ </div>
108
+ );
109
+ }
110
+
111
+ /**
112
+ * The default-model choice: which profile answers when a turn names none —
113
+ * a fresh device's first conversation, a share filed into the brain, any
114
+ * host-initiated action. "Auto" prefers a connected subscription account
115
+ * (e.g. ChatGPT for the gpt profiles) and falls back to the built-in default.
116
+ */
117
+ function DefaultModelSelect({ catalog, onChange }: { catalog: ModelCatalogResponse; onChange: (next: string | null) => void }) {
118
+ const stored = catalog.defaultModelId ?? null;
119
+ const byId = new Map(catalog.models.map((model) => [model.id, model]));
120
+ const resolved = catalog.resolvedDefaultId ? byId.get(catalog.resolvedDefaultId) : undefined;
121
+ // Offer everything visible, plus a stored default that has since been
122
+ // hidden (dropping it from the list would silently rewrite the choice).
123
+ const options = catalog.models.filter((model) => !model.hidden || model.id === stored);
124
+ return (
125
+ <div className="mt-4 flex items-center gap-3 rounded-lg border border-border-subtle bg-surface p-3">
126
+ <div className="min-w-0 flex-1">
127
+ <p className="text-sm text-foreground">Default model</p>
128
+ <p className="text-[11px] text-muted-foreground">
129
+ Used for new conversations, shares, and actions that don't pick one.
130
+ </p>
131
+ </div>
132
+ <select
133
+ value={stored ?? "auto"}
134
+ onChange={(e) => onChange(e.target.value === "auto" ? null : e.target.value)}
135
+ aria-label="Default model"
136
+ className="h-8 max-w-[45%] shrink-0 truncate rounded-lg border border-border-subtle bg-surface px-1.5 text-[11px] text-muted-foreground transition-colors hover:border-primary hover:text-foreground"
137
+ >
138
+ <option value="auto">{!stored && resolved ? `Auto (${resolved.label})` : "Auto"}</option>
139
+ {options.map((model) => (
140
+ <option key={model.id} value={model.id}>
141
+ {model.label}
142
+ </option>
143
+ ))}
144
+ </select>
145
+ </div>
146
+ );
147
+ }
148
+
149
+ /**
150
+ * User-managed OpenRouter models: added and removed here by model id, no env
151
+ * change or redeploy. They appear in the roster above as ordinary profiles
152
+ * (api-billed via OPENROUTER_API_KEY). The draft is the section's own.
153
+ */
154
+ export function OpenRouterSection({ models, onChange }: { models: string[]; onChange: (models: string[]) => void }) {
155
+ const [draft, setDraft] = useState("");
156
+
157
+ function add() {
158
+ const id = draft.trim();
159
+ if (!id || models.includes(id)) return;
160
+ onChange([...models, id]);
161
+ setDraft("");
162
+ }
163
+
164
+ return (
165
+ <div className="mt-6">
166
+ <h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
167
+ OpenRouter models
168
+ </h3>
169
+ <p className="mt-1 text-xs text-muted-foreground">
170
+ Add any OpenRouter model by its id (needs OPENROUTER_API_KEY on the
171
+ server). Added models join the list above.
172
+ </p>
173
+ {models.length > 0 && (
174
+ <ul className="mt-3 flex flex-col gap-1.5">
175
+ {models.map((model) => (
176
+ <li key={model} className="flex items-center gap-2 rounded-lg border border-border-subtle bg-surface px-3 py-2">
177
+ <span className="min-w-0 flex-1 truncate font-[family-name:var(--font-mono)] text-xs text-foreground">{model}</span>
178
+ <button
179
+ type="button"
180
+ onClick={() => onChange(models.filter((m) => m !== model))}
181
+ title={`Remove ${model}`}
182
+ aria-label={`Remove ${model}`}
183
+ className="flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-surface-raised hover:text-destructive"
184
+ >
185
+ <X className="h-3.5 w-3.5" />
186
+ </button>
187
+ </li>
188
+ ))}
189
+ </ul>
190
+ )}
191
+ <div className="mt-3 flex items-center gap-2">
192
+ <input
193
+ value={draft}
194
+ onChange={(e) => setDraft(e.target.value)}
195
+ onKeyDown={(e) => {
196
+ if (e.key === "Enter") add();
197
+ }}
198
+ placeholder="z.ai/glm-5.3-flash"
199
+ aria-label="OpenRouter model id"
200
+ className="h-8 min-w-0 flex-1 rounded-lg border border-border-subtle bg-surface px-2 font-[family-name:var(--font-mono)] text-xs text-foreground placeholder:text-muted-foreground/50 focus:border-primary focus:outline-none"
201
+ />
202
+ <Button label="Add" icon="add" tone="ghost" size="sm" block={false} disabled={!draft.trim()} onClick={add} />
203
+ </div>
204
+ </div>
205
+ );
206
+ }
207
+
208
+ function billingLabel(mode: BillingMode): string {
209
+ return mode === "api" ? "API" : "Subscription";
210
+ }
211
+
212
+ function ModelRow({
213
+ entry,
214
+ onToggle,
215
+ onBilling,
216
+ onThinking,
217
+ }: {
218
+ entry: ModelCatalogEntry;
219
+ onToggle: () => void;
220
+ onBilling: (next: BillingMode | "auto") => void;
221
+ onThinking: (next: ThinkingLevel | "auto") => void;
222
+ }) {
223
+ const Icon = entry.hidden ? EyeOff : Eye;
224
+ return (
225
+ <li className="flex items-center gap-3 rounded-lg border border-border-subtle bg-surface p-3">
226
+ <div className="min-w-0 flex-1">
227
+ <div className="flex items-center gap-2">
228
+ <p className={entry.hidden ? "truncate text-sm text-muted-foreground" : "truncate text-sm text-foreground"}>{entry.label}</p>
229
+ {entry.hidden && <Chip label="hidden" variant="kv" tone="neutral" />}
230
+ </div>
231
+ <p className="truncate text-[11px] text-muted-foreground">
232
+ {entry.id}
233
+ {entry.contextWindow ? ` · ${formatTokens(entry.contextWindow)}` : ""}
234
+ {entry.source === "declared" ? " · configured" : ""}
235
+ </p>
236
+ </div>
237
+ {/* Reasoning effort — only for profiles that take one (the gpt models).
238
+ Same tri-state pattern as billing: Default shows what it resolves
239
+ to, an explicit pick is stored as an override. */}
240
+ {entry.thinkingLevel && (
241
+ <select
242
+ value={entry.thinkingOverride ?? "auto"}
243
+ onChange={(e) => onThinking(e.target.value as ThinkingLevel | "auto")}
244
+ aria-label={`Reasoning effort for ${entry.label}`}
245
+ className="h-8 shrink-0 rounded-lg border border-border-subtle bg-surface px-1.5 text-[11px] text-muted-foreground transition-colors hover:border-primary hover:text-foreground"
246
+ >
247
+ <option value="auto">{!entry.thinkingOverride ? `Default (${entry.thinkingLevel})` : "Default"}</option>
248
+ {THINKING_LEVELS.map((level) => (
249
+ <option key={level} value={level}>
250
+ {level}
251
+ </option>
252
+ ))}
253
+ </select>
254
+ )}
255
+ {/* Tri-state billing: the collapsed control always reads as the
256
+ RESOLVED mode — the Auto option carries what auto resolves to, so
257
+ "Auto (subscription)" and a forced "Subscription" are both legible
258
+ at a glance. */}
259
+ <select
260
+ value={entry.billingOverride ?? "auto"}
261
+ onChange={(e) => onBilling(e.target.value as BillingMode | "auto")}
262
+ aria-label={`Billing for ${entry.label}`}
263
+ className="h-8 shrink-0 rounded-lg border border-border-subtle bg-surface px-1.5 text-[11px] text-muted-foreground transition-colors hover:border-primary hover:text-foreground"
264
+ >
265
+ <option value="auto">
266
+ {!entry.billingOverride && entry.billingMode ? `Auto (${billingLabel(entry.billingMode).toLowerCase()})` : "Auto"}
267
+ </option>
268
+ <option value="subscription">Subscription</option>
269
+ <option value="api">API</option>
270
+ </select>
271
+ <button
272
+ type="button"
273
+ onClick={onToggle}
274
+ title={entry.hidden ? "Show in picker" : "Hide from picker"}
275
+ aria-label={entry.hidden ? "Show in picker" : "Hide from picker"}
276
+ aria-pressed={!entry.hidden}
277
+ className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-surface-raised hover:text-foreground"
278
+ >
279
+ <Icon className="h-4 w-4" />
280
+ </button>
281
+ </li>
282
+ );
283
+ }
284
+
285
+ function formatTokens(tokens: number): string {
286
+ if (tokens >= 1_000_000) return `${tokens / 1_000_000}M context`;
287
+ if (tokens >= 1_000) return `${Math.round(tokens / 1_000)}K context`;
288
+ return `${tokens} context`;
289
+ }
290
+
291
+ function formatRefreshed(refreshedAt: number | null): string {
292
+ if (refreshedAt === null) return "never refreshed";
293
+ const minutes = Math.round((Date.now() - refreshedAt) / 60_000);
294
+ if (minutes < 1) return "refreshed just now";
295
+ if (minutes < 60) return `refreshed ${minutes}m ago`;
296
+ const hours = Math.round(minutes / 60);
297
+ if (hours < 24) return `refreshed ${hours}h ago`;
298
+ return `refreshed ${Math.round(hours / 24)}d ago`;
299
+ }