@vertesia/ui 1.4.0-dev.20260615.051508Z → 1.4.0-dev.20260629.130134Z

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 (337) hide show
  1. package/lib/core/components/shadcn/dropdown.d.ts.map +1 -1
  2. package/lib/core/components/shadcn/dropdown.js +6 -2
  3. package/lib/core/components/shadcn/dropdown.js.map +1 -1
  4. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  5. package/lib/core/components/shadcn/filters/filterBar.js +9 -2
  6. package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
  7. package/lib/core/components/shadcn/modal/ConfirmModal.d.ts +16 -1
  8. package/lib/core/components/shadcn/modal/ConfirmModal.d.ts.map +1 -1
  9. package/lib/core/components/shadcn/modal/ConfirmModal.js +25 -3
  10. package/lib/core/components/shadcn/modal/ConfirmModal.js.map +1 -1
  11. package/lib/core/components/shadcn/modal/dialog.js +1 -1
  12. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  13. package/lib/core/components/shadcn/popover.d.ts.map +1 -1
  14. package/lib/core/components/shadcn/popover.js +3 -1
  15. package/lib/core/components/shadcn/popover.js.map +1 -1
  16. package/lib/core/components/shadcn/switch.js +3 -3
  17. package/lib/core/components/shadcn/switch.js.map +1 -1
  18. package/lib/core/components/shadcn/tabs.js +1 -1
  19. package/lib/core/components/shadcn/tabs.js.map +1 -1
  20. package/lib/core/components/shadcn/tooltip.d.ts.map +1 -1
  21. package/lib/core/components/shadcn/tooltip.js +3 -1
  22. package/lib/core/components/shadcn/tooltip.js.map +1 -1
  23. package/lib/env/index.d.ts +0 -19
  24. package/lib/env/index.d.ts.map +1 -1
  25. package/lib/env/index.js +0 -6
  26. package/lib/env/index.js.map +1 -1
  27. package/lib/features/agent/PayloadBuilder.d.ts +4 -0
  28. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  29. package/lib/features/agent/PayloadBuilder.js +16 -0
  30. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  31. package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts +10 -0
  32. package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts.map +1 -0
  33. package/lib/features/agent/chat/AgentApprovalModeSelector.js +50 -0
  34. package/lib/features/agent/chat/AgentApprovalModeSelector.js.map +1 -0
  35. package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts +2 -1
  36. package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts.map +1 -1
  37. package/lib/features/agent/chat/AgentChatFixtureReplay.js +3 -3
  38. package/lib/features/agent/chat/AgentChatFixtureReplay.js.map +1 -1
  39. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +5 -2
  40. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
  41. package/lib/features/agent/chat/AgentRequestInputOverlay.js +41 -7
  42. package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
  43. package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
  44. package/lib/features/agent/chat/AgentRightPanel.js +133 -12
  45. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  46. package/lib/features/agent/chat/AnimatedThinkingDots.js +1 -1
  47. package/lib/features/agent/chat/AnimatedThinkingDots.js.map +1 -1
  48. package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
  49. package/lib/features/agent/chat/ArtifactsTab.js +11 -65
  50. package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
  51. package/lib/features/agent/chat/AskUserWidget.d.ts +3 -1
  52. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  53. package/lib/features/agent/chat/AskUserWidget.js +4 -3
  54. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  55. package/lib/features/agent/chat/ModernAgentConversation.d.ts +10 -2
  56. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  57. package/lib/features/agent/chat/ModernAgentConversation.js +526 -117
  58. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts +8 -0
  60. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -0
  61. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +19 -0
  62. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -0
  63. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -2
  64. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  65. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +551 -92
  66. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  67. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +7 -6
  69. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/Header.js +2 -2
  71. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts +8 -0
  73. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts.map +1 -0
  74. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js +61 -0
  75. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js.map +1 -0
  76. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +15 -2
  77. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
  78. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +28 -38
  79. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  80. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +1 -1
  81. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  82. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -2
  83. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  84. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +2 -1
  85. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -1
  86. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js +1 -1
  87. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -1
  88. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts +5 -0
  89. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  90. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +59 -4
  91. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  92. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +2 -2
  93. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  94. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +9 -0
  95. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
  96. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +180 -0
  97. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
  98. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
  99. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  100. package/lib/features/agent/chat/ModernAgentOutput/utils.js +92 -2
  101. package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
  102. package/lib/features/agent/chat/clipboardFiles.d.ts +15 -0
  103. package/lib/features/agent/chat/clipboardFiles.d.ts.map +1 -0
  104. package/lib/features/agent/chat/clipboardFiles.js +35 -0
  105. package/lib/features/agent/chat/clipboardFiles.js.map +1 -0
  106. package/lib/features/agent/chat/hooks/useAgentStream.d.ts +6 -0
  107. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  108. package/lib/features/agent/chat/hooks/useAgentStream.js +218 -37
  109. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  110. package/lib/features/agent/chat/hooks/useArtifacts.d.ts +1 -8
  111. package/lib/features/agent/chat/hooks/useArtifacts.d.ts.map +1 -1
  112. package/lib/features/agent/chat/hooks/useArtifacts.js +10 -28
  113. package/lib/features/agent/chat/hooks/useArtifacts.js.map +1 -1
  114. package/lib/features/agent/chat/index.d.ts +2 -1
  115. package/lib/features/agent/chat/index.d.ts.map +1 -1
  116. package/lib/features/agent/chat/index.js +2 -1
  117. package/lib/features/agent/chat/index.js.map +1 -1
  118. package/lib/features/agent/chat/workstreams.d.ts +1 -0
  119. package/lib/features/agent/chat/workstreams.d.ts.map +1 -1
  120. package/lib/features/agent/chat/workstreams.js +28 -0
  121. package/lib/features/agent/chat/workstreams.js.map +1 -1
  122. package/lib/features/facets/AgentRunnerFacetsNav.d.ts +10 -1
  123. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  124. package/lib/features/facets/AgentRunnerFacetsNav.js +6 -3
  125. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  126. package/lib/features/facets/CollectionsFacetsNav.d.ts +10 -1
  127. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  128. package/lib/features/facets/CollectionsFacetsNav.js +14 -5
  129. package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
  130. package/lib/features/facets/PromptsFacetsNav.d.ts +10 -1
  131. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  132. package/lib/features/facets/PromptsFacetsNav.js +14 -5
  133. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  134. package/lib/features/facets/RunsFacetsNav.d.ts +10 -1
  135. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  136. package/lib/features/facets/RunsFacetsNav.js +14 -5
  137. package/lib/features/facets/RunsFacetsNav.js.map +1 -1
  138. package/lib/features/index.d.ts +0 -1
  139. package/lib/features/index.d.ts.map +1 -1
  140. package/lib/features/index.js +0 -1
  141. package/lib/features/index.js.map +1 -1
  142. package/lib/features/oauth/McpConnectionsButton.d.ts +30 -0
  143. package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -0
  144. package/lib/features/oauth/McpConnectionsButton.js +70 -0
  145. package/lib/features/oauth/McpConnectionsButton.js.map +1 -0
  146. package/lib/features/oauth/McpConnectionsDialog.d.ts +25 -0
  147. package/lib/features/oauth/McpConnectionsDialog.d.ts.map +1 -0
  148. package/lib/features/oauth/McpConnectionsDialog.js +26 -0
  149. package/lib/features/oauth/McpConnectionsDialog.js.map +1 -0
  150. package/lib/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -1
  151. package/lib/features/oauth/RemoteMcpConnectionButton.js +14 -6
  152. package/lib/features/oauth/RemoteMcpConnectionButton.js.map +1 -1
  153. package/lib/features/oauth/index.d.ts +3 -0
  154. package/lib/features/oauth/index.d.ts.map +1 -1
  155. package/lib/features/oauth/index.js +3 -0
  156. package/lib/features/oauth/index.js.map +1 -1
  157. package/lib/features/oauth/useMcpConnections.d.ts +44 -0
  158. package/lib/features/oauth/useMcpConnections.d.ts.map +1 -0
  159. package/lib/features/oauth/useMcpConnections.js +168 -0
  160. package/lib/features/oauth/useMcpConnections.js.map +1 -0
  161. package/lib/features/permissions/UserPermissionsProvider.d.ts +4 -6
  162. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  163. package/lib/features/permissions/UserPermissionsProvider.js +40 -42
  164. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  165. package/lib/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
  166. package/lib/features/store/objects/DocumentPreviewPanel.js +2 -1
  167. package/lib/features/store/objects/DocumentPreviewPanel.js.map +1 -1
  168. package/lib/features/store/objects/DocumentQuickFilter.d.ts +23 -0
  169. package/lib/features/store/objects/DocumentQuickFilter.d.ts.map +1 -0
  170. package/lib/features/store/objects/DocumentQuickFilter.js +30 -0
  171. package/lib/features/store/objects/DocumentQuickFilter.js.map +1 -0
  172. package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  173. package/lib/features/store/objects/DocumentSearchResults.js +17 -1
  174. package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
  175. package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  176. package/lib/features/store/objects/components/ContentOverview.js +17 -74
  177. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  178. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +7 -1
  179. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  180. package/lib/features/store/objects/layout/DocumentTableColumn.js +27 -3
  181. package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  182. package/lib/features/store/objects/layout/documentLayout.js +1 -1
  183. package/lib/features/store/objects/layout/renderers.d.ts +2 -1
  184. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  185. package/lib/features/store/objects/layout/renderers.js +27 -20
  186. package/lib/features/store/objects/layout/renderers.js.map +1 -1
  187. package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
  188. package/lib/features/store/types/ContentObjectTypesSearch.js +4 -1
  189. package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
  190. package/lib/features/store/types/ContentObjectTypesTable.d.ts +2 -1
  191. package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
  192. package/lib/features/store/types/ContentObjectTypesTable.js +8 -3
  193. package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
  194. package/lib/i18n/instance.d.ts.map +1 -1
  195. package/lib/i18n/instance.js +1 -0
  196. package/lib/i18n/instance.js.map +1 -1
  197. package/lib/i18n/locales/ar.json +72 -45
  198. package/lib/i18n/locales/de.json +65 -34
  199. package/lib/i18n/locales/en.json +63 -47
  200. package/lib/i18n/locales/es.json +65 -35
  201. package/lib/i18n/locales/fr.json +65 -35
  202. package/lib/i18n/locales/it.json +72 -42
  203. package/lib/i18n/locales/ja.json +72 -41
  204. package/lib/i18n/locales/ko.json +72 -41
  205. package/lib/i18n/locales/pt.json +72 -42
  206. package/lib/i18n/locales/ru.json +72 -43
  207. package/lib/i18n/locales/tr.json +72 -41
  208. package/lib/i18n/locales/zh-TW.json +72 -41
  209. package/lib/i18n/locales/zh.json +72 -41
  210. package/lib/session/UserSession.d.ts +0 -6
  211. package/lib/session/UserSession.d.ts.map +1 -1
  212. package/lib/session/UserSession.js +0 -15
  213. package/lib/session/UserSession.js.map +1 -1
  214. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  215. package/lib/session/UserSessionProvider.js +39 -98
  216. package/lib/session/UserSessionProvider.js.map +1 -1
  217. package/lib/session/auth/composable.d.ts.map +1 -1
  218. package/lib/session/auth/composable.js +3 -33
  219. package/lib/session/auth/composable.js.map +1 -1
  220. package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
  221. package/lib/shell/login/SignInPrimitives.js +3 -2
  222. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  223. package/lib/vertesia-ui-core.js +1 -1
  224. package/lib/vertesia-ui-core.js.map +1 -1
  225. package/lib/vertesia-ui-env.js +1 -1
  226. package/lib/vertesia-ui-env.js.map +1 -1
  227. package/lib/vertesia-ui-features.js +1 -1
  228. package/lib/vertesia-ui-features.js.map +1 -1
  229. package/lib/vertesia-ui-i18n.js +1 -1
  230. package/lib/vertesia-ui-i18n.js.map +1 -1
  231. package/lib/vertesia-ui-session.js +1 -1
  232. package/lib/vertesia-ui-session.js.map +1 -1
  233. package/lib/vertesia-ui-shell.js +1 -1
  234. package/lib/vertesia-ui-shell.js.map +1 -1
  235. package/lib/vertesia-ui-widgets.js +1 -1
  236. package/lib/vertesia-ui-widgets.js.map +1 -1
  237. package/lib/widgets/schema-editor/editor/Editable.js +1 -1
  238. package/lib/widgets/schema-editor/editor/Editable.js.map +1 -1
  239. package/llms.txt +70 -70
  240. package/package.json +35 -32
  241. package/src/core/components/shadcn/dropdown.tsx +2 -0
  242. package/src/core/components/shadcn/filters/filterBar.tsx +9 -2
  243. package/src/core/components/shadcn/modal/ConfirmModal.tsx +65 -3
  244. package/src/core/components/shadcn/modal/dialog.tsx +1 -1
  245. package/src/core/components/shadcn/popover.tsx +1 -0
  246. package/src/core/components/shadcn/switch.tsx +4 -4
  247. package/src/core/components/shadcn/tabs.tsx +1 -1
  248. package/src/core/components/shadcn/tooltip.tsx +1 -0
  249. package/src/env/index.ts +0 -24
  250. package/src/features/agent/PayloadBuilder.tsx +18 -0
  251. package/src/features/agent/chat/AgentApprovalModeSelector.tsx +130 -0
  252. package/src/features/agent/chat/AgentChatFixtureReplay.test.tsx +22 -2
  253. package/src/features/agent/chat/AgentChatFixtureReplay.tsx +33 -27
  254. package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +122 -0
  255. package/src/features/agent/chat/AgentRequestInputOverlay.tsx +91 -17
  256. package/src/features/agent/chat/AgentRightPanel.tsx +238 -50
  257. package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -1
  258. package/src/features/agent/chat/ArtifactsTab.tsx +21 -155
  259. package/src/features/agent/chat/AskUserWidget.tsx +6 -2
  260. package/src/features/agent/chat/ModernAgentConversation.test.tsx +1157 -47
  261. package/src/features/agent/chat/ModernAgentConversation.tsx +703 -136
  262. package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +74 -0
  263. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +1420 -126
  264. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +934 -111
  265. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +31 -40
  266. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +28 -28
  267. package/src/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.tsx +83 -0
  268. package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +38 -2
  269. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +121 -98
  270. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +7 -1
  271. package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +3 -3
  272. package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +1 -1
  273. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +82 -2
  274. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +2 -2
  275. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +216 -0
  276. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +149 -0
  277. package/src/features/agent/chat/ModernAgentOutput/utils.ts +103 -2
  278. package/src/features/agent/chat/clipboardFiles.ts +33 -0
  279. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +355 -4
  280. package/src/features/agent/chat/hooks/useAgentStream.ts +270 -43
  281. package/src/features/agent/chat/hooks/useArtifacts.ts +11 -44
  282. package/src/features/agent/chat/index.ts +10 -1
  283. package/src/features/agent/chat/workstreams.ts +42 -0
  284. package/src/features/facets/AgentRunnerFacetsNav.tsx +23 -3
  285. package/src/features/facets/CollectionsFacetsNav.tsx +30 -5
  286. package/src/features/facets/PromptsFacetsNav.tsx +30 -5
  287. package/src/features/facets/RunsFacetsNav.tsx +32 -5
  288. package/src/features/index.ts +0 -1
  289. package/src/features/oauth/McpConnectionsButton.test.tsx +248 -0
  290. package/src/features/oauth/McpConnectionsButton.tsx +269 -0
  291. package/src/features/oauth/McpConnectionsDialog.tsx +142 -0
  292. package/src/features/oauth/RemoteMcpConnectionButton.tsx +37 -14
  293. package/src/features/oauth/index.ts +3 -0
  294. package/src/features/oauth/useMcpConnections.test.ts +94 -0
  295. package/src/features/oauth/useMcpConnections.ts +210 -0
  296. package/src/features/permissions/UserPermissionsProvider.tsx +41 -59
  297. package/src/features/store/objects/DocumentPreviewPanel.tsx +4 -2
  298. package/src/features/store/objects/DocumentQuickFilter.tsx +72 -0
  299. package/src/features/store/objects/DocumentSearchResults.tsx +30 -11
  300. package/src/features/store/objects/components/ContentOverview.tsx +30 -99
  301. package/src/features/store/objects/layout/DocumentTableColumn.tsx +29 -4
  302. package/src/features/store/objects/layout/documentLayout.tsx +1 -1
  303. package/src/features/store/objects/layout/renderers.tsx +80 -20
  304. package/src/features/store/types/ContentObjectTypesSearch.tsx +7 -1
  305. package/src/features/store/types/ContentObjectTypesTable.tsx +34 -4
  306. package/src/i18n/instance.ts +1 -0
  307. package/src/i18n/locales/ar.json +72 -45
  308. package/src/i18n/locales/de.json +65 -34
  309. package/src/i18n/locales/en.json +63 -47
  310. package/src/i18n/locales/es.json +65 -35
  311. package/src/i18n/locales/fr.json +65 -35
  312. package/src/i18n/locales/it.json +72 -42
  313. package/src/i18n/locales/ja.json +72 -41
  314. package/src/i18n/locales/ko.json +72 -41
  315. package/src/i18n/locales/pt.json +72 -42
  316. package/src/i18n/locales/ru.json +72 -43
  317. package/src/i18n/locales/tr.json +72 -41
  318. package/src/i18n/locales/zh-TW.json +72 -41
  319. package/src/i18n/locales/zh.json +72 -41
  320. package/src/i18n/rtl.test.ts +57 -1
  321. package/src/session/UserSession.ts +0 -16
  322. package/src/session/UserSessionProvider.tsx +51 -123
  323. package/src/session/auth/composable.ts +3 -34
  324. package/src/shell/login/SignInPrimitives.tsx +3 -2
  325. package/src/widgets/schema-editor/editor/Editable.tsx +1 -1
  326. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts +0 -73
  327. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +0 -1
  328. package/lib/features/document-viewer/UniversalDocumentViewer.js +0 -415
  329. package/lib/features/document-viewer/UniversalDocumentViewer.js.map +0 -1
  330. package/lib/features/document-viewer/index.d.ts +0 -2
  331. package/lib/features/document-viewer/index.d.ts.map +0 -1
  332. package/lib/features/document-viewer/index.js +0 -2
  333. package/lib/features/document-viewer/index.js.map +0 -1
  334. package/src/features/document-viewer/UniversalDocumentViewer.test.tsx +0 -123
  335. package/src/features/document-viewer/UniversalDocumentViewer.tsx +0 -746
  336. package/src/features/document-viewer/index.ts +0 -1
  337. package/src/session/auth/composable.test.ts +0 -79
@@ -0,0 +1,142 @@
1
+ import { useUITranslation } from '@vertesia/ui/i18n';
2
+ import { Link2, Link2Off } from 'lucide-react';
3
+ import { Button, Modal, ModalBody, ModalTitle, Spinner, Switch, VTooltip } from '../../core/index.js';
4
+ import { RemoteMcpConnectionButton } from './RemoteMcpConnectionButton.js';
5
+ import { isGroupDisabled, type McpConnectionGroup, toggleGroupDisabled } from './useMcpConnections.js';
6
+
7
+ export interface McpConnectionsDialogProps {
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ groups: McpConnectionGroup[];
11
+ loading: boolean;
12
+ /** True while group-level OAuth status is being fetched after the MCP rows are known. */
13
+ statusLoading?: boolean;
14
+ /** Refresh connection status after connect/disconnect. */
15
+ reload: () => void;
16
+ /** Collection ids deactivated for this conversation. `undefined`/empty ⇒ all active. */
17
+ disabledCollections?: string[];
18
+ /** Emits the next disabled-collection list when a server is toggled. Omit for read-only. */
19
+ onChange?: (disabled: string[]) => void;
20
+ /** Called after a successful connect/disconnect (e.g. to trigger tool re-discovery). */
21
+ onConnectionChange?: () => void;
22
+ /** Read-only: show status only, no toggles or connect/disconnect controls. */
23
+ readOnly?: boolean;
24
+ }
25
+
26
+ /**
27
+ * Dialog to manage the MCP servers available to an agent conversation.
28
+ * Each server can be connected/disconnected (OAuth) and activated/deactivated for this run.
29
+ */
30
+ export function McpConnectionsDialog({
31
+ isOpen,
32
+ onClose,
33
+ groups,
34
+ loading,
35
+ statusLoading = false,
36
+ reload,
37
+ disabledCollections,
38
+ onChange,
39
+ onConnectionChange,
40
+ readOnly = false,
41
+ }: McpConnectionsDialogProps) {
42
+ const { t } = useUITranslation();
43
+
44
+ const handleAuthChange = () => {
45
+ reload();
46
+ onConnectionChange?.();
47
+ };
48
+
49
+ return (
50
+ <Modal isOpen={isOpen} onClose={onClose} size="md" className="max-w-[92vw] sm:max-w-[620px] lg:max-w-[620px]">
51
+ <ModalTitle>{t('mcpConnections.title')}</ModalTitle>
52
+ <ModalBody>
53
+ <p className="mb-4 text-sm text-muted">{t('mcpConnections.subtitle')}</p>
54
+ {loading ? (
55
+ <div className="flex items-center justify-center py-8">
56
+ <Spinner className="size-5" />
57
+ </div>
58
+ ) : groups.length === 0 ? (
59
+ <div className="py-8 text-center text-sm text-muted">{t('mcpConnections.empty')}</div>
60
+ ) : (
61
+ <div className="space-y-1">
62
+ {groups.map((group) => {
63
+ const active = !isGroupDisabled(group, disabledCollections);
64
+ const connected = group.authStatus?.authenticated === true;
65
+ const StatusIcon = connected ? Link2 : Link2Off;
66
+ return (
67
+ <div key={group.key} className="flex items-center justify-between gap-3 py-3">
68
+ <div className="flex min-w-0 items-center gap-2">
69
+ <StatusIcon
70
+ className={`size-4 shrink-0 ${connected ? 'text-success' : 'text-muted'}`}
71
+ aria-hidden="true"
72
+ />
73
+ <VTooltip
74
+ description={
75
+ <div className="space-y-0.5">
76
+ <div className="font-medium">{group.appName}</div>
77
+ {group.memberNames.length > 1 && (
78
+ <div className="text-xs text-muted">
79
+ {group.memberNames.join(' · ')}
80
+ </div>
81
+ )}
82
+ </div>
83
+ }
84
+ placement="top"
85
+ asChild
86
+ >
87
+ <span
88
+ className={`truncate ${active ? 'text-foreground' : 'text-muted line-through'}`}
89
+ >
90
+ {group.label}
91
+ </span>
92
+ </VTooltip>
93
+ </div>
94
+ <div className="flex shrink-0 items-center gap-3">
95
+ {statusLoading && !group.authStatus ? (
96
+ <Button
97
+ variant="outline"
98
+ size="sm"
99
+ disabled
100
+ className="h-6 w-32 justify-center px-2 text-xs"
101
+ aria-label={t('mcpConnections.checkingStatus')}
102
+ title={t('mcpConnections.checkingStatus')}
103
+ >
104
+ <Spinner className="size-3" />
105
+ </Button>
106
+ ) : (
107
+ <RemoteMcpConnectionButton
108
+ appId={group.appId}
109
+ collectionId={group.representativeId}
110
+ collectionName={group.label}
111
+ authenticated={group.authStatus?.authenticated}
112
+ onAuthChange={handleAuthChange}
113
+ variant="compact"
114
+ showDisconnect
115
+ readOnly={readOnly}
116
+ />
117
+ )}
118
+ {onChange && (
119
+ <Switch
120
+ size="sm"
121
+ value={active}
122
+ onChange={(checked) =>
123
+ onChange(toggleGroupDisabled(group, disabledCollections, checked))
124
+ }
125
+ disabled={readOnly}
126
+ aria-label={
127
+ active
128
+ ? t('mcpConnections.deactivateAria', { name: group.label })
129
+ : t('mcpConnections.activateAria', { name: group.label })
130
+ }
131
+ />
132
+ )}
133
+ </div>
134
+ </div>
135
+ );
136
+ })}
137
+ </div>
138
+ )}
139
+ </ModalBody>
140
+ </Modal>
141
+ );
142
+ }
@@ -1,6 +1,6 @@
1
1
  import { useUITranslation } from '@vertesia/ui/i18n';
2
2
  import { useUserSession } from '@vertesia/ui/session';
3
- import { CheckCircle2, ExternalLink, ShieldAlertIcon } from 'lucide-react';
3
+ import { CheckCircle2, Link2, ShieldAlertIcon, Unlink2 } from 'lucide-react';
4
4
  import { useCallback, useEffect, useState } from 'react';
5
5
  import { Button, Spinner } from '../../core/index.js';
6
6
  import { useOAuthPopup } from './useOAuthPopup.js';
@@ -51,18 +51,23 @@ export function RemoteMcpConnectionButton({
51
51
  const { client } = useUserSession();
52
52
  const { t } = useUITranslation();
53
53
  const [status, setStatus] = useState<OAuthStatus | null>(null);
54
- const [loading, setLoading] = useState(providedAuthenticated === undefined);
54
+ const [loading, setLoading] = useState(providedAuthenticated === undefined && !readOnly);
55
55
  const [authenticating, setAuthenticating] = useState(false);
56
56
  const [disconnecting, setDisconnecting] = useState(false);
57
57
 
58
58
  const authenticated = providedAuthenticated ?? status?.authenticated ?? false;
59
59
  const displayName = collectionName ?? collectionId;
60
+ const compactActionClassName = 'h-6 w-32 justify-center px-2 text-xs';
60
61
 
61
62
  const loadStatus = useCallback(async () => {
62
63
  if (providedAuthenticated !== undefined) {
63
64
  setLoading(false);
64
65
  return;
65
66
  }
67
+ if (readOnly) {
68
+ setLoading(false);
69
+ return;
70
+ }
66
71
 
67
72
  try {
68
73
  setLoading(true);
@@ -73,7 +78,7 @@ export function RemoteMcpConnectionButton({
73
78
  } finally {
74
79
  setLoading(false);
75
80
  }
76
- }, [client, appId, collectionId, providedAuthenticated]);
81
+ }, [client, appId, collectionId, providedAuthenticated, readOnly]);
77
82
 
78
83
  useEffect(() => {
79
84
  void loadStatus();
@@ -132,6 +137,21 @@ export function RemoteMcpConnectionButton({
132
137
  };
133
138
 
134
139
  if (loading) {
140
+ if (variant === 'compact') {
141
+ return (
142
+ <Button
143
+ variant="outline"
144
+ size="sm"
145
+ disabled
146
+ className={compactActionClassName}
147
+ aria-label={t('mcpConnections.checkingStatus')}
148
+ title={t('mcpConnections.checkingStatus')}
149
+ >
150
+ <Spinner className="size-3" />
151
+ </Button>
152
+ );
153
+ }
154
+
135
155
  return (
136
156
  <div className="flex items-center gap-2 text-sm">
137
157
  <Spinner className="size-4" />
@@ -182,19 +202,22 @@ export function RemoteMcpConnectionButton({
182
202
  return (
183
203
  <div className="flex items-center gap-2">
184
204
  {showLabel && <span className="font-medium text-xs text-foreground">{displayName}:</span>}
185
- <div className="flex items-center gap-1 text-success">
186
- <CheckCircle2 className="size-3" />
187
- <span className="text-xs">{t('mcpOAuth.connected')}</span>
188
- </div>
189
205
  {!readOnly && showDisconnect && (
190
206
  <Button
191
- variant="ghost"
207
+ variant="outline"
192
208
  size="sm"
193
209
  onClick={handleDisconnect}
194
210
  disabled={disconnecting}
195
- className="h-6 px-2 text-xs"
211
+ className={compactActionClassName}
196
212
  >
197
- {disconnecting ? <Spinner className="size-3" /> : t('mcpOAuth.disconnect')}
213
+ {disconnecting ? (
214
+ <Spinner className="size-3" />
215
+ ) : (
216
+ <>
217
+ <Unlink2 className="size-3" />
218
+ <span>{t('mcpOAuth.disconnect')}</span>
219
+ </>
220
+ )}
198
221
  </Button>
199
222
  )}
200
223
  </div>
@@ -229,7 +252,7 @@ export function RemoteMcpConnectionButton({
229
252
  size="sm"
230
253
  onClick={handleConnect}
231
254
  disabled={authenticating}
232
- className="h-6 px-2 text-xs"
255
+ className={compactActionClassName}
233
256
  >
234
257
  {authenticating ? (
235
258
  <>
@@ -238,7 +261,7 @@ export function RemoteMcpConnectionButton({
238
261
  </>
239
262
  ) : (
240
263
  <>
241
- <ExternalLink className="size-3 me-1" />
264
+ <Link2 className="size-3" />
242
265
  <span>{t('mcpOAuth.connect')}</span>
243
266
  </>
244
267
  )}
@@ -248,7 +271,7 @@ export function RemoteMcpConnectionButton({
248
271
  }
249
272
 
250
273
  return (
251
- <Button variant="outline" size="sm" onClick={handleConnect} disabled={authenticating}>
274
+ <Button variant="outline" size="sm" onClick={handleConnect} disabled={readOnly || authenticating}>
252
275
  {authenticating ? (
253
276
  <>
254
277
  <Spinner className="size-4" />
@@ -256,7 +279,7 @@ export function RemoteMcpConnectionButton({
256
279
  </>
257
280
  ) : (
258
281
  <>
259
- <ExternalLink className="size-4 me-1" />
282
+ <Link2 className="size-4 me-1" />
260
283
  <span>{t('mcpOAuth.connect')}</span>
261
284
  </>
262
285
  )}
@@ -1,3 +1,6 @@
1
+ export * from './McpConnectionsButton.js';
2
+ export * from './McpConnectionsDialog.js';
1
3
  export * from './OAuthProviderConnectButton.js';
2
4
  export * from './RemoteMcpConnectionButton.js';
5
+ export * from './useMcpConnections.js';
3
6
  export * from './useOAuthPopup.js';
@@ -0,0 +1,94 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ countConnectedActiveGroups,
4
+ getConnectedActiveGroupLabels,
5
+ isGroupDisabled,
6
+ type McpConnectionGroup,
7
+ toggleGroupDisabled,
8
+ } from './useMcpConnections.js';
9
+
10
+ function group(memberIds: string[], authenticated?: boolean, label = 'Server'): McpConnectionGroup {
11
+ return {
12
+ key: `k:${memberIds.join(',')}`,
13
+ appId: 'app1',
14
+ appName: 'App',
15
+ label,
16
+ representativeId: memberIds[0],
17
+ memberIds,
18
+ memberNames: memberIds,
19
+ authStatus:
20
+ authenticated === undefined
21
+ ? undefined
22
+ : {
23
+ authenticated,
24
+ collection_id: memberIds[0],
25
+ collection_name: memberIds[0],
26
+ mcp_server_url: 'https://mcp.example.com',
27
+ },
28
+ };
29
+ }
30
+
31
+ describe('isGroupDisabled', () => {
32
+ it('is active (not disabled) when the disabled set is empty or undefined', () => {
33
+ const g = group(['a']);
34
+ expect(isGroupDisabled(g, undefined)).toBe(false);
35
+ expect(isGroupDisabled(g, [])).toBe(false);
36
+ });
37
+
38
+ it('is disabled only when every member id is in the disabled set', () => {
39
+ const g = group(['a', 'b']);
40
+ expect(isGroupDisabled(g, ['a'])).toBe(false);
41
+ expect(isGroupDisabled(g, ['a', 'b'])).toBe(true);
42
+ });
43
+ });
44
+
45
+ describe('countConnectedActiveGroups', () => {
46
+ it('counts only connected groups that are not disabled', () => {
47
+ expect(
48
+ countConnectedActiveGroups(
49
+ [
50
+ group(['connected'], true),
51
+ group(['not-connected'], false),
52
+ group(['unknown-status']),
53
+ group(['connected-disabled'], true),
54
+ ],
55
+ ['connected-disabled'],
56
+ ),
57
+ ).toBe(1);
58
+ });
59
+ });
60
+
61
+ describe('getConnectedActiveGroupLabels', () => {
62
+ it('returns only connected groups that are not disabled', () => {
63
+ expect(
64
+ getConnectedActiveGroupLabels(
65
+ [
66
+ group(['jira'], true, 'Jira'),
67
+ group(['github'], false, 'GitHub'),
68
+ group(['miro'], true, 'Miro'),
69
+ group(['linear'], true, 'Linear'),
70
+ ],
71
+ ['linear'],
72
+ ),
73
+ ).toEqual(['Jira', 'Miro']);
74
+ });
75
+ });
76
+
77
+ describe('toggleGroupDisabled', () => {
78
+ it('disabling adds all member ids', () => {
79
+ const g = group(['a', 'b']);
80
+ expect(toggleGroupDisabled(g, undefined, /* active */ false).sort()).toEqual(['a', 'b']);
81
+ });
82
+
83
+ it('enabling removes all member ids and keeps others', () => {
84
+ const g = group(['a', 'b']);
85
+ expect(toggleGroupDisabled(g, ['a', 'b', 'c'], /* active */ true)).toEqual(['c']);
86
+ });
87
+
88
+ it('round-trips back to the original set', () => {
89
+ const g = group(['a']);
90
+ const disabled = toggleGroupDisabled(g, [], false);
91
+ expect(disabled).toEqual(['a']);
92
+ expect(toggleGroupDisabled(g, disabled, true)).toEqual([]);
93
+ });
94
+ });
@@ -0,0 +1,210 @@
1
+ import {
2
+ type AppInstallationWithManifest,
3
+ type MCPToolCollectionObject,
4
+ normalizeToolCollection,
5
+ type OAuthAuthStatus,
6
+ } from '@vertesia/common';
7
+ import { useUserSession } from '@vertesia/ui/session';
8
+ import { useCallback, useEffect, useRef, useState } from 'react';
9
+
10
+ /**
11
+ * A group of MCP tool collections that share a single OAuth connection.
12
+ * Connection/activation operations act on the whole group.
13
+ */
14
+ export interface McpConnectionGroup {
15
+ key: string;
16
+ appId: string;
17
+ appName: string;
18
+ /** Display label: provider display_name, oauth_app name, or individual collection name */
19
+ label: string;
20
+ /** Representative collection ID used for OAuth operations (all in group share the same OAuth provider) */
21
+ representativeId: string;
22
+ /** All collection IDs in this group (used for per-conversation activation toggles) */
23
+ memberIds: string[];
24
+ /** Names of all collections in this group (for tooltip when > 1) */
25
+ memberNames: string[];
26
+ authStatus?: OAuthAuthStatus;
27
+ }
28
+
29
+ /**
30
+ * Loads the project's installed MCP tool collections that require OAuth, grouped by their
31
+ * shared OAuth provider/app, and resolves each group's current connection status.
32
+ *
33
+ * Shared by the MCP connections button (badge count) and dialog (list) so the data is
34
+ * fetched once and refreshed together after connect/disconnect.
35
+ */
36
+ export function useMcpConnections() {
37
+ const { client } = useUserSession();
38
+ const [groups, setGroups] = useState<McpConnectionGroup[]>([]);
39
+ const [loading, setLoading] = useState(true);
40
+ const [statusLoading, setStatusLoading] = useState(false);
41
+ const reloadIdRef = useRef(0);
42
+
43
+ const reload = useCallback(async () => {
44
+ const reloadId = reloadIdRef.current + 1;
45
+ reloadIdRef.current = reloadId;
46
+ setLoading(true);
47
+ setStatusLoading(false);
48
+ try {
49
+ const apps = await client.apps.getInstalledApps('tools');
50
+ const allGroups: McpConnectionGroup[] = [];
51
+
52
+ for (const app of apps) {
53
+ const inst = app as AppInstallationWithManifest;
54
+ const oauthIds = inst.oauth_collection_ids ?? [];
55
+ const manifestProviders = inst.manifest.oauth_providers ?? {};
56
+
57
+ if (!inst.manifest.tool_collections) continue;
58
+
59
+ const oauthCollections = inst.manifest.tool_collections
60
+ .map((c) => normalizeToolCollection(c))
61
+ .filter((c): c is MCPToolCollectionObject => c.type === 'mcp' && oauthIds.includes(c.id));
62
+
63
+ const providerMap = new Map<string, MCPToolCollectionObject[]>();
64
+ const oauthAppMap = new Map<string, MCPToolCollectionObject[]>();
65
+ const individualCols: MCPToolCollectionObject[] = [];
66
+
67
+ for (const col of oauthCollections) {
68
+ if (col.oauth_provider) {
69
+ const g = providerMap.get(col.oauth_provider) ?? [];
70
+ g.push(col);
71
+ providerMap.set(col.oauth_provider, g);
72
+ } else if (col.oauth_app) {
73
+ const g = oauthAppMap.get(col.oauth_app) ?? [];
74
+ g.push(col);
75
+ oauthAppMap.set(col.oauth_app, g);
76
+ } else {
77
+ individualCols.push(col);
78
+ }
79
+ }
80
+
81
+ for (const [providerKey, cols] of providerMap) {
82
+ allGroups.push({
83
+ key: `${inst.id}:provider:${providerKey}`,
84
+ appId: inst.id,
85
+ appName: inst.manifest.title || inst.manifest.name,
86
+ label: manifestProviders[providerKey]?.display_name || providerKey,
87
+ representativeId: cols[0].id,
88
+ memberIds: cols.map((c) => c.id),
89
+ memberNames: cols.map((c) => c.name),
90
+ });
91
+ }
92
+
93
+ for (const [oauthApp, cols] of oauthAppMap) {
94
+ allGroups.push({
95
+ key: `${inst.id}:oauthapp:${oauthApp}`,
96
+ appId: inst.id,
97
+ appName: inst.manifest.title || inst.manifest.name,
98
+ label: oauthApp,
99
+ representativeId: cols[0].id,
100
+ memberIds: cols.map((c) => c.id),
101
+ memberNames: cols.map((c) => c.name),
102
+ });
103
+ }
104
+
105
+ for (const col of individualCols) {
106
+ allGroups.push({
107
+ key: `${inst.id}:individual:${col.id}`,
108
+ appId: inst.id,
109
+ appName: inst.manifest.title || inst.manifest.name,
110
+ label: col.name,
111
+ representativeId: col.id,
112
+ memberIds: [col.id],
113
+ memberNames: [col.name],
114
+ });
115
+ }
116
+ }
117
+
118
+ if (reloadIdRef.current !== reloadId) {
119
+ return;
120
+ }
121
+
122
+ setGroups(allGroups);
123
+ setLoading(false);
124
+
125
+ if (allGroups.length === 0) {
126
+ return;
127
+ }
128
+
129
+ setStatusLoading(true);
130
+
131
+ // Fetch OAuth status once per app installation; getStatus(appId) returns all collection statuses.
132
+ const statusRequestsByApp = new Map<string, Promise<OAuthAuthStatus[]>>();
133
+ const groupsWithStatus = await Promise.all(
134
+ allGroups.map(async (group) => {
135
+ try {
136
+ let statusRequest = statusRequestsByApp.get(group.appId);
137
+ if (!statusRequest) {
138
+ statusRequest = client.remoteMcpConnections.getStatus(group.appId);
139
+ statusRequestsByApp.set(group.appId, statusRequest);
140
+ }
141
+ const statuses = await statusRequest;
142
+ const status = statuses.find((s) => s.collection_id === group.representativeId);
143
+ return { ...group, authStatus: status };
144
+ } catch {
145
+ return group;
146
+ }
147
+ }),
148
+ );
149
+
150
+ if (reloadIdRef.current !== reloadId) {
151
+ return;
152
+ }
153
+
154
+ setGroups(groupsWithStatus);
155
+ } catch (error) {
156
+ if (reloadIdRef.current === reloadId) {
157
+ console.error('Failed to load MCP tool collections:', error);
158
+ setGroups([]);
159
+ }
160
+ } finally {
161
+ if (reloadIdRef.current === reloadId) {
162
+ setLoading(false);
163
+ setStatusLoading(false);
164
+ }
165
+ }
166
+ }, [client]);
167
+
168
+ useEffect(() => {
169
+ void reload();
170
+ }, [reload]);
171
+
172
+ return { groups, loading, statusLoading, reload };
173
+ }
174
+
175
+ /** True when every collection in the group is present in the disabled set. */
176
+ export function isGroupDisabled(group: McpConnectionGroup, disabled?: string[]): boolean {
177
+ if (!disabled?.length) return false;
178
+ return group.memberIds.every((id) => disabled.includes(id));
179
+ }
180
+
181
+ /**
182
+ * Toggle a group's activation, returning the next disabled-collection list.
183
+ * Disabling adds all member ids; enabling removes them.
184
+ */
185
+ export function toggleGroupDisabled(
186
+ group: McpConnectionGroup,
187
+ disabled: string[] | undefined,
188
+ active: boolean,
189
+ ): string[] {
190
+ const current = new Set(disabled ?? []);
191
+ if (active) {
192
+ for (const id of group.memberIds) current.delete(id);
193
+ } else {
194
+ for (const id of group.memberIds) current.add(id);
195
+ }
196
+ return Array.from(current);
197
+ }
198
+
199
+ /** Count connected MCP groups that are enabled for the current conversation. */
200
+ export function countConnectedActiveGroups(groups: McpConnectionGroup[], disabled?: string[]): number {
201
+ return groups.filter((group) => group.authStatus?.authenticated === true && !isGroupDisabled(group, disabled))
202
+ .length;
203
+ }
204
+
205
+ /** Names of connected MCP groups that are enabled for the current conversation. */
206
+ export function getConnectedActiveGroupLabels(groups: McpConnectionGroup[], disabled?: string[]): string[] {
207
+ return groups
208
+ .filter((group) => group.authStatus?.authenticated === true && !isGroupDisabled(group, disabled))
209
+ .map((group) => group.label);
210
+ }