@schlessera/brain-ui-react 0.34.1 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (763) hide show
  1. package/README.md +89 -4
  2. package/dist/components/activity/activity-page.d.ts +17 -5
  3. package/dist/components/activity/activity-page.d.ts.map +1 -1
  4. package/dist/components/activity/activity-page.js +144 -50
  5. package/dist/components/activity/activity-page.js.map +1 -1
  6. package/dist/components/activity/activity-run-detail.d.ts +16 -1
  7. package/dist/components/activity/activity-run-detail.d.ts.map +1 -1
  8. package/dist/components/activity/activity-run-detail.js +47 -4
  9. package/dist/components/activity/activity-run-detail.js.map +1 -1
  10. package/dist/components/activity/activity-run-list.d.ts +7 -1
  11. package/dist/components/activity/activity-run-list.d.ts.map +1 -1
  12. package/dist/components/activity/activity-run-list.js +16 -8
  13. package/dist/components/activity/activity-run-list.js.map +1 -1
  14. package/dist/components/activity/activity-views.d.ts +63 -0
  15. package/dist/components/activity/activity-views.d.ts.map +1 -0
  16. package/dist/components/activity/activity-views.js +52 -0
  17. package/dist/components/activity/activity-views.js.map +1 -0
  18. package/dist/components/activity/approval-card.d.ts +11 -0
  19. package/dist/components/activity/approval-card.d.ts.map +1 -0
  20. package/dist/components/activity/approval-card.js +46 -0
  21. package/dist/components/activity/approval-card.js.map +1 -0
  22. package/dist/components/activity/digest-card.d.ts +3 -0
  23. package/dist/components/activity/digest-card.d.ts.map +1 -1
  24. package/dist/components/activity/digest-card.js +20 -16
  25. package/dist/components/activity/digest-card.js.map +1 -1
  26. package/dist/components/activity/digest-summary.d.ts +19 -0
  27. package/dist/components/activity/digest-summary.d.ts.map +1 -0
  28. package/dist/components/activity/digest-summary.js +20 -0
  29. package/dist/components/activity/digest-summary.js.map +1 -0
  30. package/dist/components/activity/push-switch.d.ts +25 -0
  31. package/dist/components/activity/push-switch.d.ts.map +1 -0
  32. package/dist/components/activity/push-switch.js +14 -0
  33. package/dist/components/activity/push-switch.js.map +1 -0
  34. package/dist/components/activity/push-toggle.d.ts +7 -0
  35. package/dist/components/activity/push-toggle.d.ts.map +1 -1
  36. package/dist/components/activity/push-toggle.js +72 -47
  37. package/dist/components/activity/push-toggle.js.map +1 -1
  38. package/dist/components/activity/span-bits.d.ts.map +1 -1
  39. package/dist/components/activity/span-bits.js +9 -7
  40. package/dist/components/activity/span-bits.js.map +1 -1
  41. package/dist/components/chat/ask-user-card.d.ts +76 -3
  42. package/dist/components/chat/ask-user-card.d.ts.map +1 -1
  43. package/dist/components/chat/ask-user-card.js +208 -149
  44. package/dist/components/chat/ask-user-card.js.map +1 -1
  45. package/dist/components/chat/ask-user-typed.d.ts +42 -0
  46. package/dist/components/chat/ask-user-typed.d.ts.map +1 -0
  47. package/dist/components/chat/ask-user-typed.js +60 -0
  48. package/dist/components/chat/ask-user-typed.js.map +1 -0
  49. package/dist/components/chat/brain-markdown-links.d.ts +2 -1
  50. package/dist/components/chat/brain-markdown-links.d.ts.map +1 -1
  51. package/dist/components/chat/brain-markdown-links.js +3 -4
  52. package/dist/components/chat/brain-markdown-links.js.map +1 -1
  53. package/dist/components/chat/brain-markdown.d.ts.map +1 -1
  54. package/dist/components/chat/brain-markdown.js +4 -2
  55. package/dist/components/chat/brain-markdown.js.map +1 -1
  56. package/dist/components/chat/chat-page.d.ts.map +1 -1
  57. package/dist/components/chat/chat-page.js +24 -9
  58. package/dist/components/chat/chat-page.js.map +1 -1
  59. package/dist/components/chat/composer-view.d.ts +75 -0
  60. package/dist/components/chat/composer-view.d.ts.map +1 -0
  61. package/dist/components/chat/composer-view.js +31 -0
  62. package/dist/components/chat/composer-view.js.map +1 -0
  63. package/dist/components/chat/composer.d.ts +4 -0
  64. package/dist/components/chat/composer.d.ts.map +1 -1
  65. package/dist/components/chat/composer.js +76 -59
  66. package/dist/components/chat/composer.js.map +1 -1
  67. package/dist/components/chat/markdown-content.d.ts +16 -1
  68. package/dist/components/chat/markdown-content.d.ts.map +1 -1
  69. package/dist/components/chat/markdown-content.js +47 -3
  70. package/dist/components/chat/markdown-content.js.map +1 -1
  71. package/dist/components/chat/mermaid-block.d.ts +4 -0
  72. package/dist/components/chat/mermaid-block.d.ts.map +1 -1
  73. package/dist/components/chat/mermaid-block.js +13 -5
  74. package/dist/components/chat/mermaid-block.js.map +1 -1
  75. package/dist/components/chat/mermaid-share.d.ts +2 -1
  76. package/dist/components/chat/mermaid-share.d.ts.map +1 -1
  77. package/dist/components/chat/mermaid-share.js +7 -8
  78. package/dist/components/chat/mermaid-share.js.map +1 -1
  79. package/dist/components/chat/mermaid-viewer.d.ts.map +1 -1
  80. package/dist/components/chat/mermaid-viewer.js +3 -1
  81. package/dist/components/chat/mermaid-viewer.js.map +1 -1
  82. package/dist/components/chat/message-bubble.d.ts +8 -1
  83. package/dist/components/chat/message-bubble.d.ts.map +1 -1
  84. package/dist/components/chat/message-bubble.js +53 -24
  85. package/dist/components/chat/message-bubble.js.map +1 -1
  86. package/dist/components/chat/message-share.d.ts +2 -1
  87. package/dist/components/chat/message-share.d.ts.map +1 -1
  88. package/dist/components/chat/message-share.js +6 -7
  89. package/dist/components/chat/message-share.js.map +1 -1
  90. package/dist/components/chat/renderers/bind.d.ts +39 -0
  91. package/dist/components/chat/renderers/bind.d.ts.map +1 -0
  92. package/dist/components/chat/renderers/bind.js +43 -0
  93. package/dist/components/chat/renderers/bind.js.map +1 -0
  94. package/dist/components/chat/renderers/brain-ui-tools.d.ts +3 -0
  95. package/dist/components/chat/renderers/brain-ui-tools.d.ts.map +1 -0
  96. package/dist/components/chat/renderers/brain-ui-tools.js +41 -0
  97. package/dist/components/chat/renderers/brain-ui-tools.js.map +1 -0
  98. package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -1
  99. package/dist/components/chat/renderers/claude-tools.js +3 -2
  100. package/dist/components/chat/renderers/claude-tools.js.map +1 -1
  101. package/dist/components/chat/renderers/index.d.ts +10 -2
  102. package/dist/components/chat/renderers/index.d.ts.map +1 -1
  103. package/dist/components/chat/renderers/index.js +15 -10
  104. package/dist/components/chat/renderers/index.js.map +1 -1
  105. package/dist/components/chat/session-drawer.d.ts +4 -0
  106. package/dist/components/chat/session-drawer.d.ts.map +1 -1
  107. package/dist/components/chat/session-drawer.js +55 -40
  108. package/dist/components/chat/session-drawer.js.map +1 -1
  109. package/dist/components/chat/session-list.d.ts +41 -0
  110. package/dist/components/chat/session-list.d.ts.map +1 -0
  111. package/dist/components/chat/session-list.js +10 -0
  112. package/dist/components/chat/session-list.js.map +1 -0
  113. package/dist/components/chat/share-block.d.ts.map +1 -1
  114. package/dist/components/chat/share-block.js +12 -11
  115. package/dist/components/chat/share-block.js.map +1 -1
  116. package/dist/components/chat/share-card.js +2 -2
  117. package/dist/components/chat/share-card.js.map +1 -1
  118. package/dist/components/chat/subagent-view.js +1 -1
  119. package/dist/components/chat/subagent-view.js.map +1 -1
  120. package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
  121. package/dist/components/chat/tool-call-timeline.js +37 -12
  122. package/dist/components/chat/tool-call-timeline.js.map +1 -1
  123. package/dist/components/chat/tool-cards/block-card.d.ts +28 -0
  124. package/dist/components/chat/tool-cards/block-card.d.ts.map +1 -0
  125. package/dist/components/chat/tool-cards/block-card.js +103 -0
  126. package/dist/components/chat/tool-cards/block-card.js.map +1 -0
  127. package/dist/components/chat/tool-cards/image-mask-card.d.ts +70 -0
  128. package/dist/components/chat/tool-cards/image-mask-card.d.ts.map +1 -0
  129. package/dist/components/chat/tool-cards/image-mask-card.js +142 -0
  130. package/dist/components/chat/tool-cards/image-mask-card.js.map +1 -0
  131. package/dist/components/chat/tool-cards/location-card.d.ts +45 -0
  132. package/dist/components/chat/tool-cards/location-card.d.ts.map +1 -0
  133. package/dist/components/chat/tool-cards/location-card.js +128 -0
  134. package/dist/components/chat/tool-cards/location-card.js.map +1 -0
  135. package/dist/components/chat/tool-views.d.ts +15 -4
  136. package/dist/components/chat/tool-views.d.ts.map +1 -1
  137. package/dist/components/chat/tool-views.js +22 -38
  138. package/dist/components/chat/tool-views.js.map +1 -1
  139. package/dist/components/chat/transcript-turn.d.ts +45 -0
  140. package/dist/components/chat/transcript-turn.d.ts.map +1 -0
  141. package/dist/components/chat/transcript-turn.js +25 -0
  142. package/dist/components/chat/transcript-turn.js.map +1 -0
  143. package/dist/components/chat/use-chat-commands.d.ts.map +1 -1
  144. package/dist/components/chat/use-chat-commands.js +13 -16
  145. package/dist/components/chat/use-chat-commands.js.map +1 -1
  146. package/dist/components/chat/welcome-state.d.ts +7 -0
  147. package/dist/components/chat/welcome-state.d.ts.map +1 -1
  148. package/dist/components/chat/welcome-state.js +13 -5
  149. package/dist/components/chat/welcome-state.js.map +1 -1
  150. package/dist/components/connectivity/connection-gate.d.ts.map +1 -1
  151. package/dist/components/connectivity/connection-gate.js +64 -6
  152. package/dist/components/connectivity/connection-gate.js.map +1 -1
  153. package/dist/components/connectivity/login-form.d.ts +31 -0
  154. package/dist/components/connectivity/login-form.d.ts.map +1 -0
  155. package/dist/components/connectivity/login-form.js +19 -0
  156. package/dist/components/connectivity/login-form.js.map +1 -0
  157. package/dist/components/connectivity/login-screen.d.ts +5 -2
  158. package/dist/components/connectivity/login-screen.d.ts.map +1 -1
  159. package/dist/components/connectivity/login-screen.js +41 -31
  160. package/dist/components/connectivity/login-screen.js.map +1 -1
  161. package/dist/components/dev/share-harness.js +1 -1
  162. package/dist/components/dev/share-harness.js.map +1 -1
  163. package/dist/components/files/file-panel.d.ts +1 -1
  164. package/dist/components/files/file-panel.d.ts.map +1 -1
  165. package/dist/components/files/file-panel.js +74 -0
  166. package/dist/components/files/file-panel.js.map +1 -1
  167. package/dist/components/files/file-tree-view.d.ts +45 -0
  168. package/dist/components/files/file-tree-view.d.ts.map +1 -0
  169. package/dist/components/files/file-tree-view.js +51 -0
  170. package/dist/components/files/file-tree-view.js.map +1 -0
  171. package/dist/components/files/file-tree.d.ts +6 -0
  172. package/dist/components/files/file-tree.d.ts.map +1 -1
  173. package/dist/components/files/file-tree.js +39 -43
  174. package/dist/components/files/file-tree.js.map +1 -1
  175. package/dist/components/files/file-viewer-binary.d.ts.map +1 -1
  176. package/dist/components/files/file-viewer-binary.js +3 -2
  177. package/dist/components/files/file-viewer-binary.js.map +1 -1
  178. package/dist/components/files/file-viewer-frame.d.ts +36 -0
  179. package/dist/components/files/file-viewer-frame.d.ts.map +1 -0
  180. package/dist/components/files/file-viewer-frame.js +26 -0
  181. package/dist/components/files/file-viewer-frame.js.map +1 -0
  182. package/dist/components/files/file-viewer.d.ts +5 -0
  183. package/dist/components/files/file-viewer.d.ts.map +1 -1
  184. package/dist/components/files/file-viewer.js +26 -32
  185. package/dist/components/files/file-viewer.js.map +1 -1
  186. package/dist/components/files/frontmatter-chips.d.ts +18 -0
  187. package/dist/components/files/frontmatter-chips.d.ts.map +1 -0
  188. package/dist/components/files/frontmatter-chips.js +11 -0
  189. package/dist/components/files/frontmatter-chips.js.map +1 -0
  190. package/dist/components/files/frontmatter-panel.d.ts +5 -1
  191. package/dist/components/files/frontmatter-panel.d.ts.map +1 -1
  192. package/dist/components/files/frontmatter-panel.js +7 -6
  193. package/dist/components/files/frontmatter-panel.js.map +1 -1
  194. package/dist/components/files/staleness.d.ts +18 -0
  195. package/dist/components/files/staleness.d.ts.map +1 -0
  196. package/dist/components/files/staleness.js +27 -0
  197. package/dist/components/files/staleness.js.map +1 -0
  198. package/dist/components/graph/graph-canvas.d.ts.map +1 -1
  199. package/dist/components/graph/graph-canvas.js +24 -1
  200. package/dist/components/graph/graph-canvas.js.map +1 -1
  201. package/dist/components/graph/graph-controls-column.d.ts +14 -0
  202. package/dist/components/graph/graph-controls-column.d.ts.map +1 -0
  203. package/dist/components/graph/graph-controls-column.js +44 -0
  204. package/dist/components/graph/graph-controls-column.js.map +1 -0
  205. package/dist/components/graph/graph-controls.d.ts +20 -5
  206. package/dist/components/graph/graph-controls.d.ts.map +1 -1
  207. package/dist/components/graph/graph-controls.js +58 -37
  208. package/dist/components/graph/graph-controls.js.map +1 -1
  209. package/dist/components/graph/graph-form.d.ts +82 -0
  210. package/dist/components/graph/graph-form.d.ts.map +1 -0
  211. package/dist/components/graph/graph-form.js +69 -0
  212. package/dist/components/graph/graph-form.js.map +1 -0
  213. package/dist/components/graph/graph-maintenance.d.ts.map +1 -1
  214. package/dist/components/graph/graph-maintenance.js +6 -10
  215. package/dist/components/graph/graph-maintenance.js.map +1 -1
  216. package/dist/components/graph/graph-node-rail.d.ts +13 -0
  217. package/dist/components/graph/graph-node-rail.d.ts.map +1 -0
  218. package/dist/components/graph/graph-node-rail.js +92 -0
  219. package/dist/components/graph/graph-node-rail.js.map +1 -0
  220. package/dist/components/graph/graph-page.d.ts +7 -0
  221. package/dist/components/graph/graph-page.d.ts.map +1 -1
  222. package/dist/components/graph/graph-page.js +102 -12
  223. package/dist/components/graph/graph-page.js.map +1 -1
  224. package/dist/components/graph/graph-scene.d.ts.map +1 -1
  225. package/dist/components/graph/graph-scene.js +100 -24
  226. package/dist/components/graph/graph-scene.js.map +1 -1
  227. package/dist/components/graph/lib/graph-helpers.d.ts +42 -12
  228. package/dist/components/graph/lib/graph-helpers.d.ts.map +1 -1
  229. package/dist/components/graph/lib/graph-helpers.js +33 -41
  230. package/dist/components/graph/lib/graph-helpers.js.map +1 -1
  231. package/dist/components/graph/node-card.d.ts +28 -0
  232. package/dist/components/graph/node-card.d.ts.map +1 -0
  233. package/dist/components/graph/node-card.js +7 -0
  234. package/dist/components/graph/node-card.js.map +1 -0
  235. package/dist/components/graph/node-popover.d.ts +6 -2
  236. package/dist/components/graph/node-popover.d.ts.map +1 -1
  237. package/dist/components/graph/node-popover.js +13 -31
  238. package/dist/components/graph/node-popover.js.map +1 -1
  239. package/dist/components/graph/use-graph-theme.d.ts +32 -4
  240. package/dist/components/graph/use-graph-theme.d.ts.map +1 -1
  241. package/dist/components/graph/use-graph-theme.js +44 -32
  242. package/dist/components/graph/use-graph-theme.js.map +1 -1
  243. package/dist/components/graph/use-node-actions.d.ts +26 -0
  244. package/dist/components/graph/use-node-actions.d.ts.map +1 -0
  245. package/dist/components/graph/use-node-actions.js +54 -0
  246. package/dist/components/graph/use-node-actions.js.map +1 -0
  247. package/dist/components/images/image-share.d.ts +2 -1
  248. package/dist/components/images/image-share.d.ts.map +1 -1
  249. package/dist/components/images/image-share.js +3 -3
  250. package/dist/components/images/image-share.js.map +1 -1
  251. package/dist/components/images/image-viewer.d.ts.map +1 -1
  252. package/dist/components/images/image-viewer.js +3 -1
  253. package/dist/components/images/image-viewer.js.map +1 -1
  254. package/dist/components/images/mask-editor.d.ts.map +1 -1
  255. package/dist/components/images/mask-editor.js +7 -5
  256. package/dist/components/images/mask-editor.js.map +1 -1
  257. package/dist/components/layout/app-shell.d.ts.map +1 -1
  258. package/dist/components/layout/app-shell.js +5 -1
  259. package/dist/components/layout/app-shell.js.map +1 -1
  260. package/dist/components/layout/desktop-palette.d.ts +23 -0
  261. package/dist/components/layout/desktop-palette.d.ts.map +1 -0
  262. package/dist/components/layout/desktop-palette.js +132 -0
  263. package/dist/components/layout/desktop-palette.js.map +1 -0
  264. package/dist/components/layout/key-cap.d.ts +9 -0
  265. package/dist/components/layout/key-cap.d.ts.map +1 -0
  266. package/dist/components/layout/key-cap.js +10 -0
  267. package/dist/components/layout/key-cap.js.map +1 -0
  268. package/dist/components/layout/mobile-tab-bar.d.ts +13 -0
  269. package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
  270. package/dist/components/layout/mobile-tab-bar.js +58 -47
  271. package/dist/components/layout/mobile-tab-bar.js.map +1 -1
  272. package/dist/components/layout/shortcut-switch.d.ts +13 -0
  273. package/dist/components/layout/shortcut-switch.d.ts.map +1 -0
  274. package/dist/components/layout/shortcut-switch.js +22 -0
  275. package/dist/components/layout/shortcut-switch.js.map +1 -0
  276. package/dist/components/layout/side-rail.d.ts +24 -0
  277. package/dist/components/layout/side-rail.d.ts.map +1 -1
  278. package/dist/components/layout/side-rail.js +65 -27
  279. package/dist/components/layout/side-rail.js.map +1 -1
  280. package/dist/components/layout/slide-panel.d.ts +12 -2
  281. package/dist/components/layout/slide-panel.d.ts.map +1 -1
  282. package/dist/components/layout/slide-panel.js +11 -2
  283. package/dist/components/layout/slide-panel.js.map +1 -1
  284. package/dist/components/layout/theme.d.ts +22 -0
  285. package/dist/components/layout/theme.d.ts.map +1 -0
  286. package/dist/components/layout/theme.js +44 -0
  287. package/dist/components/layout/theme.js.map +1 -0
  288. package/dist/components/quick-actions/add-form.d.ts +44 -0
  289. package/dist/components/quick-actions/add-form.d.ts.map +1 -0
  290. package/dist/components/quick-actions/add-form.js +30 -0
  291. package/dist/components/quick-actions/add-form.js.map +1 -0
  292. package/dist/components/quick-actions/add-modal.d.ts +7 -0
  293. package/dist/components/quick-actions/add-modal.d.ts.map +1 -1
  294. package/dist/components/quick-actions/add-modal.js +66 -20
  295. package/dist/components/quick-actions/add-modal.js.map +1 -1
  296. package/dist/components/quick-actions/search-modal.d.ts.map +1 -1
  297. package/dist/components/quick-actions/search-modal.js +48 -19
  298. package/dist/components/quick-actions/search-modal.js.map +1 -1
  299. package/dist/components/quick-actions/streaming-modal.d.ts +6 -0
  300. package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -1
  301. package/dist/components/quick-actions/streaming-modal.js +42 -17
  302. package/dist/components/quick-actions/streaming-modal.js.map +1 -1
  303. package/dist/components/quick-actions/streaming-output.d.ts +38 -0
  304. package/dist/components/quick-actions/streaming-output.d.ts.map +1 -0
  305. package/dist/components/quick-actions/streaming-output.js +22 -0
  306. package/dist/components/quick-actions/streaming-output.js.map +1 -0
  307. package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
  308. package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -1
  309. package/dist/components/quick-actions/whatsup-modal.js +36 -10
  310. package/dist/components/quick-actions/whatsup-modal.js.map +1 -1
  311. package/dist/components/settings/devices-agents-tab.d.ts +10 -0
  312. package/dist/components/settings/devices-agents-tab.d.ts.map +1 -0
  313. package/dist/components/settings/devices-agents-tab.js +131 -0
  314. package/dist/components/settings/devices-agents-tab.js.map +1 -0
  315. package/dist/components/settings/models-list.d.ts +39 -0
  316. package/dist/components/settings/models-list.d.ts.map +1 -0
  317. package/dist/components/settings/models-list.js +72 -0
  318. package/dist/components/settings/models-list.js.map +1 -0
  319. package/dist/components/settings/models-tab.d.ts +4 -0
  320. package/dist/components/settings/models-tab.d.ts.map +1 -1
  321. package/dist/components/settings/models-tab.js +52 -102
  322. package/dist/components/settings/models-tab.js.map +1 -1
  323. package/dist/components/settings/one-time-agent-credential.d.ts +3 -0
  324. package/dist/components/settings/one-time-agent-credential.d.ts.map +1 -0
  325. package/dist/components/settings/one-time-agent-credential.js +55 -0
  326. package/dist/components/settings/one-time-agent-credential.js.map +1 -0
  327. package/dist/components/settings/passkey-list.d.ts +35 -0
  328. package/dist/components/settings/passkey-list.d.ts.map +1 -0
  329. package/dist/components/settings/passkey-list.js +34 -0
  330. package/dist/components/settings/passkey-list.js.map +1 -0
  331. package/dist/components/settings/passkey-tab.d.ts +3 -0
  332. package/dist/components/settings/passkey-tab.d.ts.map +1 -1
  333. package/dist/components/settings/passkey-tab.js +53 -45
  334. package/dist/components/settings/passkey-tab.js.map +1 -1
  335. package/dist/components/settings/pi-accounts-list.d.ts +27 -0
  336. package/dist/components/settings/pi-accounts-list.d.ts.map +1 -0
  337. package/dist/components/settings/pi-accounts-list.js +15 -0
  338. package/dist/components/settings/pi-accounts-list.js.map +1 -0
  339. package/dist/components/settings/pi-accounts.d.ts +3 -0
  340. package/dist/components/settings/pi-accounts.d.ts.map +1 -1
  341. package/dist/components/settings/pi-accounts.js +73 -55
  342. package/dist/components/settings/pi-accounts.js.map +1 -1
  343. package/dist/components/settings/principal-list.d.ts +37 -0
  344. package/dist/components/settings/principal-list.d.ts.map +1 -0
  345. package/dist/components/settings/principal-list.js +18 -0
  346. package/dist/components/settings/principal-list.js.map +1 -0
  347. package/dist/components/settings/settings-panel.d.ts +10 -3
  348. package/dist/components/settings/settings-panel.d.ts.map +1 -1
  349. package/dist/components/settings/settings-panel.js +80 -6
  350. package/dist/components/settings/settings-panel.js.map +1 -1
  351. package/dist/components/settings/skills-list.d.ts +53 -0
  352. package/dist/components/settings/skills-list.d.ts.map +1 -0
  353. package/dist/components/settings/skills-list.js +28 -0
  354. package/dist/components/settings/skills-list.js.map +1 -0
  355. package/dist/components/settings/skills-tab.d.ts.map +1 -1
  356. package/dist/components/settings/skills-tab.js +65 -38
  357. package/dist/components/settings/skills-tab.js.map +1 -1
  358. package/dist/components/settings/tool-permissions-list.d.ts +18 -0
  359. package/dist/components/settings/tool-permissions-list.d.ts.map +1 -0
  360. package/dist/components/settings/tool-permissions-list.js +6 -0
  361. package/dist/components/settings/tool-permissions-list.js.map +1 -0
  362. package/dist/components/settings/tool-permissions.d.ts +2 -1
  363. package/dist/components/settings/tool-permissions.d.ts.map +1 -1
  364. package/dist/components/settings/tool-permissions.js +33 -16
  365. package/dist/components/settings/tool-permissions.js.map +1 -1
  366. package/dist/components/settings/web-search-chain.d.ts +41 -0
  367. package/dist/components/settings/web-search-chain.d.ts.map +1 -0
  368. package/dist/components/settings/web-search-chain.js +47 -0
  369. package/dist/components/settings/web-search-chain.js.map +1 -0
  370. package/dist/components/settings/web-search-settings.d.ts +4 -7
  371. package/dist/components/settings/web-search-settings.d.ts.map +1 -1
  372. package/dist/components/settings/web-search-settings.js +54 -76
  373. package/dist/components/settings/web-search-settings.js.map +1 -1
  374. package/dist/components/share/share-menu.d.ts.map +1 -1
  375. package/dist/components/share/share-menu.js +24 -4
  376. package/dist/components/share/share-menu.js.map +1 -1
  377. package/dist/components/voice/dictation-sheet.js +3 -3
  378. package/dist/components/voice/dictation-sheet.js.map +1 -1
  379. package/dist/components/voice/mic-button.js +1 -1
  380. package/dist/components/voice/mic-button.js.map +1 -1
  381. package/dist/components/voice/review-card.js +1 -1
  382. package/dist/components/voice/review-card.js.map +1 -1
  383. package/dist/config.d.ts +5 -2
  384. package/dist/config.d.ts.map +1 -1
  385. package/dist/config.js +15 -5
  386. package/dist/config.js.map +1 -1
  387. package/dist/connection.d.ts +12 -0
  388. package/dist/connection.d.ts.map +1 -0
  389. package/dist/connection.js +421 -0
  390. package/dist/connection.js.map +1 -0
  391. package/dist/default-root.d.ts +3 -0
  392. package/dist/default-root.d.ts.map +1 -0
  393. package/dist/default-root.js +16 -0
  394. package/dist/default-root.js.map +1 -0
  395. package/dist/hooks/use-color-scheme.d.ts +14 -0
  396. package/dist/hooks/use-color-scheme.d.ts.map +1 -0
  397. package/dist/hooks/use-color-scheme.js +37 -0
  398. package/dist/hooks/use-color-scheme.js.map +1 -0
  399. package/dist/hooks/use-hash-routes.d.ts.map +1 -1
  400. package/dist/hooks/use-hash-routes.js +4 -2
  401. package/dist/hooks/use-hash-routes.js.map +1 -1
  402. package/dist/hooks/use-media-query.d.ts +7 -0
  403. package/dist/hooks/use-media-query.d.ts.map +1 -0
  404. package/dist/hooks/use-media-query.js +34 -0
  405. package/dist/hooks/use-media-query.js.map +1 -0
  406. package/dist/hooks/use-share-intake.d.ts.map +1 -1
  407. package/dist/hooks/use-share-intake.js +37 -12
  408. package/dist/hooks/use-share-intake.js.map +1 -1
  409. package/dist/hooks/use-vpn-status.d.ts +1 -1
  410. package/dist/hooks/use-vpn-status.d.ts.map +1 -1
  411. package/dist/hooks/use-vpn-status.js +20 -16
  412. package/dist/hooks/use-vpn-status.js.map +1 -1
  413. package/dist/hooks/use-websocket.d.ts +5 -24
  414. package/dist/hooks/use-websocket.d.ts.map +1 -1
  415. package/dist/hooks/use-websocket.js +11 -382
  416. package/dist/hooks/use-websocket.js.map +1 -1
  417. package/dist/hooks/websocket-handlers/activity.d.ts +2 -2
  418. package/dist/hooks/websocket-handlers/activity.d.ts.map +1 -1
  419. package/dist/hooks/websocket-handlers/activity.js +4 -5
  420. package/dist/hooks/websocket-handlers/activity.js.map +1 -1
  421. package/dist/hooks/websocket-handlers/chat.d.ts +1 -0
  422. package/dist/hooks/websocket-handlers/chat.d.ts.map +1 -1
  423. package/dist/hooks/websocket-handlers/chat.js +27 -5
  424. package/dist/hooks/websocket-handlers/chat.js.map +1 -1
  425. package/dist/hooks/websocket-handlers/connection.d.ts.map +1 -1
  426. package/dist/hooks/websocket-handlers/connection.js +4 -6
  427. package/dist/hooks/websocket-handlers/connection.js.map +1 -1
  428. package/dist/hooks/websocket-handlers/mask.d.ts +1 -1
  429. package/dist/hooks/websocket-handlers/mask.d.ts.map +1 -1
  430. package/dist/hooks/websocket-handlers/mask.js +2 -3
  431. package/dist/hooks/websocket-handlers/mask.js.map +1 -1
  432. package/dist/hooks/websocket-handlers/provider.d.ts.map +1 -1
  433. package/dist/hooks/websocket-handlers/provider.js +4 -6
  434. package/dist/hooks/websocket-handlers/provider.js.map +1 -1
  435. package/dist/hooks/websocket-handlers/types.d.ts +6 -2
  436. package/dist/hooks/websocket-handlers/types.d.ts.map +1 -1
  437. package/dist/index.d.ts +5 -3
  438. package/dist/index.d.ts.map +1 -1
  439. package/dist/index.js +6 -3
  440. package/dist/index.js.map +1 -1
  441. package/dist/lib/api-client.d.ts +321 -0
  442. package/dist/lib/api-client.d.ts.map +1 -1
  443. package/dist/lib/api-client.js +243 -213
  444. package/dist/lib/api-client.js.map +1 -1
  445. package/dist/lib/backend.d.ts +19 -2
  446. package/dist/lib/backend.d.ts.map +1 -1
  447. package/dist/lib/backend.js +15 -9
  448. package/dist/lib/backend.js.map +1 -1
  449. package/dist/lib/diff.d.ts +8 -10
  450. package/dist/lib/diff.d.ts.map +1 -1
  451. package/dist/lib/diff.js +26 -53
  452. package/dist/lib/diff.js.map +1 -1
  453. package/dist/lib/format-time.d.ts +3 -0
  454. package/dist/lib/format-time.d.ts.map +1 -0
  455. package/dist/lib/format-time.js +25 -0
  456. package/dist/lib/format-time.js.map +1 -0
  457. package/dist/lib/light-dark.d.ts +37 -0
  458. package/dist/lib/light-dark.d.ts.map +1 -0
  459. package/dist/lib/light-dark.js +83 -0
  460. package/dist/lib/light-dark.js.map +1 -0
  461. package/dist/lib/mermaid-theme.d.ts +7 -2
  462. package/dist/lib/mermaid-theme.d.ts.map +1 -1
  463. package/dist/lib/mermaid-theme.js +125 -203
  464. package/dist/lib/mermaid-theme.js.map +1 -1
  465. package/dist/lib/passkeys.d.ts +6 -3
  466. package/dist/lib/passkeys.d.ts.map +1 -1
  467. package/dist/lib/passkeys.js +10 -4
  468. package/dist/lib/passkeys.js.map +1 -1
  469. package/dist/lib/push-registration.d.ts +10 -0
  470. package/dist/lib/push-registration.d.ts.map +1 -0
  471. package/dist/lib/push-registration.js +44 -0
  472. package/dist/lib/push-registration.js.map +1 -0
  473. package/dist/lib/share-intake.d.ts +2 -1
  474. package/dist/lib/share-intake.d.ts.map +1 -1
  475. package/dist/lib/share-intake.js +3 -3
  476. package/dist/lib/share-intake.js.map +1 -1
  477. package/dist/lib/share.d.ts +4 -3
  478. package/dist/lib/share.d.ts.map +1 -1
  479. package/dist/lib/share.js +6 -7
  480. package/dist/lib/share.js.map +1 -1
  481. package/dist/lib/single-key.d.ts +30 -0
  482. package/dist/lib/single-key.d.ts.map +1 -0
  483. package/dist/lib/single-key.js +45 -0
  484. package/dist/lib/single-key.js.map +1 -0
  485. package/dist/lib/tool-names.d.ts +8 -6
  486. package/dist/lib/tool-names.d.ts.map +1 -1
  487. package/dist/lib/tool-names.js +17 -7
  488. package/dist/lib/tool-names.js.map +1 -1
  489. package/dist/root-context.d.ts +229 -0
  490. package/dist/root-context.d.ts.map +1 -0
  491. package/dist/root-context.js +33 -0
  492. package/dist/root-context.js.map +1 -0
  493. package/dist/root.d.ts +38 -0
  494. package/dist/root.d.ts.map +1 -0
  495. package/dist/root.js +47 -0
  496. package/dist/root.js.map +1 -0
  497. package/dist/stores/activity-state.d.ts +29 -0
  498. package/dist/stores/activity-state.d.ts.map +1 -0
  499. package/dist/stores/activity-state.js +282 -0
  500. package/dist/stores/activity-state.js.map +1 -0
  501. package/dist/stores/activity-store.d.ts +10 -41
  502. package/dist/stores/activity-store.d.ts.map +1 -1
  503. package/dist/stores/activity-store.js +9 -271
  504. package/dist/stores/activity-store.js.map +1 -1
  505. package/dist/stores/chat-state.d.ts +212 -0
  506. package/dist/stores/chat-state.d.ts.map +1 -0
  507. package/dist/stores/chat-state.js +466 -0
  508. package/dist/stores/chat-state.js.map +1 -0
  509. package/dist/stores/chat-store.d.ts +4 -162
  510. package/dist/stores/chat-store.d.ts.map +1 -1
  511. package/dist/stores/chat-store.js +7 -418
  512. package/dist/stores/chat-store.js.map +1 -1
  513. package/dist/stores/connection-state.d.ts +40 -0
  514. package/dist/stores/connection-state.d.ts.map +1 -0
  515. package/dist/stores/connection-state.js +30 -0
  516. package/dist/stores/connection-state.js.map +1 -0
  517. package/dist/stores/connection-store.d.ts +4 -40
  518. package/dist/stores/connection-store.d.ts.map +1 -1
  519. package/dist/stores/connection-store.js +7 -27
  520. package/dist/stores/connection-store.js.map +1 -1
  521. package/dist/stores/create-stores.d.ts +23 -0
  522. package/dist/stores/create-stores.d.ts.map +1 -0
  523. package/dist/stores/create-stores.js +28 -0
  524. package/dist/stores/create-stores.js.map +1 -0
  525. package/dist/stores/file-state.d.ts +53 -0
  526. package/dist/stores/file-state.d.ts.map +1 -0
  527. package/dist/stores/file-state.js +341 -0
  528. package/dist/stores/file-state.js.map +1 -0
  529. package/dist/stores/file-store.d.ts +4 -52
  530. package/dist/stores/file-store.d.ts.map +1 -1
  531. package/dist/stores/file-store.js +7 -300
  532. package/dist/stores/file-store.js.map +1 -1
  533. package/dist/stores/graph-state.d.ts +95 -0
  534. package/dist/stores/graph-state.d.ts.map +1 -0
  535. package/dist/stores/graph-state.js +252 -0
  536. package/dist/stores/graph-state.js.map +1 -0
  537. package/dist/stores/graph-store.d.ts +7 -83
  538. package/dist/stores/graph-store.d.ts.map +1 -1
  539. package/dist/stores/graph-store.js +8 -249
  540. package/dist/stores/graph-store.js.map +1 -1
  541. package/dist/stores/mask-state.d.ts +21 -0
  542. package/dist/stores/mask-state.d.ts.map +1 -0
  543. package/dist/stores/mask-state.js +9 -0
  544. package/dist/stores/mask-state.js.map +1 -0
  545. package/dist/stores/mask-store.d.ts +4 -21
  546. package/dist/stores/mask-store.d.ts.map +1 -1
  547. package/dist/stores/mask-store.js +7 -6
  548. package/dist/stores/mask-store.js.map +1 -1
  549. package/dist/stores/principal-state.d.ts +16 -0
  550. package/dist/stores/principal-state.d.ts.map +1 -0
  551. package/dist/stores/principal-state.js +31 -0
  552. package/dist/stores/principal-state.js.map +1 -0
  553. package/dist/stores/principal-store.d.ts +5 -0
  554. package/dist/stores/principal-store.d.ts.map +1 -0
  555. package/dist/stores/principal-store.js +8 -0
  556. package/dist/stores/principal-store.js.map +1 -0
  557. package/dist/stores/provider-state.d.ts +24 -0
  558. package/dist/stores/provider-state.d.ts.map +1 -0
  559. package/dist/stores/provider-state.js +68 -0
  560. package/dist/stores/provider-state.js.map +1 -0
  561. package/dist/stores/provider-store.d.ts +4 -23
  562. package/dist/stores/provider-store.d.ts.map +1 -1
  563. package/dist/stores/provider-store.js +7 -64
  564. package/dist/stores/provider-store.js.map +1 -1
  565. package/dist/stores/share-state.d.ts +29 -0
  566. package/dist/stores/share-state.d.ts.map +1 -0
  567. package/dist/stores/share-state.js +21 -0
  568. package/dist/stores/share-state.js.map +1 -0
  569. package/dist/stores/share-store.d.ts +4 -28
  570. package/dist/stores/share-store.d.ts.map +1 -1
  571. package/dist/stores/share-store.js +7 -18
  572. package/dist/stores/share-store.js.map +1 -1
  573. package/dist/stores/store-environment.d.ts +10 -0
  574. package/dist/stores/store-environment.d.ts.map +1 -0
  575. package/dist/stores/store-environment.js +2 -0
  576. package/dist/stores/store-environment.js.map +1 -0
  577. package/dist/stores/ui-state.d.ts +71 -0
  578. package/dist/stores/ui-state.d.ts.map +1 -0
  579. package/dist/stores/ui-state.js +58 -0
  580. package/dist/stores/ui-state.js.map +1 -0
  581. package/dist/stores/ui-store.d.ts +4 -45
  582. package/dist/stores/ui-store.d.ts.map +1 -1
  583. package/dist/stores/ui-store.js +7 -36
  584. package/dist/stores/ui-store.js.map +1 -1
  585. package/dist/styles.css +1 -1
  586. package/dist/theme.css +150 -97
  587. package/dist/voice/asr-clients.d.ts +2 -1
  588. package/dist/voice/asr-clients.d.ts.map +1 -1
  589. package/dist/voice/asr-clients.js +16 -17
  590. package/dist/voice/asr-clients.js.map +1 -1
  591. package/dist/voice/use-dictation.d.ts.map +1 -1
  592. package/dist/voice/use-dictation.js +12 -8
  593. package/dist/voice/use-dictation.js.map +1 -1
  594. package/dist/voice/voice-state.d.ts +25 -0
  595. package/dist/voice/voice-state.d.ts.map +1 -0
  596. package/dist/voice/voice-state.js +29 -0
  597. package/dist/voice/voice-state.js.map +1 -0
  598. package/dist/voice/voice-store.d.ts +4 -25
  599. package/dist/voice/voice-store.d.ts.map +1 -1
  600. package/dist/voice/voice-store.js +7 -26
  601. package/dist/voice/voice-store.js.map +1 -1
  602. package/package.json +3 -2
  603. package/src/components/activity/activity-page.tsx +334 -160
  604. package/src/components/activity/activity-run-detail.tsx +81 -47
  605. package/src/components/activity/activity-run-list.tsx +27 -59
  606. package/src/components/activity/activity-views.tsx +155 -0
  607. package/src/components/activity/approval-card.tsx +80 -0
  608. package/src/components/activity/digest-card.tsx +25 -61
  609. package/src/components/activity/digest-summary.tsx +52 -0
  610. package/src/components/activity/push-switch.tsx +62 -0
  611. package/src/components/activity/push-toggle.tsx +51 -81
  612. package/src/components/activity/span-bits.tsx +8 -7
  613. package/src/components/chat/ask-user-card.tsx +292 -356
  614. package/src/components/chat/ask-user-typed.ts +77 -0
  615. package/src/components/chat/brain-markdown-links.tsx +4 -4
  616. package/src/components/chat/brain-markdown.tsx +4 -2
  617. package/src/components/chat/chat-page.tsx +38 -9
  618. package/src/components/chat/composer-view.tsx +194 -0
  619. package/src/components/chat/composer.tsx +117 -296
  620. package/src/components/chat/markdown-content.tsx +53 -2
  621. package/src/components/chat/mermaid-block.tsx +13 -5
  622. package/src/components/chat/mermaid-share.ts +8 -7
  623. package/src/components/chat/mermaid-viewer.tsx +3 -1
  624. package/src/components/chat/message-bubble.tsx +78 -94
  625. package/src/components/chat/message-share.ts +7 -7
  626. package/src/components/chat/renderers/bind.tsx +94 -0
  627. package/src/components/chat/renderers/brain-ui-tools.tsx +56 -0
  628. package/src/components/chat/renderers/claude-tools.tsx +3 -2
  629. package/src/components/chat/renderers/index.ts +15 -10
  630. package/src/components/chat/session-drawer.tsx +60 -138
  631. package/src/components/chat/session-list.tsx +113 -0
  632. package/src/components/chat/share-block.tsx +16 -12
  633. package/src/components/chat/share-card.tsx +2 -2
  634. package/src/components/chat/subagent-view.tsx +4 -4
  635. package/src/components/chat/tool-call-timeline.tsx +59 -22
  636. package/src/components/chat/tool-cards/block-card.tsx +145 -0
  637. package/src/components/chat/tool-cards/image-mask-card.tsx +214 -0
  638. package/src/components/chat/tool-cards/location-card.tsx +159 -0
  639. package/src/components/chat/tool-views.tsx +23 -73
  640. package/src/components/chat/transcript-turn.tsx +108 -0
  641. package/src/components/chat/use-chat-commands.ts +14 -16
  642. package/src/components/chat/welcome-state.tsx +36 -91
  643. package/src/components/connectivity/connection-gate.tsx +80 -9
  644. package/src/components/connectivity/login-form.tsx +122 -0
  645. package/src/components/connectivity/login-screen.tsx +45 -100
  646. package/src/components/dev/share-harness.tsx +2 -2
  647. package/src/components/files/file-panel.tsx +168 -0
  648. package/src/components/files/file-tree-view.tsx +127 -0
  649. package/src/components/files/file-tree.tsx +55 -109
  650. package/src/components/files/file-viewer-binary.tsx +3 -2
  651. package/src/components/files/file-viewer-frame.tsx +113 -0
  652. package/src/components/files/file-viewer.tsx +40 -95
  653. package/src/components/files/frontmatter-chips.tsx +42 -0
  654. package/src/components/files/frontmatter-panel.tsx +6 -71
  655. package/src/components/files/staleness.ts +29 -0
  656. package/src/components/graph/graph-canvas.tsx +24 -1
  657. package/src/components/graph/graph-controls-column.tsx +92 -0
  658. package/src/components/graph/graph-controls.tsx +83 -127
  659. package/src/components/graph/graph-form.tsx +183 -0
  660. package/src/components/graph/graph-maintenance.tsx +9 -14
  661. package/src/components/graph/graph-node-rail.tsx +147 -0
  662. package/src/components/graph/graph-page.tsx +189 -49
  663. package/src/components/graph/graph-scene.tsx +200 -30
  664. package/src/components/graph/lib/graph-helpers.ts +65 -43
  665. package/src/components/graph/node-card.tsx +64 -0
  666. package/src/components/graph/node-popover.tsx +28 -117
  667. package/src/components/graph/use-graph-theme.ts +69 -32
  668. package/src/components/graph/use-node-actions.ts +56 -0
  669. package/src/components/images/image-share.ts +4 -2
  670. package/src/components/images/image-viewer.tsx +3 -1
  671. package/src/components/images/mask-editor.tsx +7 -4
  672. package/src/components/layout/app-shell.tsx +7 -1
  673. package/src/components/layout/desktop-palette.tsx +151 -0
  674. package/src/components/layout/key-cap.tsx +15 -0
  675. package/src/components/layout/mobile-tab-bar.tsx +80 -157
  676. package/src/components/layout/shortcut-switch.tsx +32 -0
  677. package/src/components/layout/side-rail.tsx +70 -150
  678. package/src/components/layout/slide-panel.tsx +29 -2
  679. package/src/components/layout/theme.tsx +67 -0
  680. package/src/components/quick-actions/add-form.tsx +188 -0
  681. package/src/components/quick-actions/add-modal.tsx +68 -144
  682. package/src/components/quick-actions/search-modal.tsx +49 -19
  683. package/src/components/quick-actions/streaming-modal.tsx +44 -71
  684. package/src/components/quick-actions/streaming-output.tsx +112 -0
  685. package/src/components/quick-actions/whatsup-modal.tsx +38 -60
  686. package/src/components/settings/devices-agents-tab.tsx +139 -0
  687. package/src/components/settings/models-list.tsx +299 -0
  688. package/src/components/settings/models-tab.tsx +63 -337
  689. package/src/components/settings/one-time-agent-credential.tsx +131 -0
  690. package/src/components/settings/passkey-list.tsx +201 -0
  691. package/src/components/settings/passkey-tab.tsx +53 -197
  692. package/src/components/settings/pi-accounts-list.tsx +128 -0
  693. package/src/components/settings/pi-accounts.tsx +71 -170
  694. package/src/components/settings/principal-list.tsx +172 -0
  695. package/src/components/settings/settings-panel.tsx +245 -19
  696. package/src/components/settings/skills-list.tsx +276 -0
  697. package/src/components/settings/skills-tab.tsx +82 -269
  698. package/src/components/settings/tool-permissions-list.tsx +54 -0
  699. package/src/components/settings/tool-permissions.tsx +27 -46
  700. package/src/components/settings/web-search-chain.tsx +300 -0
  701. package/src/components/settings/web-search-settings.tsx +58 -328
  702. package/src/components/share/share-menu.tsx +19 -4
  703. package/src/components/voice/dictation-sheet.tsx +5 -5
  704. package/src/components/voice/mic-button.tsx +1 -1
  705. package/src/components/voice/review-card.tsx +1 -1
  706. package/src/config.ts +21 -7
  707. package/src/connection.ts +443 -0
  708. package/src/default-root.ts +16 -0
  709. package/src/hooks/use-color-scheme.ts +36 -0
  710. package/src/hooks/use-hash-routes.ts +4 -2
  711. package/src/hooks/use-media-query.ts +32 -0
  712. package/src/hooks/use-share-intake.ts +32 -12
  713. package/src/hooks/use-vpn-status.ts +23 -15
  714. package/src/hooks/use-websocket.ts +12 -426
  715. package/src/hooks/websocket-handlers/activity.ts +4 -5
  716. package/src/hooks/websocket-handlers/chat.ts +26 -5
  717. package/src/hooks/websocket-handlers/connection.ts +4 -6
  718. package/src/hooks/websocket-handlers/mask.ts +2 -3
  719. package/src/hooks/websocket-handlers/provider.ts +4 -6
  720. package/src/hooks/websocket-handlers/types.ts +6 -2
  721. package/src/index.ts +7 -3
  722. package/src/lib/api-client.ts +446 -365
  723. package/src/lib/backend.ts +20 -10
  724. package/src/lib/diff.ts +28 -62
  725. package/src/lib/format-time.ts +20 -0
  726. package/src/lib/light-dark.ts +83 -0
  727. package/src/lib/mermaid-theme.ts +183 -214
  728. package/src/lib/passkeys.ts +12 -4
  729. package/src/lib/push-registration.ts +46 -0
  730. package/src/lib/share-intake.ts +6 -3
  731. package/src/lib/share.ts +7 -4
  732. package/src/lib/single-key.ts +47 -0
  733. package/src/lib/tool-names.ts +31 -8
  734. package/src/root-context.tsx +40 -0
  735. package/src/root.ts +83 -0
  736. package/src/stores/activity-state.ts +295 -0
  737. package/src/stores/activity-store.ts +11 -285
  738. package/src/stores/chat-state.ts +795 -0
  739. package/src/stores/chat-store.ts +11 -705
  740. package/src/stores/connection-state.ts +78 -0
  741. package/src/stores/connection-store.ts +11 -76
  742. package/src/stores/create-stores.ts +31 -0
  743. package/src/stores/file-state.ts +399 -0
  744. package/src/stores/file-store.ts +9 -360
  745. package/src/stores/graph-state.ts +368 -0
  746. package/src/stores/graph-store.ts +10 -355
  747. package/src/stores/mask-state.ts +30 -0
  748. package/src/stores/mask-store.ts +10 -27
  749. package/src/stores/principal-state.ts +42 -0
  750. package/src/stores/principal-store.ts +11 -0
  751. package/src/stores/provider-state.ts +103 -0
  752. package/src/stores/provider-store.ts +10 -95
  753. package/src/stores/share-state.ts +56 -0
  754. package/src/stores/share-store.ts +11 -54
  755. package/src/stores/store-environment.ts +10 -0
  756. package/src/stores/ui-state.ts +143 -0
  757. package/src/stores/ui-store.ts +11 -93
  758. package/src/styles.css +4 -1
  759. package/src/theme.css +150 -97
  760. package/src/voice/asr-clients.ts +17 -17
  761. package/src/voice/use-dictation.ts +11 -8
  762. package/src/voice/voice-state.ts +57 -0
  763. package/src/voice/voice-store.ts +11 -55
@@ -1,8 +1,14 @@
1
1
  import { Suspense, lazy } from "react";
2
- import { KeyRound, Puzzle, SlidersHorizontal } from "lucide-react";
2
+ import { KeyRound, Laptop, Puzzle, SlidersHorizontal } from "lucide-react";
3
3
  import { useUIStore, type SettingsTab } from "../../stores/ui-store.js";
4
4
  import { SlidePanel } from "../layout/slide-panel.js";
5
5
  import { cn } from "../../lib/utils.js";
6
+ import { usePrincipalStore } from "../../stores/principal-store.js";
7
+ import { useBrainUiRoot } from "../../root-context.js";
8
+ import { useMediaQuery } from "../../hooks/use-media-query.js";
9
+ import { ThemeToggle } from "../layout/theme.js";
10
+ import { ShortcutSwitch } from "../layout/shortcut-switch.js";
11
+ import { Button, Callout, Icon, Label, ScreenHeader, Surface, type IconName } from "@schlessera/brain-ui-kit";
6
12
 
7
13
  /**
8
14
  * Each tab is fetched the first time it is opened. Settings is the largest
@@ -13,18 +19,46 @@ import { cn } from "../../lib/utils.js";
13
19
  */
14
20
  const ModelsTab = lazy(() => import("./models-tab.js").then((m) => ({ default: m.ModelsTab })));
15
21
  const PasskeyTab = lazy(() => import("./passkey-tab.js").then((m) => ({ default: m.PasskeyTab })));
22
+ const DevicesAgentsTab = lazy(() => import("./devices-agents-tab.js").then((m) => ({ default: m.DevicesAgentsTab })));
16
23
  const SkillsTab = lazy(() => import("./skills-tab.js").then((m) => ({ default: m.SkillsTab })));
17
24
 
18
- const TABS: Array<{ id: SettingsTab; label: string; icon: typeof KeyRound }> = [
25
+ /** The phone strip's tabs. Appearance and input sit above the strip there. */
26
+ type StripTab = Exclude<SettingsTab, "appearance">;
27
+
28
+ const TABS: Array<{ id: StripTab; label: string; icon: typeof KeyRound }> = [
19
29
  { id: "models", label: "Models", icon: SlidersHorizontal },
20
30
  { id: "skills", label: "Skills", icon: Puzzle },
21
31
  { id: "security", label: "Security", icon: KeyRound },
32
+ { id: "devices", label: "Devices & agents", icon: Laptop },
22
33
  ];
23
34
 
24
35
  /**
25
- * The settings surface: one panel, one entry point in the menus, a tab per
26
- * area. Only the selected tab is mounted each fetches its own data on becoming
27
- * active, so switching tabs (or reopening the panel) always shows current state.
36
+ * D5's section column, from `laptop:` up. The mono meta names what the
37
+ * section holds; it is not a count, because the column has no data of its
38
+ * own to count.
39
+ */
40
+ const SECTIONS: Array<{ id: SettingsTab; label: string; meta: string; icon: IconName }> = [
41
+ { id: "appearance", label: "Appearance & input", meta: "this device", icon: "settings" },
42
+ { id: "models", label: "Models", meta: "providers", icon: "model" },
43
+ { id: "skills", label: "Skills", meta: "catalog", icon: "capability" },
44
+ { id: "security", label: "Security", meta: "passkeys", icon: "passkey" },
45
+ { id: "devices", label: "Devices & agents", meta: "credentials", icon: "agent" },
46
+ ];
47
+
48
+ /** The rail is expanded from here (`laptop:`), and Settings becomes a pane. */
49
+ const PANE_QUERY = "(min-width: 900px)";
50
+
51
+ /**
52
+ * The settings surface: one panel, one entry point in the menus, a section
53
+ * per area. Only the selected section is mounted — each fetches its own data
54
+ * on becoming active, so switching (or reopening the panel) always shows
55
+ * current state.
56
+ *
57
+ * Two shapes. Below `laptop:` the drawer with its tab strip, unchanged: the
58
+ * theme toggle and the single-key switch sit above the tabs. From `laptop:`
59
+ * up it is D5's pane over the content area: a header row, a 216px section
60
+ * column, and the section's form at a 720px measure. There, Appearance &
61
+ * input is a section of its own.
28
62
  */
29
63
  export function SettingsPanel({
30
64
  open,
@@ -35,42 +69,234 @@ export function SettingsPanel({
35
69
  }) {
36
70
  const tab = useUIStore((s) => s.settingsTab);
37
71
  const setTab = useUIStore((s) => s.setSettingsTab);
72
+ const mintPending = usePrincipalStore((s) => s.mintPending);
73
+ const oneTimeCredential = usePrincipalStore((s) => s.oneTimeCredential);
74
+ const credentialProtected = mintPending || oneTimeCredential !== null;
75
+ const pane = useMediaQuery(PANE_QUERY);
76
+
77
+ function closeIfSafe() {
78
+ if (!credentialProtected) onClose();
79
+ }
80
+
81
+ function select(id: SettingsTab) {
82
+ if (!credentialProtected) setTab(id);
83
+ }
84
+
85
+ if (pane) {
86
+ return (
87
+ <SettingsPane
88
+ open={open}
89
+ tab={tab}
90
+ credentialProtected={credentialProtected}
91
+ onSelect={select}
92
+ onClose={closeIfSafe}
93
+ />
94
+ );
95
+ }
96
+
97
+ // The strip has no Appearance tab: a pane selection that survives a resize
98
+ // down lands on the first tab, and the controls it named are right above.
99
+ const stripTab: StripTab = tab === "appearance" ? "models" : tab;
38
100
 
39
101
  return (
40
- <SlidePanel open={open} onClose={onClose} title="Settings">
102
+ <SlidePanel open={open} onClose={closeIfSafe} title="Settings" wide>
41
103
  <div className="flex h-full flex-col">
42
104
  <div className="flex shrink-0 gap-1 border-b border-border px-2 pt-2">
43
- {TABS.map(({ id, label, icon: Icon }) => (
105
+ {TABS.map(({ id, label, icon: TabIcon }) => (
44
106
  <button
45
107
  key={id}
46
- onClick={() => setTab(id)}
47
- aria-selected={tab === id}
108
+ onClick={() => select(id)}
109
+ disabled={credentialProtected && stripTab !== id}
110
+ aria-selected={stripTab === id}
48
111
  role="tab"
49
112
  className={cn(
50
- "flex items-center gap-1.5 rounded-t-lg px-3 py-2 text-xs font-medium transition-colors",
51
- tab === id
113
+ "flex items-center gap-1.5 rounded-t-lg px-3 py-2 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
114
+ stripTab === id
52
115
  ? "border-b-2 border-primary text-foreground"
53
116
  : "text-muted-foreground hover:text-foreground"
54
117
  )}
55
118
  >
56
- <Icon className="h-3.5 w-3.5" />
119
+ <TabIcon className="h-3.5 w-3.5" />
57
120
  {label}
58
121
  </button>
59
122
  ))}
60
123
  </div>
61
124
 
125
+ {/* Appearance is not a tab: it is one control, it applies everywhere,
126
+ and the design puts the three-way toggle in Settings without
127
+ giving it a section of its own. */}
128
+ <div className="flex shrink-0 items-center justify-between gap-3 border-b border-border px-3 py-2">
129
+ <span className="text-xs text-muted-foreground">Appearance</span>
130
+ <ThemeToggle />
131
+ </div>
132
+ {/* Settings › Input (D37, as D5 draws it): the off switch for
133
+ single-key shortcuts as a group row, with the banner that says what
134
+ turning it off does. One control, applies everywhere, so it sits
135
+ beside Appearance rather than in a tab. */}
136
+ <div className="flex shrink-0 flex-col gap-2 border-b border-border px-3 py-2">
137
+ <Label text="Input" icon="capability" />
138
+ <Surface pad={0}>
139
+ <ShortcutSwitch />
140
+ </Surface>
141
+ <ShortcutBanner />
142
+ </div>
143
+
62
144
  <div className="min-h-0 flex-1">
63
- <Suspense fallback={null}>
64
- {tab === "models" ? (
65
- <ModelsTab active={open && tab === "models"} />
66
- ) : tab === "skills" ? (
67
- <SkillsTab active={open && tab === "skills"} />
145
+ <SectionBody tab={stripTab} open={open} />
146
+ </div>
147
+ </div>
148
+ </SlidePanel>
149
+ );
150
+ }
151
+
152
+ /**
153
+ * D5 from `laptop:` up: the pane. The header row carries the serif title and
154
+ * the close control; under it the section column and the form area share the
155
+ * height, and only the form area scrolls.
156
+ */
157
+ function SettingsPane({
158
+ open,
159
+ tab,
160
+ credentialProtected,
161
+ onSelect,
162
+ onClose,
163
+ }: {
164
+ open: boolean;
165
+ tab: SettingsTab;
166
+ credentialProtected: boolean;
167
+ onSelect: (tab: SettingsTab) => void;
168
+ onClose: () => void;
169
+ }) {
170
+ const appName = useBrainUiRoot().config.appName;
171
+ return (
172
+ <SlidePanel open={open} onClose={onClose} title="Settings" mode="pane">
173
+ {/* The kit header is `width: 100%`; it needs a shrinking flex child
174
+ around it, or it fills the row and pushes Close past the viewport
175
+ (the Files pane wraps its header the same way). */}
176
+ <div className="flex shrink-0 items-center border-b border-border pr-3">
177
+ <div className="min-w-0 flex-1">
178
+ <ScreenHeader variant="nav" title="Settings" back={false} divider={false} />
179
+ </div>
180
+ <div className="shrink-0">
181
+ <Button label="Close" icon="dismiss" tone="quiet" size="sm" block={false} onClick={onClose} />
182
+ </div>
183
+ </div>
184
+
185
+ <div className="flex min-h-0 flex-1">
186
+ <nav aria-label="Settings sections" className="flex w-[216px] shrink-0 flex-col border-r border-border">
187
+ <div role="tablist" aria-orientation="vertical" className="flex flex-1 flex-col gap-0.5 p-2">
188
+ {SECTIONS.map(({ id, label, meta, icon }) => {
189
+ const selected = tab === id;
190
+ return (
191
+ <button
192
+ key={id}
193
+ type="button"
194
+ role="tab"
195
+ aria-selected={selected}
196
+ // The name is the label alone: the mono meta beside it is a
197
+ // descriptor, and a test or a screen reader asking for
198
+ // "Security" should find it.
199
+ aria-label={label}
200
+ disabled={credentialProtected && !selected}
201
+ onClick={() => onSelect(id)}
202
+ className={cn(
203
+ "flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50",
204
+ selected ? "bg-surface-raised" : "hover:bg-surface-raised"
205
+ )}
206
+ >
207
+ <Icon icon={icon} size={16} color={selected ? "var(--bk-amber-ink)" : "var(--bk-color-ink-mute)"} />
208
+ <span
209
+ className={cn("min-w-0 flex-1 truncate text-[12.5px] font-semibold", !selected && "text-foreground")}
210
+ style={selected ? { color: "var(--bk-amber-ink)" } : undefined}
211
+ >
212
+ {label}
213
+ </span>
214
+ <span className="shrink-0 font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground">
215
+ {meta}
216
+ </span>
217
+ </button>
218
+ );
219
+ })}
220
+ </div>
221
+ <div className="shrink-0 border-t border-border px-4 py-3 font-[family-name:var(--font-mono)] text-[10px] text-muted-foreground">
222
+ {appName}
223
+ </div>
224
+ </nav>
225
+
226
+ <div className="min-h-0 flex-1 overflow-y-auto">
227
+ <div className="flex h-full max-w-[720px] flex-col">
228
+ {tab === "appearance" ? (
229
+ <AppearanceSection />
68
230
  ) : (
69
- <PasskeyTab active={open && tab === "security"} />
231
+ <SectionBody tab={tab} open={open} />
70
232
  )}
71
- </Suspense>
233
+ </div>
72
234
  </div>
73
235
  </div>
74
236
  </SlidePanel>
75
237
  );
76
238
  }
239
+
240
+ /**
241
+ * D5's first section, as the drop draws it: the theme under "Appearance",
242
+ * the single-key switch and its banner under "Input". Both controls apply to
243
+ * this device only, which the header says.
244
+ */
245
+ function AppearanceSection() {
246
+ return (
247
+ <div className="flex flex-col">
248
+ <ScreenHeader
249
+ variant="nav"
250
+ title="Appearance & input"
251
+ subtitle="applies on this device only"
252
+ back={false}
253
+ divider={false}
254
+ />
255
+ <div className="flex flex-col gap-2 px-4 pb-4">
256
+ <Label text="Appearance" icon="settings" />
257
+ <Surface pad={0}>
258
+ <div className="flex items-center gap-3 px-3 py-3">
259
+ <Icon icon="settings" size={17} color="var(--bk-color-ink-mute)" />
260
+ <span className="min-w-0 flex-1 text-[12.5px] font-semibold text-foreground">Theme</span>
261
+ <ThemeToggle />
262
+ </div>
263
+ </Surface>
264
+ </div>
265
+ <div className="flex flex-col gap-2 px-4 pb-4">
266
+ <Label text="Input" icon="capability" />
267
+ <Surface pad={0}>
268
+ <ShortcutSwitch />
269
+ </Surface>
270
+ <ShortcutBanner />
271
+ </div>
272
+ </div>
273
+ );
274
+ }
275
+
276
+ function ShortcutBanner() {
277
+ return (
278
+ <Callout
279
+ variant="banner"
280
+ tone="neutral"
281
+ icon="scope"
282
+ text="Turning single-key shortcuts off also removes the printed keys from buttons — a key that no longer fires should not be advertised."
283
+ />
284
+ );
285
+ }
286
+
287
+ /** The lazily fetched section, mounted only while it is the selected one. */
288
+ function SectionBody({ tab, open }: { tab: StripTab; open: boolean }) {
289
+ return (
290
+ <Suspense fallback={null}>
291
+ {tab === "models" ? (
292
+ <ModelsTab active={open} />
293
+ ) : tab === "skills" ? (
294
+ <SkillsTab active={open} />
295
+ ) : tab === "security" ? (
296
+ <PasskeyTab active={open} />
297
+ ) : (
298
+ <DevicesAgentsTab active={open} />
299
+ )}
300
+ </Suspense>
301
+ );
302
+ }
@@ -0,0 +1,276 @@
1
+ import { Button, Placeholder } from "@schlessera/brain-ui-kit";
2
+ import { Loader2, Pencil, Power, Trash2, Upload } from "lucide-react";
3
+ import type { SkillEntry, SkillInstallOutcome } from "../../lib/api-client.js";
4
+ import { cn } from "../../lib/utils.js";
5
+
6
+ /**
7
+ * Settings → Skills, rendered from props (S6). `SkillsTab` is the container:
8
+ * it owns the list request, the `active`-gated reload, every mutation and its
9
+ * generation guard, and the editor's fetch; these two views own what is on
10
+ * screen. `SkillsList` is the list with its create and install rows;
11
+ * `SkillEditor` is the one-file editor that replaces it while a skill is open.
12
+ *
13
+ * Text fields stay native (the kit has no text input); the create, install,
14
+ * save and close buttons are the kit's `Button`. The per-row edit / enable /
15
+ * delete controls stay native icon buttons: they are titled, and the kit has
16
+ * no icon-only button. The zip picker is a native file input behind a label.
17
+ *
18
+ * `busy` names the skill whose mutation is in flight, or `"*"` for none in
19
+ * particular — the container passes the skill name it is working on, and
20
+ * every row control is inert while any is running, as before.
21
+ */
22
+ export interface SkillsListProps {
23
+ skills: SkillEntry[];
24
+ /** The skill a mutation is running for, or null. */
25
+ busy: string | null;
26
+ installing: boolean;
27
+ error: string | null;
28
+ warning: string | null;
29
+ outcomes: SkillInstallOutcome[] | null;
30
+ newName: string;
31
+ githubSource: string;
32
+ overwrite: boolean;
33
+ onNewName: (value: string) => void;
34
+ onCreate: () => void;
35
+ onGithubSource: (value: string) => void;
36
+ onOverwrite: (value: boolean) => void;
37
+ onInstallZip: (file: File) => void;
38
+ onInstallGitHub: () => void;
39
+ onOpen: (skill: SkillEntry) => void;
40
+ onToggle: (skill: SkillEntry) => void;
41
+ onRemove: (skill: SkillEntry) => void;
42
+ }
43
+
44
+ export function SkillsList(p: SkillsListProps) {
45
+ const custom = p.skills.filter((s) => s.source === "custom");
46
+ const builtin = p.skills.filter((s) => s.source === "builtin");
47
+ const locked = p.busy !== null;
48
+ const canInstall = !p.installing && p.githubSource.trim().length > 0;
49
+
50
+ return (
51
+ <div className="h-full overflow-y-auto p-4">
52
+ <h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
53
+ Your skills
54
+ </h3>
55
+ <p className="mt-1 text-xs text-muted-foreground">
56
+ Custom skills live in your brain repo (<code>.agents/skills/</code>) — they
57
+ survive redeployments, ride the repo's backups, and apply to every
58
+ backend. For guided authoring, ask the agent in chat to{" "}
59
+ <span className="font-medium text-foreground">add a skill</span> — the
60
+ built-in <code>add-skill</code> skill walks through design and setup.
61
+ </p>
62
+
63
+ <div className="mt-4 flex items-center gap-2">
64
+ <input
65
+ value={p.newName}
66
+ onChange={(e) => p.onNewName(e.target.value.toLowerCase())}
67
+ onKeyDown={(e) => {
68
+ if (e.key === "Enter" && p.newName.trim()) p.onCreate();
69
+ }}
70
+ placeholder="new-skill-name (kebab-case)"
71
+ 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"
72
+ />
73
+ <Button label="Create" icon="add" tone="primary" size="sm" block={false} disabled={!p.newName.trim()} onClick={p.onCreate} />
74
+ </div>
75
+
76
+ <div className="mt-3 rounded-lg border border-border-subtle bg-surface p-3">
77
+ <p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
78
+ Install
79
+ </p>
80
+ <div className="mt-2 flex items-center gap-2">
81
+ <label
82
+ className={cn(
83
+ "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",
84
+ p.installing && "pointer-events-none opacity-50",
85
+ )}
86
+ >
87
+ <Upload className="h-3 w-3" />
88
+ Upload .zip
89
+ <input
90
+ type="file"
91
+ accept=".zip,application/zip"
92
+ className="hidden"
93
+ onChange={(e) => {
94
+ const file = e.target.files?.[0];
95
+ e.target.value = "";
96
+ if (file) p.onInstallZip(file);
97
+ }}
98
+ />
99
+ </label>
100
+ <label className="flex items-center gap-1.5 text-[11px] text-muted-foreground">
101
+ <input type="checkbox" checked={p.overwrite} onChange={(e) => p.onOverwrite(e.target.checked)} />
102
+ overwrite existing
103
+ </label>
104
+ </div>
105
+ <div className="mt-2 flex items-center gap-2">
106
+ <input
107
+ value={p.githubSource}
108
+ onChange={(e) => p.onGithubSource(e.target.value)}
109
+ onKeyDown={(e) => {
110
+ if (e.key === "Enter" && canInstall) p.onInstallGitHub();
111
+ }}
112
+ placeholder="GitHub: owner/repo or https://github.com/…/tree/main/skills"
113
+ 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"
114
+ />
115
+ {p.installing ? <Loader2 className="h-3 w-3 animate-spin text-muted-foreground" aria-hidden /> : null}
116
+ <Button label="Install" icon="install" tone="ghost" size="sm" block={false} disabled={!canInstall} onClick={p.onInstallGitHub} />
117
+ </div>
118
+ <p className="mt-1.5 text-[11px] text-muted-foreground">
119
+ A skill is any folder with a SKILL.md; one source may carry several.
120
+ Private repos use the server's GITHUB_TOKEN.
121
+ </p>
122
+ {p.outcomes && (
123
+ <ul className="mt-2 flex flex-col gap-1">
124
+ {p.outcomes.map((o, i) => (
125
+ <li key={`${o.name}-${i}`} className="text-[11px]">
126
+ {o.status === "skipped" ? (
127
+ <span className="text-muted-foreground">
128
+ ✗ {o.name} — {o.reason}
129
+ </span>
130
+ ) : (
131
+ <span className="text-primary">
132
+ ✓ {o.name} {o.status === "replaced" ? "replaced" : "installed"}
133
+ {typeof o.files === "number" ? ` (${o.files} file${o.files === 1 ? "" : "s"})` : ""}
134
+ </span>
135
+ )}
136
+ </li>
137
+ ))}
138
+ </ul>
139
+ )}
140
+ </div>
141
+
142
+ {p.error && <p className="mt-2 text-xs text-destructive">{p.error}</p>}
143
+ {p.warning && <p className="mt-2 text-xs text-muted-foreground">{p.warning}</p>}
144
+
145
+ <ul className="mt-4 flex flex-col gap-2">
146
+ {custom.length === 0 && (
147
+ <li>
148
+ <Placeholder variant="empty" message="No custom skills yet." icon="steps" pad={10} />
149
+ </li>
150
+ )}
151
+ {custom.map((skill) => (
152
+ <li key={skill.name} className="rounded-lg border border-border-subtle bg-surface p-3">
153
+ {/* A disabled skill is not faded (design-feedback §4): its state
154
+ word says so, at full contrast. */}
155
+ <div className="flex items-center gap-2">
156
+ <div className="min-w-0 flex-1">
157
+ <p className="truncate text-sm text-foreground">
158
+ {skill.name}
159
+ {!skill.enabled && (
160
+ <span className="ml-2 text-[11px] text-muted-foreground">disabled</span>
161
+ )}
162
+ </p>
163
+ <p className="truncate text-[11px] text-muted-foreground">
164
+ {skill.warning ? `⚠ ${skill.warning}` : skill.description}
165
+ </p>
166
+ </div>
167
+ <button
168
+ type="button"
169
+ onClick={() => p.onOpen(skill)}
170
+ disabled={locked}
171
+ title="Edit SKILL.md"
172
+ className="rounded-md border border-border-subtle p-1.5 text-muted-foreground transition-colors hover:border-primary hover:text-primary disabled:opacity-50"
173
+ >
174
+ <Pencil className="h-3.5 w-3.5" />
175
+ </button>
176
+ <button
177
+ type="button"
178
+ onClick={() => p.onToggle(skill)}
179
+ disabled={locked}
180
+ title={skill.enabled ? "Disable (all backends)" : "Enable"}
181
+ className={cn(
182
+ "rounded-md border border-border-subtle p-1.5 transition-colors disabled:opacity-50",
183
+ skill.enabled
184
+ ? "text-primary hover:border-primary"
185
+ : "text-muted-foreground hover:border-primary hover:text-primary",
186
+ )}
187
+ >
188
+ {p.busy === skill.name ? (
189
+ <Loader2 className="h-3.5 w-3.5 animate-spin" />
190
+ ) : (
191
+ <Power className="h-3.5 w-3.5" />
192
+ )}
193
+ </button>
194
+ <button
195
+ type="button"
196
+ onClick={() => p.onRemove(skill)}
197
+ disabled={locked}
198
+ title="Delete permanently"
199
+ className="rounded-md border border-border-subtle p-1.5 text-muted-foreground transition-colors hover:border-destructive hover:text-destructive disabled:opacity-50"
200
+ >
201
+ <Trash2 className="h-3.5 w-3.5" />
202
+ </button>
203
+ </div>
204
+ </li>
205
+ ))}
206
+ </ul>
207
+
208
+ <h3 className="mt-6 text-xs font-medium uppercase tracking-wide text-muted-foreground">
209
+ Built-in skills
210
+ </h3>
211
+ <p className="mt-1 text-xs text-muted-foreground">
212
+ Shipped by brain-kit and its modules; managed by <code>brain skills sync</code>.
213
+ A custom skill with the same name overrides a built-in.
214
+ </p>
215
+ <ul className="mt-3 flex flex-col gap-1.5">
216
+ {builtin.map((skill) => (
217
+ <li
218
+ key={skill.name}
219
+ className="flex items-center gap-2 rounded-lg border border-border-subtle bg-surface px-3 py-2"
220
+ >
221
+ <div className="min-w-0 flex-1">
222
+ <p className="truncate text-xs text-foreground">{skill.name}</p>
223
+ <p className="truncate text-[11px] text-muted-foreground">{skill.description}</p>
224
+ </div>
225
+ <span title="View SKILL.md" className="flex shrink-0">
226
+ <Button label="View" tone="quiet" size="sm" block={false} disabled={locked} onClick={() => p.onOpen(skill)} />
227
+ </span>
228
+ </li>
229
+ ))}
230
+ </ul>
231
+ </div>
232
+ );
233
+ }
234
+
235
+ export interface SkillEditorProps {
236
+ name: string;
237
+ content: string;
238
+ isNew: boolean;
239
+ readOnly: boolean;
240
+ /** A save is in flight. */
241
+ saving: boolean;
242
+ error: string | null;
243
+ onChange: (content: string) => void;
244
+ onSave: () => void;
245
+ onClose: () => void;
246
+ }
247
+
248
+ export function SkillEditor(p: SkillEditorProps) {
249
+ return (
250
+ <div className="flex h-full flex-col p-4">
251
+ <div className="flex items-center justify-between gap-2">
252
+ <h3 className="text-sm font-medium text-foreground">
253
+ {p.isNew ? "New skill" : p.name}
254
+ {p.readOnly && (
255
+ <span className="ml-2 text-[11px] text-muted-foreground">built-in · read-only</span>
256
+ )}
257
+ </h3>
258
+ <div className="flex gap-2">
259
+ {!p.readOnly && (
260
+ <Button label={p.saving ? "Saving…" : "Save"} icon="confirm" tone="primary" size="sm" block={false} disabled={p.saving} onClick={p.onSave} />
261
+ )}
262
+ <Button label="Close" icon="dismiss" tone="quiet" size="sm" block={false} onClick={p.onClose} />
263
+ </div>
264
+ </div>
265
+ {p.error && <p className="mt-2 text-xs text-destructive">{p.error}</p>}
266
+ <textarea
267
+ value={p.content}
268
+ readOnly={p.readOnly}
269
+ aria-label="SKILL.md"
270
+ onChange={(e) => p.onChange(e.target.value)}
271
+ spellCheck={false}
272
+ 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"
273
+ />
274
+ </div>
275
+ );
276
+ }