@vertesia/ui 1.5.0-dev.20260806.125520Z → 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 +332 -0
- package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
- package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +331 -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 +25 -30
- 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
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useTheme } from '../../core/components/shadcn/theme/ThemeProvider.js';
|
|
3
|
+
import { useLanguage } from '../../i18n/LanguageProvider.js';
|
|
4
|
+
import {
|
|
5
|
+
IFRAME_APP_CONTEXT_REQUEST,
|
|
6
|
+
IFRAME_APP_HOST_ORIGIN_PARAM,
|
|
7
|
+
IFRAME_APP_LOCATION_CHANGE,
|
|
8
|
+
type IframeAppContextRequest,
|
|
9
|
+
type IframeAppLocationChange,
|
|
10
|
+
isIframeAppContext,
|
|
11
|
+
isIframeAppNavigate,
|
|
12
|
+
resolveIframeHostOrigin,
|
|
13
|
+
} from './iframe-auth.js';
|
|
14
|
+
|
|
15
|
+
function preserveIframeHostOrigin(url: string | URL | null | undefined): string | URL | null | undefined {
|
|
16
|
+
if (url === null || url === undefined) return url;
|
|
17
|
+
const hostOrigin = new URL(window.location.href).searchParams.get(IFRAME_APP_HOST_ORIGIN_PARAM);
|
|
18
|
+
if (!hostOrigin) return url;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const target = new URL(url, window.location.href);
|
|
22
|
+
if (target.origin !== window.location.origin) return url;
|
|
23
|
+
target.searchParams.set(IFRAME_APP_HOST_ORIGIN_PARAM, hostOrigin);
|
|
24
|
+
return target;
|
|
25
|
+
} catch {
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Applies context and navigation supplied by an embedding Studio without changing standalone preferences. */
|
|
31
|
+
export function IframeAppContextSync() {
|
|
32
|
+
const { setTheme } = useTheme();
|
|
33
|
+
const { setLanguage } = useLanguage();
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const parentOrigin = resolveIframeHostOrigin();
|
|
37
|
+
if (!parentOrigin) return;
|
|
38
|
+
|
|
39
|
+
const reportLocation = () => {
|
|
40
|
+
const message = {
|
|
41
|
+
type: IFRAME_APP_LOCATION_CHANGE,
|
|
42
|
+
url: window.location.href,
|
|
43
|
+
} satisfies IframeAppLocationChange;
|
|
44
|
+
window.parent.postMessage(message, parentOrigin);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const originalPushState = window.history.pushState;
|
|
48
|
+
const originalReplaceState = window.history.replaceState;
|
|
49
|
+
const pushState: History['pushState'] = (data, unused, url) => {
|
|
50
|
+
originalPushState.call(window.history, data, unused, preserveIframeHostOrigin(url));
|
|
51
|
+
reportLocation();
|
|
52
|
+
};
|
|
53
|
+
const replaceState: History['replaceState'] = (data, unused, url) => {
|
|
54
|
+
originalReplaceState.call(window.history, data, unused, preserveIframeHostOrigin(url));
|
|
55
|
+
reportLocation();
|
|
56
|
+
};
|
|
57
|
+
window.history.pushState = pushState;
|
|
58
|
+
window.history.replaceState = replaceState;
|
|
59
|
+
|
|
60
|
+
const onMessage = (event: MessageEvent<unknown>) => {
|
|
61
|
+
if (event.source !== window.parent || event.origin !== parentOrigin) return;
|
|
62
|
+
if (isIframeAppContext(event.data)) {
|
|
63
|
+
const context = event.data;
|
|
64
|
+
setTheme(context.theme, { persist: false });
|
|
65
|
+
setLanguage(context.language, { persist: false });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (isIframeAppNavigate(event.data)) {
|
|
69
|
+
let target: URL;
|
|
70
|
+
try {
|
|
71
|
+
target = new URL(event.data.url, window.location.href);
|
|
72
|
+
} catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (target.origin !== window.location.origin) return;
|
|
76
|
+
if (target.href === window.location.href) {
|
|
77
|
+
// Acknowledge no-op navigation so the host does not wait forever and suppress later app routing.
|
|
78
|
+
reportLocation();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
window.history.replaceState(window.history.state, '', target);
|
|
82
|
+
window.dispatchEvent(new PopStateEvent('popstate', { state: window.history.state }));
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const request = { type: IFRAME_APP_CONTEXT_REQUEST } satisfies IframeAppContextRequest;
|
|
86
|
+
window.addEventListener('message', onMessage);
|
|
87
|
+
window.addEventListener('popstate', reportLocation);
|
|
88
|
+
window.addEventListener('hashchange', reportLocation);
|
|
89
|
+
window.parent.postMessage(request, parentOrigin);
|
|
90
|
+
reportLocation();
|
|
91
|
+
return () => {
|
|
92
|
+
window.removeEventListener('message', onMessage);
|
|
93
|
+
window.removeEventListener('popstate', reportLocation);
|
|
94
|
+
window.removeEventListener('hashchange', reportLocation);
|
|
95
|
+
if (window.history.pushState === pushState) window.history.pushState = originalPushState;
|
|
96
|
+
if (window.history.replaceState === replaceState) window.history.replaceState = originalReplaceState;
|
|
97
|
+
};
|
|
98
|
+
}, [setLanguage, setTheme]);
|
|
99
|
+
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import {
|
|
5
|
+
IFRAME_APP_HOST_ORIGIN_PARAM,
|
|
6
|
+
IFRAME_AUTH_REQUEST,
|
|
7
|
+
IFRAME_AUTH_RESPONSE,
|
|
8
|
+
requestIframeHostAuthToken,
|
|
9
|
+
resolveIframeHostOrigin,
|
|
10
|
+
} from './iframe-auth.js';
|
|
11
|
+
|
|
12
|
+
const originalParent = Object.getOwnPropertyDescriptor(window, 'parent');
|
|
13
|
+
const originalReferrer = Object.getOwnPropertyDescriptor(document, 'referrer');
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
window.history.replaceState(null, '', '/');
|
|
17
|
+
window.sessionStorage.clear();
|
|
18
|
+
if (originalParent) Object.defineProperty(window, 'parent', originalParent);
|
|
19
|
+
else Reflect.deleteProperty(window, 'parent');
|
|
20
|
+
if (originalReferrer) Object.defineProperty(document, 'referrer', originalReferrer);
|
|
21
|
+
else Reflect.deleteProperty(document, 'referrer');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('iframe host authentication', () => {
|
|
25
|
+
it('resolves an explicit trusted host origin', () => {
|
|
26
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
27
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
28
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
|
|
29
|
+
|
|
30
|
+
expect(resolveIframeHostOrigin()).toBe('https://cloud.vertesia.io');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('accepts a branch Studio UI origin', () => {
|
|
34
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
35
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
36
|
+
window.history.replaceState(
|
|
37
|
+
null,
|
|
38
|
+
'',
|
|
39
|
+
`/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fdev-feat-iframe.ui.dev1.vertesia.io`,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
expect(resolveIframeHostOrigin()).toBe('https://dev-feat-iframe.ui.dev1.vertesia.io');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('rejects untrusted query and referrer origins', () => {
|
|
46
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
47
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
48
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fevil.example.com`);
|
|
49
|
+
Object.defineProperty(document, 'referrer', {
|
|
50
|
+
configurable: true,
|
|
51
|
+
value: 'https://referrer.example.com/embed',
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(resolveIframeHostOrigin()).toBeUndefined();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('rejects a shared Vertesia app-gateway origin', () => {
|
|
58
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
59
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
60
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fapps.dev1.vertesia.io`);
|
|
61
|
+
|
|
62
|
+
expect(resolveIframeHostOrigin()).toBeUndefined();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('rejects an origin containing embedded credentials', () => {
|
|
66
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
67
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
68
|
+
window.history.replaceState(
|
|
69
|
+
null,
|
|
70
|
+
'',
|
|
71
|
+
`/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fuser%3Asecret%40cloud.vertesia.io`,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(resolveIframeHostOrigin()).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('accepts a loopback host for a loopback child app', () => {
|
|
78
|
+
const parentWindow = { postMessage: () => undefined } as unknown as Window;
|
|
79
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
80
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=http%3A%2F%2Flocalhost%3A5173`);
|
|
81
|
+
|
|
82
|
+
expect(resolveIframeHostOrigin()).toBe('http://localhost:5173');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('ignores an empty early response and waits for a usable host token', async () => {
|
|
86
|
+
const requests: unknown[] = [];
|
|
87
|
+
const parentWindow = { postMessage: (message: unknown) => requests.push(message) } as unknown as Window;
|
|
88
|
+
Object.defineProperty(window, 'parent', { configurable: true, value: parentWindow });
|
|
89
|
+
window.history.replaceState(null, '', `/?${IFRAME_APP_HOST_ORIGIN_PARAM}=https%3A%2F%2Fcloud.vertesia.io`);
|
|
90
|
+
|
|
91
|
+
let settled = false;
|
|
92
|
+
const tokenPromise = requestIframeHostAuthToken().then((token) => {
|
|
93
|
+
settled = true;
|
|
94
|
+
return token;
|
|
95
|
+
});
|
|
96
|
+
const request = requests[0] as { type: string; requestId: string };
|
|
97
|
+
expect(request.type).toBe(IFRAME_AUTH_REQUEST);
|
|
98
|
+
|
|
99
|
+
window.dispatchEvent(
|
|
100
|
+
new MessageEvent('message', {
|
|
101
|
+
data: { type: IFRAME_AUTH_RESPONSE, requestId: request.requestId },
|
|
102
|
+
origin: 'https://cloud.vertesia.io',
|
|
103
|
+
source: parentWindow,
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
await Promise.resolve();
|
|
107
|
+
expect(settled).toBe(false);
|
|
108
|
+
|
|
109
|
+
window.dispatchEvent(
|
|
110
|
+
new MessageEvent('message', {
|
|
111
|
+
data: { type: IFRAME_AUTH_RESPONSE, requestId: request.requestId, token: 'fresh-token' },
|
|
112
|
+
origin: 'https://cloud.vertesia.io',
|
|
113
|
+
source: parentWindow,
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
await expect(tokenPromise).resolves.toBe('fresh-token');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { SUPPORTED_LANGUAGES, type SupportedLanguage } from '../../i18n/rtl.js';
|
|
2
|
+
|
|
3
|
+
export const IFRAME_AUTH_REQUEST = 'vertesia:iframe-auth-request';
|
|
4
|
+
export const IFRAME_AUTH_RESPONSE = 'vertesia:iframe-auth-response';
|
|
5
|
+
export const IFRAME_APP_CONTEXT_REQUEST = 'vertesia:iframe-context-request';
|
|
6
|
+
export const IFRAME_APP_CONTEXT = 'vertesia:iframe-context';
|
|
7
|
+
export const IFRAME_APP_NAVIGATE = 'vertesia:iframe-navigate';
|
|
8
|
+
export const IFRAME_APP_LOCATION_CHANGE = 'vertesia:iframe-location-change';
|
|
9
|
+
export const IFRAME_APP_SLOT_PARAM = '__vertesia_slot';
|
|
10
|
+
export const IFRAME_APP_HOST_ORIGIN_PARAM = '__vertesia_host_origin';
|
|
11
|
+
export const IFRAME_APP_CONTENT_SLOT = 'content';
|
|
12
|
+
|
|
13
|
+
export interface IframeAuthRequest {
|
|
14
|
+
type: typeof IFRAME_AUTH_REQUEST;
|
|
15
|
+
requestId: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface IframeAuthResponse {
|
|
19
|
+
type: typeof IFRAME_AUTH_RESPONSE;
|
|
20
|
+
requestId: string;
|
|
21
|
+
token?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface IframeAppContextRequest {
|
|
25
|
+
type: typeof IFRAME_APP_CONTEXT_REQUEST;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface IframeAppContext {
|
|
29
|
+
type: typeof IFRAME_APP_CONTEXT;
|
|
30
|
+
theme: 'dark' | 'light' | 'system';
|
|
31
|
+
language: SupportedLanguage;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface IframeAppNavigate {
|
|
35
|
+
type: typeof IFRAME_APP_NAVIGATE;
|
|
36
|
+
url: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface IframeAppLocationChange {
|
|
40
|
+
type: typeof IFRAME_APP_LOCATION_CHANGE;
|
|
41
|
+
url: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isIframeAuthRequest(value: unknown): value is IframeAuthRequest {
|
|
45
|
+
if (!value || typeof value !== 'object') return false;
|
|
46
|
+
const message = value as Partial<IframeAuthRequest>;
|
|
47
|
+
return message.type === IFRAME_AUTH_REQUEST && typeof message.requestId === 'string' && !!message.requestId;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isIframeAuthResponse(value: unknown): value is IframeAuthResponse {
|
|
51
|
+
if (!value || typeof value !== 'object') return false;
|
|
52
|
+
const message = value as Partial<IframeAuthResponse>;
|
|
53
|
+
return (
|
|
54
|
+
message.type === IFRAME_AUTH_RESPONSE &&
|
|
55
|
+
typeof message.requestId === 'string' &&
|
|
56
|
+
!!message.requestId &&
|
|
57
|
+
(message.token === undefined || typeof message.token === 'string')
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function isIframeAppContextRequest(value: unknown): value is IframeAppContextRequest {
|
|
62
|
+
if (!value || typeof value !== 'object') return false;
|
|
63
|
+
return (value as Partial<IframeAppContextRequest>).type === IFRAME_APP_CONTEXT_REQUEST;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function isIframeAppContext(value: unknown): value is IframeAppContext {
|
|
67
|
+
if (!value || typeof value !== 'object') return false;
|
|
68
|
+
const message = value as Partial<IframeAppContext>;
|
|
69
|
+
return (
|
|
70
|
+
message.type === IFRAME_APP_CONTEXT &&
|
|
71
|
+
(message.theme === 'dark' || message.theme === 'light' || message.theme === 'system') &&
|
|
72
|
+
typeof message.language === 'string' &&
|
|
73
|
+
(SUPPORTED_LANGUAGES as readonly string[]).includes(message.language)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function isIframeAppNavigate(value: unknown): value is IframeAppNavigate {
|
|
78
|
+
if (!value || typeof value !== 'object') return false;
|
|
79
|
+
const message = value as Partial<IframeAppNavigate>;
|
|
80
|
+
return message.type === IFRAME_APP_NAVIGATE && typeof message.url === 'string' && !!message.url;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function isIframeAppLocationChange(value: unknown): value is IframeAppLocationChange {
|
|
84
|
+
if (!value || typeof value !== 'object') return false;
|
|
85
|
+
const message = value as Partial<IframeAppLocationChange>;
|
|
86
|
+
return message.type === IFRAME_APP_LOCATION_CHANGE && typeof message.url === 'string' && !!message.url;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
90
|
+
|
|
91
|
+
function parseHttpOrigin(value: string | null | undefined): URL | undefined {
|
|
92
|
+
if (!value) return undefined;
|
|
93
|
+
try {
|
|
94
|
+
const url = new URL(value);
|
|
95
|
+
const isLoopback = LOOPBACK_HOSTS.has(url.hostname);
|
|
96
|
+
return url.protocol === 'https:' || (url.protocol === 'http:' && isLoopback) ? url : undefined;
|
|
97
|
+
} catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function hasEmbeddedCredentials(value: string | null | undefined): boolean {
|
|
103
|
+
if (!value) return false;
|
|
104
|
+
const normalized = value.trim();
|
|
105
|
+
const schemeEnd = normalized.indexOf('://');
|
|
106
|
+
if (schemeEnd < 0) return false;
|
|
107
|
+
|
|
108
|
+
const authorityStart = schemeEnd + 3;
|
|
109
|
+
const authoritySuffix = normalized.slice(authorityStart);
|
|
110
|
+
const authorityEnd = authoritySuffix.search(/[/?#]/);
|
|
111
|
+
const authority = authorityEnd < 0 ? authoritySuffix : authoritySuffix.slice(0, authorityEnd);
|
|
112
|
+
return authority.includes('@');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isVertesiaStudioHost(host: string): boolean {
|
|
116
|
+
if (host === 'studio.vertesia.io') return true;
|
|
117
|
+
|
|
118
|
+
const labels = host.split('.');
|
|
119
|
+
if (labels.at(-2) !== 'vertesia' || labels.at(-1) !== 'io') return false;
|
|
120
|
+
|
|
121
|
+
const platformLabels = labels.slice(0, -2);
|
|
122
|
+
const cloudIndex = platformLabels.lastIndexOf('cloud');
|
|
123
|
+
if (cloudIndex >= 0 && platformLabels.length - cloudIndex <= 2) return true;
|
|
124
|
+
|
|
125
|
+
const uiIndex = platformLabels.lastIndexOf('ui');
|
|
126
|
+
return uiIndex >= 0 && platformLabels.length - uiIndex === 2;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function parseTrustedIframeHostOrigin(value: string | null | undefined): string | undefined {
|
|
130
|
+
if (hasEmbeddedCredentials(value)) return undefined;
|
|
131
|
+
const url = parseHttpOrigin(value);
|
|
132
|
+
if (!url) return undefined;
|
|
133
|
+
|
|
134
|
+
const host = url.hostname;
|
|
135
|
+
const isStudioHost = isVertesiaStudioHost(host);
|
|
136
|
+
const isLocalDevelopment = LOOPBACK_HOSTS.has(host) && LOOPBACK_HOSTS.has(window.location.hostname);
|
|
137
|
+
return (url.protocol === 'https:' && isStudioHost) || isLocalDevelopment ? url.origin : undefined;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Resolve a trusted embedding Studio origin without relying on referrer surviving a reload or auth redirect.
|
|
142
|
+
* The URL value is a continuity hint rather than a trust anchor: only Studio UI host patterns are accepted, and
|
|
143
|
+
* loopback parents are accepted only when the child app is also running on loopback.
|
|
144
|
+
*/
|
|
145
|
+
export function resolveIframeHostOrigin(): string | undefined {
|
|
146
|
+
if (window.parent === window) return undefined;
|
|
147
|
+
|
|
148
|
+
const explicitOrigin = parseTrustedIframeHostOrigin(
|
|
149
|
+
new URL(window.location.href).searchParams.get(IFRAME_APP_HOST_ORIGIN_PARAM),
|
|
150
|
+
);
|
|
151
|
+
if (explicitOrigin) return explicitOrigin;
|
|
152
|
+
|
|
153
|
+
return parseTrustedIframeHostOrigin(document.referrer);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Ask an embedding Studio window for a fresh Vertesia token. Both sides validate the request nonce,
|
|
158
|
+
* source window, and exact origin. The explicit host-origin parameter survives framed redirects and
|
|
159
|
+
* hard navigations; referrer remains a compatibility fallback for older hosts.
|
|
160
|
+
* Standalone/top-level apps return undefined and continue through the normal sign-in flow.
|
|
161
|
+
*/
|
|
162
|
+
export function requestIframeHostAuthToken(timeoutMs = 5000): Promise<string | undefined> {
|
|
163
|
+
const parentOrigin = resolveIframeHostOrigin();
|
|
164
|
+
if (!parentOrigin) return Promise.resolve(undefined);
|
|
165
|
+
|
|
166
|
+
const requestId = crypto.randomUUID();
|
|
167
|
+
return new Promise((resolve) => {
|
|
168
|
+
let timeout: number;
|
|
169
|
+
let retry: number;
|
|
170
|
+
let retryDelay = 250;
|
|
171
|
+
const finish = (token?: string) => {
|
|
172
|
+
window.removeEventListener('message', onMessage);
|
|
173
|
+
clearTimeout(timeout);
|
|
174
|
+
clearTimeout(retry);
|
|
175
|
+
resolve(token);
|
|
176
|
+
};
|
|
177
|
+
const onMessage = (event: MessageEvent<unknown>) => {
|
|
178
|
+
if (event.source !== window.parent || event.origin !== parentOrigin || !isIframeAuthResponse(event.data)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (event.data.requestId === requestId && event.data.token) finish(event.data.token);
|
|
182
|
+
};
|
|
183
|
+
const request = { type: IFRAME_AUTH_REQUEST, requestId } satisfies IframeAuthRequest;
|
|
184
|
+
const sendRequest = () => {
|
|
185
|
+
window.parent.postMessage(request, parentOrigin);
|
|
186
|
+
retry = window.setTimeout(sendRequest, retryDelay);
|
|
187
|
+
retryDelay = Math.min(retryDelay * 2, 1000);
|
|
188
|
+
};
|
|
189
|
+
timeout = window.setTimeout(() => finish(), timeoutMs);
|
|
190
|
+
window.addEventListener('message', onMessage);
|
|
191
|
+
sendRequest();
|
|
192
|
+
});
|
|
193
|
+
}
|
package/src/shell/apps/index.ts
CHANGED
|
@@ -44,6 +44,7 @@ function renderSurface(props?: {
|
|
|
44
44
|
onSendChangesToAgent?: () => void;
|
|
45
45
|
hasUnsentChanges?: boolean;
|
|
46
46
|
toolbarStatus?: React.ReactNode;
|
|
47
|
+
onContentChange?: (content: string, generation?: string) => void;
|
|
47
48
|
flushChangesRef?: React.MutableRefObject<(() => Promise<false | ArtifactEditingSurfaceDocumentEdit>) | null>;
|
|
48
49
|
}) {
|
|
49
50
|
return render(
|
|
@@ -61,6 +62,7 @@ function renderSurface(props?: {
|
|
|
61
62
|
onSendChangesToAgent={props?.onSendChangesToAgent}
|
|
62
63
|
hasUnsentChanges={props?.hasUnsentChanges}
|
|
63
64
|
toolbarStatus={props?.toolbarStatus}
|
|
65
|
+
onContentChange={props?.onContentChange}
|
|
64
66
|
flushChangesRef={props?.flushChangesRef}
|
|
65
67
|
/>
|
|
66
68
|
</I18nProvider>,
|
|
@@ -292,6 +294,7 @@ describe('ArtifactEditingSurface', () => {
|
|
|
292
294
|
|
|
293
295
|
it('rebases focused full-document edits over a non-overlapping agent change after 412', async () => {
|
|
294
296
|
const user = userEvent.setup();
|
|
297
|
+
const onContentChange = vi.fn();
|
|
295
298
|
const baseContent = 'First paragraph.\n\nSecond paragraph.';
|
|
296
299
|
const remoteContent = 'First paragraph updated remotely.\n\nSecond paragraph.';
|
|
297
300
|
mocks.getArtifactContent
|
|
@@ -314,16 +317,22 @@ describe('ArtifactEditingSurface', () => {
|
|
|
314
317
|
.mockRejectedValueOnce({ status: 412 })
|
|
315
318
|
.mockResolvedValueOnce({ path: 'drafts/document.md', generation: 'generation-merged' });
|
|
316
319
|
|
|
317
|
-
const view = renderSurface({ viewMode: 'document' });
|
|
320
|
+
const view = renderSurface({ viewMode: 'document', onContentChange });
|
|
318
321
|
const editor = await screen.findByRole('textbox', { name: 'Markdown document editor' }, LAZY_EDITOR_WAIT);
|
|
319
322
|
await user.click(editor);
|
|
320
323
|
|
|
321
324
|
view.rerender(
|
|
322
325
|
<I18nProvider lng="en">
|
|
323
|
-
<ArtifactEditingSurface
|
|
326
|
+
<ArtifactEditingSurface
|
|
327
|
+
runId="run-1"
|
|
328
|
+
path="drafts/document.md"
|
|
329
|
+
refreshKey={1}
|
|
330
|
+
viewMode="document"
|
|
331
|
+
onContentChange={onContentChange}
|
|
332
|
+
/>
|
|
324
333
|
</I18nProvider>,
|
|
325
334
|
);
|
|
326
|
-
await waitFor(() => expect(
|
|
335
|
+
await waitFor(() => expect(onContentChange).toHaveBeenCalledWith(remoteContent, 'generation-agent'));
|
|
327
336
|
|
|
328
337
|
editor.focus();
|
|
329
338
|
const secondParagraphText = editor.querySelectorAll('p')[1]?.firstChild;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Element } from 'hast';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import Markdown, { type Components, defaultUrlTransform } from 'react-markdown';
|
|
4
|
-
import rehypeKatex from 'rehype-katex';
|
|
5
4
|
import { defListHastHandlers, remarkDefinitionList } from 'remark-definition-list';
|
|
6
5
|
import remarkDirective from 'remark-directive';
|
|
7
6
|
import remarkGfm from 'remark-gfm';
|
|
@@ -24,6 +23,55 @@ type MarkdownTree = Parameters<typeof visit>[0];
|
|
|
24
23
|
type MarkdownNode = { value?: unknown };
|
|
25
24
|
type MarkdownParent = { children?: unknown[] };
|
|
26
25
|
type RemarkPluginList = NonNullable<React.ComponentProps<typeof Markdown>['remarkPlugins']>;
|
|
26
|
+
type RehypePluginList = NonNullable<React.ComponentProps<typeof Markdown>['rehypePlugins']>;
|
|
27
|
+
type RehypePlugin = RehypePluginList[number];
|
|
28
|
+
|
|
29
|
+
// A `$` that the math preprocessor left unescaped — the only way remark-math can produce a math
|
|
30
|
+
// node. Currency is escaped to `\$` by `preprocessMathDelimiters`, so it does not match.
|
|
31
|
+
const MATH_DELIMITER_REGEX = /(?:^|[^\\])\$/;
|
|
32
|
+
const NO_REHYPE_PLUGINS: RehypePluginList = [];
|
|
33
|
+
|
|
34
|
+
let rehypeKatex: RehypePlugin | undefined;
|
|
35
|
+
let rehypeKatexPromise: Promise<RehypePlugin> | undefined;
|
|
36
|
+
|
|
37
|
+
function loadRehypeKatex(): Promise<RehypePlugin> {
|
|
38
|
+
if (!rehypeKatexPromise) {
|
|
39
|
+
rehypeKatexPromise = import('rehype-katex').then(({ default: plugin }) => {
|
|
40
|
+
rehypeKatex = plugin;
|
|
41
|
+
return plugin;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return rehypeKatexPromise;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* KaTeX is ~250 KB and most markdown has no math in it, so it is fetched the first time a document
|
|
49
|
+
* containing math delimiters is rendered. Until it resolves, math renders unstyled; once loaded it
|
|
50
|
+
* stays loaded for the rest of the session and later renderers pick it up without a second pass.
|
|
51
|
+
*/
|
|
52
|
+
function useRehypePlugins(markdown: string): RehypePluginList {
|
|
53
|
+
const hasMath = React.useMemo(() => MATH_DELIMITER_REGEX.test(markdown), [markdown]);
|
|
54
|
+
const [plugin, setPlugin] = React.useState(() => rehypeKatex);
|
|
55
|
+
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
if (!hasMath || plugin) return;
|
|
58
|
+
let cancelled = false;
|
|
59
|
+
loadRehypeKatex()
|
|
60
|
+
.then((loaded) => {
|
|
61
|
+
if (!cancelled) {
|
|
62
|
+
setPlugin(() => loaded);
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
.catch((err: unknown) => {
|
|
66
|
+
console.error('Failed to load KaTeX; math will render unstyled', err);
|
|
67
|
+
});
|
|
68
|
+
return () => {
|
|
69
|
+
cancelled = true;
|
|
70
|
+
};
|
|
71
|
+
}, [hasMath, plugin]);
|
|
72
|
+
|
|
73
|
+
return React.useMemo(() => (plugin ? [plugin] : NO_REHYPE_PLUGINS), [plugin]);
|
|
74
|
+
}
|
|
27
75
|
|
|
28
76
|
// Custom URL schemes that we handle in our components
|
|
29
77
|
const ALLOWED_CUSTOM_SCHEMES = [
|
|
@@ -151,7 +199,7 @@ export function MarkdownRenderer({
|
|
|
151
199
|
}, [remarkPlugins, removeComments]);
|
|
152
200
|
|
|
153
201
|
// Rehype plugins (HTML processing, including KaTeX for math)
|
|
154
|
-
const rehypePluginsArray =
|
|
202
|
+
const rehypePluginsArray = useRehypePlugins(normalizedMarkdown);
|
|
155
203
|
|
|
156
204
|
// Remark-rehype bridge options (custom AST handlers for definition lists)
|
|
157
205
|
const remarkRehypeOptions = React.useMemo(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import mermaid from 'mermaid';
|
|
2
1
|
import { useEffect, useId, useRef, useState } from 'react';
|
|
3
2
|
|
|
3
|
+
type Mermaid = typeof import('mermaid').default;
|
|
4
|
+
|
|
4
5
|
const MERMAID_FONT_FAMILY =
|
|
5
6
|
'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
6
7
|
|
|
@@ -78,27 +79,41 @@ export function makeSvgResponsive(svg: string): string {
|
|
|
78
79
|
});
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
82
|
+
let mermaidPromise: Promise<Mermaid> | undefined;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Load Mermaid on first render of a diagram, initialized with a browser-focused config close to
|
|
86
|
+
* Mermaid Playground defaults. Mermaid is several hundred KB and most pages never render a diagram,
|
|
87
|
+
* so it is imported dynamically to keep it out of the eager bundle of every consuming app.
|
|
88
|
+
*/
|
|
89
|
+
function loadMermaid(): Promise<Mermaid> {
|
|
90
|
+
if (!mermaidPromise) {
|
|
91
|
+
mermaidPromise = import('mermaid').then(({ default: mermaid }) => {
|
|
92
|
+
mermaid.initialize({
|
|
93
|
+
startOnLoad: false,
|
|
94
|
+
theme: 'default',
|
|
95
|
+
securityLevel: 'loose',
|
|
96
|
+
fontFamily: MERMAID_FONT_FAMILY,
|
|
97
|
+
suppressErrorRendering: true,
|
|
98
|
+
flowchart: {
|
|
99
|
+
htmlLabels: true,
|
|
100
|
+
useMaxWidth: true,
|
|
101
|
+
nodeSpacing: 40,
|
|
102
|
+
rankSpacing: 50,
|
|
103
|
+
padding: 12,
|
|
104
|
+
},
|
|
105
|
+
sequence: {
|
|
106
|
+
useMaxWidth: true,
|
|
107
|
+
},
|
|
108
|
+
themeVariables: {
|
|
109
|
+
fontFamily: MERMAID_FONT_FAMILY,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
return mermaid;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return mermaidPromise;
|
|
116
|
+
}
|
|
102
117
|
|
|
103
118
|
export interface MermaidDiagramProps {
|
|
104
119
|
/** The mermaid diagram code */
|
|
@@ -147,6 +162,7 @@ export function MermaidDiagram({ code, className }: MermaidDiagramProps) {
|
|
|
147
162
|
const normalizedCode = normalizeMermaidCodeForBrowser(code);
|
|
148
163
|
|
|
149
164
|
// Render the diagram
|
|
165
|
+
const mermaid = await loadMermaid();
|
|
150
166
|
const { svg: renderedSvg } = await mermaid.render(id, normalizedCode);
|
|
151
167
|
const responsiveSvg = makeSvgResponsive(renderedSvg);
|
|
152
168
|
|