@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,7 +1,7 @@
1
- import { useEffect, useState } from "react";
2
- import { Check, Download, Loader2, Pencil, Plus, Power, Trash2, Upload, X } from "lucide-react";
3
- import { api, type SkillDetail, type SkillEntry, type SkillInstallOutcome } from "../../lib/api-client.js";
4
- import { cn } from "../../lib/utils.js";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import type { SkillDetail, SkillEntry, SkillInstallOutcome } from "../../lib/api-client.js";
3
+ import { useBrainUiRoot } from "../../root-context.js";
4
+ import { SkillEditor, SkillsList } from "./skills-list.js";
5
5
 
6
6
  /**
7
7
  * Settings → Skills: manage the user's CUSTOM skills — create, edit,
@@ -13,6 +13,10 @@ import { cn } from "../../lib/utils.js";
13
13
  *
14
14
  * For guided authoring there is a better surface than this editor: the
15
15
  * `add-skill` skill — ask the agent in chat.
16
+ *
17
+ * This is the container (S6): the list request, the `active`-gated reload,
18
+ * every mutation and its generation guard, and the editor's fetch live here;
19
+ * `SkillsList` and `SkillEditor` draw from props.
16
20
  */
17
21
 
18
22
  const TEMPLATE = (name: string) => `---
@@ -26,6 +30,10 @@ Instructions for the agent. Keep them imperative and specific.
26
30
  `;
27
31
 
28
32
  export function SkillsTab({ active }: { active: boolean }) {
33
+ const root = useBrainUiRoot();
34
+ const api = root.api;
35
+ const lifetime = useRef(0);
36
+ const listRequest = useRef(0);
29
37
  const [skills, setSkills] = useState<SkillEntry[]>([]);
30
38
  const [error, setError] = useState<string | null>(null);
31
39
  const [warning, setWarning] = useState<string | null>(null);
@@ -42,39 +50,60 @@ export function SkillsTab({ active }: { active: boolean }) {
42
50
  const [installing, setInstalling] = useState(false);
43
51
  const [outcomes, setOutcomes] = useState<SkillInstallOutcome[] | null>(null);
44
52
 
45
- async function reload() {
53
+ const reload = useCallback(async () => {
54
+ const generation = lifetime.current;
55
+ const request = ++listRequest.current;
56
+ const current = () => generation === lifetime.current && request === listRequest.current;
46
57
  try {
47
58
  const { skills } = await api.skillsList();
59
+ if (!current()) return;
48
60
  setSkills(skills);
49
61
  setError(null);
50
62
  } catch (err) {
51
- setError(err instanceof Error ? err.message : "Could not load skills");
63
+ if (current()) setError(err instanceof Error ? err.message : "Could not load skills");
52
64
  }
53
- }
65
+ }, [api]);
54
66
 
55
67
  useEffect(() => {
68
+ lifetime.current++;
69
+ setSkills([]);
70
+ setError(null);
71
+ setWarning(null);
72
+ setBusy(null);
73
+ setEditing(null);
74
+ setNewName("");
75
+ setGithubSource("");
76
+ setOverwrite(false);
77
+ setInstalling(false);
78
+ setOutcomes(null);
56
79
  if (active) void reload();
57
- }, [active]);
80
+ const invalidate = () => { lifetime.current++; };
81
+ return invalidate;
82
+ }, [active, root, reload]);
58
83
 
59
84
  async function run(name: string, fn: () => Promise<{ warning?: string } | void>) {
85
+ const generation = lifetime.current;
60
86
  setBusy(name);
61
87
  setError(null);
62
88
  setWarning(null);
63
89
  try {
64
90
  const result = await fn();
91
+ if (generation !== lifetime.current) return;
65
92
  if (result && "warning" in result && result.warning) setWarning(result.warning);
66
93
  await reload();
67
94
  } catch (err) {
68
- setError(err instanceof Error ? err.message : "Skill operation failed");
95
+ if (generation === lifetime.current) setError(err instanceof Error ? err.message : "Skill operation failed");
69
96
  } finally {
70
- setBusy(null);
97
+ if (generation === lifetime.current) setBusy(null);
71
98
  }
72
99
  }
73
100
 
74
101
  async function openEditor(entry: SkillEntry) {
102
+ const generation = lifetime.current;
75
103
  setBusy(entry.name);
76
104
  try {
77
105
  const detail: SkillDetail = await api.skillGet(entry.name);
106
+ if (generation !== lifetime.current) return;
78
107
  setEditing({
79
108
  name: entry.name,
80
109
  content: detail.content,
@@ -83,9 +112,9 @@ export function SkillsTab({ active }: { active: boolean }) {
83
112
  });
84
113
  setError(null);
85
114
  } catch (err) {
86
- setError(err instanceof Error ? err.message : "Could not load skill");
115
+ if (generation === lifetime.current) setError(err instanceof Error ? err.message : "Could not load skill");
87
116
  } finally {
88
- setBusy(null);
117
+ if (generation === lifetime.current) setBusy(null);
89
118
  }
90
119
  }
91
120
 
@@ -98,292 +127,76 @@ export function SkillsTab({ active }: { active: boolean }) {
98
127
 
99
128
  async function saveEditor() {
100
129
  if (!editing || editing.readOnly) return;
130
+ const generation = lifetime.current;
101
131
  const { name, content, isNew } = editing;
102
132
  await run(name, async () => {
103
133
  const result = isNew
104
134
  ? await api.skillCreate(name, content)
105
135
  : await api.skillUpdate(name, content);
106
- setEditing(null);
136
+ if (generation === lifetime.current) setEditing(null);
107
137
  return result;
108
138
  });
109
139
  }
110
140
 
111
141
  async function install(fn: () => Promise<{ outcomes: SkillInstallOutcome[]; warning?: string }>) {
142
+ const generation = lifetime.current;
112
143
  setInstalling(true);
113
144
  setError(null);
114
145
  setWarning(null);
115
146
  setOutcomes(null);
116
147
  try {
117
148
  const result = await fn();
149
+ if (generation !== lifetime.current) return;
118
150
  setOutcomes(result.outcomes);
119
151
  if (result.warning) setWarning(result.warning);
120
152
  await reload();
121
153
  } catch (err) {
122
- setError(err instanceof Error ? err.message : "Install failed");
154
+ if (generation === lifetime.current) setError(err instanceof Error ? err.message : "Install failed");
123
155
  } finally {
124
- setInstalling(false);
156
+ if (generation === lifetime.current) setInstalling(false);
125
157
  }
126
158
  }
127
159
 
128
- const custom = skills.filter((s) => s.source === "custom");
129
- const builtin = skills.filter((s) => s.source === "builtin");
130
-
131
160
  if (editing) {
132
161
  return (
133
- <div className="flex h-full flex-col p-4">
134
- <div className="flex items-center justify-between gap-2">
135
- <h3 className="text-sm font-medium text-foreground">
136
- {editing.isNew ? "New skill" : editing.name}
137
- {editing.readOnly && (
138
- <span className="ml-2 text-[11px] text-muted-foreground">built-in · read-only</span>
139
- )}
140
- </h3>
141
- <div className="flex gap-2">
142
- {!editing.readOnly && (
143
- <button
144
- onClick={() => void saveEditor()}
145
- disabled={busy !== null}
146
- className="flex items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110 disabled:opacity-50"
147
- >
148
- {busy ? <Loader2 className="h-3 w-3 animate-spin" /> : <Check className="h-3 w-3" />}
149
- Save
150
- </button>
151
- )}
152
- <button
153
- onClick={() => setEditing(null)}
154
- className="flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground"
155
- >
156
- <X className="h-3 w-3" />
157
- Close
158
- </button>
159
- </div>
160
- </div>
161
- {error && <p className="mt-2 text-xs text-destructive">{error}</p>}
162
- <textarea
163
- value={editing.content}
164
- readOnly={editing.readOnly}
165
- onChange={(e) => setEditing({ ...editing, content: e.target.value })}
166
- spellCheck={false}
167
- className="mt-3 min-h-0 flex-1 resize-none rounded-lg border border-border-subtle bg-background p-3 font-mono text-xs text-foreground focus:border-primary focus:outline-none"
168
- />
169
- </div>
162
+ <SkillEditor
163
+ name={editing.name}
164
+ content={editing.content}
165
+ isNew={editing.isNew}
166
+ readOnly={editing.readOnly}
167
+ saving={busy !== null}
168
+ error={error}
169
+ onChange={(content) => setEditing({ ...editing, content })}
170
+ onSave={() => void saveEditor()}
171
+ onClose={() => setEditing(null)}
172
+ />
170
173
  );
171
174
  }
172
175
 
173
176
  return (
174
- <div className="h-full overflow-y-auto p-4">
175
- <h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
176
- Your skills
177
- </h3>
178
- <p className="mt-1 text-xs text-muted-foreground">
179
- Custom skills live in your brain repo (<code>.agents/skills/</code>) — they
180
- survive redeployments, ride the repo's backups, and apply to every
181
- backend. For guided authoring, ask the agent in chat to{" "}
182
- <span className="font-medium text-foreground">add a skill</span> — the
183
- built-in <code>add-skill</code> skill walks through design and setup.
184
- </p>
185
-
186
- <div className="mt-4 flex items-center gap-2">
187
- <input
188
- value={newName}
189
- onChange={(e) => setNewName(e.target.value.toLowerCase())}
190
- onKeyDown={(e) => {
191
- if (e.key === "Enter") startCreate();
192
- }}
193
- placeholder="new-skill-name (kebab-case)"
194
- className="min-w-0 flex-1 rounded-md border border-border-subtle bg-background px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none"
195
- />
196
- <button
197
- onClick={startCreate}
198
- disabled={!newName.trim()}
199
- className="flex items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110 disabled:opacity-50"
200
- >
201
- <Plus className="h-3 w-3" />
202
- Create
203
- </button>
204
- </div>
205
-
206
- <div className="mt-3 rounded-lg border border-border-subtle bg-surface p-3">
207
- <p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
208
- Install
209
- </p>
210
- <div className="mt-2 flex items-center gap-2">
211
- <label
212
- className={cn(
213
- "flex cursor-pointer items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-foreground transition-colors hover:border-primary hover:text-primary",
214
- installing && "pointer-events-none opacity-50"
215
- )}
216
- >
217
- <Upload className="h-3 w-3" />
218
- Upload .zip
219
- <input
220
- type="file"
221
- accept=".zip,application/zip"
222
- className="hidden"
223
- onChange={(e) => {
224
- const file = e.target.files?.[0];
225
- e.target.value = "";
226
- if (file) void install(() => api.skillInstallZip(file, overwrite));
227
- }}
228
- />
229
- </label>
230
- <label className="flex items-center gap-1.5 text-[11px] text-muted-foreground">
231
- <input
232
- type="checkbox"
233
- checked={overwrite}
234
- onChange={(e) => setOverwrite(e.target.checked)}
235
- />
236
- overwrite existing
237
- </label>
238
- </div>
239
- <div className="mt-2 flex items-center gap-2">
240
- <input
241
- value={githubSource}
242
- onChange={(e) => setGithubSource(e.target.value)}
243
- onKeyDown={(e) => {
244
- if (e.key === "Enter" && githubSource.trim() && !installing) {
245
- void install(() => api.skillInstallGitHub(githubSource.trim(), overwrite));
246
- }
247
- }}
248
- placeholder="GitHub: owner/repo or https://github.com/…/tree/main/skills"
249
- className="min-w-0 flex-1 rounded-md border border-border-subtle bg-background px-2 py-1.5 text-xs text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none"
250
- />
251
- <button
252
- onClick={() =>
253
- void install(() => api.skillInstallGitHub(githubSource.trim(), overwrite))
254
- }
255
- disabled={installing || !githubSource.trim()}
256
- className="flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-foreground transition-colors hover:border-primary hover:text-primary disabled:opacity-50"
257
- >
258
- {installing ? <Loader2 className="h-3 w-3 animate-spin" /> : <Download className="h-3 w-3" />}
259
- Install
260
- </button>
261
- </div>
262
- <p className="mt-1.5 text-[11px] text-muted-foreground">
263
- A skill is any folder with a SKILL.md; one source may carry several.
264
- Private repos use the server's GITHUB_TOKEN.
265
- </p>
266
- {outcomes && (
267
- <ul className="mt-2 flex flex-col gap-1">
268
- {outcomes.map((o, i) => (
269
- <li key={`${o.name}-${i}`} className="text-[11px]">
270
- {o.status === "skipped" ? (
271
- <span className="text-muted-foreground">
272
- ✗ {o.name} — {o.reason}
273
- </span>
274
- ) : (
275
- <span className="text-primary">
276
- ✓ {o.name} {o.status === "replaced" ? "replaced" : "installed"}
277
- {typeof o.files === "number" ? ` (${o.files} file${o.files === 1 ? "" : "s"})` : ""}
278
- </span>
279
- )}
280
- </li>
281
- ))}
282
- </ul>
283
- )}
284
- </div>
285
-
286
- {error && <p className="mt-2 text-xs text-destructive">{error}</p>}
287
- {warning && <p className="mt-2 text-xs text-muted-foreground">{warning}</p>}
288
-
289
- <ul className="mt-4 flex flex-col gap-2">
290
- {custom.length === 0 && (
291
- <li className="rounded-lg border border-dashed border-border-subtle p-3 text-xs text-muted-foreground">
292
- No custom skills yet.
293
- </li>
294
- )}
295
- {custom.map((skill) => (
296
- <li
297
- key={skill.name}
298
- className={cn(
299
- "rounded-lg border border-border-subtle bg-surface p-3",
300
- !skill.enabled && "opacity-60"
301
- )}
302
- >
303
- <div className="flex items-center gap-2">
304
- <div className="min-w-0 flex-1">
305
- <p className="truncate text-sm text-foreground">
306
- {skill.name}
307
- {!skill.enabled && (
308
- <span className="ml-2 text-[11px] text-muted-foreground">disabled</span>
309
- )}
310
- </p>
311
- <p className="truncate text-[11px] text-muted-foreground">
312
- {skill.warning ? `⚠ ${skill.warning}` : skill.description}
313
- </p>
314
- </div>
315
- <button
316
- onClick={() => void openEditor(skill)}
317
- disabled={busy !== null}
318
- title="Edit SKILL.md"
319
- className="rounded-md border border-border-subtle p-1.5 text-muted-foreground transition-colors hover:border-primary hover:text-primary disabled:opacity-50"
320
- >
321
- <Pencil className="h-3.5 w-3.5" />
322
- </button>
323
- <button
324
- onClick={() =>
325
- void run(skill.name, () => api.skillSetEnabled(skill.name, !skill.enabled))
326
- }
327
- disabled={busy !== null}
328
- title={skill.enabled ? "Disable (all backends)" : "Enable"}
329
- className={cn(
330
- "rounded-md border border-border-subtle p-1.5 transition-colors disabled:opacity-50",
331
- skill.enabled
332
- ? "text-primary hover:border-primary"
333
- : "text-muted-foreground hover:border-primary hover:text-primary"
334
- )}
335
- >
336
- {busy === skill.name ? (
337
- <Loader2 className="h-3.5 w-3.5 animate-spin" />
338
- ) : (
339
- <Power className="h-3.5 w-3.5" />
340
- )}
341
- </button>
342
- <button
343
- onClick={() => {
344
- if (confirm(`Delete the skill "${skill.name}" permanently?`)) {
345
- void run(skill.name, () => api.skillRemove(skill.name));
346
- }
347
- }}
348
- disabled={busy !== null}
349
- title="Delete permanently"
350
- className="rounded-md border border-border-subtle p-1.5 text-muted-foreground transition-colors hover:border-destructive hover:text-destructive disabled:opacity-50"
351
- >
352
- <Trash2 className="h-3.5 w-3.5" />
353
- </button>
354
- </div>
355
- </li>
356
- ))}
357
- </ul>
358
-
359
- <h3 className="mt-6 text-xs font-medium uppercase tracking-wide text-muted-foreground">
360
- Built-in skills
361
- </h3>
362
- <p className="mt-1 text-xs text-muted-foreground">
363
- Shipped by brain-kit and its modules; managed by <code>brain skills sync</code>.
364
- A custom skill with the same name overrides a built-in.
365
- </p>
366
- <ul className="mt-3 flex flex-col gap-1.5">
367
- {builtin.map((skill) => (
368
- <li
369
- key={skill.name}
370
- className="flex items-center gap-2 rounded-lg border border-border-subtle bg-surface px-3 py-2"
371
- >
372
- <div className="min-w-0 flex-1">
373
- <p className="truncate text-xs text-foreground">{skill.name}</p>
374
- <p className="truncate text-[11px] text-muted-foreground">{skill.description}</p>
375
- </div>
376
- <button
377
- onClick={() => void openEditor(skill)}
378
- disabled={busy !== null}
379
- title="View SKILL.md"
380
- className="shrink-0 rounded-md border border-border-subtle px-2 py-1 text-[11px] text-muted-foreground transition-colors hover:border-primary hover:text-primary disabled:opacity-50"
381
- >
382
- View
383
- </button>
384
- </li>
385
- ))}
386
- </ul>
387
- </div>
177
+ <SkillsList
178
+ skills={skills}
179
+ busy={busy}
180
+ installing={installing}
181
+ error={error}
182
+ warning={warning}
183
+ outcomes={outcomes}
184
+ newName={newName}
185
+ githubSource={githubSource}
186
+ overwrite={overwrite}
187
+ onNewName={setNewName}
188
+ onCreate={startCreate}
189
+ onGithubSource={setGithubSource}
190
+ onOverwrite={setOverwrite}
191
+ onInstallZip={(file) => void install(() => api.skillInstallZip(file, overwrite))}
192
+ onInstallGitHub={() => void install(() => api.skillInstallGitHub(githubSource.trim(), overwrite))}
193
+ onOpen={(skill) => void openEditor(skill)}
194
+ onToggle={(skill) => void run(skill.name, () => api.skillSetEnabled(skill.name, !skill.enabled))}
195
+ onRemove={(skill) => {
196
+ if (confirm(`Delete the skill "${skill.name}" permanently?`)) {
197
+ void run(skill.name, () => api.skillRemove(skill.name));
198
+ }
199
+ }}
200
+ />
388
201
  );
389
202
  }
@@ -0,0 +1,54 @@
1
+ import { Callout, Label, ListRow, Surface } from "@schlessera/brain-ui-kit";
2
+
3
+ /**
4
+ * The always-allowed tools, rendered from props (S7, the `settings`
5
+ * directory). The design's settings screen is `Label` + `Surface(pad=0)` +
6
+ * grouped `ListRow`s "exercising all four trailing slots"; a grant is a
7
+ * mono-titled row whose trailing action is *Revoke*. The kit's trailing
8
+ * action is decorative — "the row carries the handler" — so tapping the row
9
+ * revokes, and the row dims while the revoke is in flight.
10
+ * `ToolPermissionsSection` is the container that owns the request.
11
+ */
12
+ export interface ToolPermissionsListProps {
13
+ tools: string[];
14
+ /** The tool whose revoke is in flight. */
15
+ busy: string | null;
16
+ error: string | null;
17
+ onRevoke: (tool: string) => void;
18
+ }
19
+
20
+ export function ToolPermissionsList(p: ToolPermissionsListProps) {
21
+ return (
22
+ <div className="mt-6 flex flex-col gap-2">
23
+ <Label text="Always-allowed tools" icon="capability" />
24
+ <p className="text-xs text-muted-foreground">
25
+ These run without an approval card ("Always allow" on a past approval).
26
+ Destructive command confirmations still ask every time. Tap one to ask
27
+ for approval again.
28
+ </p>
29
+ {p.tools.length > 0 && (
30
+ <Surface pad={0}>
31
+ {p.tools.map((tool, i) => (
32
+ <ListRow
33
+ key={tool}
34
+ variant="group"
35
+ mono
36
+ icon="capability"
37
+ iconTone="amber"
38
+ title={tool}
39
+ actionLabel={p.busy === tool ? "Revoking…" : "Revoke"}
40
+ dim={p.busy === tool}
41
+ last={i === p.tools.length - 1}
42
+ onClick={p.busy === tool ? undefined : () => p.onRevoke(tool)}
43
+ />
44
+ ))}
45
+ </Surface>
46
+ )}
47
+ {p.error && (
48
+ <div role="alert">
49
+ <Callout tone="red" variant="banner" icon="failed" mono text={p.error} />
50
+ </div>
51
+ )}
52
+ </div>
53
+ );
54
+ }
@@ -1,72 +1,53 @@
1
- import { useEffect, useState } from "react";
2
- import { X } from "lucide-react";
3
- import { api } from "../../lib/api-client.js";
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { useBrainApi } from "../../root-context.js";
3
+ import { ToolPermissionsList } from "./tool-permissions-list.js";
4
4
 
5
5
  /**
6
6
  * The user's remembered "always allow" tool grants — accumulated by the
7
7
  * approval cards' "Always allow" button, revocable here. Renders nothing
8
8
  * while the list is empty: the section only exists once there is something
9
- * to manage.
9
+ * to manage. This is the container (S7); `ToolPermissionsList` draws the
10
+ * rows on the kit.
10
11
  */
11
12
  export function ToolPermissionsSection({ active }: { active: boolean }) {
13
+ const api = useBrainApi();
14
+ const lifetime = useRef(0);
12
15
  const [tools, setTools] = useState<string[]>([]);
13
16
  const [error, setError] = useState<string | null>(null);
14
17
  const [busy, setBusy] = useState<string | null>(null);
15
18
 
16
19
  useEffect(() => {
17
- if (!active) return;
18
- api
19
- .toolPermissions()
20
- .then(({ tools }) => setTools(tools))
21
- .catch((err) =>
22
- setError(err instanceof Error ? err.message : "Could not load tool permissions")
23
- );
24
- }, [active]);
20
+ const generation = ++lifetime.current;
21
+ const current = () => generation === lifetime.current;
22
+ setTools([]);
23
+ setError(null);
24
+ setBusy(null);
25
+ if (active) {
26
+ api.toolPermissions()
27
+ .then(({ tools }) => { if (current()) setTools(tools); })
28
+ .catch((err) => {
29
+ if (current()) setError(err instanceof Error ? err.message : "Could not load tool permissions");
30
+ });
31
+ }
32
+ const invalidate = () => { lifetime.current++; };
33
+ return invalidate;
34
+ }, [active, api]);
25
35
 
26
36
  async function revoke(tool: string) {
37
+ const generation = lifetime.current;
27
38
  setBusy(tool);
28
39
  setError(null);
29
40
  try {
30
41
  const { tools } = await api.toolPermissionRevoke(tool);
31
- setTools(tools);
42
+ if (generation === lifetime.current) setTools(tools);
32
43
  } catch (err) {
33
- setError(err instanceof Error ? err.message : "Could not revoke");
44
+ if (generation === lifetime.current) setError(err instanceof Error ? err.message : "Could not revoke");
34
45
  } finally {
35
- setBusy(null);
46
+ if (generation === lifetime.current) setBusy(null);
36
47
  }
37
48
  }
38
49
 
39
50
  if (tools.length === 0 && !error) return null;
40
51
 
41
- return (
42
- <div className="mt-6">
43
- <h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
44
- Always-allowed tools
45
- </h3>
46
- <p className="mt-1 text-xs text-muted-foreground">
47
- These run without an approval card ("Always allow" on a past approval).
48
- Destructive command confirmations still ask every time.
49
- </p>
50
- <ul className="mt-4 flex flex-col gap-1.5">
51
- {tools.map((tool) => (
52
- <li
53
- key={tool}
54
- className="flex items-center justify-between gap-3 rounded-lg border border-border-subtle bg-surface px-3 py-2"
55
- >
56
- <code className="truncate text-xs text-foreground">{tool}</code>
57
- <button
58
- onClick={() => void revoke(tool)}
59
- disabled={busy === tool}
60
- title="Ask for approval again"
61
- className="flex shrink-0 items-center gap-1 rounded-md border border-border-subtle px-2 py-1 text-[11px] font-medium text-muted-foreground transition-colors hover:border-destructive hover:text-destructive disabled:opacity-50"
62
- >
63
- <X className="h-3 w-3" />
64
- Revoke
65
- </button>
66
- </li>
67
- ))}
68
- </ul>
69
- {error && <p className="mt-2 text-xs text-destructive">{error}</p>}
70
- </div>
71
- );
52
+ return <ToolPermissionsList tools={tools} busy={busy} error={error} onRevoke={(tool) => void revoke(tool)} />;
72
53
  }