@vertesia/ui 1.5.0-dev.20260807.073259Z → 1.5.0-dev.20260901.005903Z
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/README.md +1 -7
- package/lib/core/components/FormItem.d.ts.map +1 -1
- package/lib/core/components/FormItem.js +2 -3
- package/lib/core/components/FormItem.js.map +1 -1
- package/lib/core/components/InfoTip.d.ts +20 -0
- package/lib/core/components/InfoTip.d.ts.map +1 -0
- package/lib/core/components/InfoTip.js +18 -0
- package/lib/core/components/InfoTip.js.map +1 -0
- package/lib/core/components/index.d.ts +1 -0
- package/lib/core/components/index.d.ts.map +1 -1
- package/lib/core/components/index.js +1 -0
- package/lib/core/components/index.js.map +1 -1
- package/lib/core/components/shadcn/Panel.d.ts.map +1 -1
- package/lib/core/components/shadcn/Panel.js +3 -3
- package/lib/core/components/shadcn/Panel.js.map +1 -1
- package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +1 -1
- package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
- package/lib/core/components/shadcn/filters/filter/dateFilter.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filter/dateFilter.js +1 -1
- package/lib/core/components/shadcn/filters/filter/dateFilter.js.map +1 -1
- package/lib/core/components/shadcn/filters/filters.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filters.js +1 -1
- package/lib/core/components/shadcn/filters/filters.js.map +1 -1
- package/lib/core/components/shadcn/index.d.ts +1 -0
- package/lib/core/components/shadcn/index.d.ts.map +1 -1
- package/lib/core/components/shadcn/index.js +1 -0
- package/lib/core/components/shadcn/index.js.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.js +1 -3
- package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
- package/lib/core/components/shadcn/overflowTabs.d.ts +59 -0
- package/lib/core/components/shadcn/overflowTabs.d.ts.map +1 -0
- package/lib/core/components/shadcn/overflowTabs.js +173 -0
- package/lib/core/components/shadcn/overflowTabs.js.map +1 -0
- package/lib/core/components/shadcn/selectBox.js +2 -2
- package/lib/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/core/components/shadcn/theme/ThemeProvider.d.ts +3 -1
- package/lib/core/components/shadcn/theme/ThemeProvider.d.ts.map +1 -1
- package/lib/core/components/shadcn/theme/ThemeProvider.js +8 -9
- package/lib/core/components/shadcn/theme/ThemeProvider.js.map +1 -1
- package/lib/core/utils/dayjs.d.ts +12 -0
- package/lib/core/utils/dayjs.d.ts.map +1 -0
- package/lib/core/utils/dayjs.js +16 -0
- package/lib/core/utils/dayjs.js.map +1 -0
- package/lib/env/index.d.ts +17 -0
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +18 -1
- package/lib/env/index.js.map +1 -1
- package/lib/features/agent/PayloadBuilder.d.ts +1 -0
- package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
- package/lib/features/agent/PayloadBuilder.js +22 -5
- package/lib/features/agent/PayloadBuilder.js.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.js +3 -135
- package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.js +19 -4
- package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +99 -29
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +10 -9
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +5 -8
- 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 +45 -4
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.js +3 -3
- package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +9 -121
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.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 +19 -11
- package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
- package/lib/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
- package/lib/features/agent/chat/VegaLiteChart.js +11 -3
- package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.js +3 -0
- package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.js +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.js.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts +14 -2
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.js +20 -2
- package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.d.ts +3 -3
- package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.js +6 -1
- package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/features/facets/DocumentsFacetsNav.d.ts +3 -3
- package/lib/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/DocumentsFacetsNav.js +20 -8
- package/lib/features/facets/DocumentsFacetsNav.js.map +1 -1
- package/lib/features/facets/InteractionsFacetsNav.d.ts +3 -3
- package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/InteractionsFacetsNav.js +11 -1
- package/lib/features/facets/InteractionsFacetsNav.js.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts +3 -3
- package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.js +6 -1
- package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
- package/lib/features/facets/RunsFacetsNav.d.ts +4 -14
- package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/RunsFacetsNav.js +26 -15
- package/lib/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts +4 -3
- package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/WorkflowExecutionsFacetsNav.js +18 -10
- package/lib/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
- package/lib/features/facets/index.d.ts +1 -1
- package/lib/features/facets/index.d.ts.map +1 -1
- package/lib/features/facets/index.js.map +1 -1
- package/lib/features/facets/utils/SearchInterface.d.ts +4 -3
- package/lib/features/facets/utils/SearchInterface.d.ts.map +1 -1
- package/lib/features/facets/utils/SearchInterface.js +4 -0
- package/lib/features/facets/utils/SearchInterface.js.map +1 -1
- package/lib/features/layout/GenericPageNavHeader.d.ts +8 -1
- package/lib/features/layout/GenericPageNavHeader.d.ts.map +1 -1
- package/lib/features/layout/GenericPageNavHeader.js +9 -1
- package/lib/features/layout/GenericPageNavHeader.js.map +1 -1
- package/lib/features/magic-pdf/DownloadPopover.d.ts +3 -2
- package/lib/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
- package/lib/features/magic-pdf/DownloadPopover.js.map +1 -1
- package/lib/features/magic-pdf/GroundedExtractionView.d.ts.map +1 -1
- package/lib/features/magic-pdf/GroundedExtractionView.js +51 -64
- package/lib/features/magic-pdf/GroundedExtractionView.js.map +1 -1
- package/lib/features/oauth/McpConnectionsButton.d.ts +1 -1
- package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -1
- package/lib/features/oauth/McpConnectionsButton.js +2 -2
- package/lib/features/oauth/McpConnectionsButton.js.map +1 -1
- package/lib/features/oauth/McpConnectionsDialog.d.ts +1 -1
- package/lib/features/oauth/McpConnectionsDialog.js +2 -2
- package/lib/features/oauth/McpConnectionsDialog.js.map +1 -1
- package/lib/features/oauth/useMcpConnections.d.ts +4 -5
- package/lib/features/oauth/useMcpConnections.d.ts.map +1 -1
- package/lib/features/oauth/useMcpConnections.js +20 -4
- package/lib/features/oauth/useMcpConnections.js.map +1 -1
- package/lib/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -1
- package/lib/features/pdf-viewer/PdfPageRenderer.js +9 -11
- package/lib/features/pdf-viewer/PdfPageRenderer.js.map +1 -1
- package/lib/features/pdf-viewer/lazyReactPdf.d.ts +10 -0
- package/lib/features/pdf-viewer/lazyReactPdf.d.ts.map +1 -0
- package/lib/features/pdf-viewer/lazyReactPdf.js +25 -0
- package/lib/features/pdf-viewer/lazyReactPdf.js.map +1 -0
- package/lib/features/store/collections/CollectionsTable.d.ts.map +1 -1
- package/lib/features/store/collections/CollectionsTable.js +1 -3
- package/lib/features/store/collections/CollectionsTable.js.map +1 -1
- package/lib/features/store/collections/EditCollectionView.js +1 -1
- package/lib/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/features/store/objects/ExportPropertiesModal.d.ts +3 -1
- package/lib/features/store/objects/ExportPropertiesModal.d.ts.map +1 -1
- package/lib/features/store/objects/ExportPropertiesModal.js +5 -5
- package/lib/features/store/objects/ExportPropertiesModal.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +4 -10
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/components/TextEditorPanel.d.ts.map +1 -1
- package/lib/features/store/objects/components/TextEditorPanel.js +8 -3
- package/lib/features/store/objects/components/TextEditorPanel.js.map +1 -1
- package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/features/store/objects/layout/renderers.js +1 -5
- package/lib/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts +44 -62
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.js +47 -2
- package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js +5 -0
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.d.ts +6 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.js +4 -3
- package/lib/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
- package/lib/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
- package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js +2 -2
- package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.js +1 -3
- package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.js +12 -2
- package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
- package/lib/features/store/types/IntakePolicyForm.d.ts.map +1 -1
- package/lib/features/store/types/IntakePolicyForm.js +15 -15
- package/lib/features/store/types/IntakePolicyForm.js.map +1 -1
- package/lib/features/store/types/ObjectSchemaEditor.d.ts.map +1 -1
- package/lib/features/store/types/ObjectSchemaEditor.js +6 -2
- package/lib/features/store/types/ObjectSchemaEditor.js.map +1 -1
- package/lib/features/store/types/TableLayoutEditor.d.ts.map +1 -1
- package/lib/features/store/types/TableLayoutEditor.js +2 -0
- package/lib/features/store/types/TableLayoutEditor.js.map +1 -1
- package/lib/features/store/types/TypeRegistry.d.ts +282 -0
- package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
- package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +281 -0
- package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
- package/lib/features/user/UserInfo.d.ts.map +1 -1
- package/lib/features/user/UserInfo.js +2 -4
- package/lib/features/user/UserInfo.js.map +1 -1
- package/lib/features/views/ViewActions.d.ts +32 -0
- package/lib/features/views/ViewActions.d.ts.map +1 -0
- package/lib/features/views/ViewActions.js +186 -0
- package/lib/features/views/ViewActions.js.map +1 -0
- package/lib/features/views/ViewDropTarget.d.ts +15 -0
- package/lib/features/views/ViewDropTarget.d.ts.map +1 -0
- package/lib/features/views/ViewDropTarget.js +79 -0
- package/lib/features/views/ViewDropTarget.js.map +1 -0
- package/lib/features/views/ViewExperience.d.ts +3 -2
- package/lib/features/views/ViewExperience.d.ts.map +1 -1
- package/lib/features/views/ViewExperience.js +103 -12
- package/lib/features/views/ViewExperience.js.map +1 -1
- package/lib/features/views/ViewNavigation.d.ts +1 -1
- package/lib/features/views/ViewNavigation.d.ts.map +1 -1
- package/lib/features/views/ViewNavigation.js +14 -5
- package/lib/features/views/ViewNavigation.js.map +1 -1
- package/lib/features/views/ViewResults.d.ts +1 -1
- package/lib/features/views/ViewResults.d.ts.map +1 -1
- package/lib/features/views/ViewResults.js +124 -34
- package/lib/features/views/ViewResults.js.map +1 -1
- package/lib/features/views/index.d.ts +1 -0
- package/lib/features/views/index.d.ts.map +1 -1
- package/lib/features/views/index.js +1 -0
- package/lib/features/views/index.js.map +1 -1
- package/lib/features/views/types.d.ts +46 -1
- package/lib/features/views/types.d.ts.map +1 -1
- package/lib/features/views/viewState.d.ts.map +1 -1
- package/lib/features/views/viewState.js +34 -0
- package/lib/features/views/viewState.js.map +1 -1
- package/lib/i18n/LanguageProvider.d.ts +3 -1
- package/lib/i18n/LanguageProvider.d.ts.map +1 -1
- package/lib/i18n/LanguageProvider.js +9 -7
- package/lib/i18n/LanguageProvider.js.map +1 -1
- package/lib/i18n/instance.d.ts +2 -0
- package/lib/i18n/instance.d.ts.map +1 -1
- package/lib/i18n/instance.js +45 -26
- package/lib/i18n/instance.js.map +1 -1
- package/lib/i18n/locales/ar.json +296 -15
- package/lib/i18n/locales/de.json +294 -13
- package/lib/i18n/locales/en.json +65 -4
- package/lib/i18n/locales/es.json +295 -14
- package/lib/i18n/locales/fr.json +294 -13
- package/lib/i18n/locales/it.json +294 -13
- package/lib/i18n/locales/ja.json +292 -10
- package/lib/i18n/locales/ko.json +292 -10
- package/lib/i18n/locales/pt.json +294 -13
- package/lib/i18n/locales/ru.json +291 -10
- package/lib/i18n/locales/tr.json +291 -10
- package/lib/i18n/locales/zh-TW.json +292 -10
- package/lib/i18n/locales/zh.json +292 -10
- package/lib/router/RouteComponent.d.ts +8 -0
- package/lib/router/RouteComponent.d.ts.map +1 -1
- package/lib/router/RouteComponent.js +41 -9
- package/lib/router/RouteComponent.js.map +1 -1
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +20 -29
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +25 -19
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/session/auth/domainRouting.d.ts +11 -0
- package/lib/session/auth/domainRouting.d.ts.map +1 -1
- package/lib/session/auth/domainRouting.js +13 -0
- package/lib/session/auth/domainRouting.js.map +1 -1
- package/lib/session/auth/firebase.js +1 -1
- package/lib/session/auth/firebase.js.map +1 -1
- package/lib/session/useUXTracking.d.ts.map +1 -1
- package/lib/session/useUXTracking.js +6 -1
- package/lib/session/useUXTracking.js.map +1 -1
- package/lib/shell/VertesiaShell.d.ts.map +1 -1
- package/lib/shell/VertesiaShell.js +2 -1
- package/lib/shell/VertesiaShell.js.map +1 -1
- package/lib/shell/apps/AppInstallationProvider.d.ts +4 -2
- package/lib/shell/apps/AppInstallationProvider.d.ts.map +1 -1
- package/lib/shell/apps/IframeAppContextSync.d.ts +3 -0
- package/lib/shell/apps/IframeAppContextSync.d.ts.map +1 -0
- package/lib/shell/apps/IframeAppContextSync.js +95 -0
- package/lib/shell/apps/IframeAppContextSync.js.map +1 -0
- package/lib/shell/apps/iframe-auth.d.ts +55 -0
- package/lib/shell/apps/iframe-auth.d.ts.map +1 -0
- package/lib/shell/apps/iframe-auth.js +154 -0
- package/lib/shell/apps/iframe-auth.js.map +1 -0
- package/lib/shell/apps/index.d.ts +2 -0
- package/lib/shell/apps/index.d.ts.map +1 -1
- package/lib/shell/apps/index.js +2 -0
- package/lib/shell/apps/index.js.map +1 -1
- package/lib/vertesia-ui-core.js +199 -4
- 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 +975 -35
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.BJBGsq-8.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.BJBGsq-8.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.BY5YG5cX.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.BY5YG5cX.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.Bd5_1BXO.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.Bd5_1BXO.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.Bvwej2HH.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.Bvwej2HH.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.CMT3f4gf.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.CMT3f4gf.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.D56DNPJW.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.D56DNPJW.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DDzKLNx6.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DDzKLNx6.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.D_Am1LpF.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.D_Am1LpF.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DrZizgGV.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DrZizgGV.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.DwHsq86z.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.DwHsq86z.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.PLpo0Bbz.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.PLpo0Bbz.chunk.js.map +1 -0
- package/lib/vertesia-ui-i18n.js +2 -38
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-i18n.xVbXALqz.chunk.js +5 -0
- package/lib/vertesia-ui-i18n.xVbXALqz.chunk.js.map +1 -0
- package/lib/vertesia-ui-layout.js +80 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-rich-text.js +278 -4
- package/lib/vertesia-ui-rich-text.js.map +1 -1
- package/lib/vertesia-ui-router.js +1 -1
- package/lib/vertesia-ui-router.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 +118 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +336 -20
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/lib/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/widgets/markdown/MarkdownRenderer.js +43 -2
- package/lib/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/widgets/markdown/MermaidDiagram.d.ts.map +1 -1
- package/lib/widgets/markdown/MermaidDiagram.js +35 -22
- package/lib/widgets/markdown/MermaidDiagram.js.map +1 -1
- package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
- package/lib/widgets/monacoEditor/MonacoEditor.js +14 -10
- package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
- package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
- package/package.json +24 -29
- package/src/core/components/FormItem.tsx +2 -5
- package/src/core/components/InfoTip.test.tsx +33 -0
- package/src/core/components/InfoTip.tsx +32 -0
- package/src/core/components/index.ts +1 -0
- package/src/core/components/shadcn/Panel.tsx +3 -7
- package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +1 -1
- package/src/core/components/shadcn/filters/filter/dateFilter.tsx +1 -1
- package/src/core/components/shadcn/filters/filters.tsx +1 -1
- package/src/core/components/shadcn/index.ts +1 -0
- package/src/core/components/shadcn/modal/dialog.test.tsx +35 -0
- package/src/core/components/shadcn/modal/dialog.tsx +0 -4
- package/src/core/components/shadcn/overflowTabs.tsx +320 -0
- package/src/core/components/shadcn/selectBox.tsx +2 -2
- package/src/core/components/shadcn/theme/ThemeProvider.tsx +10 -9
- package/src/core/utils/dayjs.ts +17 -0
- package/src/css/base.css +78 -0
- package/src/env/index.test.ts +94 -0
- package/src/env/index.ts +36 -1
- package/src/features/agent/PayloadBuilder.test.ts +68 -0
- package/src/features/agent/PayloadBuilder.tsx +28 -4
- package/src/features/agent/chat/AgentRightPanel.tsx +2 -252
- package/src/features/agent/chat/ArtifactsTab.tsx +1 -0
- package/src/features/agent/chat/AskUserWidget.test.tsx +20 -1
- package/src/features/agent/chat/AskUserWidget.tsx +22 -6
- package/src/features/agent/chat/ModernAgentConversation.test.tsx +160 -0
- package/src/features/agent/chat/ModernAgentConversation.tsx +111 -31
- package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +86 -67
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +90 -7
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +4 -6
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.test.ts +103 -1
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +50 -4
- package/src/features/agent/chat/ModernAgentOutput/BatchProgressPanel.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +18 -1
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/StreamingMessage.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +37 -167
- package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +94 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.ts +19 -10
- package/src/features/agent/chat/VegaLiteChart.tsx +32 -14
- package/src/features/agent/chat/hooks/useAgentStream.test.tsx +18 -0
- package/src/features/agent/chat/hooks/useAgentStream.ts +3 -0
- package/src/features/document-viewer/UniversalDocumentViewer.tsx +1 -1
- package/src/features/facets/AgentRunnerFacetsNav.tsx +44 -4
- package/src/features/facets/CollectionsFacetsNav.tsx +15 -4
- package/src/features/facets/DocumentsFacetsNav.tsx +25 -8
- package/src/features/facets/FacetQueryHandlers.test.ts +84 -0
- package/src/features/facets/InteractionsFacetsNav.tsx +20 -4
- package/src/features/facets/PromptsFacetsNav.tsx +15 -4
- package/src/features/facets/RunsFacetsNav.test.ts +59 -0
- package/src/features/facets/RunsFacetsNav.tsx +40 -30
- package/src/features/facets/WorkflowExecutionsFacetsNav.test.ts +57 -0
- package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +36 -16
- package/src/features/facets/index.ts +1 -0
- package/src/features/facets/utils/SearchInterface.tsx +12 -3
- package/src/features/layout/GenericPageNavHeader.tsx +16 -0
- package/src/features/magic-pdf/DownloadPopover.tsx +1 -2
- package/src/features/magic-pdf/GroundedExtractionView.test.tsx +7 -1
- package/src/features/magic-pdf/GroundedExtractionView.tsx +162 -242
- package/src/features/oauth/McpConnectionsButton.test.tsx +18 -1
- package/src/features/oauth/McpConnectionsButton.tsx +6 -2
- package/src/features/oauth/McpConnectionsDialog.tsx +3 -3
- package/src/features/oauth/useMcpConnections.test.ts +1 -0
- package/src/features/oauth/useMcpConnections.ts +24 -7
- package/src/features/pdf-viewer/PdfPageRenderer.tsx +76 -71
- package/src/features/pdf-viewer/lazyReactPdf.ts +33 -0
- package/src/features/store/collections/CollectionsTable.tsx +1 -4
- package/src/features/store/collections/EditCollectionView.tsx +1 -1
- package/src/features/store/objects/ExportPropertiesModal.tsx +25 -16
- package/src/features/store/objects/components/ContentOverview.tsx +2 -28
- package/src/features/store/objects/components/TextEditorPanel.tsx +13 -3
- package/src/features/store/objects/layout/renderers.tsx +1 -6
- package/src/features/store/objects/search/DocumentSearchContext.test.ts +45 -0
- package/src/features/store/objects/search/DocumentSearchContext.ts +54 -4
- package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +5 -0
- package/src/features/store/objects/upload/DocumentUploadModal.tsx +10 -3
- package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +15 -6
- package/src/features/store/types/ContentObjectTypesTable.tsx +1 -4
- package/src/features/store/types/IntakePolicyEditor.tsx +14 -5
- package/src/features/store/types/IntakePolicyForm.tsx +120 -20
- package/src/features/store/types/ObjectSchemaEditor.tsx +6 -2
- package/src/features/store/types/TableLayoutEditor.tsx +2 -0
- package/src/features/user/UserInfo.test.tsx +10 -0
- package/src/features/user/UserInfo.tsx +2 -7
- package/src/features/views/ViewActions.test.tsx +80 -0
- package/src/features/views/ViewActions.tsx +352 -0
- package/src/features/views/ViewDropTarget.test.tsx +150 -0
- package/src/features/views/ViewDropTarget.tsx +140 -0
- package/src/features/views/ViewExperience.test.tsx +72 -0
- package/src/features/views/ViewExperience.tsx +189 -22
- package/src/features/views/ViewMedia.test.tsx +180 -0
- package/src/features/views/ViewNavigation.test.tsx +42 -0
- package/src/features/views/ViewNavigation.tsx +43 -5
- package/src/features/views/ViewResults.tsx +243 -26
- package/src/features/views/index.ts +1 -0
- package/src/features/views/types.ts +50 -0
- package/src/features/views/viewState.test.ts +7 -1
- package/src/features/views/viewState.ts +32 -0
- package/src/i18n/LanguageProvider.tsx +15 -8
- package/src/i18n/instance.test.ts +30 -0
- package/src/i18n/instance.ts +67 -40
- package/src/i18n/locales/ar.json +1192 -911
- package/src/i18n/locales/de.json +1148 -867
- package/src/i18n/locales/en.json +65 -4
- package/src/i18n/locales/es.json +1159 -878
- package/src/i18n/locales/fr.json +1159 -878
- package/src/i18n/locales/it.json +1159 -878
- package/src/i18n/locales/ja.json +1148 -866
- package/src/i18n/locales/ko.json +1148 -866
- package/src/i18n/locales/pt.json +1159 -878
- package/src/i18n/locales/ru.json +1170 -889
- package/src/i18n/locales/tr.json +1148 -867
- package/src/i18n/locales/zh-TW.json +1148 -866
- package/src/i18n/locales/zh.json +1148 -866
- package/src/i18n/rtl.test.ts +16 -7
- package/src/rich-text/VertesiaRichTextEditor.test.tsx +33 -1
- package/src/router/RouteComponent.test.tsx +139 -0
- package/src/router/RouteComponent.tsx +54 -9
- package/src/session/UserSessionProvider.tsx +20 -31
- package/src/session/auth/composable.scope.test.ts +1 -1
- package/src/session/auth/composable.test.ts +61 -1
- package/src/session/auth/composable.ts +29 -23
- package/src/session/auth/domainRouting.test.ts +24 -1
- package/src/session/auth/domainRouting.ts +29 -0
- package/src/session/auth/firebase.ts +1 -1
- package/src/session/useUXTracking.tsx +6 -1
- package/src/shell/VertesiaShell.tsx +2 -0
- package/src/shell/apps/IframeAppContextSync.test.tsx +196 -0
- package/src/shell/apps/IframeAppContextSync.tsx +101 -0
- package/src/shell/apps/iframe-auth.test.ts +118 -0
- package/src/shell/apps/iframe-auth.ts +193 -0
- package/src/shell/apps/index.ts +2 -0
- package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +12 -3
- package/src/widgets/markdown/MarkdownRenderer.tsx +50 -2
- package/src/widgets/markdown/MermaidDiagram.tsx +38 -22
- package/src/widgets/monacoEditor/MonacoEditor.tsx +27 -20
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts +0 -25
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts.map +0 -1
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js +0 -42
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js.map +0 -1
- package/src/features/magic-pdf/GroundedExtractionAssistantPanel.tsx +0 -86
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { AgentMessage } from '@vertesia/common';
|
|
2
|
-
import { cn,
|
|
2
|
+
import { cn, DropdownMenuItem, OverflowMoreMenu, useOverflowTabs } from '@vertesia/ui/core';
|
|
3
3
|
import { i18nInstance, NAMESPACE, useUITranslation } from '@vertesia/ui/i18n';
|
|
4
4
|
import { CheckCircle, ChevronDown, Clock } from 'lucide-react';
|
|
5
|
-
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
6
5
|
import { getWorkstreamId } from './utils';
|
|
7
6
|
|
|
8
7
|
interface WorkstreamTabsProps {
|
|
@@ -19,7 +18,6 @@ const TAB_ITEM_BASE =
|
|
|
19
18
|
'flex items-center gap-1.5 px-2 py-1 text-xs font-medium whitespace-nowrap transition-colors border-b-2 shrink-0 cursor-pointer';
|
|
20
19
|
const TAB_ITEM_INACTIVE = 'border-transparent text-muted hover:bg-muted';
|
|
21
20
|
const TAB_ITEM_ACTIVE = 'border-info bg-info text-info';
|
|
22
|
-
const TAB_GAP_PX = 4; // matches the `gap-1` between tab items
|
|
23
21
|
|
|
24
22
|
// Shorten long workstream names for the tab row.
|
|
25
23
|
function truncateName(name: string) {
|
|
@@ -50,93 +48,39 @@ function WorkstreamMoreMenu({
|
|
|
50
48
|
count,
|
|
51
49
|
completionStatus,
|
|
52
50
|
}: WorkstreamMoreMenuProps) {
|
|
53
|
-
const [open, setOpen] = useState(false);
|
|
54
|
-
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
55
|
-
const openedByHover = useRef(false);
|
|
56
|
-
|
|
57
|
-
const cancelClose = () => {
|
|
58
|
-
if (closeTimer.current) {
|
|
59
|
-
clearTimeout(closeTimer.current);
|
|
60
|
-
closeTimer.current = null;
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
const openOnHover = () => {
|
|
64
|
-
cancelClose();
|
|
65
|
-
openedByHover.current = true;
|
|
66
|
-
setOpen(true);
|
|
67
|
-
};
|
|
68
|
-
// Delay the close so the pointer can travel across the gap onto the menu.
|
|
69
|
-
const closeAfterDelay = () => {
|
|
70
|
-
cancelClose();
|
|
71
|
-
closeTimer.current = setTimeout(() => setOpen(false), 150);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// Clear any pending close timer on unmount.
|
|
75
|
-
useEffect(() => () => clearTimeout(closeTimer.current ?? undefined), []);
|
|
76
|
-
|
|
77
51
|
return (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
open={open}
|
|
83
|
-
onOpenChange={(next) => {
|
|
84
|
-
// Fired by click / keyboard / dismiss (not by hover); keep our state in sync.
|
|
85
|
-
cancelClose();
|
|
86
|
-
if (next) openedByHover.current = false;
|
|
87
|
-
setOpen(next);
|
|
88
|
-
}}
|
|
52
|
+
<OverflowMoreMenu
|
|
53
|
+
label={label}
|
|
54
|
+
triggerClassName={cn(TAB_ITEM_BASE, active ? TAB_ITEM_ACTIVE : TAB_ITEM_INACTIVE)}
|
|
55
|
+
icon={<ChevronDown className="ms-0.5 size-3.5" />}
|
|
89
56
|
>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
align="end"
|
|
104
|
-
className="w-max"
|
|
105
|
-
onMouseEnter={cancelClose}
|
|
106
|
-
onMouseLeave={closeAfterDelay}
|
|
107
|
-
onCloseAutoFocus={(e) => {
|
|
108
|
-
// Keep hover-opens from returning the focus ring to the trigger.
|
|
109
|
-
if (openedByHover.current) e.preventDefault();
|
|
110
|
-
}}
|
|
111
|
-
>
|
|
112
|
-
{items.map(([id, name]) => {
|
|
113
|
-
const showCount = (count?.get(id) ?? 0) > 0;
|
|
114
|
-
return (
|
|
115
|
-
<DropdownMenuItem
|
|
116
|
-
key={id}
|
|
117
|
-
onClick={() => onSelect(id)}
|
|
118
|
-
className={cn('flex items-center gap-2', id === current && 'text-info')}
|
|
119
|
-
>
|
|
120
|
-
<span className="truncate">{name}</span>
|
|
121
|
-
{showCount && (
|
|
122
|
-
<span className="ms-auto inline-flex items-center gap-1">
|
|
123
|
-
<span className="inline-flex items-center justify-center rounded-full bg-muted px-1.5 text-[10px] text-muted">
|
|
124
|
-
{count?.get(id)}
|
|
125
|
-
</span>
|
|
126
|
-
{completionStatus &&
|
|
127
|
-
id !== 'all' &&
|
|
128
|
-
(completionStatus.get(id) ? (
|
|
129
|
-
<CheckCircle className="size-3 text-success" />
|
|
130
|
-
) : (
|
|
131
|
-
<Clock className="size-3 text-attention" />
|
|
132
|
-
))}
|
|
57
|
+
{items.map(([id, name]) => {
|
|
58
|
+
const showCount = (count?.get(id) ?? 0) > 0;
|
|
59
|
+
return (
|
|
60
|
+
<DropdownMenuItem
|
|
61
|
+
key={id}
|
|
62
|
+
onClick={() => onSelect(id)}
|
|
63
|
+
className={cn('flex items-center gap-2', id === current && 'text-info')}
|
|
64
|
+
>
|
|
65
|
+
<span className="truncate">{name}</span>
|
|
66
|
+
{showCount && (
|
|
67
|
+
<span className="ms-auto inline-flex items-center gap-1">
|
|
68
|
+
<span className="inline-flex items-center justify-center rounded-full bg-muted px-1.5 text-[10px] text-muted">
|
|
69
|
+
{count?.get(id)}
|
|
133
70
|
</span>
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
71
|
+
{completionStatus &&
|
|
72
|
+
id !== 'all' &&
|
|
73
|
+
(completionStatus.get(id) ? (
|
|
74
|
+
<CheckCircle className="size-3 text-success" />
|
|
75
|
+
) : (
|
|
76
|
+
<Clock className="size-3 text-attention" />
|
|
77
|
+
))}
|
|
78
|
+
</span>
|
|
79
|
+
)}
|
|
80
|
+
</DropdownMenuItem>
|
|
81
|
+
);
|
|
82
|
+
})}
|
|
83
|
+
</OverflowMoreMenu>
|
|
140
84
|
);
|
|
141
85
|
}
|
|
142
86
|
|
|
@@ -161,82 +105,10 @@ function WorkstreamOverflowBar({
|
|
|
161
105
|
completionStatus,
|
|
162
106
|
}: WorkstreamOverflowBarProps) {
|
|
163
107
|
const { t } = useUITranslation();
|
|
164
|
-
const containerRef
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// into the last slot (before More) and `count` counts the tabs shown before it.
|
|
169
|
-
const [layout, setLayout] = useState<{ count: number; promote: boolean }>({
|
|
170
|
-
count: entries.length,
|
|
171
|
-
promote: false,
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
const recompute = () => {
|
|
175
|
-
const container = containerRef.current;
|
|
176
|
-
if (!container) return;
|
|
177
|
-
const containerWidth = container.clientWidth;
|
|
178
|
-
const widths = entries.map((_, i) => itemRefs.current[i]?.offsetWidth ?? 0);
|
|
179
|
-
const totalAll = widths.reduce((sum, w) => sum + w, 0) + TAB_GAP_PX * Math.max(0, entries.length - 1);
|
|
180
|
-
|
|
181
|
-
// How many tabs (in order, optionally skipping one) fit within `available`.
|
|
182
|
-
const fitCount = (available: number, skipIndex: number) => {
|
|
183
|
-
let used = 0;
|
|
184
|
-
let fitted = 0;
|
|
185
|
-
for (let i = 0; i < entries.length; i++) {
|
|
186
|
-
if (i === skipIndex) continue;
|
|
187
|
-
const cand = used + (fitted > 0 ? TAB_GAP_PX : 0) + widths[i];
|
|
188
|
-
if (cand > available) break;
|
|
189
|
-
used = cand;
|
|
190
|
-
fitted += 1;
|
|
191
|
-
}
|
|
192
|
-
return fitted;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
let next: { count: number; promote: boolean };
|
|
196
|
-
if (totalAll <= containerWidth) {
|
|
197
|
-
next = { count: entries.length, promote: false };
|
|
198
|
-
} else {
|
|
199
|
-
const moreWidth = moreRef.current?.offsetWidth ?? 0;
|
|
200
|
-
const naturalCount = Math.max(1, fitCount(containerWidth - moreWidth - TAB_GAP_PX, -1));
|
|
201
|
-
const activeIndex = entries.findIndex(([id]) => id === activeWorkstream);
|
|
202
|
-
if (activeIndex < 0 || activeIndex < naturalCount) {
|
|
203
|
-
next = { count: naturalCount, promote: false };
|
|
204
|
-
} else {
|
|
205
|
-
// Active tab overflowed: reserve its slot at the end, fit leading tabs before it.
|
|
206
|
-
const leadAvailable = containerWidth - moreWidth - widths[activeIndex] - TAB_GAP_PX * 2;
|
|
207
|
-
next = { count: fitCount(leadAvailable, activeIndex), promote: true };
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
setLayout((prev) => (prev.count === next.count && prev.promote === next.promote ? prev : next));
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// Re-measure after every render (tab/label changes) and on container resize.
|
|
214
|
-
const recomputeRef = useRef(recompute);
|
|
215
|
-
recomputeRef.current = recompute;
|
|
216
|
-
useLayoutEffect(() => {
|
|
217
|
-
recomputeRef.current();
|
|
218
|
-
});
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
const container = containerRef.current;
|
|
221
|
-
if (!container || typeof ResizeObserver === 'undefined') return;
|
|
222
|
-
const observer = new ResizeObserver(() => recomputeRef.current());
|
|
223
|
-
observer.observe(container);
|
|
224
|
-
return () => observer.disconnect();
|
|
225
|
-
}, []);
|
|
226
|
-
|
|
227
|
-
const activeIndex = entries.findIndex(([id]) => id === activeWorkstream);
|
|
228
|
-
let visible: WorkstreamEntry[];
|
|
229
|
-
let overflow: WorkstreamEntry[];
|
|
230
|
-
if (layout.promote && activeIndex >= 0) {
|
|
231
|
-
// Pull the active tab into the last visible slot; the tab it displaces overflows.
|
|
232
|
-
const others = entries.filter((_, i) => i !== activeIndex);
|
|
233
|
-
visible = [...others.slice(0, layout.count), entries[activeIndex]];
|
|
234
|
-
overflow = others.slice(layout.count);
|
|
235
|
-
} else {
|
|
236
|
-
visible = entries.slice(0, layout.count);
|
|
237
|
-
overflow = entries.slice(layout.count);
|
|
238
|
-
}
|
|
239
|
-
const activeInOverflow = overflow.some(([id]) => id === activeWorkstream);
|
|
108
|
+
const { containerRef, setItemRef, setMoreRef, visible, overflow, activeInOverflow } = useOverflowTabs(
|
|
109
|
+
entries,
|
|
110
|
+
([id]) => id === activeWorkstream,
|
|
111
|
+
);
|
|
240
112
|
const moreLabel = t('agent.moreTabs');
|
|
241
113
|
|
|
242
114
|
// Inner tab content (name + count badge + completion icon), shared by the hidden
|
|
@@ -280,15 +152,13 @@ function WorkstreamOverflowBar({
|
|
|
280
152
|
type="button"
|
|
281
153
|
key={id}
|
|
282
154
|
tabIndex={-1}
|
|
283
|
-
ref={(
|
|
284
|
-
itemRefs.current[i] = el;
|
|
285
|
-
}}
|
|
155
|
+
ref={setItemRef(i)}
|
|
286
156
|
className={cn(TAB_ITEM_BASE, TAB_ITEM_INACTIVE)}
|
|
287
157
|
>
|
|
288
158
|
{renderTabInner(id, name, false)}
|
|
289
159
|
</button>
|
|
290
160
|
))}
|
|
291
|
-
<button type="button" tabIndex={-1} ref={
|
|
161
|
+
<button type="button" tabIndex={-1} ref={setMoreRef} className={cn(TAB_ITEM_BASE, TAB_ITEM_INACTIVE)}>
|
|
292
162
|
{moreLabel}
|
|
293
163
|
<ChevronDown className="ms-0.5 size-3.5" />
|
|
294
164
|
</button>
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
getSlidingViewMessageBuckets,
|
|
13
13
|
groupMessagesWithStreaming,
|
|
14
14
|
isInProgress,
|
|
15
|
+
isStreamingDataVisibleInWorkstream,
|
|
15
16
|
isStreamReplacedByMessage,
|
|
16
17
|
isToolActivityMessage,
|
|
17
18
|
mergeConsecutiveToolGroups,
|
|
@@ -1310,6 +1311,43 @@ describe('ModernAgentOutput summary conversation items', () => {
|
|
|
1310
1311
|
expect(summaryMessages).toEqual([answer]);
|
|
1311
1312
|
});
|
|
1312
1313
|
|
|
1314
|
+
it('does not duplicate persisted reasoning without streaming metadata across intervening activity', () => {
|
|
1315
|
+
const activity = makeMessage({
|
|
1316
|
+
timestamp: 2500,
|
|
1317
|
+
type: AgentMessageType.THOUGHT,
|
|
1318
|
+
message: 'Launching workstream',
|
|
1319
|
+
details: {
|
|
1320
|
+
tool: 'launch_workstream',
|
|
1321
|
+
tool_status: 'completed',
|
|
1322
|
+
tool_run_id: 'tool-1',
|
|
1323
|
+
},
|
|
1324
|
+
});
|
|
1325
|
+
const reasoning = makeMessage({
|
|
1326
|
+
timestamp: 3000,
|
|
1327
|
+
type: AgentMessageType.THOUGHT,
|
|
1328
|
+
message: 'Launching parallel processing',
|
|
1329
|
+
details: {
|
|
1330
|
+
display_role: 'reasoning',
|
|
1331
|
+
},
|
|
1332
|
+
});
|
|
1333
|
+
|
|
1334
|
+
const summaryMessages = buildSummaryDisplayMessages(
|
|
1335
|
+
[activity, reasoning],
|
|
1336
|
+
new Map([
|
|
1337
|
+
[
|
|
1338
|
+
'stream-1',
|
|
1339
|
+
{
|
|
1340
|
+
text: 'Launching parallel processing',
|
|
1341
|
+
startTimestamp: 2000,
|
|
1342
|
+
isComplete: true,
|
|
1343
|
+
},
|
|
1344
|
+
],
|
|
1345
|
+
]),
|
|
1346
|
+
);
|
|
1347
|
+
|
|
1348
|
+
expect(summaryMessages).toEqual([activity, reasoning]);
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1313
1351
|
it('does not duplicate completed tool preamble streams once persisted prose replaces them', () => {
|
|
1314
1352
|
const preamble = makeMessage({
|
|
1315
1353
|
timestamp: 3000,
|
|
@@ -1391,6 +1429,33 @@ describe('ModernAgentOutput summary conversation items', () => {
|
|
|
1391
1429
|
});
|
|
1392
1430
|
|
|
1393
1431
|
describe('ModernAgentOutput utils - streamed deduplication', () => {
|
|
1432
|
+
it('shows a workstream stream only in its owning workstream', () => {
|
|
1433
|
+
const stream = {
|
|
1434
|
+
text: 'Child work in progress',
|
|
1435
|
+
startTimestamp: 1000,
|
|
1436
|
+
workstreamId: 'research',
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1439
|
+
expect(isStreamingDataVisibleInWorkstream(stream, 'all')).toBe(false);
|
|
1440
|
+
expect(isStreamingDataVisibleInWorkstream(stream, 'main')).toBe(false);
|
|
1441
|
+
expect(isStreamingDataVisibleInWorkstream(stream, 'research')).toBe(true);
|
|
1442
|
+
expect(isStreamingDataVisibleInWorkstream(stream, 'writing')).toBe(false);
|
|
1443
|
+
|
|
1444
|
+
const streams = new Map([['stream-1', stream]]);
|
|
1445
|
+
expect(groupMessagesWithStreaming([], streams, 'all')).toHaveLength(0);
|
|
1446
|
+
expect(groupMessagesWithStreaming([], streams, 'research')).toHaveLength(1);
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1449
|
+
it('keeps main-agent streams in the main conversation', () => {
|
|
1450
|
+
const stream = {
|
|
1451
|
+
text: 'Main response in progress',
|
|
1452
|
+
startTimestamp: 1000,
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1455
|
+
expect(isStreamingDataVisibleInWorkstream(stream, 'all')).toBe(true);
|
|
1456
|
+
expect(isStreamingDataVisibleInWorkstream(stream, 'main')).toBe(true);
|
|
1457
|
+
});
|
|
1458
|
+
|
|
1394
1459
|
it('skips a stale streaming item once an equivalent streamed answer is persisted', () => {
|
|
1395
1460
|
const answer = makeMessage({
|
|
1396
1461
|
timestamp: 2000,
|
|
@@ -1498,6 +1563,35 @@ describe('ModernAgentOutput utils - streamed deduplication', () => {
|
|
|
1498
1563
|
),
|
|
1499
1564
|
).toBe(false);
|
|
1500
1565
|
});
|
|
1566
|
+
|
|
1567
|
+
it('replaces matching streamed prose with persisted thinking prose, but not a generic marker', () => {
|
|
1568
|
+
const matchingThinking = makeMessage({
|
|
1569
|
+
timestamp: 2000,
|
|
1570
|
+
type: AgentMessageType.THOUGHT,
|
|
1571
|
+
message: 'Launching parallel processing',
|
|
1572
|
+
details: {
|
|
1573
|
+
activity_id: 'activity-1',
|
|
1574
|
+
display_role: 'thinking',
|
|
1575
|
+
},
|
|
1576
|
+
});
|
|
1577
|
+
const genericMarker = makeMessage({
|
|
1578
|
+
timestamp: 2000,
|
|
1579
|
+
type: AgentMessageType.THOUGHT,
|
|
1580
|
+
message: 'Thinking...',
|
|
1581
|
+
details: {
|
|
1582
|
+
activity_id: 'activity-1',
|
|
1583
|
+
display_role: 'thinking',
|
|
1584
|
+
},
|
|
1585
|
+
});
|
|
1586
|
+
const streaming = {
|
|
1587
|
+
text: 'Launching parallel processing',
|
|
1588
|
+
startTimestamp: 1000,
|
|
1589
|
+
activityId: 'activity-1',
|
|
1590
|
+
};
|
|
1591
|
+
|
|
1592
|
+
expect(isStreamReplacedByMessage(streaming, [matchingThinking])).toBe(true);
|
|
1593
|
+
expect(isStreamReplacedByMessage(streaming, [genericMarker])).toBe(false);
|
|
1594
|
+
});
|
|
1501
1595
|
});
|
|
1502
1596
|
|
|
1503
1597
|
describe('ModernAgentOutput utils - adjacent rendered deduplication', () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { VertesiaClient } from '@vertesia/client';
|
|
2
2
|
import { type AgentMessage, AgentMessageType } from '@vertesia/common';
|
|
3
|
-
import dayjs from 'dayjs';
|
|
3
|
+
import dayjs from '../../../../core/utils/dayjs.js';
|
|
4
4
|
import { getWorkstreamActivityDetails, getWorkstreamLaunchDetails } from '../workstreams.js';
|
|
5
5
|
|
|
6
6
|
function getAgentChatDebugParam(hash: string): string | null {
|
|
@@ -327,6 +327,18 @@ export interface StreamingData {
|
|
|
327
327
|
streamingId?: string;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Match live stream ownership to the persisted-message timeline filter. The `all` conversation
|
|
332
|
+
* view is the main-agent timeline (plus workstream lifecycle markers), not a merged transcript of
|
|
333
|
+
* every child workstream.
|
|
334
|
+
*/
|
|
335
|
+
export function isStreamingDataVisibleInWorkstream(streaming: StreamingData, activeWorkstream?: string): boolean {
|
|
336
|
+
if (!activeWorkstream) return true;
|
|
337
|
+
|
|
338
|
+
const streamWorkstream = streaming.workstreamId || 'main';
|
|
339
|
+
return activeWorkstream === 'all' ? streamWorkstream === 'main' : activeWorkstream === streamWorkstream;
|
|
340
|
+
}
|
|
341
|
+
|
|
330
342
|
function normalizeComparableText(text: unknown): string | undefined {
|
|
331
343
|
if (typeof text !== 'string') return undefined;
|
|
332
344
|
const normalized = text.replace(/\r\n/g, '\n').trim();
|
|
@@ -353,7 +365,7 @@ export function isStreamReplacedByMessage(streaming: StreamingData, messages: Ag
|
|
|
353
365
|
if (streaming.streamingId && messageStreamingId) {
|
|
354
366
|
if (messageStreamingId !== streaming.streamingId) return false;
|
|
355
367
|
if (message.details?.display_role === 'thinking') {
|
|
356
|
-
return
|
|
368
|
+
return getMessageComparableText(message) === streamingText;
|
|
357
369
|
}
|
|
358
370
|
if (isToolCallMessage(message) || message.details?.tool_status) {
|
|
359
371
|
return false;
|
|
@@ -363,7 +375,7 @@ export function isStreamReplacedByMessage(streaming: StreamingData, messages: Ag
|
|
|
363
375
|
|
|
364
376
|
if (streaming.activityId && message.details?.activity_id === streaming.activityId) {
|
|
365
377
|
if (message.details?.display_role === 'thinking') {
|
|
366
|
-
return
|
|
378
|
+
return getMessageComparableText(message) === streamingText;
|
|
367
379
|
}
|
|
368
380
|
if (isToolCallMessage(message) || message.details?.tool_status) {
|
|
369
381
|
return false;
|
|
@@ -380,8 +392,9 @@ export function isStreamReplacedByMessage(streaming: StreamingData, messages: Ag
|
|
|
380
392
|
return false;
|
|
381
393
|
}
|
|
382
394
|
|
|
383
|
-
|
|
384
|
-
|
|
395
|
+
// Exact persisted prose is authoritative even when an older or alternate producer omitted
|
|
396
|
+
// streaming correlation metadata. This comparison spans the whole timeline so intervening
|
|
397
|
+
// tool/workstream activity cannot leave the completed preview rendered a second time.
|
|
385
398
|
return getMessageComparableText(message) === streamingText;
|
|
386
399
|
});
|
|
387
400
|
}
|
|
@@ -713,11 +726,7 @@ export function groupMessagesWithStreaming(
|
|
|
713
726
|
if (!data.text) return;
|
|
714
727
|
if (isStreamReplacedByMessage(data, messages)) return;
|
|
715
728
|
|
|
716
|
-
|
|
717
|
-
if (activeWorkstream && activeWorkstream !== 'all') {
|
|
718
|
-
const streamWorkstream = data.workstreamId || 'main';
|
|
719
|
-
if (activeWorkstream !== streamWorkstream) return;
|
|
720
|
-
}
|
|
729
|
+
if (!isStreamingDataVisibleInWorkstream(data, activeWorkstream)) return;
|
|
721
730
|
|
|
722
731
|
items.push({
|
|
723
732
|
kind: 'streaming',
|
|
@@ -4,14 +4,19 @@ import { useUITranslation } from '@vertesia/ui/i18n';
|
|
|
4
4
|
import { useUserSession } from '@vertesia/ui/session';
|
|
5
5
|
import { Check, Copy, Download, Loader2, Maximize2, Minimize2, X } from 'lucide-react';
|
|
6
6
|
import Papa from 'papaparse';
|
|
7
|
-
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
|
-
import { VegaEmbed } from 'react-vega';
|
|
7
|
+
import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
9
8
|
import type { View } from 'vega';
|
|
10
9
|
import type { TopLevelSpec as VisualizationSpec } from 'vega-lite';
|
|
11
10
|
import { cn } from '../../../core/components/libs/utils';
|
|
12
11
|
import type { VegaLiteChartSpec } from './AgentChart';
|
|
13
12
|
import { getArtifactCacheKey, getFileCacheKey, isProjectFilePath, useArtifactUrlCache } from './useArtifactUrlCache';
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Vega and its Vega-Lite compiler are ~1 MB and are only needed once a chart is actually rendered,
|
|
16
|
+
* so they are pulled in on demand instead of at module load.
|
|
17
|
+
*/
|
|
18
|
+
const VegaEmbed = lazy(() => import('react-vega').then(({ VegaEmbed: component }) => ({ default: component })));
|
|
19
|
+
|
|
15
20
|
type VegaLiteChartProps = {
|
|
16
21
|
spec: VegaLiteChartSpec;
|
|
17
22
|
/**
|
|
@@ -38,6 +43,15 @@ function VegaErrorDisplay({ error, chartTitle }: { error: string; chartTitle?: s
|
|
|
38
43
|
);
|
|
39
44
|
}
|
|
40
45
|
|
|
46
|
+
// Shown while the Vega runtime is being fetched on first chart render
|
|
47
|
+
function VegaLoadingPlaceholder() {
|
|
48
|
+
return (
|
|
49
|
+
<output className="flex items-center justify-center w-full h-full">
|
|
50
|
+
<Loader2 className="w-5 h-5 animate-spin text-gray-500 dark:text-gray-400" />
|
|
51
|
+
</output>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
// Fullscreen dialog component with smooth animations
|
|
42
56
|
function FullscreenDialog({
|
|
43
57
|
isOpen,
|
|
@@ -1122,12 +1136,14 @@ export const VegaLiteChart = memo(
|
|
|
1122
1136
|
className="bg-white dark:bg-gray-900 rounded overflow-hidden"
|
|
1123
1137
|
style={{ width: '100%', height: baseHeight, minWidth: 0 }}
|
|
1124
1138
|
>
|
|
1125
|
-
<
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1139
|
+
<Suspense fallback={<VegaLoadingPlaceholder />}>
|
|
1140
|
+
<VegaEmbed
|
|
1141
|
+
spec={chartSpec}
|
|
1142
|
+
onEmbed={(result) => handleNewView(result.view)}
|
|
1143
|
+
onError={handleError}
|
|
1144
|
+
options={{ renderer: options?.renderer || 'canvas', actions: false }}
|
|
1145
|
+
/>
|
|
1146
|
+
</Suspense>
|
|
1131
1147
|
</div>
|
|
1132
1148
|
</div>
|
|
1133
1149
|
</div>
|
|
@@ -1141,12 +1157,14 @@ export const VegaLiteChart = memo(
|
|
|
1141
1157
|
>
|
|
1142
1158
|
<div className="w-full h-full min-h-[calc(100vh-200px)]">
|
|
1143
1159
|
{fullscreenSpec && (
|
|
1144
|
-
<
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1160
|
+
<Suspense fallback={<VegaLoadingPlaceholder />}>
|
|
1161
|
+
<VegaEmbed
|
|
1162
|
+
spec={fullscreenSpec}
|
|
1163
|
+
onEmbed={(result) => handleFullscreenNewView(result.view)}
|
|
1164
|
+
onError={handleError}
|
|
1165
|
+
options={{ renderer: options?.renderer || 'canvas', actions: false }}
|
|
1166
|
+
/>
|
|
1167
|
+
</Suspense>
|
|
1150
1168
|
)}
|
|
1151
1169
|
</div>
|
|
1152
1170
|
{/* Floating toolbar in fullscreen */}
|
|
@@ -43,6 +43,24 @@ describe('useAgentStream', () => {
|
|
|
43
43
|
vi.clearAllMocks();
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
+
it('keeps the stream subscribed while an interactive conversation is idle', async () => {
|
|
47
|
+
const streamMessages = vi.fn<
|
|
48
|
+
(
|
|
49
|
+
id: string,
|
|
50
|
+
onMessage?: (message: AgentMessage, exitFn?: (payload: unknown) => void) => void,
|
|
51
|
+
since?: number,
|
|
52
|
+
signal?: AbortSignal,
|
|
53
|
+
options?: AgentRunStreamMessagesOptions,
|
|
54
|
+
) => Promise<unknown>
|
|
55
|
+
>(() => new Promise(() => {}));
|
|
56
|
+
const client = createClient(streamMessages);
|
|
57
|
+
|
|
58
|
+
renderHook(() => useAgentStream(client, 'agent-run-1'));
|
|
59
|
+
|
|
60
|
+
await waitFor(() => expect(streamMessages).toHaveBeenCalled());
|
|
61
|
+
expect(streamMessages.mock.calls[0][4]).toMatchObject({ closeOnIdle: false });
|
|
62
|
+
});
|
|
63
|
+
|
|
46
64
|
it('marks initial history as empty when the history fetch returns no messages', async () => {
|
|
47
65
|
const streamMessages = vi.fn<
|
|
48
66
|
(
|
|
@@ -473,6 +473,9 @@ export function useAgentStream(
|
|
|
473
473
|
since,
|
|
474
474
|
abortController.signal,
|
|
475
475
|
{
|
|
476
|
+
// Interactive conversations remain RUNNING at IDLE and must keep the
|
|
477
|
+
// subscription open so follow-up turns arrive on the same stream.
|
|
478
|
+
closeOnIdle: false,
|
|
476
479
|
onHistoryLoaded: (historical) => {
|
|
477
480
|
if (abortController.signal.aborted) return;
|
|
478
481
|
const timelineMessages = historical.filter(shouldStoreTimelineMessage);
|
|
@@ -10,19 +10,48 @@ import {
|
|
|
10
10
|
} from '@vertesia/ui/core';
|
|
11
11
|
import { RefreshCw } from 'lucide-react';
|
|
12
12
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
createSearchQueryKeyGuard,
|
|
15
|
+
filterValueToQueryValue,
|
|
16
|
+
type SearchInterface,
|
|
17
|
+
setSearchQueryValue,
|
|
18
|
+
} from './utils/SearchInterface';
|
|
14
19
|
import type { EnrichedFacetBucket } from './utils/VInteractionFacet';
|
|
15
20
|
import { VInteractionFacet } from './utils/VInteractionFacet';
|
|
16
21
|
import { VStringFacet } from './utils/VStringFacet';
|
|
17
22
|
import { VUserFacet } from './utils/VUserFacet';
|
|
18
23
|
|
|
24
|
+
export interface AgentRunnerFilterQuery {
|
|
25
|
+
object?: string;
|
|
26
|
+
id?: string;
|
|
27
|
+
run_kind?: string;
|
|
28
|
+
interaction?: string;
|
|
29
|
+
status?: string;
|
|
30
|
+
initiated_by?: string;
|
|
31
|
+
start?: string;
|
|
32
|
+
end?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const agentRunnerFilterNames = [
|
|
36
|
+
'id',
|
|
37
|
+
'run_kind',
|
|
38
|
+
'interaction',
|
|
39
|
+
'status',
|
|
40
|
+
'initiated_by',
|
|
41
|
+
'start',
|
|
42
|
+
'end',
|
|
43
|
+
] as const satisfies readonly (keyof AgentRunnerFilterQuery)[];
|
|
44
|
+
const isAgentRunnerFilterName = createSearchQueryKeyGuard<AgentRunnerFilterQuery>(agentRunnerFilterNames);
|
|
45
|
+
|
|
19
46
|
interface AgentRunnerFacetsNavProps {
|
|
20
47
|
facets: {
|
|
21
48
|
statuses?: FacetBucket[];
|
|
22
49
|
initiated_by?: FacetBucket[];
|
|
23
50
|
interactions?: EnrichedFacetBucket[];
|
|
51
|
+
/** `run_kind` buckets — `agent` (autonomous runs) and `process` (process runs). */
|
|
52
|
+
kinds?: FacetBucket[];
|
|
24
53
|
};
|
|
25
|
-
search: SearchInterface
|
|
54
|
+
search: SearchInterface<AgentRunnerFilterQuery>;
|
|
26
55
|
actions?: React.ReactNode[];
|
|
27
56
|
selectionCount?: number;
|
|
28
57
|
/**
|
|
@@ -47,6 +76,14 @@ export function useAgentRunnerFilterGroups(facets: AgentRunnerFacetsNavProps['fa
|
|
|
47
76
|
multiple: false,
|
|
48
77
|
});
|
|
49
78
|
|
|
79
|
+
customFilterGroups.push(
|
|
80
|
+
VStringFacet({
|
|
81
|
+
buckets: facets.kinds || [],
|
|
82
|
+
name: 'run_kind',
|
|
83
|
+
placeholder: 'Kind',
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
86
|
+
|
|
50
87
|
customFilterGroups.push(
|
|
51
88
|
VInteractionFacet({
|
|
52
89
|
buckets: facets.interactions || [],
|
|
@@ -89,13 +126,16 @@ export function useAgentRunnerFilterGroups(facets: AgentRunnerFacetsNavProps['fa
|
|
|
89
126
|
}
|
|
90
127
|
|
|
91
128
|
// Create filter change handler for agent runners
|
|
92
|
-
export function createAgentRunnerFilterHandler(search: SearchInterface) {
|
|
129
|
+
export function createAgentRunnerFilterHandler(search: SearchInterface<AgentRunnerFilterQuery>) {
|
|
93
130
|
return (newFilters: BaseFilter[]) => {
|
|
94
131
|
// Clear all filters first, then apply new ones
|
|
95
132
|
search.clearFilters(false, false);
|
|
96
133
|
|
|
97
134
|
newFilters.forEach((filter) => {
|
|
98
135
|
if (filter.value && filter.value.length > 0) {
|
|
136
|
+
if (!isAgentRunnerFilterName(filter.name)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
99
139
|
const filterName = filter.name;
|
|
100
140
|
const filterValue = filterValueToQueryValue(filter);
|
|
101
141
|
setSearchQueryValue(search, filterName, filterValue);
|
|
@@ -154,7 +194,7 @@ export function AgentRunnerFacetsNav({
|
|
|
154
194
|
{!selectionCount && (
|
|
155
195
|
<div className="flex items-center justify-between px-2 py-1">
|
|
156
196
|
<div className="text-sm text-muted-foreground">
|
|
157
|
-
{search.initialized ? `${search.totalCount}
|
|
197
|
+
{search.initialized ? `${search.totalCount} runs` : 'Loading runs...'}
|
|
158
198
|
</div>
|
|
159
199
|
</div>
|
|
160
200
|
)}
|