@vertesia/ui 1.4.0-dev.20260615.042549Z → 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.
- package/lib/core/components/shadcn/dropdown.d.ts.map +1 -1
- package/lib/core/components/shadcn/dropdown.js +6 -2
- package/lib/core/components/shadcn/dropdown.js.map +1 -1
- package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filterBar.js +9 -2
- package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/core/components/shadcn/modal/ConfirmModal.d.ts +16 -1
- package/lib/core/components/shadcn/modal/ConfirmModal.d.ts.map +1 -1
- package/lib/core/components/shadcn/modal/ConfirmModal.js +25 -3
- package/lib/core/components/shadcn/modal/ConfirmModal.js.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.js +1 -1
- package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
- package/lib/core/components/shadcn/popover.d.ts.map +1 -1
- package/lib/core/components/shadcn/popover.js +3 -1
- package/lib/core/components/shadcn/popover.js.map +1 -1
- package/lib/core/components/shadcn/switch.js +3 -3
- package/lib/core/components/shadcn/switch.js.map +1 -1
- package/lib/core/components/shadcn/tabs.js +1 -1
- package/lib/core/components/shadcn/tabs.js.map +1 -1
- package/lib/core/components/shadcn/tooltip.d.ts.map +1 -1
- package/lib/core/components/shadcn/tooltip.js +3 -1
- package/lib/core/components/shadcn/tooltip.js.map +1 -1
- package/lib/env/index.d.ts +0 -19
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +0 -6
- package/lib/env/index.js.map +1 -1
- package/lib/features/agent/PayloadBuilder.d.ts +4 -0
- package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
- package/lib/features/agent/PayloadBuilder.js +16 -0
- package/lib/features/agent/PayloadBuilder.js.map +1 -1
- package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts +10 -0
- package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts.map +1 -0
- package/lib/features/agent/chat/AgentApprovalModeSelector.js +50 -0
- package/lib/features/agent/chat/AgentApprovalModeSelector.js.map +1 -0
- package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts +2 -1
- package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentChatFixtureReplay.js +3 -3
- package/lib/features/agent/chat/AgentChatFixtureReplay.js.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +5 -2
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.js +41 -7
- package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.js +133 -12
- package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/features/agent/chat/AnimatedThinkingDots.js +1 -1
- package/lib/features/agent/chat/AnimatedThinkingDots.js.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js +11 -65
- package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts +3 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.js +4 -3
- package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.d.ts +10 -2
- package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +526 -117
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts +8 -0
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +19 -0
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -2
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +551 -92
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +7 -6
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.js +2 -2
- package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts +8 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js +61 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +15 -2
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +28 -38
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -2
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +2 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts +5 -0
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +59 -4
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +2 -2
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +9 -0
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +180 -0
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.js +92 -2
- package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
- package/lib/features/agent/chat/clipboardFiles.d.ts +15 -0
- package/lib/features/agent/chat/clipboardFiles.d.ts.map +1 -0
- package/lib/features/agent/chat/clipboardFiles.js +35 -0
- package/lib/features/agent/chat/clipboardFiles.js.map +1 -0
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts +6 -0
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.js +218 -37
- package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/features/agent/chat/hooks/useArtifacts.d.ts +1 -8
- package/lib/features/agent/chat/hooks/useArtifacts.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useArtifacts.js +10 -28
- package/lib/features/agent/chat/hooks/useArtifacts.js.map +1 -1
- package/lib/features/agent/chat/index.d.ts +2 -1
- package/lib/features/agent/chat/index.d.ts.map +1 -1
- package/lib/features/agent/chat/index.js +2 -1
- package/lib/features/agent/chat/index.js.map +1 -1
- package/lib/features/agent/chat/workstreams.d.ts +1 -0
- package/lib/features/agent/chat/workstreams.d.ts.map +1 -1
- package/lib/features/agent/chat/workstreams.js +28 -0
- package/lib/features/agent/chat/workstreams.js.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts +10 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.js +6 -3
- package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.d.ts +10 -1
- package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.js +14 -5
- package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts +10 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.js +14 -5
- package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
- package/lib/features/facets/RunsFacetsNav.d.ts +10 -1
- package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/RunsFacetsNav.js +14 -5
- package/lib/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/features/index.d.ts +0 -1
- package/lib/features/index.d.ts.map +1 -1
- package/lib/features/index.js +0 -1
- package/lib/features/index.js.map +1 -1
- package/lib/features/oauth/McpConnectionsButton.d.ts +30 -0
- package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -0
- package/lib/features/oauth/McpConnectionsButton.js +70 -0
- package/lib/features/oauth/McpConnectionsButton.js.map +1 -0
- package/lib/features/oauth/McpConnectionsDialog.d.ts +25 -0
- package/lib/features/oauth/McpConnectionsDialog.d.ts.map +1 -0
- package/lib/features/oauth/McpConnectionsDialog.js +26 -0
- package/lib/features/oauth/McpConnectionsDialog.js.map +1 -0
- package/lib/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -1
- package/lib/features/oauth/RemoteMcpConnectionButton.js +14 -6
- package/lib/features/oauth/RemoteMcpConnectionButton.js.map +1 -1
- package/lib/features/oauth/index.d.ts +3 -0
- package/lib/features/oauth/index.d.ts.map +1 -1
- package/lib/features/oauth/index.js +3 -0
- package/lib/features/oauth/index.js.map +1 -1
- package/lib/features/oauth/useMcpConnections.d.ts +44 -0
- package/lib/features/oauth/useMcpConnections.d.ts.map +1 -0
- package/lib/features/oauth/useMcpConnections.js +168 -0
- package/lib/features/oauth/useMcpConnections.js.map +1 -0
- package/lib/features/permissions/UserPermissionsProvider.d.ts +4 -6
- package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
- package/lib/features/permissions/UserPermissionsProvider.js +40 -42
- package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
- package/lib/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentPreviewPanel.js +2 -1
- package/lib/features/store/objects/DocumentPreviewPanel.js.map +1 -1
- package/lib/features/store/objects/DocumentQuickFilter.d.ts +23 -0
- package/lib/features/store/objects/DocumentQuickFilter.d.ts.map +1 -0
- package/lib/features/store/objects/DocumentQuickFilter.js +30 -0
- package/lib/features/store/objects/DocumentQuickFilter.js.map +1 -0
- package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentSearchResults.js +17 -1
- package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +17 -74
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +7 -1
- package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
- package/lib/features/store/objects/layout/DocumentTableColumn.js +27 -3
- package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
- package/lib/features/store/objects/layout/documentLayout.js +1 -1
- package/lib/features/store/objects/layout/renderers.d.ts +2 -1
- package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/features/store/objects/layout/renderers.js +27 -20
- package/lib/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesSearch.js +4 -1
- package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts +2 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.js +8 -3
- package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/i18n/instance.d.ts.map +1 -1
- package/lib/i18n/instance.js +1 -0
- package/lib/i18n/instance.js.map +1 -1
- package/lib/i18n/locales/ar.json +72 -45
- package/lib/i18n/locales/de.json +65 -34
- package/lib/i18n/locales/en.json +63 -47
- package/lib/i18n/locales/es.json +65 -35
- package/lib/i18n/locales/fr.json +65 -35
- package/lib/i18n/locales/it.json +72 -42
- package/lib/i18n/locales/ja.json +72 -41
- package/lib/i18n/locales/ko.json +72 -41
- package/lib/i18n/locales/pt.json +72 -42
- package/lib/i18n/locales/ru.json +72 -43
- package/lib/i18n/locales/tr.json +72 -41
- package/lib/i18n/locales/zh-TW.json +72 -41
- package/lib/i18n/locales/zh.json +72 -41
- package/lib/session/UserSession.d.ts +0 -6
- package/lib/session/UserSession.d.ts.map +1 -1
- package/lib/session/UserSession.js +0 -15
- package/lib/session/UserSession.js.map +1 -1
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +39 -98
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +3 -33
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
- package/lib/shell/login/SignInPrimitives.js +3 -2
- package/lib/shell/login/SignInPrimitives.js.map +1 -1
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +1 -1
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +1 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/lib/widgets/schema-editor/editor/Editable.js +1 -1
- package/lib/widgets/schema-editor/editor/Editable.js.map +1 -1
- package/llms.txt +70 -70
- package/package.json +35 -32
- package/src/core/components/shadcn/dropdown.tsx +2 -0
- package/src/core/components/shadcn/filters/filterBar.tsx +9 -2
- package/src/core/components/shadcn/modal/ConfirmModal.tsx +65 -3
- package/src/core/components/shadcn/modal/dialog.tsx +1 -1
- package/src/core/components/shadcn/popover.tsx +1 -0
- package/src/core/components/shadcn/switch.tsx +4 -4
- package/src/core/components/shadcn/tabs.tsx +1 -1
- package/src/core/components/shadcn/tooltip.tsx +1 -0
- package/src/env/index.ts +0 -24
- package/src/features/agent/PayloadBuilder.tsx +18 -0
- package/src/features/agent/chat/AgentApprovalModeSelector.tsx +130 -0
- package/src/features/agent/chat/AgentChatFixtureReplay.test.tsx +22 -2
- package/src/features/agent/chat/AgentChatFixtureReplay.tsx +33 -27
- package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +122 -0
- package/src/features/agent/chat/AgentRequestInputOverlay.tsx +91 -17
- package/src/features/agent/chat/AgentRightPanel.tsx +238 -50
- package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -1
- package/src/features/agent/chat/ArtifactsTab.tsx +21 -155
- package/src/features/agent/chat/AskUserWidget.tsx +6 -2
- package/src/features/agent/chat/ModernAgentConversation.test.tsx +1157 -47
- package/src/features/agent/chat/ModernAgentConversation.tsx +703 -136
- package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +74 -0
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +1420 -126
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +934 -111
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +31 -40
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +28 -28
- package/src/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.tsx +83 -0
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +38 -2
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +121 -98
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +7 -1
- package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +3 -3
- package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +82 -2
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +2 -2
- package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +216 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +149 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.ts +103 -2
- package/src/features/agent/chat/clipboardFiles.ts +33 -0
- package/src/features/agent/chat/hooks/useAgentStream.test.tsx +355 -4
- package/src/features/agent/chat/hooks/useAgentStream.ts +270 -43
- package/src/features/agent/chat/hooks/useArtifacts.ts +11 -44
- package/src/features/agent/chat/index.ts +10 -1
- package/src/features/agent/chat/workstreams.ts +42 -0
- package/src/features/facets/AgentRunnerFacetsNav.tsx +23 -3
- package/src/features/facets/CollectionsFacetsNav.tsx +30 -5
- package/src/features/facets/PromptsFacetsNav.tsx +30 -5
- package/src/features/facets/RunsFacetsNav.tsx +32 -5
- package/src/features/index.ts +0 -1
- package/src/features/oauth/McpConnectionsButton.test.tsx +248 -0
- package/src/features/oauth/McpConnectionsButton.tsx +269 -0
- package/src/features/oauth/McpConnectionsDialog.tsx +142 -0
- package/src/features/oauth/RemoteMcpConnectionButton.tsx +37 -14
- package/src/features/oauth/index.ts +3 -0
- package/src/features/oauth/useMcpConnections.test.ts +94 -0
- package/src/features/oauth/useMcpConnections.ts +210 -0
- package/src/features/permissions/UserPermissionsProvider.tsx +41 -59
- package/src/features/store/objects/DocumentPreviewPanel.tsx +4 -2
- package/src/features/store/objects/DocumentQuickFilter.tsx +72 -0
- package/src/features/store/objects/DocumentSearchResults.tsx +30 -11
- package/src/features/store/objects/components/ContentOverview.tsx +30 -99
- package/src/features/store/objects/layout/DocumentTableColumn.tsx +29 -4
- package/src/features/store/objects/layout/documentLayout.tsx +1 -1
- package/src/features/store/objects/layout/renderers.tsx +80 -20
- package/src/features/store/types/ContentObjectTypesSearch.tsx +7 -1
- package/src/features/store/types/ContentObjectTypesTable.tsx +34 -4
- package/src/i18n/instance.ts +1 -0
- package/src/i18n/locales/ar.json +72 -45
- package/src/i18n/locales/de.json +65 -34
- package/src/i18n/locales/en.json +63 -47
- package/src/i18n/locales/es.json +65 -35
- package/src/i18n/locales/fr.json +65 -35
- package/src/i18n/locales/it.json +72 -42
- package/src/i18n/locales/ja.json +72 -41
- package/src/i18n/locales/ko.json +72 -41
- package/src/i18n/locales/pt.json +72 -42
- package/src/i18n/locales/ru.json +72 -43
- package/src/i18n/locales/tr.json +72 -41
- package/src/i18n/locales/zh-TW.json +72 -41
- package/src/i18n/locales/zh.json +72 -41
- package/src/i18n/rtl.test.ts +57 -1
- package/src/session/UserSession.ts +0 -16
- package/src/session/UserSessionProvider.tsx +51 -123
- package/src/session/auth/composable.ts +3 -34
- package/src/shell/login/SignInPrimitives.tsx +3 -2
- package/src/widgets/schema-editor/editor/Editable.tsx +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts +0 -73
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +0 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.js +0 -415
- package/lib/features/document-viewer/UniversalDocumentViewer.js.map +0 -1
- package/lib/features/document-viewer/index.d.ts +0 -2
- package/lib/features/document-viewer/index.d.ts.map +0 -1
- package/lib/features/document-viewer/index.js +0 -2
- package/lib/features/document-viewer/index.js.map +0 -1
- package/src/features/document-viewer/UniversalDocumentViewer.test.tsx +0 -123
- package/src/features/document-viewer/UniversalDocumentViewer.tsx +0 -746
- package/src/features/document-viewer/index.ts +0 -1
- package/src/session/auth/composable.test.ts +0 -79
|
@@ -17,6 +17,15 @@ interface CollectionsFacetsNavProps {
|
|
|
17
17
|
dynamic?: FacetBucket[];
|
|
18
18
|
};
|
|
19
19
|
search: SearchInterface;
|
|
20
|
+
/**
|
|
21
|
+
* Optional controlled filter state. When provided, the parent owns the filter list (and is
|
|
22
|
+
* responsible for translating it into the search query via {@link useCollectionsFilterHandler}).
|
|
23
|
+
* This lets other surfaces — e.g. per-row "quick filter" buttons in the table — add filters that
|
|
24
|
+
* show up in the filter bar. When omitted, the component manages its own filter state internally.
|
|
25
|
+
*/
|
|
26
|
+
filters?: BaseFilter[];
|
|
27
|
+
setFilters?: React.Dispatch<React.SetStateAction<BaseFilter[]>>;
|
|
28
|
+
filterGroups?: FilterGroup[];
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
// Hook to create filter groups for collections
|
|
@@ -85,14 +94,30 @@ export function useCollectionsFilterHandler(search: SearchInterface) {
|
|
|
85
94
|
}
|
|
86
95
|
|
|
87
96
|
// Component for collections filtering
|
|
88
|
-
export function CollectionsFacetsNav({
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
export function CollectionsFacetsNav({
|
|
98
|
+
facets,
|
|
99
|
+
search,
|
|
100
|
+
filters: controlledFilters,
|
|
101
|
+
setFilters: controlledSetFilters,
|
|
102
|
+
filterGroups: controlledFilterGroups,
|
|
103
|
+
}: CollectionsFacetsNavProps) {
|
|
104
|
+
const [internalFilters, setInternalFilters] = useState<BaseFilter[]>([]);
|
|
105
|
+
const internalFilterGroups = useCollectionsFilterGroups(facets);
|
|
91
106
|
const handleFilterLogic = useCollectionsFilterHandler(search);
|
|
92
107
|
|
|
108
|
+
// Controlled when the parent supplies both the filter list and its setter; otherwise self-managed.
|
|
109
|
+
const isControlled = controlledFilters !== undefined && controlledSetFilters !== undefined;
|
|
110
|
+
const filters = isControlled ? controlledFilters : internalFilters;
|
|
111
|
+
const filterGroups = controlledFilterGroups ?? internalFilterGroups;
|
|
112
|
+
|
|
93
113
|
const handleFilterChange: React.Dispatch<React.SetStateAction<BaseFilter[]>> = (value) => {
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
if (isControlled) {
|
|
115
|
+
// The parent's setter is expected to also run the filter→query translation.
|
|
116
|
+
controlledSetFilters(value);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const newFilters = typeof value === 'function' ? value(internalFilters) : value;
|
|
120
|
+
setInternalFilters(newFilters);
|
|
96
121
|
handleFilterLogic(newFilters);
|
|
97
122
|
};
|
|
98
123
|
|
|
@@ -17,6 +17,15 @@ interface PromptsFacetsNavProps {
|
|
|
17
17
|
tags?: FacetBucket[];
|
|
18
18
|
};
|
|
19
19
|
search: SearchInterface;
|
|
20
|
+
/**
|
|
21
|
+
* Optional controlled filter state. When provided, the parent owns the filter list (and is
|
|
22
|
+
* responsible for translating it into the search query via {@link usePromptsFilterHandler}). This
|
|
23
|
+
* lets other surfaces — e.g. per-row "quick filter" buttons in the table — add filters that show
|
|
24
|
+
* up in the filter bar. When omitted, the component manages its own filter state internally.
|
|
25
|
+
*/
|
|
26
|
+
filters?: BaseFilter[];
|
|
27
|
+
setFilters?: React.Dispatch<React.SetStateAction<BaseFilter[]>>;
|
|
28
|
+
filterGroups?: FilterGroup[];
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
// Hook to create filter groups for prompts
|
|
@@ -76,14 +85,30 @@ export function usePromptsFilterHandler(search: SearchInterface) {
|
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
// Component for prompts filtering
|
|
79
|
-
export function PromptsFacetsNav({
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
export function PromptsFacetsNav({
|
|
89
|
+
facets,
|
|
90
|
+
search,
|
|
91
|
+
filters: controlledFilters,
|
|
92
|
+
setFilters: controlledSetFilters,
|
|
93
|
+
filterGroups: controlledFilterGroups,
|
|
94
|
+
}: PromptsFacetsNavProps) {
|
|
95
|
+
const [internalFilters, setInternalFilters] = useState<BaseFilter[]>([]);
|
|
96
|
+
const internalFilterGroups = usePromptsFilterGroups(facets);
|
|
82
97
|
const handleFilterLogic = usePromptsFilterHandler(search);
|
|
83
98
|
|
|
99
|
+
// Controlled when the parent supplies both the filter list and its setter; otherwise self-managed.
|
|
100
|
+
const isControlled = controlledFilters !== undefined && controlledSetFilters !== undefined;
|
|
101
|
+
const filters = isControlled ? controlledFilters : internalFilters;
|
|
102
|
+
const filterGroups = controlledFilterGroups ?? internalFilterGroups;
|
|
103
|
+
|
|
84
104
|
const handleFilterChange: React.Dispatch<React.SetStateAction<BaseFilter[]>> = (value) => {
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
if (isControlled) {
|
|
106
|
+
// The parent's setter is expected to also run the filter→query translation.
|
|
107
|
+
controlledSetFilters(value);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const newFilters = typeof value === 'function' ? value(internalFilters) : value;
|
|
111
|
+
setInternalFilters(newFilters);
|
|
87
112
|
handleFilterLogic(newFilters);
|
|
88
113
|
};
|
|
89
114
|
|
|
@@ -31,6 +31,15 @@ interface RunsFacetsNavProps {
|
|
|
31
31
|
search: SearchInterface;
|
|
32
32
|
actions?: React.ReactNode[];
|
|
33
33
|
selectionCount?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Optional controlled filter state. When provided, the parent owns the filter list (and is
|
|
36
|
+
* responsible for translating it into the search query via {@link useRunsFilterHandler}). This
|
|
37
|
+
* lets other surfaces — e.g. per-row "quick filter" buttons in the table — add filters that show
|
|
38
|
+
* up in the filter bar. When omitted, the component manages its own filter state internally.
|
|
39
|
+
*/
|
|
40
|
+
filters?: BaseFilter[];
|
|
41
|
+
setFilters?: React.Dispatch<React.SetStateAction<BaseFilter[]>>;
|
|
42
|
+
filterGroups?: FilterGroup[];
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
// Hook to create filter groups for runs
|
|
@@ -179,14 +188,32 @@ export function useRunsFilterHandler(search: SearchInterface) {
|
|
|
179
188
|
}
|
|
180
189
|
|
|
181
190
|
// Legacy component for backward compatibility
|
|
182
|
-
export function RunsFacetsNav({
|
|
183
|
-
|
|
184
|
-
|
|
191
|
+
export function RunsFacetsNav({
|
|
192
|
+
facets,
|
|
193
|
+
search,
|
|
194
|
+
actions,
|
|
195
|
+
selectionCount,
|
|
196
|
+
filters: controlledFilters,
|
|
197
|
+
setFilters: controlledSetFilters,
|
|
198
|
+
filterGroups: controlledFilterGroups,
|
|
199
|
+
}: RunsFacetsNavProps) {
|
|
200
|
+
const [internalFilters, setInternalFilters] = useState<BaseFilter[]>([]);
|
|
201
|
+
const internalFilterGroups = useRunsFilterGroups(facets);
|
|
185
202
|
const handleFilterLogic = useRunsFilterHandler(search);
|
|
186
203
|
|
|
204
|
+
// Controlled when the parent supplies both the filter list and its setter; otherwise self-managed.
|
|
205
|
+
const isControlled = controlledFilters !== undefined && controlledSetFilters !== undefined;
|
|
206
|
+
const filters = isControlled ? controlledFilters : internalFilters;
|
|
207
|
+
const filterGroups = controlledFilterGroups ?? internalFilterGroups;
|
|
208
|
+
|
|
187
209
|
const handleFilterChange: React.Dispatch<React.SetStateAction<BaseFilter[]>> = (value) => {
|
|
188
|
-
|
|
189
|
-
|
|
210
|
+
if (isControlled) {
|
|
211
|
+
// The parent's setter is expected to also run the filter→query translation.
|
|
212
|
+
controlledSetFilters(value);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const newFilters = typeof value === 'function' ? value(internalFilters) : value;
|
|
216
|
+
setInternalFilters(newFilters);
|
|
190
217
|
handleFilterLogic(newFilters);
|
|
191
218
|
};
|
|
192
219
|
|
package/src/features/index.ts
CHANGED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { renderWithProviders } from '../../__tests__/test-utils.js';
|
|
4
|
+
import { McpConnectionsActionMenu, McpConnectionsInlineList } from './McpConnectionsButton.js';
|
|
5
|
+
|
|
6
|
+
const mocks = vi.hoisted(() => ({
|
|
7
|
+
getCollectionStatus: vi.fn(),
|
|
8
|
+
getInstalledApps: vi.fn(),
|
|
9
|
+
getStatus: vi.fn(),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
const mockClient = {
|
|
13
|
+
apps: {
|
|
14
|
+
getInstalledApps: mocks.getInstalledApps,
|
|
15
|
+
},
|
|
16
|
+
remoteMcpConnections: {
|
|
17
|
+
getCollectionStatus: mocks.getCollectionStatus,
|
|
18
|
+
getStatus: mocks.getStatus,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
vi.mock('@vertesia/ui/session', () => ({
|
|
23
|
+
useUserSession: () => ({
|
|
24
|
+
client: mockClient,
|
|
25
|
+
}),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
function deferred<T>() {
|
|
29
|
+
let resolve!: (value: T) => void;
|
|
30
|
+
let reject!: (reason?: unknown) => void;
|
|
31
|
+
const promise = new Promise<T>((res, rej) => {
|
|
32
|
+
resolve = res;
|
|
33
|
+
reject = rej;
|
|
34
|
+
});
|
|
35
|
+
return { promise, resolve, reject };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('MCP connection controls', () => {
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
vi.clearAllMocks();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('shows available MCP servers and their connection and availability state inline', async () => {
|
|
44
|
+
mocks.getInstalledApps.mockResolvedValue([
|
|
45
|
+
{
|
|
46
|
+
id: 'app-1',
|
|
47
|
+
manifest: {
|
|
48
|
+
name: 'mcp-app',
|
|
49
|
+
title: 'MCP App',
|
|
50
|
+
oauth_providers: {},
|
|
51
|
+
tool_collections: [
|
|
52
|
+
{
|
|
53
|
+
type: 'mcp',
|
|
54
|
+
id: 'jira',
|
|
55
|
+
name: 'Jira',
|
|
56
|
+
namespace: 'jira',
|
|
57
|
+
url: 'https://jira-mcp.example.com',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: 'mcp',
|
|
61
|
+
id: 'miro',
|
|
62
|
+
name: 'Miro',
|
|
63
|
+
namespace: 'miro',
|
|
64
|
+
url: 'https://miro-mcp.example.com',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'mcp',
|
|
68
|
+
id: 'linear',
|
|
69
|
+
name: 'Linear',
|
|
70
|
+
namespace: 'linear',
|
|
71
|
+
url: 'https://linear-mcp.example.com',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: 'mcp',
|
|
75
|
+
id: 'github',
|
|
76
|
+
name: 'GitHub',
|
|
77
|
+
namespace: 'github',
|
|
78
|
+
url: 'https://github-mcp.example.com',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
oauth_collection_ids: ['jira', 'miro', 'linear', 'github'],
|
|
83
|
+
},
|
|
84
|
+
]);
|
|
85
|
+
mocks.getStatus.mockResolvedValue([
|
|
86
|
+
{
|
|
87
|
+
authenticated: true,
|
|
88
|
+
collection_id: 'jira',
|
|
89
|
+
collection_name: 'Jira',
|
|
90
|
+
mcp_server_url: 'https://jira-mcp.example.com',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
authenticated: true,
|
|
94
|
+
collection_id: 'miro',
|
|
95
|
+
collection_name: 'Miro',
|
|
96
|
+
mcp_server_url: 'https://miro-mcp.example.com',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
authenticated: true,
|
|
100
|
+
collection_id: 'linear',
|
|
101
|
+
collection_name: 'Linear',
|
|
102
|
+
mcp_server_url: 'https://linear-mcp.example.com',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
authenticated: false,
|
|
106
|
+
collection_id: 'github',
|
|
107
|
+
collection_name: 'GitHub',
|
|
108
|
+
mcp_server_url: 'https://github-mcp.example.com',
|
|
109
|
+
},
|
|
110
|
+
]);
|
|
111
|
+
const onChange = vi.fn();
|
|
112
|
+
|
|
113
|
+
renderWithProviders(<McpConnectionsInlineList disabledCollections={['linear']} onChange={onChange} />);
|
|
114
|
+
|
|
115
|
+
await screen.findByText('Jira');
|
|
116
|
+
await waitFor(() => expect(mocks.getStatus).toHaveBeenCalledTimes(1));
|
|
117
|
+
|
|
118
|
+
expect(screen.getByText('Miro')).not.toBeNull();
|
|
119
|
+
expect(screen.getByText('Linear')).not.toBeNull();
|
|
120
|
+
expect(screen.getByText('GitHub')).not.toBeNull();
|
|
121
|
+
expect(screen.queryByText('Connected')).toBeNull();
|
|
122
|
+
expect(screen.getAllByRole('button', { name: 'Disconnect' })).toHaveLength(3);
|
|
123
|
+
const connectButton = screen.getByRole('button', { name: 'Connect' });
|
|
124
|
+
const disconnectButton = screen.getAllByRole('button', { name: 'Disconnect' })[0];
|
|
125
|
+
expect(connectButton.className).toContain('w-32');
|
|
126
|
+
expect(disconnectButton.className).toContain('w-32');
|
|
127
|
+
expect(screen.getAllByText('Enabled')).toHaveLength(3);
|
|
128
|
+
expect(screen.getByText('Disabled')).not.toBeNull();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('renders MCP rows before connection statuses finish loading', async () => {
|
|
132
|
+
const statusRequest =
|
|
133
|
+
deferred<
|
|
134
|
+
Array<{
|
|
135
|
+
authenticated: boolean;
|
|
136
|
+
collection_id: string;
|
|
137
|
+
collection_name: string;
|
|
138
|
+
mcp_server_url: string;
|
|
139
|
+
}>
|
|
140
|
+
>();
|
|
141
|
+
mocks.getInstalledApps.mockResolvedValue([
|
|
142
|
+
{
|
|
143
|
+
id: 'app-1',
|
|
144
|
+
manifest: {
|
|
145
|
+
name: 'jira-app',
|
|
146
|
+
title: 'Jira App',
|
|
147
|
+
oauth_providers: {},
|
|
148
|
+
tool_collections: [
|
|
149
|
+
{
|
|
150
|
+
type: 'mcp',
|
|
151
|
+
id: 'jira',
|
|
152
|
+
name: 'Jira',
|
|
153
|
+
namespace: 'jira',
|
|
154
|
+
url: 'https://jira-mcp.example.com',
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
oauth_collection_ids: ['jira'],
|
|
159
|
+
},
|
|
160
|
+
]);
|
|
161
|
+
mocks.getStatus.mockReturnValue(statusRequest.promise);
|
|
162
|
+
|
|
163
|
+
renderWithProviders(<McpConnectionsInlineList onChange={vi.fn()} />);
|
|
164
|
+
|
|
165
|
+
expect(await screen.findByText('Jira')).not.toBeNull();
|
|
166
|
+
const checkingButton = screen.getByRole('button', { name: 'Checking status' });
|
|
167
|
+
expect((checkingButton as HTMLButtonElement).disabled).toBe(true);
|
|
168
|
+
expect(checkingButton.className).toContain('w-32');
|
|
169
|
+
expect(mocks.getCollectionStatus).not.toHaveBeenCalled();
|
|
170
|
+
|
|
171
|
+
await act(async () => {
|
|
172
|
+
statusRequest.resolve([
|
|
173
|
+
{
|
|
174
|
+
authenticated: true,
|
|
175
|
+
collection_id: 'jira',
|
|
176
|
+
collection_name: 'Jira',
|
|
177
|
+
mcp_server_url: 'https://jira-mcp.example.com',
|
|
178
|
+
},
|
|
179
|
+
]);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
await waitFor(() => expect(screen.getByRole('button', { name: 'Disconnect' })).not.toBeNull());
|
|
183
|
+
expect(screen.queryByText('Connected')).toBeNull();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('renders MCP in a separate slash action menu', async () => {
|
|
187
|
+
mocks.getInstalledApps.mockResolvedValue([
|
|
188
|
+
{
|
|
189
|
+
id: 'app-1',
|
|
190
|
+
manifest: {
|
|
191
|
+
name: 'jira-app',
|
|
192
|
+
title: 'Jira',
|
|
193
|
+
oauth_providers: {},
|
|
194
|
+
tool_collections: [
|
|
195
|
+
{
|
|
196
|
+
type: 'mcp',
|
|
197
|
+
id: 'jira',
|
|
198
|
+
name: 'Jira',
|
|
199
|
+
namespace: 'jira',
|
|
200
|
+
url: 'https://mcp.example.com',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
type: 'mcp',
|
|
204
|
+
id: 'github',
|
|
205
|
+
name: 'GitHub',
|
|
206
|
+
namespace: 'github',
|
|
207
|
+
url: 'https://github-mcp.example.com',
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
},
|
|
211
|
+
oauth_collection_ids: ['jira', 'github'],
|
|
212
|
+
},
|
|
213
|
+
]);
|
|
214
|
+
mocks.getStatus.mockResolvedValue([
|
|
215
|
+
{
|
|
216
|
+
authenticated: true,
|
|
217
|
+
collection_id: 'jira',
|
|
218
|
+
collection_name: 'Jira',
|
|
219
|
+
mcp_server_url: 'https://mcp.example.com',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
authenticated: false,
|
|
223
|
+
collection_id: 'github',
|
|
224
|
+
collection_name: 'GitHub',
|
|
225
|
+
mcp_server_url: 'https://github-mcp.example.com',
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
|
|
229
|
+
renderWithProviders(<McpConnectionsActionMenu />);
|
|
230
|
+
|
|
231
|
+
const trigger = await screen.findByRole('button', { name: /settings/i });
|
|
232
|
+
await waitFor(() => expect(mocks.getStatus).toHaveBeenCalledTimes(1));
|
|
233
|
+
expect(mocks.getStatus).toHaveBeenCalledWith('app-1');
|
|
234
|
+
expect(trigger.textContent).toBe('/');
|
|
235
|
+
|
|
236
|
+
fireEvent.pointerDown(trigger);
|
|
237
|
+
|
|
238
|
+
const menuItem = await screen.findByText('MCP');
|
|
239
|
+
expect(menuItem).not.toBeNull();
|
|
240
|
+
expect(screen.getByText('1')).not.toBeNull();
|
|
241
|
+
|
|
242
|
+
fireEvent.click(menuItem);
|
|
243
|
+
|
|
244
|
+
await waitFor(() => {
|
|
245
|
+
expect(screen.getByText('Manage the MCP servers available to this conversation.')).not.toBeNull();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { useUITranslation } from '@vertesia/ui/i18n';
|
|
2
|
+
import { Link2, Link2Off } from 'lucide-react';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Badge, Button, Dropdown, MenuItem, Spinner, Switch, VTooltip } from '../../core/index.js';
|
|
5
|
+
import { McpConnectionsDialog } from './McpConnectionsDialog.js';
|
|
6
|
+
import { RemoteMcpConnectionButton } from './RemoteMcpConnectionButton.js';
|
|
7
|
+
import {
|
|
8
|
+
countConnectedActiveGroups,
|
|
9
|
+
getConnectedActiveGroupLabels,
|
|
10
|
+
isGroupDisabled,
|
|
11
|
+
toggleGroupDisabled,
|
|
12
|
+
useMcpConnections,
|
|
13
|
+
} from './useMcpConnections.js';
|
|
14
|
+
|
|
15
|
+
export interface McpConnectionsButtonProps {
|
|
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
|
+
/** Button visual style. */
|
|
25
|
+
variant?: 'primary' | 'outline' | 'ghost' | 'secondary';
|
|
26
|
+
size?: 'xs' | 'sm' | 'md';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Toolbar button that opens the MCP connections dialog. The badge shows how many MCP
|
|
31
|
+
* servers are connected and active for this conversation.
|
|
32
|
+
* Renders nothing when the project has no OAuth MCP servers installed.
|
|
33
|
+
*/
|
|
34
|
+
export function McpConnectionsButton({
|
|
35
|
+
disabledCollections,
|
|
36
|
+
onChange,
|
|
37
|
+
onConnectionChange,
|
|
38
|
+
readOnly = false,
|
|
39
|
+
variant = 'outline',
|
|
40
|
+
size = 'sm',
|
|
41
|
+
}: McpConnectionsButtonProps) {
|
|
42
|
+
const { t } = useUITranslation();
|
|
43
|
+
const { groups, loading, statusLoading, reload } = useMcpConnections();
|
|
44
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
45
|
+
|
|
46
|
+
if (!loading && groups.length === 0) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const activeCount = countConnectedActiveGroups(groups, disabledCollections);
|
|
51
|
+
const activeLabels = getConnectedActiveGroupLabels(groups, disabledCollections);
|
|
52
|
+
const visibleLabels = activeLabels.slice(0, 2);
|
|
53
|
+
const hiddenLabelCount = activeLabels.length - visibleLabels.length;
|
|
54
|
+
const summary =
|
|
55
|
+
visibleLabels.length > 0
|
|
56
|
+
? `${visibleLabels.join(', ')}${hiddenLabelCount > 0 ? ` +${hiddenLabelCount}` : ''}`
|
|
57
|
+
: undefined;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<>
|
|
61
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
62
|
+
{summary && (
|
|
63
|
+
<span className="max-w-48 truncate text-muted" title={activeLabels.join(', ')}>
|
|
64
|
+
{summary}
|
|
65
|
+
</span>
|
|
66
|
+
)}
|
|
67
|
+
<Button
|
|
68
|
+
variant={variant}
|
|
69
|
+
size={size}
|
|
70
|
+
className="shrink-0"
|
|
71
|
+
onClick={() => setIsOpen(true)}
|
|
72
|
+
disabled={loading}
|
|
73
|
+
aria-label={t('mcpConnections.manage')}
|
|
74
|
+
>
|
|
75
|
+
<span>{t('mcpConnections.label')}</span>
|
|
76
|
+
{activeCount > 0 && <Badge variant="success">{activeCount}</Badge>}
|
|
77
|
+
</Button>
|
|
78
|
+
</div>
|
|
79
|
+
<McpConnectionsDialog
|
|
80
|
+
isOpen={isOpen}
|
|
81
|
+
onClose={() => setIsOpen(false)}
|
|
82
|
+
groups={groups}
|
|
83
|
+
loading={loading}
|
|
84
|
+
reload={reload}
|
|
85
|
+
statusLoading={statusLoading}
|
|
86
|
+
disabledCollections={disabledCollections}
|
|
87
|
+
onChange={onChange}
|
|
88
|
+
onConnectionChange={onConnectionChange}
|
|
89
|
+
readOnly={readOnly}
|
|
90
|
+
/>
|
|
91
|
+
</>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Inline MCP status list for forms. It shows all available OAuth MCP groups
|
|
97
|
+
* without requiring the user to open the management dialog.
|
|
98
|
+
*/
|
|
99
|
+
export function McpConnectionsInlineList({
|
|
100
|
+
disabledCollections,
|
|
101
|
+
onChange,
|
|
102
|
+
onConnectionChange,
|
|
103
|
+
readOnly = false,
|
|
104
|
+
}: Omit<McpConnectionsButtonProps, 'variant' | 'size'>) {
|
|
105
|
+
const { t } = useUITranslation();
|
|
106
|
+
const { groups, loading, statusLoading, reload } = useMcpConnections();
|
|
107
|
+
|
|
108
|
+
if (!loading && groups.length === 0) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const handleAuthChange = () => {
|
|
113
|
+
void reload();
|
|
114
|
+
onConnectionChange?.();
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
if (loading && groups.length === 0) {
|
|
118
|
+
return (
|
|
119
|
+
<div className="flex items-center gap-2 border-y border-border/70 py-2 text-sm text-muted">
|
|
120
|
+
<Spinner className="size-4" />
|
|
121
|
+
<span>{t('mcpConnections.label')}</span>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div className="space-y-1">
|
|
128
|
+
{groups.map((group) => {
|
|
129
|
+
const active = !isGroupDisabled(group, disabledCollections);
|
|
130
|
+
const connected = group.authStatus?.authenticated === true;
|
|
131
|
+
const StatusIcon = connected ? Link2 : Link2Off;
|
|
132
|
+
return (
|
|
133
|
+
<div key={group.key} className="flex flex-wrap items-center gap-x-3 gap-y-2 py-2 text-sm">
|
|
134
|
+
<div className="flex min-w-36 flex-1 items-center gap-2">
|
|
135
|
+
<StatusIcon
|
|
136
|
+
className={`size-4 shrink-0 ${connected ? 'text-success' : 'text-muted'}`}
|
|
137
|
+
aria-hidden="true"
|
|
138
|
+
/>
|
|
139
|
+
<VTooltip
|
|
140
|
+
description={
|
|
141
|
+
<div className="space-y-0.5">
|
|
142
|
+
<div className="font-medium">{group.appName}</div>
|
|
143
|
+
{group.memberNames.length > 1 && (
|
|
144
|
+
<div className="text-xs text-muted">{group.memberNames.join(' · ')}</div>
|
|
145
|
+
)}
|
|
146
|
+
</div>
|
|
147
|
+
}
|
|
148
|
+
placement="top"
|
|
149
|
+
asChild
|
|
150
|
+
>
|
|
151
|
+
<span
|
|
152
|
+
className={`block truncate ${active ? 'text-foreground' : 'text-muted line-through'}`}
|
|
153
|
+
>
|
|
154
|
+
{group.label}
|
|
155
|
+
</span>
|
|
156
|
+
</VTooltip>
|
|
157
|
+
</div>
|
|
158
|
+
{statusLoading && !group.authStatus ? (
|
|
159
|
+
<Button
|
|
160
|
+
variant="outline"
|
|
161
|
+
size="sm"
|
|
162
|
+
disabled
|
|
163
|
+
className="h-6 w-32 justify-center px-2 text-xs"
|
|
164
|
+
aria-label={t('mcpConnections.checkingStatus')}
|
|
165
|
+
title={t('mcpConnections.checkingStatus')}
|
|
166
|
+
>
|
|
167
|
+
<Spinner className="size-3" />
|
|
168
|
+
</Button>
|
|
169
|
+
) : (
|
|
170
|
+
<RemoteMcpConnectionButton
|
|
171
|
+
appId={group.appId}
|
|
172
|
+
collectionId={group.representativeId}
|
|
173
|
+
collectionName={group.label}
|
|
174
|
+
authenticated={group.authStatus?.authenticated}
|
|
175
|
+
onAuthChange={handleAuthChange}
|
|
176
|
+
variant="compact"
|
|
177
|
+
showDisconnect
|
|
178
|
+
readOnly={readOnly}
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
181
|
+
{onChange && (
|
|
182
|
+
<div className="flex min-w-24 items-center justify-end gap-2 text-xs">
|
|
183
|
+
<span className={active ? 'text-muted' : 'text-attention'}>
|
|
184
|
+
{active ? t('mcpConnections.enabled') : t('mcpConnections.disabled')}
|
|
185
|
+
</span>
|
|
186
|
+
<Switch
|
|
187
|
+
size="sm"
|
|
188
|
+
value={active}
|
|
189
|
+
onChange={(checked) =>
|
|
190
|
+
onChange(toggleGroupDisabled(group, disabledCollections, checked))
|
|
191
|
+
}
|
|
192
|
+
disabled={readOnly}
|
|
193
|
+
aria-label={
|
|
194
|
+
active
|
|
195
|
+
? t('mcpConnections.deactivateAria', { name: group.label })
|
|
196
|
+
: t('mcpConnections.activateAria', { name: group.label })
|
|
197
|
+
}
|
|
198
|
+
/>
|
|
199
|
+
</div>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
})}
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Compact composer action menu for MCP. The slash trigger keeps MCP out of the
|
|
210
|
+
* main composer toolbar while still exposing the connection dialog when relevant.
|
|
211
|
+
*/
|
|
212
|
+
export function McpConnectionsActionMenu({
|
|
213
|
+
disabledCollections,
|
|
214
|
+
onChange,
|
|
215
|
+
onConnectionChange,
|
|
216
|
+
readOnly = false,
|
|
217
|
+
}: Omit<McpConnectionsButtonProps, 'variant' | 'size'>) {
|
|
218
|
+
const { t } = useUITranslation();
|
|
219
|
+
const { groups, loading, statusLoading, reload } = useMcpConnections();
|
|
220
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
221
|
+
|
|
222
|
+
if (!loading && groups.length === 0) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const activeCount = countConnectedActiveGroups(groups, disabledCollections);
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<>
|
|
230
|
+
<Dropdown
|
|
231
|
+
align="left"
|
|
232
|
+
trigger={
|
|
233
|
+
<Button
|
|
234
|
+
variant="ghost"
|
|
235
|
+
size="icon"
|
|
236
|
+
className="size-8 rounded-md text-muted hover:bg-muted"
|
|
237
|
+
aria-label={t('mcpConnections.settings')}
|
|
238
|
+
title={t('mcpConnections.settings')}
|
|
239
|
+
disabled={loading}
|
|
240
|
+
>
|
|
241
|
+
<span
|
|
242
|
+
className="flex size-5 items-center justify-center rounded-[3px] border border-muted text-sm font-semibold leading-none"
|
|
243
|
+
aria-hidden="true"
|
|
244
|
+
>
|
|
245
|
+
/
|
|
246
|
+
</span>
|
|
247
|
+
</Button>
|
|
248
|
+
}
|
|
249
|
+
>
|
|
250
|
+
<MenuItem onClick={() => setIsOpen(true)} isDisabled={loading}>
|
|
251
|
+
<span>{t('mcpConnections.title')}</span>
|
|
252
|
+
{activeCount > 0 && <Badge variant="success">{activeCount}</Badge>}
|
|
253
|
+
</MenuItem>
|
|
254
|
+
</Dropdown>
|
|
255
|
+
<McpConnectionsDialog
|
|
256
|
+
isOpen={isOpen}
|
|
257
|
+
onClose={() => setIsOpen(false)}
|
|
258
|
+
groups={groups}
|
|
259
|
+
loading={loading}
|
|
260
|
+
reload={reload}
|
|
261
|
+
statusLoading={statusLoading}
|
|
262
|
+
disabledCollections={disabledCollections}
|
|
263
|
+
onChange={onChange}
|
|
264
|
+
onConnectionChange={onConnectionChange}
|
|
265
|
+
readOnly={readOnly}
|
|
266
|
+
/>
|
|
267
|
+
</>
|
|
268
|
+
);
|
|
269
|
+
}
|