@vertesia/ui 1.5.0-dev.20260807.073259Z → 1.5.0-dev.20260826.064249Z
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/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 +29 -62
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.js +2 -0
- package/lib/features/store/objects/search/DocumentSearchContext.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 +11 -1
- package/lib/features/store/types/IntakePolicyEditor.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 +272 -0
- package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
- package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +271 -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 +261 -15
- package/lib/i18n/locales/de.json +259 -13
- package/lib/i18n/locales/en.json +30 -4
- package/lib/i18n/locales/es.json +260 -14
- package/lib/i18n/locales/fr.json +259 -13
- package/lib/i18n/locales/it.json +259 -13
- package/lib/i18n/locales/ja.json +257 -10
- package/lib/i18n/locales/ko.json +257 -10
- package/lib/i18n/locales/pt.json +259 -13
- package/lib/i18n/locales/ru.json +256 -10
- package/lib/i18n/locales/tr.json +256 -10
- package/lib/i18n/locales/zh-TW.json +257 -10
- package/lib/i18n/locales/zh.json +257 -10
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +8 -16
- 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/firebase.js +1 -1
- package/lib/session/auth/firebase.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 +4 -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 +32 -34
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +16 -16
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-rich-text.js +4 -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 +1 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +20 -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/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.ts +4 -2
- 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 +11 -1
- 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 +1157 -911
- package/src/i18n/locales/de.json +1113 -867
- package/src/i18n/locales/en.json +30 -4
- package/src/i18n/locales/es.json +1124 -878
- package/src/i18n/locales/fr.json +1124 -878
- package/src/i18n/locales/it.json +1124 -878
- package/src/i18n/locales/ja.json +1113 -866
- package/src/i18n/locales/ko.json +1113 -866
- package/src/i18n/locales/pt.json +1124 -878
- package/src/i18n/locales/ru.json +1135 -889
- package/src/i18n/locales/tr.json +1113 -867
- package/src/i18n/locales/zh-TW.json +1113 -866
- package/src/i18n/locales/zh.json +1113 -866
- package/src/i18n/rtl.test.ts +16 -7
- package/src/rich-text/VertesiaRichTextEditor.test.tsx +33 -1
- package/src/session/UserSessionProvider.tsx +8 -20
- 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/firebase.ts +1 -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
package/src/i18n/rtl.test.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
1
4
|
import i18next from 'i18next';
|
|
2
5
|
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import {
|
|
6
|
+
import { AVAILABLE_LOCALES, NAMESPACE } from './instance.js';
|
|
4
7
|
import { isRTL, RTL_LANGUAGES, resolveLanguage, SUPPORTED_LANGUAGES } from './rtl.js';
|
|
5
8
|
|
|
6
9
|
describe('isRTL', () => {
|
|
@@ -67,10 +70,10 @@ describe('RTL_LANGUAGES set', () => {
|
|
|
67
70
|
});
|
|
68
71
|
|
|
69
72
|
describe('SUPPORTED_LANGUAGES divergence guard', () => {
|
|
70
|
-
it('matches exactly the locales
|
|
71
|
-
const
|
|
73
|
+
it('matches exactly the locales the i18n instance can serve', () => {
|
|
74
|
+
const available = [...AVAILABLE_LOCALES].sort();
|
|
72
75
|
const supported = [...SUPPORTED_LANGUAGES].sort();
|
|
73
|
-
expect(
|
|
76
|
+
expect(available).toEqual(supported);
|
|
74
77
|
});
|
|
75
78
|
});
|
|
76
79
|
|
|
@@ -95,8 +98,10 @@ describe('empty translation fallback', () => {
|
|
|
95
98
|
expect(t('test.emptyTranslationFallback')).toBe('English fallback');
|
|
96
99
|
});
|
|
97
100
|
|
|
101
|
+
// Reads the locale files rather than `i18nInstance.options.resources`: only the `en` fallback is
|
|
102
|
+
// bundled there now, the rest are fetched on demand.
|
|
98
103
|
it('does not ship parser-created empty locale entries', () => {
|
|
99
|
-
const
|
|
104
|
+
const localesDir = join(dirname(fileURLToPath(import.meta.url)), 'locales');
|
|
100
105
|
const emptyEntries: string[] = [];
|
|
101
106
|
|
|
102
107
|
const collectEmptyEntries = (value: unknown, path: string[]) => {
|
|
@@ -121,8 +126,12 @@ describe('empty translation fallback', () => {
|
|
|
121
126
|
}
|
|
122
127
|
};
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
const localeFiles = readdirSync(localesDir).filter((name) => name.endsWith('.json'));
|
|
130
|
+
expect(localeFiles.length).toBe(SUPPORTED_LANGUAGES.length);
|
|
131
|
+
|
|
132
|
+
for (const file of localeFiles) {
|
|
133
|
+
const resource: unknown = JSON.parse(readFileSync(join(localesDir, file), 'utf-8'));
|
|
134
|
+
collectEmptyEntries(resource, [file.replace(/\.json$/, '')]);
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
expect(emptyEntries).toEqual([]);
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/** @vitest-environment jsdom */
|
|
2
2
|
|
|
3
3
|
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS,
|
|
6
|
+
MarkdownRichTextEditor,
|
|
7
|
+
type MarkdownRichTextEditorProps,
|
|
8
|
+
setEditorMarkdown,
|
|
9
|
+
} from '@vertesia/rich-text';
|
|
5
10
|
import { describe, expect, it, vi } from 'vitest';
|
|
6
11
|
import { I18nProvider } from '../i18n/index.js';
|
|
7
12
|
import {
|
|
@@ -174,6 +179,33 @@ describe('VertesiaMarkdownRichTextEditor', () => {
|
|
|
174
179
|
expect(await screen.findByRole('heading', { name: 'Setext heading' })).not.toBeNull();
|
|
175
180
|
expect(screen.getByRole('textbox', { name: 'Markdown document editor' })).not.toBeNull();
|
|
176
181
|
expect(screen.queryByRole('heading', { name: 'Some Markdown formatting may change' })).toBeNull();
|
|
182
|
+
// The document editor debounces serialization, so wait past that window: otherwise this
|
|
183
|
+
// assertion passes merely because a spurious change has not been flushed yet.
|
|
184
|
+
await new Promise((resolve) => setTimeout(resolve, DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS * 2));
|
|
185
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('does not report a change when the document is locked or unlocked', async () => {
|
|
189
|
+
const onChange = vi.fn();
|
|
190
|
+
const renderEditable = (editable: boolean) => (
|
|
191
|
+
<I18nProvider lng="en">
|
|
192
|
+
<VertesiaMarkdownDocumentEditor
|
|
193
|
+
value={'Setext heading\n=============='}
|
|
194
|
+
onChange={onChange}
|
|
195
|
+
editable={editable}
|
|
196
|
+
/>
|
|
197
|
+
</I18nProvider>
|
|
198
|
+
);
|
|
199
|
+
const view = render(renderEditable(true));
|
|
200
|
+
|
|
201
|
+
expect(await screen.findByRole('heading', { name: 'Setext heading' })).not.toBeNull();
|
|
202
|
+
// Both directions matter: either toggle emits an editor update on its own.
|
|
203
|
+
view.rerender(renderEditable(false));
|
|
204
|
+
await new Promise((resolve) => setTimeout(resolve, DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS * 2));
|
|
205
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
206
|
+
|
|
207
|
+
view.rerender(renderEditable(true));
|
|
208
|
+
await new Promise((resolve) => setTimeout(resolve, DOCUMENT_EDITOR_CHANGE_DEBOUNCE_MS * 2));
|
|
177
209
|
expect(onChange).not.toHaveBeenCalled();
|
|
178
210
|
});
|
|
179
211
|
|
|
@@ -123,18 +123,15 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
|
|
|
123
123
|
authFlowRef.current = () => {
|
|
124
124
|
// Make this effect idempotent - only run auth flow once
|
|
125
125
|
if (hasInitiatedAuthRef.current) {
|
|
126
|
-
|
|
126
|
+
Env.logger.debug('Skipping duplicate auth flow initiation');
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
hasInitiatedAuthRef.current = true;
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
Env.logger.info('Starting auth flow');
|
|
131
|
+
Env.logger.debug('Starting auth flow');
|
|
133
132
|
const currentUrl = new URL(window.location.href);
|
|
134
133
|
const { accountId: selectedAccount, projectId: selectedProject } = resolveAuthSelection(currentUrl);
|
|
135
|
-
|
|
136
|
-
console.log('Auth: selected project', selectedProject);
|
|
137
|
-
Env.logger.info('Selected account and project', {
|
|
134
|
+
Env.logger.debug('Selected account and project', {
|
|
138
135
|
vertesia: {
|
|
139
136
|
account_id: selectedAccount,
|
|
140
137
|
project_id: selectedProject,
|
|
@@ -207,20 +204,14 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
|
|
|
207
204
|
|
|
208
205
|
// If the current host is not in the Firebase allowlist, central auth owns sign-in.
|
|
209
206
|
if (!session.isLoggedIn()) {
|
|
210
|
-
|
|
211
|
-
Env.logger.info('Not logged in & no token/state', {
|
|
207
|
+
Env.logger.debug('Not logged in & no token/state', {
|
|
212
208
|
vertesia: {
|
|
213
209
|
account_id: selectedAccount,
|
|
214
210
|
project_id: selectedProject,
|
|
215
211
|
},
|
|
216
212
|
});
|
|
217
213
|
if (shouldRedirectToCentralAuth()) {
|
|
218
|
-
|
|
219
|
-
'Auth: host is not in Firebase auth allowlist, redirecting to central auth with selection',
|
|
220
|
-
selectedAccount,
|
|
221
|
-
selectedProject,
|
|
222
|
-
);
|
|
223
|
-
Env.logger.info('Redirecting to central auth with selection', {
|
|
214
|
+
Env.logger.debug('Redirecting to central auth with selection', {
|
|
224
215
|
vertesia: {
|
|
225
216
|
account_id: selectedAccount,
|
|
226
217
|
project_id: selectedProject,
|
|
@@ -230,8 +221,7 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
|
|
|
230
221
|
return; // Don't register onAuthStateChanged listener when redirecting
|
|
231
222
|
}
|
|
232
223
|
|
|
233
|
-
|
|
234
|
-
Env.logger.info('Host is in Firebase auth allowlist', {
|
|
224
|
+
Env.logger.debug('Host is in Firebase auth allowlist', {
|
|
235
225
|
vertesia: {
|
|
236
226
|
account_id: selectedAccount,
|
|
237
227
|
project_id: selectedProject,
|
|
@@ -241,8 +231,7 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
|
|
|
241
231
|
|
|
242
232
|
unsubscribe = onAuthStateChanged(getFirebaseAuth(), async (firebaseUser) => {
|
|
243
233
|
if (firebaseUser) {
|
|
244
|
-
|
|
245
|
-
Env.logger.info('Successful login with firebase', {
|
|
234
|
+
Env.logger.debug('Successful login with firebase', {
|
|
246
235
|
vertesia: {
|
|
247
236
|
account_id: selectedAccount,
|
|
248
237
|
project_id: selectedProject,
|
|
@@ -274,8 +263,7 @@ export function UserSessionProvider({ children, loadOnboardingStatus = true }: U
|
|
|
274
263
|
});
|
|
275
264
|
} else {
|
|
276
265
|
// anonymous user
|
|
277
|
-
|
|
278
|
-
Env.logger.info('Using anonymous user', {
|
|
266
|
+
Env.logger.debug('Using anonymous user', {
|
|
279
267
|
vertesia: {
|
|
280
268
|
account_id: selectedAccount,
|
|
281
269
|
project_id: selectedProject,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
const logger = { info: vi.fn(), warn: vi.fn(), error: vi.fn() };
|
|
4
|
+
const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() };
|
|
5
5
|
|
|
6
6
|
vi.mock('@vertesia/ui/env', () => ({
|
|
7
7
|
Env: {
|
|
@@ -5,7 +5,7 @@ function makeJwt(payload: Record<string, unknown>) {
|
|
|
5
5
|
return `${encode({ alg: 'ES256', typ: 'JWT' })}.${encode(payload)}.signature`;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
async function importComposableAuth() {
|
|
8
|
+
async function importComposableAuth(authTokenProvider?: () => Promise<string | undefined>) {
|
|
9
9
|
vi.resetModules();
|
|
10
10
|
const [{ Env }, composableAuth] = await Promise.all([import('@vertesia/ui/env'), import('./composable')]);
|
|
11
11
|
Env.init({
|
|
@@ -19,6 +19,7 @@ async function importComposableAuth() {
|
|
|
19
19
|
zeno: 'https://zeno-server-dev-feat-appgen.api.dev1.vertesia.io',
|
|
20
20
|
sts: 'https://sts.dev1.vertesia.io',
|
|
21
21
|
},
|
|
22
|
+
authTokenProvider,
|
|
22
23
|
});
|
|
23
24
|
return composableAuth;
|
|
24
25
|
}
|
|
@@ -53,6 +54,65 @@ describe('getComposableToken', () => {
|
|
|
53
54
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
54
55
|
});
|
|
55
56
|
|
|
57
|
+
it('reacquires a fresh injected token instead of reusing an expired cached credential', async () => {
|
|
58
|
+
const expiredToken = makeJwt({
|
|
59
|
+
iss: 'https://sts.dev1.vertesia.io',
|
|
60
|
+
exp: Math.floor(Date.now() / 1000) - 60,
|
|
61
|
+
account: { id: 'account-id', name: 'Account' },
|
|
62
|
+
project: { id: 'project-id', name: 'Project', account: 'account-id' },
|
|
63
|
+
project_roles: ['developer'],
|
|
64
|
+
});
|
|
65
|
+
const freshToken = makeJwt({
|
|
66
|
+
iss: 'https://sts.dev1.vertesia.io',
|
|
67
|
+
exp: Math.floor(Date.now() / 1000) + 3600,
|
|
68
|
+
account: { id: 'account-id', name: 'Account' },
|
|
69
|
+
project: { id: 'project-id', name: 'Project', account: 'account-id' },
|
|
70
|
+
project_roles: ['developer'],
|
|
71
|
+
});
|
|
72
|
+
const authTokenProvider = vi.fn(() => Promise.resolve(freshToken));
|
|
73
|
+
const fetchMock = vi.fn();
|
|
74
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
75
|
+
|
|
76
|
+
const { getComposableToken } = await importComposableAuth(authTokenProvider);
|
|
77
|
+
const result = await getComposableToken('account-id', 'project-id', expiredToken, false, true);
|
|
78
|
+
|
|
79
|
+
expect(result.rawToken).toBe(freshToken);
|
|
80
|
+
expect(authTokenProvider).toHaveBeenCalledOnce();
|
|
81
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('falls back to the cached credential when the injected provider is unavailable', async () => {
|
|
85
|
+
const expiringToken = makeJwt({
|
|
86
|
+
iss: 'https://sts.dev1.vertesia.io',
|
|
87
|
+
exp: Math.floor(Date.now() / 1000) + 60,
|
|
88
|
+
account: { id: 'account-id', name: 'Account' },
|
|
89
|
+
project: { id: 'project-id', name: 'Project', account: 'account-id' },
|
|
90
|
+
project_roles: ['developer'],
|
|
91
|
+
});
|
|
92
|
+
const refreshedToken = makeJwt({
|
|
93
|
+
iss: 'https://sts.dev1.vertesia.io',
|
|
94
|
+
exp: Math.floor(Date.now() / 1000) + 3600,
|
|
95
|
+
account: { id: 'account-id', name: 'Account' },
|
|
96
|
+
project: { id: 'project-id', name: 'Project', account: 'account-id' },
|
|
97
|
+
project_roles: ['developer'],
|
|
98
|
+
});
|
|
99
|
+
const authTokenProvider = vi.fn(() => Promise.resolve(undefined));
|
|
100
|
+
const fetchMock = vi.fn().mockResolvedValue({
|
|
101
|
+
ok: true,
|
|
102
|
+
status: 200,
|
|
103
|
+
json: () => Promise.resolve({ token: refreshedToken }),
|
|
104
|
+
});
|
|
105
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
106
|
+
|
|
107
|
+
const { getComposableToken } = await importComposableAuth(authTokenProvider);
|
|
108
|
+
const result = await getComposableToken('account-id', 'project-id', expiringToken, false, true);
|
|
109
|
+
|
|
110
|
+
expect(result.rawToken).toBe(refreshedToken);
|
|
111
|
+
expect(authTokenProvider).toHaveBeenCalledOnce();
|
|
112
|
+
expect(fetchMock).toHaveBeenCalledOnce();
|
|
113
|
+
expect(fetchMock.mock.calls[0]?.[1]?.headers).toMatchObject({ Authorization: `Bearer ${expiringToken}` });
|
|
114
|
+
});
|
|
115
|
+
|
|
56
116
|
it('exchanges a bare STS-issued Vertesia token so roles can be hydrated', async () => {
|
|
57
117
|
const sourceToken = makeJwt({
|
|
58
118
|
iss: 'https://sts.dev1.vertesia.io',
|
|
@@ -92,6 +92,9 @@ function isVertesiaIssuedToken(token: string | undefined): token is string {
|
|
|
92
92
|
|
|
93
93
|
function canUseVertesiaTokenDirectly(token: string, accountId?: string, projectId?: string): boolean {
|
|
94
94
|
const decoded = decodeToken(token);
|
|
95
|
+
if (!decoded.exp || decoded.exp <= Date.now() / 1000 + 300) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
95
98
|
const hasAuthorizationClaims = Boolean(
|
|
96
99
|
decoded.permissions?.length ||
|
|
97
100
|
decoded.account_roles?.length ||
|
|
@@ -117,8 +120,7 @@ export async function fetchComposableToken(
|
|
|
117
120
|
ttl?: number,
|
|
118
121
|
retryCount = 0,
|
|
119
122
|
): Promise<string> {
|
|
120
|
-
|
|
121
|
-
Env.logger.info('Getting/refreshing composable token', {
|
|
123
|
+
Env.logger.debug('Getting/refreshing composable token', {
|
|
122
124
|
vertesia: {
|
|
123
125
|
account_id: accountId,
|
|
124
126
|
project_id: projectId,
|
|
@@ -128,14 +130,12 @@ export async function fetchComposableToken(
|
|
|
128
130
|
|
|
129
131
|
const idToken = await getIdToken(); //get from firebase
|
|
130
132
|
if (!idToken) {
|
|
131
|
-
console.log('No id token found - using cookie auth');
|
|
132
133
|
throw new Error('No id token found');
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
// Use STS endpoint - either configured or default to sts.vertesia.io
|
|
136
137
|
const stsEndpoint = Env.endpoints.sts;
|
|
137
|
-
|
|
138
|
-
Env.logger.info('Using STS for token generation', {
|
|
138
|
+
Env.logger.debug('Using STS for token generation', {
|
|
139
139
|
vertesia: {
|
|
140
140
|
account_id: accountId,
|
|
141
141
|
project_id: projectId,
|
|
@@ -176,8 +176,7 @@ export async function fetchComposableToken(
|
|
|
176
176
|
|
|
177
177
|
if (idToken && stsRes?.status === 404) {
|
|
178
178
|
// User not found in token-server - call ensure-user endpoint
|
|
179
|
-
|
|
180
|
-
Env.logger.info('404: User not found - calling ensure-user endpoint', {
|
|
179
|
+
Env.logger.debug('404: User not found - calling ensure-user endpoint', {
|
|
181
180
|
vertesia: {
|
|
182
181
|
account_id: accountId,
|
|
183
182
|
project_id: projectId,
|
|
@@ -195,8 +194,7 @@ export async function fetchComposableToken(
|
|
|
195
194
|
|
|
196
195
|
if (ensureResponse.status === 412) {
|
|
197
196
|
// No invite - trigger signup
|
|
198
|
-
|
|
199
|
-
Env.logger.info('412: No invite found - signup required', {
|
|
197
|
+
Env.logger.debug('412: No invite found - signup required', {
|
|
200
198
|
vertesia: {
|
|
201
199
|
account_id: accountId,
|
|
202
200
|
project_id: projectId,
|
|
@@ -234,8 +232,7 @@ export async function fetchComposableToken(
|
|
|
234
232
|
}
|
|
235
233
|
|
|
236
234
|
// User created/exists - retry token generation
|
|
237
|
-
|
|
238
|
-
Env.logger.info('User ensured - retrying token generation', {
|
|
235
|
+
Env.logger.debug('User ensured - retrying token generation', {
|
|
239
236
|
vertesia: {
|
|
240
237
|
account_id: accountId,
|
|
241
238
|
project_id: projectId,
|
|
@@ -245,8 +242,7 @@ export async function fetchComposableToken(
|
|
|
245
242
|
}
|
|
246
243
|
|
|
247
244
|
if (idToken && stsRes?.status === 412) {
|
|
248
|
-
|
|
249
|
-
Env.logger.error("412: auth succeeded but user doesn't exist - signup required", {
|
|
245
|
+
Env.logger.info("412: auth succeeded but user doesn't exist - signup required", {
|
|
250
246
|
vertesia: {
|
|
251
247
|
account_id: accountId,
|
|
252
248
|
project_id: projectId,
|
|
@@ -258,7 +254,7 @@ export async function fetchComposableToken(
|
|
|
258
254
|
Env.logger.error('No email found in id token');
|
|
259
255
|
throw new Error('No email found in id token');
|
|
260
256
|
}
|
|
261
|
-
Env.logger.
|
|
257
|
+
Env.logger.info('User not found', {
|
|
262
258
|
vertesia: {
|
|
263
259
|
account_id: accountId,
|
|
264
260
|
project_id: projectId,
|
|
@@ -354,8 +350,7 @@ export async function fetchComposableToken(
|
|
|
354
350
|
}
|
|
355
351
|
|
|
356
352
|
const { token } = await stsRes.json();
|
|
357
|
-
|
|
358
|
-
Env.logger.info('Successfully got token from STS');
|
|
353
|
+
Env.logger.debug('Successfully got token from STS');
|
|
359
354
|
return token;
|
|
360
355
|
} catch (error) {
|
|
361
356
|
if (
|
|
@@ -460,13 +455,24 @@ export async function getComposableToken(
|
|
|
460
455
|
if (!devAuthToken && !useInternalAuth && getFirebaseAuth().currentUser) {
|
|
461
456
|
//we have a firebase user, get the token from there
|
|
462
457
|
AUTH_TOKEN_RAW = await fetchComposableTokenFromFirebaseToken(selectedAccount, selectedProject);
|
|
463
|
-
} else if (!devAuthToken
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
458
|
+
} else if (!devAuthToken) {
|
|
459
|
+
// Embedded apps can reacquire a fresh credential from their host after their cached token expires.
|
|
460
|
+
const refreshCredential = (await Env.authTokenProvider?.()) ?? initToken ?? AUTH_TOKEN_RAW;
|
|
461
|
+
if (
|
|
462
|
+
refreshCredential &&
|
|
463
|
+
isVertesiaIssuedToken(refreshCredential) &&
|
|
464
|
+
canUseVertesiaTokenDirectly(refreshCredential, selectedAccount, selectedProject)
|
|
465
|
+
) {
|
|
466
|
+
AUTH_TOKEN_RAW = refreshCredential;
|
|
467
|
+
} else if (refreshCredential) {
|
|
468
|
+
AUTH_TOKEN_RAW = await fetchComposableToken(
|
|
469
|
+
() => Promise.resolve(refreshCredential),
|
|
470
|
+
selectedAccount,
|
|
471
|
+
selectedProject,
|
|
472
|
+
);
|
|
473
|
+
} else {
|
|
474
|
+
AUTH_TOKEN_RAW = undefined;
|
|
475
|
+
}
|
|
470
476
|
} else if (devAuthToken) {
|
|
471
477
|
AUTH_TOKEN_RAW = devAuthToken;
|
|
472
478
|
}
|
|
@@ -139,7 +139,7 @@ export async function getFirebaseAuthToken(refresh?: boolean) {
|
|
|
139
139
|
return user
|
|
140
140
|
.getIdToken(refresh)
|
|
141
141
|
.then((token) => {
|
|
142
|
-
Env.logger.
|
|
142
|
+
Env.logger.debug('Got Firebase token', {
|
|
143
143
|
vertesia: {
|
|
144
144
|
user_email: user.email,
|
|
145
145
|
user_name: user.displayName,
|
|
@@ -3,6 +3,7 @@ import { TypeRegistryProvider, UserPermissionProvider } from '@vertesia/ui/featu
|
|
|
3
3
|
import { LanguageBoundI18nProvider, LanguageProvider, type SupportedLanguage } from '@vertesia/ui/i18n';
|
|
4
4
|
import { DevSessionProvider, UserSessionProvider } from '@vertesia/ui/session';
|
|
5
5
|
import type { ReactNode } from 'react';
|
|
6
|
+
import { IframeAppContextSync } from './apps/IframeAppContextSync.js';
|
|
6
7
|
import { SigninScreen } from './login/SigninScreen';
|
|
7
8
|
import { SplashScreen } from './SplashScreen';
|
|
8
9
|
|
|
@@ -35,6 +36,7 @@ export function VertesiaShell({
|
|
|
35
36
|
<ThemeProvider defaultTheme="system" storageKey="vite-ui-theme">
|
|
36
37
|
<LanguageProvider defaultLanguage={defaultLanguage}>
|
|
37
38
|
<LanguageBoundI18nProvider>
|
|
39
|
+
<IframeAppContextSync />
|
|
38
40
|
{!authToken && (
|
|
39
41
|
<>
|
|
40
42
|
<SplashScreen icon={loadingIcon} />
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { act, cleanup, render, screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { ThemeProvider, useTheme } from '../../core/index.js';
|
|
6
|
+
import { LanguageProvider, useLanguage } from '../../i18n/index.js';
|
|
7
|
+
import { IframeAppContextSync } from './IframeAppContextSync.js';
|
|
8
|
+
import {
|
|
9
|
+
IFRAME_APP_CONTEXT,
|
|
10
|
+
IFRAME_APP_CONTEXT_REQUEST,
|
|
11
|
+
IFRAME_APP_HOST_ORIGIN_PARAM,
|
|
12
|
+
IFRAME_APP_LOCATION_CHANGE,
|
|
13
|
+
IFRAME_APP_NAVIGATE,
|
|
14
|
+
} from './iframe-auth.js';
|
|
15
|
+
|
|
16
|
+
const originalParent = Object.getOwnPropertyDescriptor(window, 'parent');
|
|
17
|
+
const originalReferrer = Object.getOwnPropertyDescriptor(document, 'referrer');
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
cleanup();
|
|
21
|
+
window.history.replaceState(null, '', '/');
|
|
22
|
+
localStorage.clear();
|
|
23
|
+
sessionStorage.clear();
|
|
24
|
+
document.documentElement.classList.remove('light', 'dark');
|
|
25
|
+
if (originalParent) Object.defineProperty(window, 'parent', originalParent);
|
|
26
|
+
else Reflect.deleteProperty(window, 'parent');
|
|
27
|
+
if (originalReferrer) Object.defineProperty(document, 'referrer', originalReferrer);
|
|
28
|
+
else Reflect.deleteProperty(document, 'referrer');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function ContextProbe() {
|
|
32
|
+
const { theme } = useTheme();
|
|
33
|
+
const { language } = useLanguage();
|
|
34
|
+
return <div>{`${theme}:${language}`}</div>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('IframeAppContextSync', () => {
|
|
38
|
+
it('requests and applies host presentation state without overwriting standalone preferences', async () => {
|
|
39
|
+
const postMessage = vi.fn();
|
|
40
|
+
const parentWindow = { postMessage } as unknown as Window;
|
|
41
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
42
|
+
Object.defineProperty(document, 'referrer', {
|
|
43
|
+
configurable: true,
|
|
44
|
+
value: 'https://cloud.vertesia.io/app/sample',
|
|
45
|
+
});
|
|
46
|
+
localStorage.setItem('custom-theme', 'dark');
|
|
47
|
+
localStorage.setItem('custom-language', 'en');
|
|
48
|
+
|
|
49
|
+
render(
|
|
50
|
+
<ThemeProvider storageKey="custom-theme">
|
|
51
|
+
<LanguageProvider storageKey="custom-language">
|
|
52
|
+
<IframeAppContextSync />
|
|
53
|
+
<ContextProbe />
|
|
54
|
+
</LanguageProvider>
|
|
55
|
+
</ThemeProvider>,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
expect(parentWindow.postMessage).toHaveBeenCalledWith(
|
|
59
|
+
{ type: IFRAME_APP_CONTEXT_REQUEST },
|
|
60
|
+
'https://cloud.vertesia.io',
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
window.dispatchEvent(
|
|
64
|
+
new MessageEvent('message', {
|
|
65
|
+
data: { type: IFRAME_APP_CONTEXT, theme: 'light', language: 'fr' },
|
|
66
|
+
origin: 'https://attacker.example.com',
|
|
67
|
+
source: parentWindow,
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
expect(screen.getByText('dark:en')).toBeTruthy();
|
|
71
|
+
|
|
72
|
+
act(() => {
|
|
73
|
+
window.dispatchEvent(
|
|
74
|
+
new MessageEvent('message', {
|
|
75
|
+
data: { type: IFRAME_APP_CONTEXT, theme: 'light', language: 'fr' },
|
|
76
|
+
origin: 'https://cloud.vertesia.io',
|
|
77
|
+
source: parentWindow,
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await waitFor(() => expect(screen.getByText('light:fr')).toBeTruthy());
|
|
83
|
+
expect(localStorage.getItem('custom-theme')).toBe('dark');
|
|
84
|
+
expect(localStorage.getItem('custom-language')).toBe('en');
|
|
85
|
+
expect(postMessage.mock.calls.filter(([message]) => message.type === IFRAME_APP_CONTEXT_REQUEST)).toHaveLength(
|
|
86
|
+
1,
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('applies same-origin host navigation without reloading the document', () => {
|
|
91
|
+
const parentWindow = { postMessage: vi.fn() } as unknown as Window;
|
|
92
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
93
|
+
Object.defineProperty(document, 'referrer', {
|
|
94
|
+
configurable: true,
|
|
95
|
+
value: 'https://cloud.vertesia.io/app/sample',
|
|
96
|
+
});
|
|
97
|
+
localStorage.setItem('vite-ui-theme', 'dark');
|
|
98
|
+
localStorage.setItem('vertesia-ui-language', 'en');
|
|
99
|
+
window.history.replaceState(null, '', '/app/');
|
|
100
|
+
const popstate = vi.fn();
|
|
101
|
+
window.addEventListener('popstate', popstate);
|
|
102
|
+
|
|
103
|
+
render(
|
|
104
|
+
<ThemeProvider>
|
|
105
|
+
<LanguageProvider>
|
|
106
|
+
<IframeAppContextSync />
|
|
107
|
+
</LanguageProvider>
|
|
108
|
+
</ThemeProvider>,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
window.dispatchEvent(
|
|
112
|
+
new MessageEvent('message', {
|
|
113
|
+
data: { type: IFRAME_APP_NAVIGATE, url: 'https://attacker.example.com/stolen' },
|
|
114
|
+
origin: 'https://cloud.vertesia.io',
|
|
115
|
+
source: parentWindow,
|
|
116
|
+
}),
|
|
117
|
+
);
|
|
118
|
+
expect(window.location.pathname).toBe('/app/');
|
|
119
|
+
|
|
120
|
+
const target = `${window.location.origin}/app/reports?__vertesia_slot=content`;
|
|
121
|
+
window.dispatchEvent(
|
|
122
|
+
new MessageEvent('message', {
|
|
123
|
+
data: { type: IFRAME_APP_NAVIGATE, url: target },
|
|
124
|
+
origin: 'https://cloud.vertesia.io',
|
|
125
|
+
source: parentWindow,
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(window.location.pathname).toBe('/app/reports');
|
|
130
|
+
expect(window.location.search).toBe('?__vertesia_slot=content');
|
|
131
|
+
expect(popstate).toHaveBeenCalledTimes(1);
|
|
132
|
+
window.removeEventListener('popstate', popstate);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('acknowledges host navigation when the iframe is already at the requested URL', () => {
|
|
136
|
+
const parentWindow = { postMessage: vi.fn() } as unknown as Window;
|
|
137
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
138
|
+
localStorage.setItem('vite-ui-theme', 'dark');
|
|
139
|
+
window.history.replaceState(
|
|
140
|
+
null,
|
|
141
|
+
'',
|
|
142
|
+
`/app/reports?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
render(
|
|
146
|
+
<ThemeProvider>
|
|
147
|
+
<LanguageProvider>
|
|
148
|
+
<IframeAppContextSync />
|
|
149
|
+
</LanguageProvider>
|
|
150
|
+
</ThemeProvider>,
|
|
151
|
+
);
|
|
152
|
+
parentWindow.postMessage = vi.fn();
|
|
153
|
+
|
|
154
|
+
window.dispatchEvent(
|
|
155
|
+
new MessageEvent('message', {
|
|
156
|
+
data: { type: IFRAME_APP_NAVIGATE, url: window.location.href },
|
|
157
|
+
origin: 'https://cloud.vertesia.io',
|
|
158
|
+
source: parentWindow,
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
expect(parentWindow.postMessage).toHaveBeenCalledWith(
|
|
163
|
+
{ type: IFRAME_APP_LOCATION_CHANGE, url: window.location.href },
|
|
164
|
+
'https://cloud.vertesia.io',
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('reports app-initiated history navigation to the embedding Studio', () => {
|
|
169
|
+
const parentWindow = { postMessage: vi.fn() } as unknown as Window;
|
|
170
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
171
|
+
window.history.replaceState(null, '', `/app/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
|
|
172
|
+
localStorage.setItem('vite-ui-theme', 'dark');
|
|
173
|
+
localStorage.setItem('vertesia-ui-language', 'en');
|
|
174
|
+
|
|
175
|
+
render(
|
|
176
|
+
<ThemeProvider>
|
|
177
|
+
<LanguageProvider>
|
|
178
|
+
<IframeAppContextSync />
|
|
179
|
+
</LanguageProvider>
|
|
180
|
+
</ThemeProvider>,
|
|
181
|
+
);
|
|
182
|
+
parentWindow.postMessage = vi.fn();
|
|
183
|
+
|
|
184
|
+
window.history.pushState(null, '', '/app/reports?period=week');
|
|
185
|
+
|
|
186
|
+
expect(parentWindow.postMessage).toHaveBeenCalledWith(
|
|
187
|
+
{
|
|
188
|
+
type: IFRAME_APP_LOCATION_CHANGE,
|
|
189
|
+
url:
|
|
190
|
+
`${window.location.origin}/app/reports?period=week&` +
|
|
191
|
+
`${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`,
|
|
192
|
+
},
|
|
193
|
+
'https://cloud.vertesia.io',
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
});
|