@vertesia/ui 1.5.0-dev.20260717.131047Z → 1.5.0-dev.20260725.083715Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/core/components/SidePanel.js +1 -1
- package/lib/core/components/SidePanel.js.map +1 -1
- package/lib/core/components/shadcn/button.d.ts +10 -3
- package/lib/core/components/shadcn/button.d.ts.map +1 -1
- package/lib/core/components/shadcn/button.js +41 -9
- package/lib/core/components/shadcn/button.js.map +1 -1
- package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filterBar.js +1 -1
- package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.d.ts +1 -1
- package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.js +3 -1
- package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
- package/lib/core/components/shadcn/tabs.d.ts +12 -1
- package/lib/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/core/components/shadcn/tabs.js +12 -4
- package/lib/core/components/shadcn/tabs.js.map +1 -1
- package/lib/core/components/shadcn/theme/ThemeSwitcher.js +1 -1
- package/lib/core/components/shadcn/theme/ThemeSwitcher.js.map +1 -1
- package/lib/features/agent/chat/AgentChatPlaybackControls.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentChatPlaybackControls.js +2 -2
- package/lib/features/agent/chat/AgentChatPlaybackControls.js.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.js +2 -2
- package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts +5 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.js +2 -2
- package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.d.ts +5 -1
- package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js +53 -13
- package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
- package/lib/features/agent/chat/DocumentEditingActionCard.d.ts +6 -0
- package/lib/features/agent/chat/DocumentEditingActionCard.d.ts.map +1 -0
- package/lib/features/agent/chat/DocumentEditingActionCard.js +129 -0
- package/lib/features/agent/chat/DocumentEditingActionCard.js.map +1 -0
- package/lib/features/agent/chat/ImageLightbox.d.ts.map +1 -1
- package/lib/features/agent/chat/ImageLightbox.js +1 -1
- package/lib/features/agent/chat/ImageLightbox.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.d.ts +19 -1
- package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +125 -27
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.d.ts +45 -0
- package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.js +40 -0
- package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +3 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +96 -51
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts +2 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +9 -5
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.d.ts +25 -0
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.js +33 -0
- package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.js +4 -2
- package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +2 -2
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +3 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +23 -24
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.d.ts +14 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.js +21 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.d.ts +30 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.js +53 -0
- package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +21 -2
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +15 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.js +29 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.d.ts +33 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.js +129 -0
- package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +7 -0
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.js +11 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.js +24 -9
- package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/features/agent/chat/index.d.ts +2 -1
- package/lib/features/agent/chat/index.d.ts.map +1 -1
- package/lib/features/agent/chat/index.js +3 -0
- package/lib/features/agent/chat/index.js.map +1 -1
- package/lib/features/environment/SelectEnvironment.d.ts +28 -0
- package/lib/features/environment/SelectEnvironment.d.ts.map +1 -0
- package/lib/features/environment/SelectEnvironment.js +97 -0
- package/lib/features/environment/SelectEnvironment.js.map +1 -0
- package/lib/features/environment/index.d.ts +2 -0
- package/lib/features/environment/index.d.ts.map +1 -0
- package/lib/features/environment/index.js +2 -0
- package/lib/features/environment/index.js.map +1 -0
- package/lib/features/index.d.ts +2 -0
- package/lib/features/index.d.ts.map +1 -1
- package/lib/features/index.js +2 -0
- package/lib/features/index.js.map +1 -1
- package/lib/features/magic-pdf/AnnotatedImageSlider.js +12 -12
- package/lib/features/magic-pdf/AnnotatedImageSlider.js.map +1 -1
- package/lib/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
- package/lib/features/magic-pdf/DownloadPopover.js +3 -17
- package/lib/features/magic-pdf/DownloadPopover.js.map +1 -1
- package/lib/features/magic-pdf/ExtractedContentView.js +2 -6
- package/lib/features/magic-pdf/ExtractedContentView.js.map +1 -1
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts +25 -0
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts.map +1 -0
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js +42 -0
- package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js.map +1 -0
- package/lib/features/magic-pdf/GroundedExtractionView.d.ts +27 -0
- package/lib/features/magic-pdf/GroundedExtractionView.d.ts.map +1 -0
- package/lib/features/magic-pdf/GroundedExtractionView.js +377 -0
- package/lib/features/magic-pdf/GroundedExtractionView.js.map +1 -0
- package/lib/features/magic-pdf/MagicPdfProvider.d.ts +0 -2
- package/lib/features/magic-pdf/MagicPdfProvider.d.ts.map +1 -1
- package/lib/features/magic-pdf/MagicPdfProvider.js +15 -42
- package/lib/features/magic-pdf/MagicPdfProvider.js.map +1 -1
- package/lib/features/magic-pdf/MagicPdfView.d.ts.map +1 -1
- package/lib/features/magic-pdf/MagicPdfView.js +2 -19
- package/lib/features/magic-pdf/MagicPdfView.js.map +1 -1
- package/lib/features/magic-pdf/index.d.ts +1 -0
- package/lib/features/magic-pdf/index.d.ts.map +1 -1
- package/lib/features/magic-pdf/index.js +1 -0
- package/lib/features/magic-pdf/index.js.map +1 -1
- package/lib/features/magic-pdf/types.d.ts +1 -1
- package/lib/features/magic-pdf/types.d.ts.map +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.map +1 -1
- package/lib/features/oauth/McpConnectionsDialog.js +1 -1
- package/lib/features/oauth/McpConnectionsDialog.js.map +1 -1
- package/lib/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -1
- package/lib/features/oauth/RemoteMcpConnectionButton.js +1 -1
- package/lib/features/oauth/RemoteMcpConnectionButton.js.map +1 -1
- package/lib/features/pdf-viewer/PdfPageSlider.js +2 -2
- package/lib/features/pdf-viewer/PdfPageSlider.js.map +1 -1
- package/lib/features/pdf-viewer/SimplePdfViewer.d.ts.map +1 -1
- package/lib/features/pdf-viewer/SimplePdfViewer.js +3 -3
- package/lib/features/pdf-viewer/SimplePdfViewer.js.map +1 -1
- package/lib/features/permissions/UserPermissionsProvider.js +1 -1
- package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
- package/lib/features/store/objects/DocumentQuickFilter.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentQuickFilter.js +5 -5
- package/lib/features/store/objects/DocumentQuickFilter.js.map +1 -1
- package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentSearchResults.js +4 -4
- package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/features/store/objects/components/ContentDispositionButton.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentDispositionButton.js +1 -1
- package/lib/features/store/objects/components/ContentDispositionButton.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts +2 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +159 -31
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.d.ts +16 -0
- package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.d.ts.map +1 -0
- package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.js +116 -0
- package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.js.map +1 -0
- package/lib/features/store/objects/components/DocumentEditingLockStatus.d.ts +7 -0
- package/lib/features/store/objects/components/DocumentEditingLockStatus.d.ts.map +1 -0
- package/lib/features/store/objects/components/DocumentEditingLockStatus.js +13 -0
- package/lib/features/store/objects/components/DocumentEditingLockStatus.js.map +1 -0
- package/lib/features/store/objects/components/DocumentEditingPanel.d.ts +48 -0
- package/lib/features/store/objects/components/DocumentEditingPanel.d.ts.map +1 -0
- package/lib/features/store/objects/components/DocumentEditingPanel.js +720 -0
- package/lib/features/store/objects/components/DocumentEditingPanel.js.map +1 -0
- package/lib/features/store/objects/components/DocumentIcon.js +1 -1
- package/lib/features/store/objects/components/TextEditorPanel.d.ts.map +1 -1
- package/lib/features/store/objects/components/TextEditorPanel.js +22 -9
- package/lib/features/store/objects/components/TextEditorPanel.js.map +1 -1
- package/lib/features/store/objects/components/VectorSearchWidget.js +1 -1
- package/lib/features/store/objects/components/VectorSearchWidget.js.map +1 -1
- package/lib/features/store/objects/components/documentArtifactRefs.d.ts +26 -0
- package/lib/features/store/objects/components/documentArtifactRefs.d.ts.map +1 -0
- package/lib/features/store/objects/components/documentArtifactRefs.js +52 -0
- package/lib/features/store/objects/components/documentArtifactRefs.js.map +1 -0
- package/lib/features/store/objects/components/documentEditingAgentConfig.d.ts +4 -0
- package/lib/features/store/objects/components/documentEditingAgentConfig.d.ts.map +1 -0
- package/lib/features/store/objects/components/documentEditingAgentConfig.js +40 -0
- package/lib/features/store/objects/components/documentEditingAgentConfig.js.map +1 -0
- package/lib/features/store/objects/components/documentEditingPrompts.d.ts +3 -0
- package/lib/features/store/objects/components/documentEditingPrompts.d.ts.map +1 -0
- package/lib/features/store/objects/components/documentEditingPrompts.js +13 -0
- package/lib/features/store/objects/components/documentEditingPrompts.js.map +1 -0
- package/lib/features/store/objects/components/documentEditingRun.d.ts +27 -0
- package/lib/features/store/objects/components/documentEditingRun.d.ts.map +1 -0
- package/lib/features/store/objects/components/documentEditingRun.js +126 -0
- package/lib/features/store/objects/components/documentEditingRun.js.map +1 -0
- package/lib/features/store/objects/components/documentEditingTarget.d.ts +20 -0
- package/lib/features/store/objects/components/documentEditingTarget.d.ts.map +1 -0
- package/lib/features/store/objects/components/documentEditingTarget.js +40 -0
- package/lib/features/store/objects/components/documentEditingTarget.js.map +1 -0
- package/lib/features/store/objects/components/index.d.ts +1 -0
- package/lib/features/store/objects/components/index.d.ts.map +1 -1
- package/lib/features/store/objects/components/index.js +1 -0
- package/lib/features/store/objects/components/index.js.map +1 -1
- package/lib/features/store/objects/components/useContentPanelHooks.d.ts +6 -3
- package/lib/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -1
- package/lib/features/store/objects/components/useContentPanelHooks.js +57 -37
- package/lib/features/store/objects/components/useContentPanelHooks.js.map +1 -1
- package/lib/features/store/objects/components/useDownloadFile.d.ts +2 -1
- package/lib/features/store/objects/components/useDownloadFile.d.ts.map +1 -1
- package/lib/features/store/objects/components/useDownloadFile.js +3 -0
- package/lib/features/store/objects/components/useDownloadFile.js.map +1 -1
- package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/features/store/objects/layout/renderers.js +2 -2
- package/lib/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/features/store/objects/selection/SelectionActions.js +1 -1
- package/lib/features/store/objects/selection/SelectionActions.js.map +1 -1
- package/lib/features/store/objects/selection/actions/StartWorkflowButton.js +1 -1
- package/lib/features/store/objects/selection/actions/StartWorkflowButton.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.js +4 -4
- package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/features/store/types/IntakePolicyEditor.d.ts +15 -0
- package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -0
- package/lib/features/store/types/IntakePolicyEditor.js +455 -0
- package/lib/features/store/types/IntakePolicyEditor.js.map +1 -0
- package/lib/features/store/types/IntakePolicyForm.d.ts +11 -0
- package/lib/features/store/types/IntakePolicyForm.d.ts.map +1 -0
- package/lib/features/store/types/IntakePolicyForm.js +91 -0
- package/lib/features/store/types/IntakePolicyForm.js.map +1 -0
- package/lib/features/store/types/SelectContentTypeModal.js +1 -1
- package/lib/features/store/types/SelectContentTypeModal.js.map +1 -1
- package/lib/features/store/types/index.d.ts +2 -0
- package/lib/features/store/types/index.d.ts.map +1 -1
- package/lib/features/store/types/index.js +2 -0
- package/lib/features/store/types/index.js.map +1 -1
- package/lib/features/store/types/intake-policy-editor.logic.d.ts +7 -0
- package/lib/features/store/types/intake-policy-editor.logic.d.ts.map +1 -0
- package/lib/features/store/types/intake-policy-editor.logic.js +60 -0
- package/lib/features/store/types/intake-policy-editor.logic.js.map +1 -0
- package/lib/features/store/types/typeCatalogCache.d.ts +5 -0
- package/lib/features/store/types/typeCatalogCache.d.ts.map +1 -0
- package/lib/features/store/types/typeCatalogCache.js +40 -0
- package/lib/features/store/types/typeCatalogCache.js.map +1 -0
- package/lib/features/user/UserInfo.js +7 -3
- package/lib/features/user/UserInfo.js.map +1 -1
- package/lib/features/views/ViewExperience.d.ts +20 -0
- package/lib/features/views/ViewExperience.d.ts.map +1 -0
- package/lib/features/views/ViewExperience.js +188 -0
- package/lib/features/views/ViewExperience.js.map +1 -0
- package/lib/features/views/ViewNavigation.d.ts +3 -0
- package/lib/features/views/ViewNavigation.d.ts.map +1 -0
- package/lib/features/views/ViewNavigation.js +36 -0
- package/lib/features/views/ViewNavigation.js.map +1 -0
- package/lib/features/views/ViewResults.d.ts +9 -0
- package/lib/features/views/ViewResults.d.ts.map +1 -0
- package/lib/features/views/ViewResults.js +229 -0
- package/lib/features/views/ViewResults.js.map +1 -0
- package/lib/features/views/ViewSearch.d.ts +3 -0
- package/lib/features/views/ViewSearch.d.ts.map +1 -0
- package/lib/features/views/ViewSearch.js +74 -0
- package/lib/features/views/ViewSearch.js.map +1 -0
- package/lib/features/views/index.d.ts +7 -0
- package/lib/features/views/index.d.ts.map +1 -0
- package/lib/features/views/index.js +7 -0
- package/lib/features/views/index.js.map +1 -0
- package/lib/features/views/types.d.ts +39 -0
- package/lib/features/views/types.d.ts.map +1 -0
- package/lib/features/views/types.js +2 -0
- package/lib/features/views/types.js.map +1 -0
- package/lib/features/views/viewState.d.ts +14 -0
- package/lib/features/views/viewState.d.ts.map +1 -0
- package/lib/features/views/viewState.js +117 -0
- package/lib/features/views/viewState.js.map +1 -0
- package/lib/i18n/locales/ar.json +134 -1
- package/lib/i18n/locales/de.json +130 -1
- package/lib/i18n/locales/en.json +363 -33
- package/lib/i18n/locales/es.json +131 -1
- package/lib/i18n/locales/fr.json +131 -1
- package/lib/i18n/locales/it.json +131 -1
- package/lib/i18n/locales/ja.json +129 -1
- package/lib/i18n/locales/ko.json +129 -1
- package/lib/i18n/locales/pt.json +131 -1
- package/lib/i18n/locales/ru.json +132 -1
- package/lib/i18n/locales/tr.json +130 -1
- package/lib/i18n/locales/zh-TW.json +129 -1
- package/lib/i18n/locales/zh.json +129 -1
- package/lib/rich-text/EditorToolbar.d.ts +37 -0
- package/lib/rich-text/EditorToolbar.d.ts.map +1 -0
- package/lib/rich-text/EditorToolbar.js +215 -0
- package/lib/rich-text/EditorToolbar.js.map +1 -0
- package/lib/rich-text/VertesiaRichTextEditor.d.ts +26 -0
- package/lib/rich-text/VertesiaRichTextEditor.d.ts.map +1 -0
- package/lib/rich-text/VertesiaRichTextEditor.js +67 -0
- package/lib/rich-text/VertesiaRichTextEditor.js.map +1 -0
- package/lib/rich-text/index.d.ts +2 -0
- package/lib/rich-text/index.d.ts.map +1 -0
- package/lib/rich-text/index.js +2 -0
- package/lib/rich-text/index.js.map +1 -0
- package/lib/router/HistoryNavigator.d.ts.map +1 -1
- package/lib/router/HistoryNavigator.js +23 -13
- package/lib/router/HistoryNavigator.js.map +1 -1
- package/lib/router/Nav.d.ts.map +1 -1
- package/lib/router/Nav.js +15 -6
- package/lib/router/Nav.js.map +1 -1
- package/lib/session/UserSession.d.ts.map +1 -1
- package/lib/session/UserSession.js +5 -3
- package/lib/session/UserSession.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-features.js +40 -28
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +15 -15
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-rich-text.js +5 -0
- package/lib/vertesia-ui-rich-text.js.map +1 -0
- 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 +25 -7
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/lib/widgets/form/Form.js +1 -1
- package/lib/widgets/form/Form.js.map +1 -1
- package/lib/widgets/json-view/JSONSwitcher.js +1 -1
- package/lib/widgets/json-view/JSONSwitcher.js.map +1 -1
- package/lib/widgets/json-view/JSONView.js +6 -6
- package/lib/widgets/json-view/JSONView.js.map +1 -1
- package/lib/widgets/markdown/AgentResourceResolver.d.ts +31 -0
- package/lib/widgets/markdown/AgentResourceResolver.d.ts.map +1 -0
- package/lib/widgets/markdown/AgentResourceResolver.js +39 -0
- package/lib/widgets/markdown/AgentResourceResolver.js.map +1 -0
- package/lib/widgets/markdown/ArtifactEditingSurface.d.ts +63 -0
- package/lib/widgets/markdown/ArtifactEditingSurface.d.ts.map +1 -0
- package/lib/widgets/markdown/ArtifactEditingSurface.js +582 -0
- package/lib/widgets/markdown/ArtifactEditingSurface.js.map +1 -0
- package/lib/widgets/markdown/CollaborativeMarkdownRenderer.d.ts +69 -0
- package/lib/widgets/markdown/CollaborativeMarkdownRenderer.d.ts.map +1 -0
- package/lib/widgets/markdown/CollaborativeMarkdownRenderer.js +374 -0
- package/lib/widgets/markdown/CollaborativeMarkdownRenderer.js.map +1 -0
- package/lib/widgets/markdown/MarkdownLink.d.ts +3 -1
- package/lib/widgets/markdown/MarkdownLink.d.ts.map +1 -1
- package/lib/widgets/markdown/MarkdownLink.js +41 -14
- package/lib/widgets/markdown/MarkdownLink.js.map +1 -1
- package/lib/widgets/markdown/MarkdownRenderer.d.ts +8 -1
- package/lib/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/widgets/markdown/MarkdownRenderer.js +20 -4
- package/lib/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/widgets/markdown/index.d.ts +5 -1
- package/lib/widgets/markdown/index.d.ts.map +1 -1
- package/lib/widgets/markdown/index.js +5 -1
- package/lib/widgets/markdown/index.js.map +1 -1
- package/lib/widgets/markdown/normalizeCustomSchemeLinks.d.ts.map +1 -1
- package/lib/widgets/markdown/normalizeCustomSchemeLinks.js +14 -2
- package/lib/widgets/markdown/normalizeCustomSchemeLinks.js.map +1 -1
- package/lib/widgets/markdown/textDiff.d.ts +52 -0
- package/lib/widgets/markdown/textDiff.d.ts.map +1 -0
- package/lib/widgets/markdown/textDiff.js +362 -0
- package/lib/widgets/markdown/textDiff.js.map +1 -0
- package/lib/widgets/markdown/useArtifactContent.d.ts +5 -3
- package/lib/widgets/markdown/useArtifactContent.d.ts.map +1 -1
- package/lib/widgets/markdown/useArtifactContent.js +6 -3
- package/lib/widgets/markdown/useArtifactContent.js.map +1 -1
- package/lib/widgets/markdown/useResolvedUrl.d.ts +1 -5
- package/lib/widgets/markdown/useResolvedUrl.d.ts.map +1 -1
- package/lib/widgets/markdown/useResolvedUrl.js +19 -31
- package/lib/widgets/markdown/useResolvedUrl.js.map +1 -1
- package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
- package/lib/widgets/monacoEditor/MonacoEditor.js +29 -0
- package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
- package/lib/widgets/schema-editor/ManagedSchema.d.ts +8 -0
- package/lib/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
- package/lib/widgets/schema-editor/ManagedSchema.js +16 -0
- package/lib/widgets/schema-editor/ManagedSchema.js.map +1 -1
- package/lib/widgets/schema-editor/editor/EditableSchemaProperty.d.ts +2 -0
- package/lib/widgets/schema-editor/editor/EditableSchemaProperty.d.ts.map +1 -1
- package/lib/widgets/schema-editor/editor/EditableSchemaProperty.js +1 -0
- package/lib/widgets/schema-editor/editor/EditableSchemaProperty.js.map +1 -1
- package/lib/widgets/schema-editor/editor/PropertyViewer.d.ts.map +1 -1
- package/lib/widgets/schema-editor/editor/PropertyViewer.js +4 -1
- package/lib/widgets/schema-editor/editor/PropertyViewer.js.map +1 -1
- package/lib/widgets/schema-editor/editor/SchemaEditor.d.ts.map +1 -1
- package/lib/widgets/schema-editor/editor/SchemaEditor.js +22 -11
- package/lib/widgets/schema-editor/editor/SchemaEditor.js.map +1 -1
- package/lib/widgets/xml-viewer/hooks/useXMLViewer.d.ts +9 -0
- package/lib/widgets/xml-viewer/hooks/useXMLViewer.d.ts.map +1 -1
- package/lib/widgets/xml-viewer/hooks/useXMLViewer.js +20 -17
- package/lib/widgets/xml-viewer/hooks/useXMLViewer.js.map +1 -1
- package/package.json +37 -33
- package/src/__tests__/a11y.test.tsx +77 -1
- package/src/__tests__/axe-helper.ts +17 -7
- package/src/__tests__/setup.ts +25 -0
- package/src/core/components/SidePanel.tsx +1 -1
- package/src/core/components/shadcn/button.tsx +67 -12
- package/src/core/components/shadcn/filters/filterBar.tsx +1 -0
- package/src/core/components/shadcn/modal/dialog.tsx +4 -2
- package/src/core/components/shadcn/tabs.test.tsx +65 -0
- package/src/core/components/shadcn/tabs.tsx +25 -3
- package/src/core/components/shadcn/theme/ThemeSwitcher.tsx +1 -1
- package/src/features/agent/chat/AgentChatPlaybackControls.tsx +0 -5
- package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +31 -0
- package/src/features/agent/chat/AgentRequestInputOverlay.tsx +6 -2
- package/src/features/agent/chat/AgentRightPanel.tsx +16 -1
- package/src/features/agent/chat/ArtifactsTab.test.tsx +55 -0
- package/src/features/agent/chat/ArtifactsTab.tsx +222 -61
- package/src/features/agent/chat/DocumentEditingActionCard.test.tsx +105 -0
- package/src/features/agent/chat/DocumentEditingActionCard.tsx +210 -0
- package/src/features/agent/chat/ImageLightbox.tsx +0 -1
- package/src/features/agent/chat/ModernAgentConversation.test.tsx +285 -40
- package/src/features/agent/chat/ModernAgentConversation.tsx +247 -77
- package/src/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.test.tsx +79 -0
- package/src/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.tsx +94 -0
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +263 -35
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +236 -118
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +17 -0
- package/src/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.test.tsx +44 -0
- package/src/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.tsx +88 -0
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +3 -3
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +0 -2
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +34 -47
- package/src/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.tsx +40 -0
- package/src/features/agent/chat/ModernAgentOutput/ResourceChip.test.tsx +148 -0
- package/src/features/agent/chat/ModernAgentOutput/ResourceChip.tsx +141 -0
- package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +33 -1
- package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.test.ts +80 -0
- package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +21 -1
- package/src/features/agent/chat/ModernAgentOutput/resourceLinks.tsx +43 -0
- package/src/features/agent/chat/ModernAgentOutput/resourceSummary.test.ts +229 -0
- package/src/features/agent/chat/ModernAgentOutput/resourceSummary.ts +152 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +17 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.ts +14 -1
- package/src/features/agent/chat/hooks/useAgentStream.test.tsx +188 -0
- package/src/features/agent/chat/hooks/useAgentStream.ts +28 -8
- package/src/features/agent/chat/index.ts +11 -0
- package/src/features/environment/SelectEnvironment.tsx +186 -0
- package/src/features/environment/index.ts +1 -0
- package/src/features/index.ts +2 -0
- package/src/features/magic-pdf/AnnotatedImageSlider.tsx +62 -66
- package/src/features/magic-pdf/DownloadPopover.tsx +5 -48
- package/src/features/magic-pdf/ExtractedContentView.tsx +2 -14
- package/src/features/magic-pdf/GroundedExtractionAssistantPanel.tsx +86 -0
- package/src/features/magic-pdf/GroundedExtractionView.test.tsx +65 -0
- package/src/features/magic-pdf/GroundedExtractionView.tsx +1055 -0
- package/src/features/magic-pdf/MagicPdfProvider.tsx +17 -47
- package/src/features/magic-pdf/MagicPdfView.tsx +3 -51
- package/src/features/magic-pdf/index.ts +1 -0
- package/src/features/magic-pdf/types.ts +1 -1
- package/src/features/oauth/McpConnectionsButton.tsx +0 -2
- package/src/features/oauth/McpConnectionsDialog.tsx +0 -1
- package/src/features/oauth/RemoteMcpConnectionButton.tsx +0 -1
- package/src/features/pdf-viewer/PdfPageSlider.tsx +5 -5
- package/src/features/pdf-viewer/SimplePdfViewer.tsx +11 -12
- package/src/features/permissions/UserPermissionsProvider.tsx +1 -1
- package/src/features/store/objects/DocumentQuickFilter.tsx +13 -15
- package/src/features/store/objects/DocumentSearchResults.tsx +5 -8
- package/src/features/store/objects/components/ContentDispositionButton.tsx +5 -1
- package/src/features/store/objects/components/ContentOverview.tsx +356 -105
- package/src/features/store/objects/components/DocumentEditingConfigurationSelector.test.ts +34 -0
- package/src/features/store/objects/components/DocumentEditingConfigurationSelector.tsx +211 -0
- package/src/features/store/objects/components/DocumentEditingLockStatus.test.tsx +32 -0
- package/src/features/store/objects/components/DocumentEditingLockStatus.tsx +45 -0
- package/src/features/store/objects/components/DocumentEditingPanel.test.tsx +336 -0
- package/src/features/store/objects/components/DocumentEditingPanel.tsx +1236 -0
- package/src/features/store/objects/components/DocumentIcon.tsx +1 -1
- package/src/features/store/objects/components/TextEditorPanel.test.tsx +48 -0
- package/src/features/store/objects/components/TextEditorPanel.tsx +41 -20
- package/src/features/store/objects/components/VectorSearchWidget.tsx +2 -2
- package/src/features/store/objects/components/documentArtifactRefs.test.ts +65 -0
- package/src/features/store/objects/components/documentArtifactRefs.ts +72 -0
- package/src/features/store/objects/components/documentEditingAgentConfig.test.ts +28 -0
- package/src/features/store/objects/components/documentEditingAgentConfig.ts +41 -0
- package/src/features/store/objects/components/documentEditingPrompts.test.ts +26 -0
- package/src/features/store/objects/components/documentEditingPrompts.ts +12 -0
- package/src/features/store/objects/components/documentEditingRun.test.ts +176 -0
- package/src/features/store/objects/components/documentEditingRun.ts +184 -0
- package/src/features/store/objects/components/documentEditingTarget.test.ts +96 -0
- package/src/features/store/objects/components/documentEditingTarget.ts +63 -0
- package/src/features/store/objects/components/index.ts +1 -0
- package/src/features/store/objects/components/useContentPanelHooks.ts +55 -42
- package/src/features/store/objects/components/useDownloadFile.test.ts +20 -0
- package/src/features/store/objects/components/useDownloadFile.ts +5 -1
- package/src/features/store/objects/layout/renderers.tsx +1 -2
- package/src/features/store/objects/selection/SelectionActions.tsx +1 -1
- package/src/features/store/objects/selection/actions/StartWorkflowButton.tsx +2 -2
- package/src/features/store/types/ContentObjectTypesTable.tsx +12 -14
- package/src/features/store/types/IntakePolicyEditor.tsx +679 -0
- package/src/features/store/types/IntakePolicyForm.tsx +838 -0
- package/src/features/store/types/SelectContentTypeModal.tsx +2 -2
- package/src/features/store/types/index.ts +2 -0
- package/src/features/store/types/intake-policy-editor.logic.test.ts +109 -0
- package/src/features/store/types/intake-policy-editor.logic.ts +87 -0
- package/src/features/store/types/typeCatalogCache.ts +45 -0
- package/src/features/user/UserInfo.tsx +7 -7
- package/src/features/views/ViewExperience.test.tsx +273 -0
- package/src/features/views/ViewExperience.tsx +408 -0
- package/src/features/views/ViewNavigation.test.tsx +86 -0
- package/src/features/views/ViewNavigation.tsx +187 -0
- package/src/features/views/ViewResults.test.ts +82 -0
- package/src/features/views/ViewResults.tsx +609 -0
- package/src/features/views/ViewSearch.test.tsx +147 -0
- package/src/features/views/ViewSearch.tsx +205 -0
- package/src/features/views/index.ts +6 -0
- package/src/features/views/types.ts +57 -0
- package/src/features/views/viewState.test.ts +111 -0
- package/src/features/views/viewState.ts +132 -0
- package/src/i18n/locales/ar.json +134 -1
- package/src/i18n/locales/de.json +130 -1
- package/src/i18n/locales/en.json +1083 -753
- package/src/i18n/locales/es.json +131 -1
- package/src/i18n/locales/fr.json +131 -1
- package/src/i18n/locales/it.json +131 -1
- package/src/i18n/locales/ja.json +129 -1
- package/src/i18n/locales/ko.json +129 -1
- package/src/i18n/locales/pt.json +131 -1
- package/src/i18n/locales/ru.json +132 -1
- package/src/i18n/locales/tr.json +130 -1
- package/src/i18n/locales/zh-TW.json +129 -1
- package/src/i18n/locales/zh.json +129 -1
- package/src/rich-text/EditorToolbar.tsx +708 -0
- package/src/rich-text/VertesiaRichTextEditor.test.tsx +211 -0
- package/src/rich-text/VertesiaRichTextEditor.tsx +241 -0
- package/src/rich-text/index.ts +9 -0
- package/src/router/HistoryNavigator.test.ts +48 -0
- package/src/router/HistoryNavigator.ts +24 -13
- package/src/router/Nav.tsx +18 -8
- package/src/session/UserSession.test.ts +39 -0
- package/src/session/UserSession.ts +5 -3
- package/src/widgets/form/Form.tsx +1 -1
- package/src/widgets/json-view/JSONSwitcher.tsx +2 -2
- package/src/widgets/json-view/JSONView.tsx +7 -7
- package/src/widgets/markdown/AgentResourceResolver.test.ts +24 -0
- package/src/widgets/markdown/AgentResourceResolver.tsx +70 -0
- package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +537 -0
- package/src/widgets/markdown/ArtifactEditingSurface.tsx +878 -0
- package/src/widgets/markdown/CollaborativeMarkdownRenderer.test.tsx +484 -0
- package/src/widgets/markdown/CollaborativeMarkdownRenderer.tsx +825 -0
- package/src/widgets/markdown/MarkdownLink.test.tsx +122 -0
- package/src/widgets/markdown/MarkdownLink.tsx +102 -17
- package/src/widgets/markdown/MarkdownRenderer.tsx +30 -3
- package/src/widgets/markdown/index.ts +39 -1
- package/src/widgets/markdown/normalizeCustomSchemeLinks.ts +15 -2
- package/src/widgets/markdown/textDiff.test.ts +156 -0
- package/src/widgets/markdown/textDiff.ts +399 -0
- package/src/widgets/markdown/useArtifactContent.ts +9 -3
- package/src/widgets/markdown/useResolvedUrl.test.ts +29 -40
- package/src/widgets/markdown/useResolvedUrl.ts +33 -35
- package/src/widgets/monacoEditor/MonacoEditor.tsx +29 -0
- package/src/widgets/schema-editor/ManagedSchema.ts +22 -0
- package/src/widgets/schema-editor/editor/EditableSchemaProperty.tsx +3 -0
- package/src/widgets/schema-editor/editor/PropertyViewer.tsx +14 -3
- package/src/widgets/schema-editor/editor/SchemaEditor.tsx +80 -29
- package/src/widgets/xml-viewer/hooks/useXMLViewer.test.ts +26 -0
- package/src/widgets/xml-viewer/hooks/useXMLViewer.ts +23 -18
|
@@ -0,0 +1,1236 @@
|
|
|
1
|
+
import type { ContentObject, CreateAgentRunPayload, InteractionExecutionConfiguration } from '@vertesia/common';
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Center,
|
|
5
|
+
ConfirmModal,
|
|
6
|
+
errorMessage,
|
|
7
|
+
Modal,
|
|
8
|
+
ResizableHandle,
|
|
9
|
+
ResizablePanel,
|
|
10
|
+
ResizablePanelGroup,
|
|
11
|
+
Spinner,
|
|
12
|
+
useToast,
|
|
13
|
+
VTooltip,
|
|
14
|
+
} from '@vertesia/ui/core';
|
|
15
|
+
import { useUITranslation } from '@vertesia/ui/i18n';
|
|
16
|
+
import { useUserSession } from '@vertesia/ui/session';
|
|
17
|
+
import {
|
|
18
|
+
ArtifactEditingSurface,
|
|
19
|
+
type ArtifactEditingSurfaceDocumentEdit,
|
|
20
|
+
createUnifiedLineDiff,
|
|
21
|
+
diffTextSegments,
|
|
22
|
+
isArtifactRefreshEvent,
|
|
23
|
+
type MarkdownEditingAction,
|
|
24
|
+
} from '@vertesia/ui/widgets';
|
|
25
|
+
import {
|
|
26
|
+
Check,
|
|
27
|
+
FilePenLine,
|
|
28
|
+
FileText,
|
|
29
|
+
GitCompareArrows,
|
|
30
|
+
ListChecks,
|
|
31
|
+
RefreshCw,
|
|
32
|
+
RotateCcw,
|
|
33
|
+
Save,
|
|
34
|
+
Sparkles,
|
|
35
|
+
X,
|
|
36
|
+
} from 'lucide-react';
|
|
37
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
38
|
+
import {
|
|
39
|
+
ModernAgentConversation,
|
|
40
|
+
type SendAgentMessageFn,
|
|
41
|
+
type StartWorkflowOptions,
|
|
42
|
+
} from '../../../agent/chat/ModernAgentConversation.js';
|
|
43
|
+
import { resolveTypeCached } from '../../types/typeCatalogCache.js';
|
|
44
|
+
import {
|
|
45
|
+
type DocumentEditingConfiguration,
|
|
46
|
+
DocumentEditingConfigurationSelector,
|
|
47
|
+
getDocumentEditingProjectDefault,
|
|
48
|
+
} from './DocumentEditingConfigurationSelector.js';
|
|
49
|
+
import { DocumentEditingLockStatus } from './DocumentEditingLockStatus.js';
|
|
50
|
+
import { persistRunLocalArtifactRefs } from './documentArtifactRefs.js';
|
|
51
|
+
import {
|
|
52
|
+
DOCUMENT_EDITING_EXCLUDED_TOOLS,
|
|
53
|
+
DOCUMENT_EDITING_INITIAL_SKILLS,
|
|
54
|
+
DOCUMENT_EDITING_TOOLS,
|
|
55
|
+
} from './documentEditingAgentConfig.js';
|
|
56
|
+
import { createDirectEditsAppliedPrompt } from './documentEditingPrompts.js';
|
|
57
|
+
import {
|
|
58
|
+
createDocumentEditingRunIdentity,
|
|
59
|
+
DOCUMENT_EDITING_DEFAULT_INTERACTION,
|
|
60
|
+
type DocumentEditingRunProperties,
|
|
61
|
+
findDocumentEditingRun,
|
|
62
|
+
} from './documentEditingRun.js';
|
|
63
|
+
import { resolveDocumentEditingTarget } from './documentEditingTarget.js';
|
|
64
|
+
import { SaveVersionConfirmModal } from './SaveVersionConfirmModal.js';
|
|
65
|
+
|
|
66
|
+
type ModelOptions = NonNullable<InteractionExecutionConfiguration['model_options']>;
|
|
67
|
+
|
|
68
|
+
export interface DocumentEditingModelConfiguration {
|
|
69
|
+
env: string;
|
|
70
|
+
model: string;
|
|
71
|
+
options?: ModelOptions;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface DocumentEditingPanelProps {
|
|
75
|
+
object: ContentObject;
|
|
76
|
+
initialContent: string;
|
|
77
|
+
onClose: () => void;
|
|
78
|
+
onDocumentUpdated: (updatedDocumentId: string, createdVersion: boolean) => void;
|
|
79
|
+
sendMessageRef: React.MutableRefObject<SendAgentMessageFn | null>;
|
|
80
|
+
/** Model configuration for new editing runs. Overrides the project default when supplied. */
|
|
81
|
+
model?: DocumentEditingModelConfiguration;
|
|
82
|
+
/** Start a new run once the document target and existing-run lookup are resolved. */
|
|
83
|
+
startImmediately?: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface DocumentEditingWorkspaceProps {
|
|
87
|
+
/** Document to edit (any revision); the workspace resolves and targets the head revision. */
|
|
88
|
+
object: ContentObject;
|
|
89
|
+
/** Known document text shown while the working copy hydrates. */
|
|
90
|
+
initialContent?: string;
|
|
91
|
+
/** Called after publishing, including whether the save created a new revision. */
|
|
92
|
+
onDocumentUpdated?: (updatedDocumentId: string, createdVersion: boolean) => void;
|
|
93
|
+
/** When provided, a close button is rendered in the workspace header. */
|
|
94
|
+
onClose?: () => void;
|
|
95
|
+
/** Optional external handle to send chat messages programmatically. */
|
|
96
|
+
sendMessageRef?: React.MutableRefObject<SendAgentMessageFn | null>;
|
|
97
|
+
/** Model configuration for new editing runs. Overrides the project default when supplied. */
|
|
98
|
+
model?: DocumentEditingModelConfiguration;
|
|
99
|
+
/** Start a new run once the document target and existing-run lookup are resolved. Defaults to false. */
|
|
100
|
+
startImmediately?: boolean;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function shortenRunId(id: string): string {
|
|
104
|
+
return id.length > 12 ? `${id.slice(0, 4)}…${id.slice(-4)}` : id;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getDocumentDraftPath(documentRootId: string): string {
|
|
108
|
+
return `drafts/${documentRootId}.md`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function createDocumentEditingPrompt(
|
|
112
|
+
object: ContentObject,
|
|
113
|
+
documentId: string,
|
|
114
|
+
documentEtag: string | undefined,
|
|
115
|
+
draftPath: string,
|
|
116
|
+
userPrompt: string,
|
|
117
|
+
): string {
|
|
118
|
+
const documentName = object.name || object.content?.name || 'Document';
|
|
119
|
+
return [
|
|
120
|
+
'You are collaborating with the user on one specific Markdown document in Vertesia.',
|
|
121
|
+
`Canonical document: [${documentName}](store:${documentId})`,
|
|
122
|
+
`Canonical base revision ID: ${documentId}`,
|
|
123
|
+
`Canonical base ETag: ${documentEtag ?? 'unavailable'}`,
|
|
124
|
+
`Working copy artifact: ${draftPath}`,
|
|
125
|
+
'',
|
|
126
|
+
'The working copy was hydrated and read before your first turn. It is the source of truth for this editing',
|
|
127
|
+
'session. Apply requested changes only to that artifact using edit_artifact. Preserve all unrelated content',
|
|
128
|
+
'exactly. User block edits may already be applied to the artifact; acknowledge them and continue from the',
|
|
129
|
+
'current artifact generation. Attachments may contain review comments to apply in bulk.',
|
|
130
|
+
'',
|
|
131
|
+
'Do not call update_document, create_document, or write_artifact for this working copy. The user publishes',
|
|
132
|
+
'the artifact back to the canonical document with the Save to document button, which enforces the base ETag.',
|
|
133
|
+
'',
|
|
134
|
+
'You may use execute_shell to regenerate charts, diagrams, and other derived assets. Write generated files',
|
|
135
|
+
"under '/home/daytona/out/' so they sync back to the run, then reference them from Markdown with a run-local",
|
|
136
|
+
"link such as 'artifact:out/chart.png'. Saving the document persists and rewrites those links automatically.",
|
|
137
|
+
'',
|
|
138
|
+
'Images: never inline image data as base64 data URIs — it bloats the document and cannot be reliably edited.',
|
|
139
|
+
"Keep existing image references (e.g. 'artifact:documents/…' URLs) exactly as they are: they point to durable",
|
|
140
|
+
"storage that outlives this session. Files already in this run's artifact space may be referenced with",
|
|
141
|
+
"run-local links like 'artifact:files/photo.png' — publishing copies them into durable storage and rewrites",
|
|
142
|
+
'the links automatically.',
|
|
143
|
+
'',
|
|
144
|
+
`User request: ${userPrompt}`,
|
|
145
|
+
].join('\n');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Chat prompt asking the agent to merge external canonical changes into the working copy. */
|
|
149
|
+
export function createDocumentReconcilePrompt(
|
|
150
|
+
documentRootId: string,
|
|
151
|
+
headDocumentId: string,
|
|
152
|
+
draftPath: string,
|
|
153
|
+
): string {
|
|
154
|
+
return [
|
|
155
|
+
'The canonical document was updated outside this session, so publishing the working copy was rejected.',
|
|
156
|
+
`1) Fetch the latest canonical revision ${headDocumentId} with fetch_document into 'drafts/${documentRootId}.theirs.md'.`,
|
|
157
|
+
`2) Compare it with the working copy '${draftPath}' and merge the external changes into the working copy with edit_artifact, preserving this session's edits.`,
|
|
158
|
+
'3) Reply with a short list of what was merged, plus any conflicting passages and how you resolved them, so I can review before saving again.',
|
|
159
|
+
].join('\n');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Chat prompt asking the agent for a changelog of the working copy vs the session baseline. */
|
|
163
|
+
export function createDocumentChangeSummaryPrompt(
|
|
164
|
+
documentRootId: string,
|
|
165
|
+
originalDocumentId: string,
|
|
166
|
+
draftPath: string,
|
|
167
|
+
): string {
|
|
168
|
+
return [
|
|
169
|
+
`Summarize the changes in the working copy '${draftPath}' relative to the original document revision ${originalDocumentId}.`,
|
|
170
|
+
`If you no longer have the original content, fetch it with fetch_document into 'drafts/${documentRootId}.base.md'.`,
|
|
171
|
+
'Do not modify the working copy.',
|
|
172
|
+
'Reply with a concise changelog: grouped bullets, most important first, suitable for a revision note.',
|
|
173
|
+
].join('\n');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function getErrorStatus(error: unknown): number | undefined {
|
|
177
|
+
if (!error || typeof error !== 'object' || !('status' in error)) return undefined;
|
|
178
|
+
return typeof error.status === 'number' ? error.status : undefined;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function DocumentWorkingCopyDiff({ original, workingCopy }: { original: string; workingCopy: string }) {
|
|
182
|
+
const segments = useMemo(() => diffTextSegments(original, workingCopy), [original, workingCopy]);
|
|
183
|
+
const counts = useMemo(
|
|
184
|
+
() => ({
|
|
185
|
+
added: segments.reduce((total, segment) => total + (segment.type === 'added' ? segment.text.length : 0), 0),
|
|
186
|
+
removed: segments.reduce(
|
|
187
|
+
(total, segment) => total + (segment.type === 'removed' ? segment.text.length : 0),
|
|
188
|
+
0,
|
|
189
|
+
),
|
|
190
|
+
}),
|
|
191
|
+
[segments],
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<div className="flex h-full min-h-0 flex-col bg-muted/10">
|
|
196
|
+
<div className="flex shrink-0 items-center justify-end gap-3 border-b border-mixer-muted/20 px-5 py-2 text-xs">
|
|
197
|
+
<span className="text-destructive">−{counts.removed}</span>
|
|
198
|
+
<span className="text-success">+{counts.added}</span>
|
|
199
|
+
</div>
|
|
200
|
+
<div className="min-h-0 flex-1 overflow-auto p-5">
|
|
201
|
+
<pre className="mx-auto max-w-5xl whitespace-pre-wrap break-words rounded-lg border border-mixer-muted/25 bg-background p-5 font-mono text-xs leading-6 shadow-sm">
|
|
202
|
+
{segments.map((segment, index) => {
|
|
203
|
+
if (segment.type === 'removed') {
|
|
204
|
+
return (
|
|
205
|
+
<del
|
|
206
|
+
key={index}
|
|
207
|
+
className="bg-mixer-destructive/15 text-destructive line-through decoration-destructive/50"
|
|
208
|
+
>
|
|
209
|
+
{segment.text}
|
|
210
|
+
</del>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (segment.type === 'added') {
|
|
214
|
+
return (
|
|
215
|
+
<ins key={index} className="bg-mixer-success/15 text-success no-underline">
|
|
216
|
+
{segment.text}
|
|
217
|
+
</ins>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return <span key={index}>{segment.text}</span>;
|
|
221
|
+
})}
|
|
222
|
+
</pre>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Full document editing workspace: working copy surface plus the editing conversation.
|
|
230
|
+
* Standalone so host applications can embed it in their own layout; DocumentEditingPanel
|
|
231
|
+
* wraps it in a full-screen modal for the Studio object page.
|
|
232
|
+
*/
|
|
233
|
+
export function DocumentEditingWorkspace({
|
|
234
|
+
object,
|
|
235
|
+
initialContent = '',
|
|
236
|
+
onDocumentUpdated,
|
|
237
|
+
onClose,
|
|
238
|
+
sendMessageRef,
|
|
239
|
+
model,
|
|
240
|
+
startImmediately = false,
|
|
241
|
+
}: DocumentEditingWorkspaceProps) {
|
|
242
|
+
const { client, project, store, user } = useUserSession();
|
|
243
|
+
const { t } = useUITranslation();
|
|
244
|
+
const toast = useToast();
|
|
245
|
+
const internalSendMessageRef = useRef<SendAgentMessageFn | null>(null);
|
|
246
|
+
const messageRef = sendMessageRef ?? internalSendMessageRef;
|
|
247
|
+
const [agentRunId, setAgentRunId] = useState<string | undefined>();
|
|
248
|
+
const [isStarting, setIsStarting] = useState(false);
|
|
249
|
+
const [isTerminating, setIsTerminating] = useState(false);
|
|
250
|
+
const [isResolvingRun, setIsResolvingRun] = useState(true);
|
|
251
|
+
const [isResolvingTarget, setIsResolvingTarget] = useState(true);
|
|
252
|
+
const [targetResolutionFailed, setTargetResolutionFailed] = useState(false);
|
|
253
|
+
const [targetResolutionAttempt, setTargetResolutionAttempt] = useState(0);
|
|
254
|
+
const [showNewSessionConfirm, setShowNewSessionConfirm] = useState(false);
|
|
255
|
+
const providedConfigurationKey = JSON.stringify(
|
|
256
|
+
model
|
|
257
|
+
? {
|
|
258
|
+
environment: model.env,
|
|
259
|
+
model: model.model,
|
|
260
|
+
model_options: model.options,
|
|
261
|
+
}
|
|
262
|
+
: {},
|
|
263
|
+
);
|
|
264
|
+
const hasProvidedConfiguration = model !== undefined;
|
|
265
|
+
const providedConfiguration = useMemo<DocumentEditingConfiguration>(
|
|
266
|
+
() => JSON.parse(providedConfigurationKey) as DocumentEditingConfiguration,
|
|
267
|
+
[providedConfigurationKey],
|
|
268
|
+
);
|
|
269
|
+
const [isLoadingConfiguration, setIsLoadingConfiguration] = useState(!hasProvidedConfiguration);
|
|
270
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
271
|
+
const [showSaveConfirmation, setShowSaveConfirmation] = useState(false);
|
|
272
|
+
const [isSendingChanges, setIsSendingChanges] = useState(false);
|
|
273
|
+
const [isAgentWorking, setIsAgentWorking] = useState(false);
|
|
274
|
+
const [isEditingManuallyUnlocked, setIsEditingManuallyUnlocked] = useState(false);
|
|
275
|
+
const [hasDirectEditorChanges, setHasDirectEditorChanges] = useState(false);
|
|
276
|
+
const [artifactRefresh, setArtifactRefresh] = useState<{
|
|
277
|
+
key: number;
|
|
278
|
+
details?: Record<string, unknown>;
|
|
279
|
+
}>({ key: 0 });
|
|
280
|
+
const [artifactContent, setArtifactContent] = useState(initialContent);
|
|
281
|
+
const [artifactLoaded, setArtifactLoaded] = useState(false);
|
|
282
|
+
const [originalContent, setOriginalContent] = useState(initialContent);
|
|
283
|
+
const [savedContent, setSavedContent] = useState(initialContent);
|
|
284
|
+
const [workspaceView, setWorkspaceView] = useState<'document' | 'editor' | 'diff'>('document');
|
|
285
|
+
const [saveConflict, setSaveConflict] = useState<{ headId: string } | undefined>();
|
|
286
|
+
const [targetDocumentId, setTargetDocumentId] = useState(object.id);
|
|
287
|
+
const [targetEtag, setTargetEtag] = useState(object.content?.etag);
|
|
288
|
+
const [resolvedEditingPolicy, setResolvedEditingPolicy] = useState<{
|
|
289
|
+
key: string;
|
|
290
|
+
interaction: string;
|
|
291
|
+
}>();
|
|
292
|
+
const [executionConfiguration, setExecutionConfiguration] =
|
|
293
|
+
useState<DocumentEditingConfiguration>(providedConfiguration);
|
|
294
|
+
const configurationSourceRef = useRef<'none' | 'host' | 'project' | 'run' | 'user'>(
|
|
295
|
+
hasProvidedConfiguration ? 'host' : 'none',
|
|
296
|
+
);
|
|
297
|
+
const automaticStartKeyRef = useRef<string | undefined>(undefined);
|
|
298
|
+
const seenUpdatesRef = useRef(new Set<string>());
|
|
299
|
+
const artifactGenerationRef = useRef<string | undefined>(undefined);
|
|
300
|
+
const agentWorkingRef = useRef(false);
|
|
301
|
+
const flushArtifactChangesRef = useRef<(() => Promise<false | ArtifactEditingSurfaceDocumentEdit>) | null>(null);
|
|
302
|
+
const documentRootId = object.revision?.root || object.id;
|
|
303
|
+
const draftPath = useMemo(() => getDocumentDraftPath(documentRootId), [documentRootId]);
|
|
304
|
+
const startedBy = user?.sub ? `user:${user.sub}` : undefined;
|
|
305
|
+
const editingScopeKey = `${project?.id ?? 'no-project'}:${documentRootId}`;
|
|
306
|
+
const editingPolicyKey = `${editingScopeKey}:${object.type?.id ?? 'no-type'}`;
|
|
307
|
+
const editingInteraction =
|
|
308
|
+
resolvedEditingPolicy?.key === editingPolicyKey ? resolvedEditingPolicy.interaction : undefined;
|
|
309
|
+
const editingScopeRef = useRef(editingScopeKey);
|
|
310
|
+
const originalDocumentRef = useRef({ editingScopeKey, id: object.id });
|
|
311
|
+
const lookupIdentityRef = useRef({ documentId: object.id, documentRootId });
|
|
312
|
+
const isDirty = artifactLoaded && artifactContent !== savedContent;
|
|
313
|
+
const isEditingLocked = isAgentWorking && !isEditingManuallyUnlocked;
|
|
314
|
+
|
|
315
|
+
if (lookupIdentityRef.current.documentRootId !== documentRootId) {
|
|
316
|
+
lookupIdentityRef.current = { documentId: object.id, documentRootId };
|
|
317
|
+
}
|
|
318
|
+
if (originalDocumentRef.current.editingScopeKey !== editingScopeKey) {
|
|
319
|
+
originalDocumentRef.current = { editingScopeKey, id: object.id };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
useEffect(() => {
|
|
323
|
+
if (editingScopeRef.current === editingScopeKey) return;
|
|
324
|
+
editingScopeRef.current = editingScopeKey;
|
|
325
|
+
configurationSourceRef.current = hasProvidedConfiguration ? 'host' : 'none';
|
|
326
|
+
setExecutionConfiguration(providedConfiguration);
|
|
327
|
+
setIsLoadingConfiguration(!hasProvidedConfiguration);
|
|
328
|
+
seenUpdatesRef.current.clear();
|
|
329
|
+
setArtifactContent(initialContent);
|
|
330
|
+
setOriginalContent(initialContent);
|
|
331
|
+
setSavedContent(initialContent);
|
|
332
|
+
setArtifactLoaded(false);
|
|
333
|
+
setHasDirectEditorChanges(false);
|
|
334
|
+
setIsAgentWorking(false);
|
|
335
|
+
setIsEditingManuallyUnlocked(false);
|
|
336
|
+
agentWorkingRef.current = false;
|
|
337
|
+
setWorkspaceView('document');
|
|
338
|
+
setTargetDocumentId(object.id);
|
|
339
|
+
setTargetEtag(object.content?.etag);
|
|
340
|
+
}, [
|
|
341
|
+
editingScopeKey,
|
|
342
|
+
hasProvidedConfiguration,
|
|
343
|
+
initialContent,
|
|
344
|
+
object.content?.etag,
|
|
345
|
+
object.id,
|
|
346
|
+
providedConfiguration,
|
|
347
|
+
]);
|
|
348
|
+
|
|
349
|
+
useEffect(() => {
|
|
350
|
+
let cancelled = false;
|
|
351
|
+
const requestScopeKey = editingScopeKey;
|
|
352
|
+
const requestedDocumentId = originalDocumentRef.current.id;
|
|
353
|
+
setIsResolvingTarget(true);
|
|
354
|
+
setTargetResolutionFailed(false);
|
|
355
|
+
|
|
356
|
+
// Commit the target id, ETag, and text only after all reads succeed. A failed
|
|
357
|
+
// head lookup must never turn a historical revision into an editable fallback.
|
|
358
|
+
void resolveDocumentEditingTarget(store.objects, requestedDocumentId)
|
|
359
|
+
.then((target) => {
|
|
360
|
+
if (cancelled || originalDocumentRef.current.editingScopeKey !== requestScopeKey) return;
|
|
361
|
+
|
|
362
|
+
originalDocumentRef.current = { editingScopeKey: requestScopeKey, id: target.id };
|
|
363
|
+
lookupIdentityRef.current = { documentId: target.id, documentRootId };
|
|
364
|
+
setTargetDocumentId(target.id);
|
|
365
|
+
setTargetEtag(target.etag);
|
|
366
|
+
setOriginalContent(target.content);
|
|
367
|
+
setSavedContent(target.content);
|
|
368
|
+
})
|
|
369
|
+
.catch((error: unknown) => {
|
|
370
|
+
console.warn('Failed to resolve the document editing target', {
|
|
371
|
+
error,
|
|
372
|
+
attempt: targetResolutionAttempt,
|
|
373
|
+
});
|
|
374
|
+
if (!cancelled && originalDocumentRef.current.editingScopeKey === requestScopeKey) {
|
|
375
|
+
setTargetResolutionFailed(true);
|
|
376
|
+
}
|
|
377
|
+
})
|
|
378
|
+
.finally(() => {
|
|
379
|
+
if (!cancelled && originalDocumentRef.current.editingScopeKey === requestScopeKey) {
|
|
380
|
+
setIsResolvingTarget(false);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
return () => {
|
|
385
|
+
cancelled = true;
|
|
386
|
+
};
|
|
387
|
+
}, [documentRootId, editingScopeKey, store.objects, targetResolutionAttempt]);
|
|
388
|
+
|
|
389
|
+
useEffect(() => {
|
|
390
|
+
let cancelled = false;
|
|
391
|
+
const typeId = object.type?.id;
|
|
392
|
+
|
|
393
|
+
if (!typeId) {
|
|
394
|
+
setResolvedEditingPolicy({
|
|
395
|
+
key: editingPolicyKey,
|
|
396
|
+
interaction: DOCUMENT_EDITING_DEFAULT_INTERACTION,
|
|
397
|
+
});
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
void resolveTypeCached(client, typeId).then((type) => {
|
|
402
|
+
if (cancelled) return;
|
|
403
|
+
setResolvedEditingPolicy({
|
|
404
|
+
key: editingPolicyKey,
|
|
405
|
+
interaction: type?.editing?.interaction?.trim() || DOCUMENT_EDITING_DEFAULT_INTERACTION,
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
return () => {
|
|
410
|
+
cancelled = true;
|
|
411
|
+
};
|
|
412
|
+
}, [client, editingPolicyKey, object.type?.id]);
|
|
413
|
+
|
|
414
|
+
useEffect(() => {
|
|
415
|
+
if (agentRunId || configurationSourceRef.current === 'run') return;
|
|
416
|
+
|
|
417
|
+
if (hasProvidedConfiguration) {
|
|
418
|
+
configurationSourceRef.current = 'host';
|
|
419
|
+
setExecutionConfiguration(providedConfiguration);
|
|
420
|
+
setIsLoadingConfiguration(false);
|
|
421
|
+
} else if (configurationSourceRef.current === 'host') {
|
|
422
|
+
configurationSourceRef.current = 'none';
|
|
423
|
+
setExecutionConfiguration({});
|
|
424
|
+
}
|
|
425
|
+
}, [agentRunId, hasProvidedConfiguration, providedConfiguration]);
|
|
426
|
+
|
|
427
|
+
useEffect(() => {
|
|
428
|
+
if (hasProvidedConfiguration) {
|
|
429
|
+
setIsLoadingConfiguration(false);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (!project) {
|
|
434
|
+
setIsLoadingConfiguration(false);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
let cancelled = false;
|
|
439
|
+
const requestScopeKey = editingScopeKey;
|
|
440
|
+
setIsLoadingConfiguration(true);
|
|
441
|
+
void client.projects
|
|
442
|
+
.retrieve(project.id)
|
|
443
|
+
.then((fullProject) => {
|
|
444
|
+
if (
|
|
445
|
+
cancelled ||
|
|
446
|
+
editingScopeRef.current !== requestScopeKey ||
|
|
447
|
+
configurationSourceRef.current !== 'none'
|
|
448
|
+
) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
configurationSourceRef.current = 'project';
|
|
452
|
+
setExecutionConfiguration(getDocumentEditingProjectDefault(fullProject));
|
|
453
|
+
})
|
|
454
|
+
.catch((error: unknown) => {
|
|
455
|
+
console.warn('Failed to load the default document editing model', error);
|
|
456
|
+
})
|
|
457
|
+
.finally(() => {
|
|
458
|
+
if (!cancelled) setIsLoadingConfiguration(false);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
return () => {
|
|
462
|
+
cancelled = true;
|
|
463
|
+
};
|
|
464
|
+
}, [client, editingScopeKey, hasProvidedConfiguration, project]);
|
|
465
|
+
|
|
466
|
+
useEffect(() => {
|
|
467
|
+
setAgentRunId(undefined);
|
|
468
|
+
if (!startedBy || !editingInteraction) {
|
|
469
|
+
setIsResolvingRun(false);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
let cancelled = false;
|
|
474
|
+
setIsResolvingRun(true);
|
|
475
|
+
void findDocumentEditingRun(
|
|
476
|
+
client.agents,
|
|
477
|
+
lookupIdentityRef.current.documentId,
|
|
478
|
+
documentRootId,
|
|
479
|
+
startedBy,
|
|
480
|
+
editingInteraction,
|
|
481
|
+
)
|
|
482
|
+
.then((run) => {
|
|
483
|
+
if (cancelled || !run) return;
|
|
484
|
+
setAgentRunId(run.id);
|
|
485
|
+
if (run.config?.environment && run.config.model) {
|
|
486
|
+
configurationSourceRef.current = 'run';
|
|
487
|
+
setExecutionConfiguration({
|
|
488
|
+
environment: run.config.environment,
|
|
489
|
+
model: run.config.model,
|
|
490
|
+
model_options: run.config.model_options,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
})
|
|
494
|
+
.catch((error: unknown) => {
|
|
495
|
+
console.warn('Failed to look up an existing document editing run', error);
|
|
496
|
+
})
|
|
497
|
+
.finally(() => {
|
|
498
|
+
if (!cancelled) setIsResolvingRun(false);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
return () => {
|
|
502
|
+
cancelled = true;
|
|
503
|
+
};
|
|
504
|
+
}, [client, documentRootId, editingInteraction, startedBy]);
|
|
505
|
+
|
|
506
|
+
const handleConfigurationChange = useCallback((value: DocumentEditingConfiguration) => {
|
|
507
|
+
configurationSourceRef.current = 'user';
|
|
508
|
+
setExecutionConfiguration(value);
|
|
509
|
+
}, []);
|
|
510
|
+
|
|
511
|
+
const handleCopyRunId = useCallback(() => {
|
|
512
|
+
if (!agentRunId) return;
|
|
513
|
+
navigator.clipboard
|
|
514
|
+
.writeText(agentRunId)
|
|
515
|
+
.then(() => toast({ status: 'success', title: t('agent.runIdCopied'), duration: 2000 }))
|
|
516
|
+
.catch((error: unknown) => console.warn('Failed to copy the agent run id', error));
|
|
517
|
+
}, [agentRunId, t, toast]);
|
|
518
|
+
|
|
519
|
+
const handleStartNewSession = useCallback(async () => {
|
|
520
|
+
if (!agentRunId || isTerminating) return;
|
|
521
|
+
setIsTerminating(true);
|
|
522
|
+
try {
|
|
523
|
+
await client.agents.terminate(agentRunId, 'cancel');
|
|
524
|
+
toast({ status: 'success', title: t('agent.workflowCancelled'), duration: 2000 });
|
|
525
|
+
} catch (error: unknown) {
|
|
526
|
+
console.warn('Failed to terminate the document editing run', error);
|
|
527
|
+
} finally {
|
|
528
|
+
setIsTerminating(false);
|
|
529
|
+
}
|
|
530
|
+
seenUpdatesRef.current.clear();
|
|
531
|
+
setAgentRunId(undefined);
|
|
532
|
+
setArtifactLoaded(false);
|
|
533
|
+
setArtifactContent(savedContent);
|
|
534
|
+
setHasDirectEditorChanges(false);
|
|
535
|
+
agentWorkingRef.current = false;
|
|
536
|
+
setIsAgentWorking(false);
|
|
537
|
+
setIsEditingManuallyUnlocked(false);
|
|
538
|
+
}, [agentRunId, client.agents, isTerminating, savedContent, t, toast]);
|
|
539
|
+
|
|
540
|
+
const startWorkflow = useCallback(
|
|
541
|
+
async (initialMessage?: string, options?: StartWorkflowOptions) => {
|
|
542
|
+
if (
|
|
543
|
+
!project ||
|
|
544
|
+
!editingInteraction ||
|
|
545
|
+
isResolvingRun ||
|
|
546
|
+
isResolvingTarget ||
|
|
547
|
+
targetResolutionFailed ||
|
|
548
|
+
isStarting ||
|
|
549
|
+
isLoadingConfiguration
|
|
550
|
+
) {
|
|
551
|
+
return undefined;
|
|
552
|
+
}
|
|
553
|
+
setIsStarting(true);
|
|
554
|
+
try {
|
|
555
|
+
if (!executionConfiguration.environment || !executionConfiguration.model) {
|
|
556
|
+
toast({ status: 'error', title: t('agent.documentEditingDefaultsRequired'), duration: 5000 });
|
|
557
|
+
return undefined;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const prompt = createDocumentEditingPrompt(
|
|
561
|
+
object,
|
|
562
|
+
targetDocumentId,
|
|
563
|
+
targetEtag,
|
|
564
|
+
draftPath,
|
|
565
|
+
initialMessage?.trim() || t('agent.documentEditingInitialRequest'),
|
|
566
|
+
);
|
|
567
|
+
const identity = createDocumentEditingRunIdentity(targetDocumentId, documentRootId);
|
|
568
|
+
const payload: CreateAgentRunPayload<{ user_prompt: string }, DocumentEditingRunProperties> = {
|
|
569
|
+
interaction: editingInteraction,
|
|
570
|
+
interactive: true,
|
|
571
|
+
tool_approval_mode: options?.tool_approval_mode,
|
|
572
|
+
tool_names: DOCUMENT_EDITING_TOOLS,
|
|
573
|
+
excluded_tools: DOCUMENT_EDITING_EXCLUDED_TOOLS,
|
|
574
|
+
initial_skills: DOCUMENT_EDITING_INITIAL_SKILLS,
|
|
575
|
+
initial_tool_calls: [
|
|
576
|
+
{
|
|
577
|
+
id: 'hydrate-working-copy',
|
|
578
|
+
tool: 'fetch_document',
|
|
579
|
+
input: { id: targetDocumentId, mode: 'content', output_artifact: { path: draftPath } },
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: 'read-working-copy',
|
|
583
|
+
tool: 'read_artifact',
|
|
584
|
+
input: { path: draftPath },
|
|
585
|
+
},
|
|
586
|
+
],
|
|
587
|
+
data: { user_prompt: prompt },
|
|
588
|
+
config: {
|
|
589
|
+
environment: executionConfiguration.environment,
|
|
590
|
+
model: executionConfiguration.model,
|
|
591
|
+
model_options: executionConfiguration.model_options,
|
|
592
|
+
},
|
|
593
|
+
started_by: startedBy,
|
|
594
|
+
tags: identity.tags,
|
|
595
|
+
properties: identity.properties,
|
|
596
|
+
};
|
|
597
|
+
const run = await client.agents.start(payload);
|
|
598
|
+
setAgentRunId(run.id);
|
|
599
|
+
return { agent_run_id: run.id };
|
|
600
|
+
} catch (error: unknown) {
|
|
601
|
+
console.error('Failed to start document editing agent', error);
|
|
602
|
+
toast({
|
|
603
|
+
status: 'error',
|
|
604
|
+
title: t('agent.documentEditingStartFailed'),
|
|
605
|
+
description: error instanceof Error ? error.message : undefined,
|
|
606
|
+
duration: 5000,
|
|
607
|
+
});
|
|
608
|
+
return undefined;
|
|
609
|
+
} finally {
|
|
610
|
+
setIsStarting(false);
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
[
|
|
614
|
+
client.agents,
|
|
615
|
+
documentRootId,
|
|
616
|
+
draftPath,
|
|
617
|
+
executionConfiguration,
|
|
618
|
+
editingInteraction,
|
|
619
|
+
isLoadingConfiguration,
|
|
620
|
+
isResolvingRun,
|
|
621
|
+
isResolvingTarget,
|
|
622
|
+
isStarting,
|
|
623
|
+
object,
|
|
624
|
+
project,
|
|
625
|
+
startedBy,
|
|
626
|
+
t,
|
|
627
|
+
targetDocumentId,
|
|
628
|
+
targetEtag,
|
|
629
|
+
targetResolutionFailed,
|
|
630
|
+
toast,
|
|
631
|
+
],
|
|
632
|
+
);
|
|
633
|
+
|
|
634
|
+
const handleArtifactContentChange = useCallback((content: string, generation?: string) => {
|
|
635
|
+
artifactGenerationRef.current = generation;
|
|
636
|
+
setArtifactContent(content);
|
|
637
|
+
setArtifactLoaded(true);
|
|
638
|
+
}, []);
|
|
639
|
+
|
|
640
|
+
useEffect(() => {
|
|
641
|
+
if (
|
|
642
|
+
!startImmediately ||
|
|
643
|
+
agentRunId ||
|
|
644
|
+
!project ||
|
|
645
|
+
!editingInteraction ||
|
|
646
|
+
isResolvingRun ||
|
|
647
|
+
isResolvingTarget ||
|
|
648
|
+
targetResolutionFailed ||
|
|
649
|
+
isStarting ||
|
|
650
|
+
isLoadingConfiguration ||
|
|
651
|
+
!executionConfiguration.environment ||
|
|
652
|
+
!executionConfiguration.model
|
|
653
|
+
) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const automaticStartKey = JSON.stringify({
|
|
658
|
+
scope: editingScopeKey,
|
|
659
|
+
interaction: editingInteraction,
|
|
660
|
+
document: targetDocumentId,
|
|
661
|
+
configuration: executionConfiguration,
|
|
662
|
+
});
|
|
663
|
+
if (automaticStartKeyRef.current === automaticStartKey) return;
|
|
664
|
+
automaticStartKeyRef.current = automaticStartKey;
|
|
665
|
+
|
|
666
|
+
void startWorkflow(t('agent.documentEditingStartRequest'), { tool_approval_mode: 'full_control' });
|
|
667
|
+
}, [
|
|
668
|
+
agentRunId,
|
|
669
|
+
editingInteraction,
|
|
670
|
+
editingScopeKey,
|
|
671
|
+
executionConfiguration,
|
|
672
|
+
isLoadingConfiguration,
|
|
673
|
+
isResolvingRun,
|
|
674
|
+
isResolvingTarget,
|
|
675
|
+
isStarting,
|
|
676
|
+
project,
|
|
677
|
+
startImmediately,
|
|
678
|
+
startWorkflow,
|
|
679
|
+
t,
|
|
680
|
+
targetDocumentId,
|
|
681
|
+
targetResolutionFailed,
|
|
682
|
+
]);
|
|
683
|
+
|
|
684
|
+
const handleAgentWorkingChange = useCallback((isWorking: boolean) => {
|
|
685
|
+
const wasWorking = agentWorkingRef.current;
|
|
686
|
+
agentWorkingRef.current = isWorking;
|
|
687
|
+
setIsAgentWorking(isWorking);
|
|
688
|
+
|
|
689
|
+
if (!isWorking) {
|
|
690
|
+
setIsEditingManuallyUnlocked(false);
|
|
691
|
+
if (wasWorking) {
|
|
692
|
+
setArtifactRefresh((current) => ({ key: current.key + 1 }));
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}, []);
|
|
696
|
+
|
|
697
|
+
const sendEditingMessage = useCallback(
|
|
698
|
+
(message: string, inputMetadata?: Record<string, unknown>) => {
|
|
699
|
+
const sendMessage = messageRef.current;
|
|
700
|
+
if (!sendMessage) {
|
|
701
|
+
toast({ status: 'warning', title: t('agent.artifactEditingUnavailable'), duration: 3000 });
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
sendMessage(message, inputMetadata);
|
|
705
|
+
},
|
|
706
|
+
[messageRef, t, toast],
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
const handleArtifactAction = useCallback(
|
|
710
|
+
(action: MarkdownEditingAction) => {
|
|
711
|
+
const blockType = action.anchor.block_type.replaceAll('_', ' ');
|
|
712
|
+
const displayMessage = action.comment?.trim() || t('agent.editedSelectionMessage', { blockType });
|
|
713
|
+
sendEditingMessage(displayMessage, { editing_action: action });
|
|
714
|
+
},
|
|
715
|
+
[sendEditingMessage, t],
|
|
716
|
+
);
|
|
717
|
+
|
|
718
|
+
const handleSave = useCallback(
|
|
719
|
+
async (createVersion: boolean, versionLabel?: string) => {
|
|
720
|
+
if (
|
|
721
|
+
!artifactLoaded ||
|
|
722
|
+
!targetEtag ||
|
|
723
|
+
!isDirty ||
|
|
724
|
+
isEditingLocked ||
|
|
725
|
+
isSaving ||
|
|
726
|
+
isResolvingTarget ||
|
|
727
|
+
targetResolutionFailed
|
|
728
|
+
) {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
setIsSaving(true);
|
|
732
|
+
try {
|
|
733
|
+
// Persist run-local artifact references (session-generated charts, files)
|
|
734
|
+
// into durable documents/ storage and rewrite the links before publishing —
|
|
735
|
+
// the same pass create_document applies. Run artifact storage does not
|
|
736
|
+
// outlive the session, so the canonical document must never depend on it.
|
|
737
|
+
let contentToSave = artifactContent;
|
|
738
|
+
if (agentRunId) {
|
|
739
|
+
const persistence = await persistRunLocalArtifactRefs(
|
|
740
|
+
client.files,
|
|
741
|
+
contentToSave,
|
|
742
|
+
agentRunId,
|
|
743
|
+
crypto.randomUUID(),
|
|
744
|
+
);
|
|
745
|
+
contentToSave = persistence.content;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
const contentType = object.content?.type || 'text/markdown';
|
|
749
|
+
const fileName = object.content?.name || 'content.md';
|
|
750
|
+
const file = new File([new Blob([contentToSave], { type: contentType })], fileName, {
|
|
751
|
+
type: contentType,
|
|
752
|
+
});
|
|
753
|
+
const response = await store.objects.update(
|
|
754
|
+
targetDocumentId,
|
|
755
|
+
{ content: file },
|
|
756
|
+
{ createRevision: createVersion, revisionLabel: versionLabel, ifMatch: targetEtag },
|
|
757
|
+
);
|
|
758
|
+
setTargetDocumentId(response.id);
|
|
759
|
+
setTargetEtag(response.content?.etag);
|
|
760
|
+
setSavedContent(contentToSave);
|
|
761
|
+
setSaveConflict(undefined);
|
|
762
|
+
setShowSaveConfirmation(false);
|
|
763
|
+
onDocumentUpdated?.(response.id, createVersion);
|
|
764
|
+
toast({ status: 'success', title: t('store.textSaved'), duration: 2500 });
|
|
765
|
+
|
|
766
|
+
// Sync the rewritten links back into the working copy so it matches the
|
|
767
|
+
// published revision. A concurrent agent edit (412) just leaves the copy
|
|
768
|
+
// dirty, which is accurate — it no longer matches what was published.
|
|
769
|
+
if (agentRunId && contentToSave !== artifactContent && artifactGenerationRef.current) {
|
|
770
|
+
try {
|
|
771
|
+
await client.agents.updateArtifactContent(agentRunId, draftPath, {
|
|
772
|
+
content: contentToSave,
|
|
773
|
+
generation: artifactGenerationRef.current,
|
|
774
|
+
});
|
|
775
|
+
setArtifactRefresh((current) => ({ key: current.key + 1 }));
|
|
776
|
+
} catch (syncError: unknown) {
|
|
777
|
+
console.warn('Failed to sync persisted artifact links into the working copy', syncError);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
} catch (error: unknown) {
|
|
781
|
+
// Two conflict shapes: an in-place edit of the target revision fails the
|
|
782
|
+
// If-Match precondition (412), while a new external revision moves the head
|
|
783
|
+
// and the save is rejected as not-head (400). Both mean the canonical
|
|
784
|
+
// document changed since this session's baseline.
|
|
785
|
+
const status = getErrorStatus(error);
|
|
786
|
+
let isConflict = status === 412;
|
|
787
|
+
if (status === 412 || status === 400) {
|
|
788
|
+
try {
|
|
789
|
+
const target = await resolveDocumentEditingTarget(store.objects, targetDocumentId);
|
|
790
|
+
if (target.id !== targetDocumentId || status === 412) {
|
|
791
|
+
isConflict = true;
|
|
792
|
+
// Re-point the save target at the new head so the user can choose
|
|
793
|
+
// to overwrite it, and offer an agent-assisted merge instead.
|
|
794
|
+
setTargetDocumentId(target.id);
|
|
795
|
+
setTargetEtag(target.etag);
|
|
796
|
+
setSaveConflict({ headId: target.id });
|
|
797
|
+
}
|
|
798
|
+
} catch (resolveError: unknown) {
|
|
799
|
+
console.warn('Failed to resolve the new head after a save conflict', resolveError);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
toast({
|
|
803
|
+
status: 'error',
|
|
804
|
+
title: t('store.errorSavingText'),
|
|
805
|
+
description: isConflict
|
|
806
|
+
? t('store.textConflict')
|
|
807
|
+
: errorMessage(error, t('store.errorSavingTextDefault')),
|
|
808
|
+
duration: 5000,
|
|
809
|
+
});
|
|
810
|
+
} finally {
|
|
811
|
+
setIsSaving(false);
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
[
|
|
815
|
+
agentRunId,
|
|
816
|
+
artifactContent,
|
|
817
|
+
artifactLoaded,
|
|
818
|
+
client.agents,
|
|
819
|
+
client.files,
|
|
820
|
+
draftPath,
|
|
821
|
+
isDirty,
|
|
822
|
+
isEditingLocked,
|
|
823
|
+
isResolvingTarget,
|
|
824
|
+
isSaving,
|
|
825
|
+
object.content?.name,
|
|
826
|
+
object.content?.type,
|
|
827
|
+
onDocumentUpdated,
|
|
828
|
+
store.objects,
|
|
829
|
+
t,
|
|
830
|
+
targetDocumentId,
|
|
831
|
+
targetEtag,
|
|
832
|
+
targetResolutionFailed,
|
|
833
|
+
toast,
|
|
834
|
+
],
|
|
835
|
+
);
|
|
836
|
+
|
|
837
|
+
const handleReconcile = useCallback(() => {
|
|
838
|
+
const sendMessage = messageRef.current;
|
|
839
|
+
if (!sendMessage || !saveConflict) {
|
|
840
|
+
toast({ status: 'warning', title: t('agent.artifactEditingUnavailable'), duration: 3000 });
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
sendMessage(createDocumentReconcilePrompt(documentRootId, saveConflict.headId, draftPath));
|
|
844
|
+
setSaveConflict(undefined);
|
|
845
|
+
setWorkspaceView('document');
|
|
846
|
+
}, [documentRootId, draftPath, messageRef, saveConflict, t, toast]);
|
|
847
|
+
|
|
848
|
+
const handleSummarizeChanges = useCallback(() => {
|
|
849
|
+
const sendMessage = messageRef.current;
|
|
850
|
+
if (!sendMessage) {
|
|
851
|
+
toast({ status: 'warning', title: t('agent.artifactEditingUnavailable'), duration: 3000 });
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
sendMessage(createDocumentChangeSummaryPrompt(documentRootId, originalDocumentRef.current.id, draftPath));
|
|
855
|
+
}, [documentRootId, draftPath, messageRef, t, toast]);
|
|
856
|
+
|
|
857
|
+
const flushFullEditorChanges = useCallback(async (): Promise<boolean> => {
|
|
858
|
+
if (workspaceView !== 'editor' || !hasDirectEditorChanges) return true;
|
|
859
|
+
return Boolean(await flushArtifactChangesRef.current?.());
|
|
860
|
+
}, [hasDirectEditorChanges, workspaceView]);
|
|
861
|
+
|
|
862
|
+
const handleWorkspaceViewChange = useCallback(
|
|
863
|
+
async (nextView: 'document' | 'editor' | 'diff') => {
|
|
864
|
+
if (nextView === workspaceView) return;
|
|
865
|
+
if (!(await flushFullEditorChanges())) return;
|
|
866
|
+
setWorkspaceView(nextView);
|
|
867
|
+
},
|
|
868
|
+
[flushFullEditorChanges, workspaceView],
|
|
869
|
+
);
|
|
870
|
+
|
|
871
|
+
const handleCloseWorkspace = useCallback(async () => {
|
|
872
|
+
if (!(await flushFullEditorChanges())) return;
|
|
873
|
+
onClose?.();
|
|
874
|
+
}, [flushFullEditorChanges, onClose]);
|
|
875
|
+
|
|
876
|
+
const handleSendChangesToAgent = useCallback(async () => {
|
|
877
|
+
const sendMessage = messageRef.current;
|
|
878
|
+
if (!sendMessage || !agentRunId || isEditingLocked || isSendingChanges) {
|
|
879
|
+
toast({ status: 'warning', title: t('agent.artifactEditingUnavailable'), duration: 3000 });
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
setIsSendingChanges(true);
|
|
884
|
+
try {
|
|
885
|
+
const flushed = await flushArtifactChangesRef.current?.();
|
|
886
|
+
if (!flushed) return;
|
|
887
|
+
// Hand the agent the exact persisted delta so it can update its context
|
|
888
|
+
// without spending another turn reading or re-applying the artifact.
|
|
889
|
+
const unifiedDiff = createUnifiedLineDiff(flushed.previous, flushed.current, { context: 1 });
|
|
890
|
+
if (unifiedDiff) sendMessage(createDirectEditsAppliedPrompt(draftPath, unifiedDiff));
|
|
891
|
+
setHasDirectEditorChanges(false);
|
|
892
|
+
toast({ status: 'success', title: t('agent.changesSentToAgent'), duration: 2000 });
|
|
893
|
+
} finally {
|
|
894
|
+
setIsSendingChanges(false);
|
|
895
|
+
}
|
|
896
|
+
}, [agentRunId, draftPath, isEditingLocked, isSendingChanges, messageRef, t, toast]);
|
|
897
|
+
|
|
898
|
+
return (
|
|
899
|
+
<div className="flex h-full min-h-0 flex-col">
|
|
900
|
+
<div className="flex h-14 shrink-0 items-center justify-between gap-3 border-b border-mixer-muted/20 px-4">
|
|
901
|
+
<div className="min-w-0">
|
|
902
|
+
<div className="truncate font-semibold">{object.name || object.content?.name}</div>
|
|
903
|
+
<div className="flex items-center gap-2 text-xs text-muted">
|
|
904
|
+
<span className="flex shrink-0 items-center gap-1.5">
|
|
905
|
+
{isDirty ? (
|
|
906
|
+
<span aria-hidden className="size-1.5 rounded-full bg-attention" />
|
|
907
|
+
) : artifactLoaded ? (
|
|
908
|
+
<Check className="size-3 text-success" />
|
|
909
|
+
) : null}
|
|
910
|
+
{isDirty ? t('store.unsavedChanges') : t('store.textSaved')}
|
|
911
|
+
</span>
|
|
912
|
+
<span aria-hidden className="text-mixer-muted/60">
|
|
913
|
+
·
|
|
914
|
+
</span>
|
|
915
|
+
<VTooltip description={`${t('agent.workingCopy')}: ${draftPath}`} asChild>
|
|
916
|
+
<span className="min-w-0 truncate font-mono">drafts/{shortenRunId(documentRootId)}.md</span>
|
|
917
|
+
</VTooltip>
|
|
918
|
+
<span aria-hidden className="text-mixer-muted/60">
|
|
919
|
+
·
|
|
920
|
+
</span>
|
|
921
|
+
<VTooltip
|
|
922
|
+
description={`${t('agent.originalDocument')}: ${originalDocumentRef.current.id}`}
|
|
923
|
+
asChild
|
|
924
|
+
>
|
|
925
|
+
<span className="shrink-0 font-mono">
|
|
926
|
+
{t('agent.originalDocument').toLowerCase()}{' '}
|
|
927
|
+
{shortenRunId(originalDocumentRef.current.id)}
|
|
928
|
+
</span>
|
|
929
|
+
</VTooltip>
|
|
930
|
+
</div>
|
|
931
|
+
</div>
|
|
932
|
+
<div className="flex shrink-0 items-center gap-1.5">
|
|
933
|
+
<div className="flex items-center rounded-md border border-mixer-muted/25 bg-muted/10 p-0.5">
|
|
934
|
+
<Button
|
|
935
|
+
variant={workspaceView === 'document' ? 'secondary' : 'ghost'}
|
|
936
|
+
size="sm"
|
|
937
|
+
className="h-7 gap-1.5"
|
|
938
|
+
onClick={() => void handleWorkspaceViewChange('document')}
|
|
939
|
+
>
|
|
940
|
+
<FileText className="size-3.5" />
|
|
941
|
+
{t('agent.document')}
|
|
942
|
+
</Button>
|
|
943
|
+
<Button
|
|
944
|
+
variant={workspaceView === 'editor' ? 'secondary' : 'ghost'}
|
|
945
|
+
size="sm"
|
|
946
|
+
className="h-7 gap-1.5"
|
|
947
|
+
onClick={() => void handleWorkspaceViewChange('editor')}
|
|
948
|
+
>
|
|
949
|
+
<FilePenLine className="size-3.5" />
|
|
950
|
+
{t('agent.fullEditor')}
|
|
951
|
+
</Button>
|
|
952
|
+
<Button
|
|
953
|
+
variant={workspaceView === 'diff' ? 'secondary' : 'ghost'}
|
|
954
|
+
size="sm"
|
|
955
|
+
className="h-7 gap-1.5"
|
|
956
|
+
onClick={() => void handleWorkspaceViewChange('diff')}
|
|
957
|
+
disabled={!artifactLoaded || artifactContent === originalContent}
|
|
958
|
+
>
|
|
959
|
+
<GitCompareArrows className="size-3.5" />
|
|
960
|
+
{t('agent.reviewChanges')}
|
|
961
|
+
</Button>
|
|
962
|
+
</div>
|
|
963
|
+
{workspaceView === 'diff' ? (
|
|
964
|
+
<Button
|
|
965
|
+
variant="ghost"
|
|
966
|
+
size="sm"
|
|
967
|
+
className="h-8 gap-1.5"
|
|
968
|
+
onClick={handleSummarizeChanges}
|
|
969
|
+
disabled={!artifactLoaded || artifactContent === originalContent}
|
|
970
|
+
>
|
|
971
|
+
<ListChecks className="size-3.5" />
|
|
972
|
+
{t('agent.summarizeChanges')}
|
|
973
|
+
</Button>
|
|
974
|
+
) : null}
|
|
975
|
+
<VTooltip description={t('agent.refresh')} asChild>
|
|
976
|
+
<Button
|
|
977
|
+
variant="ghost"
|
|
978
|
+
size="sm"
|
|
979
|
+
onClick={() => setArtifactRefresh((current) => ({ key: current.key + 1 }))}
|
|
980
|
+
disabled={!agentRunId}
|
|
981
|
+
aria-label={t('agent.refresh')}
|
|
982
|
+
>
|
|
983
|
+
<RefreshCw className="size-4" />
|
|
984
|
+
</Button>
|
|
985
|
+
</VTooltip>
|
|
986
|
+
<div aria-hidden className="mx-1 h-6 w-px bg-mixer-muted/25" />
|
|
987
|
+
<DocumentEditingConfigurationSelector
|
|
988
|
+
value={executionConfiguration}
|
|
989
|
+
onChange={handleConfigurationChange}
|
|
990
|
+
disabled={Boolean(agentRunId) || isStarting || isResolvingRun}
|
|
991
|
+
isLoading={isLoadingConfiguration}
|
|
992
|
+
/>
|
|
993
|
+
{!agentRunId ? (
|
|
994
|
+
<Button
|
|
995
|
+
variant="primary"
|
|
996
|
+
size="sm"
|
|
997
|
+
className="h-8 gap-1.5"
|
|
998
|
+
onClick={() => void startWorkflow(t('agent.documentEditingStartRequest'))}
|
|
999
|
+
disabled={
|
|
1000
|
+
isStarting ||
|
|
1001
|
+
isResolvingRun ||
|
|
1002
|
+
isResolvingTarget ||
|
|
1003
|
+
isLoadingConfiguration ||
|
|
1004
|
+
targetResolutionFailed ||
|
|
1005
|
+
!project ||
|
|
1006
|
+
!editingInteraction ||
|
|
1007
|
+
!executionConfiguration.environment ||
|
|
1008
|
+
!executionConfiguration.model
|
|
1009
|
+
}
|
|
1010
|
+
>
|
|
1011
|
+
{isStarting ? <Spinner size="sm" /> : <Sparkles className="size-4" />}
|
|
1012
|
+
{isStarting ? t('agent.startingAgent') : t('agent.documentEditingStart')}
|
|
1013
|
+
</Button>
|
|
1014
|
+
) : null}
|
|
1015
|
+
{agentRunId ? (
|
|
1016
|
+
<>
|
|
1017
|
+
<VTooltip description={agentRunId} asChild>
|
|
1018
|
+
<Button
|
|
1019
|
+
variant="ghost"
|
|
1020
|
+
size="sm"
|
|
1021
|
+
className="font-mono text-[11px] text-muted"
|
|
1022
|
+
onClick={handleCopyRunId}
|
|
1023
|
+
aria-label={t('agent.copyRunId')}
|
|
1024
|
+
>
|
|
1025
|
+
{shortenRunId(agentRunId)}
|
|
1026
|
+
</Button>
|
|
1027
|
+
</VTooltip>
|
|
1028
|
+
<VTooltip description={t('agent.startNewConversation')} asChild>
|
|
1029
|
+
<Button
|
|
1030
|
+
variant="ghost"
|
|
1031
|
+
size="sm"
|
|
1032
|
+
onClick={() => {
|
|
1033
|
+
if (isDirty) {
|
|
1034
|
+
setShowNewSessionConfirm(true);
|
|
1035
|
+
} else {
|
|
1036
|
+
void handleStartNewSession();
|
|
1037
|
+
}
|
|
1038
|
+
}}
|
|
1039
|
+
disabled={isTerminating}
|
|
1040
|
+
aria-label={t('agent.startNewConversation')}
|
|
1041
|
+
>
|
|
1042
|
+
<RotateCcw className="size-4" />
|
|
1043
|
+
</Button>
|
|
1044
|
+
</VTooltip>
|
|
1045
|
+
</>
|
|
1046
|
+
) : null}
|
|
1047
|
+
<div aria-hidden className="mx-1 h-6 w-px bg-mixer-muted/25" />
|
|
1048
|
+
<Button
|
|
1049
|
+
variant="primary"
|
|
1050
|
+
className="min-w-36 gap-2"
|
|
1051
|
+
onClick={() => setShowSaveConfirmation(true)}
|
|
1052
|
+
disabled={
|
|
1053
|
+
!isDirty ||
|
|
1054
|
+
!targetEtag ||
|
|
1055
|
+
isEditingLocked ||
|
|
1056
|
+
isSaving ||
|
|
1057
|
+
isResolvingTarget ||
|
|
1058
|
+
targetResolutionFailed
|
|
1059
|
+
}
|
|
1060
|
+
>
|
|
1061
|
+
{isSaving ? <Spinner size="sm" /> : <Save className="size-4" />}
|
|
1062
|
+
{t('agent.saveToDocument')}
|
|
1063
|
+
</Button>
|
|
1064
|
+
{onClose ? (
|
|
1065
|
+
<Button
|
|
1066
|
+
variant="ghost"
|
|
1067
|
+
size="sm"
|
|
1068
|
+
onClick={() => void handleCloseWorkspace()}
|
|
1069
|
+
aria-label={t('agent.close')}
|
|
1070
|
+
>
|
|
1071
|
+
<X className="size-4" />
|
|
1072
|
+
</Button>
|
|
1073
|
+
) : null}
|
|
1074
|
+
</div>
|
|
1075
|
+
</div>
|
|
1076
|
+
{saveConflict ? (
|
|
1077
|
+
<div className="flex shrink-0 items-center justify-between gap-3 border-b border-mixer-attention/30 bg-mixer-attention/10 px-4 py-2 text-sm">
|
|
1078
|
+
<span className="min-w-0 truncate text-attention">{t('agent.saveConflictNotice')}</span>
|
|
1079
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
1080
|
+
<Button variant="outline" size="sm" onClick={handleReconcile}>
|
|
1081
|
+
{t('agent.askAgentToReconcile')}
|
|
1082
|
+
</Button>
|
|
1083
|
+
<Button
|
|
1084
|
+
variant="ghost"
|
|
1085
|
+
size="sm"
|
|
1086
|
+
onClick={() => setSaveConflict(undefined)}
|
|
1087
|
+
aria-label={t('agent.close')}
|
|
1088
|
+
>
|
|
1089
|
+
<X className="size-4" />
|
|
1090
|
+
</Button>
|
|
1091
|
+
</div>
|
|
1092
|
+
</div>
|
|
1093
|
+
) : null}
|
|
1094
|
+
<ResizablePanelGroup direction="horizontal" className="min-h-0 flex-1">
|
|
1095
|
+
<ResizablePanel defaultSize={65} minSize={35} className="min-w-0 bg-background">
|
|
1096
|
+
<div className="flex h-full min-h-0 flex-col">
|
|
1097
|
+
<div className="min-h-0 flex-1">
|
|
1098
|
+
{workspaceView === 'diff' ? (
|
|
1099
|
+
<DocumentWorkingCopyDiff original={originalContent} workingCopy={artifactContent} />
|
|
1100
|
+
) : (
|
|
1101
|
+
<ArtifactEditingSurface
|
|
1102
|
+
runId={agentRunId}
|
|
1103
|
+
path={draftPath}
|
|
1104
|
+
viewMode={workspaceView === 'editor' ? 'document' : 'components'}
|
|
1105
|
+
baselineContent={originalContent}
|
|
1106
|
+
initialContent={savedContent}
|
|
1107
|
+
refreshKey={artifactRefresh.key}
|
|
1108
|
+
refreshDetails={artifactRefresh.details}
|
|
1109
|
+
readOnly={isEditingLocked}
|
|
1110
|
+
allowComments={Boolean(agentRunId)}
|
|
1111
|
+
onContentChange={handleArtifactContentChange}
|
|
1112
|
+
onAction={handleArtifactAction}
|
|
1113
|
+
onSendMessage={sendEditingMessage}
|
|
1114
|
+
onSendChangesToAgent={handleSendChangesToAgent}
|
|
1115
|
+
hasUnsentChanges={isDirty && hasDirectEditorChanges}
|
|
1116
|
+
isSendingChanges={isSendingChanges}
|
|
1117
|
+
sendChangesDisabled={!agentRunId || isEditingLocked}
|
|
1118
|
+
toolbarStatus={
|
|
1119
|
+
isAgentWorking ? (
|
|
1120
|
+
<DocumentEditingLockStatus
|
|
1121
|
+
isLocked={isEditingLocked}
|
|
1122
|
+
onToggleLock={() =>
|
|
1123
|
+
setIsEditingManuallyUnlocked((isUnlocked) => !isUnlocked)
|
|
1124
|
+
}
|
|
1125
|
+
/>
|
|
1126
|
+
) : undefined
|
|
1127
|
+
}
|
|
1128
|
+
onDocumentEdit={() => setHasDirectEditorChanges(true)}
|
|
1129
|
+
flushChangesRef={flushArtifactChangesRef}
|
|
1130
|
+
/>
|
|
1131
|
+
)}
|
|
1132
|
+
</div>
|
|
1133
|
+
</div>
|
|
1134
|
+
</ResizablePanel>
|
|
1135
|
+
<ResizableHandle withHandle />
|
|
1136
|
+
<ResizablePanel defaultSize={35} minSize={25} className="min-w-[320px]">
|
|
1137
|
+
{isResolvingRun || isResolvingTarget ? (
|
|
1138
|
+
<Center className="h-full">
|
|
1139
|
+
<Spinner size="lg" />
|
|
1140
|
+
</Center>
|
|
1141
|
+
) : targetResolutionFailed ? (
|
|
1142
|
+
<Center className="h-full flex-col gap-3 px-6 text-center">
|
|
1143
|
+
<div className="text-sm text-muted">{t('agent.failedToLoadDocument')}</div>
|
|
1144
|
+
<Button
|
|
1145
|
+
variant="outline"
|
|
1146
|
+
size="sm"
|
|
1147
|
+
onClick={() => setTargetResolutionAttempt((attempt) => attempt + 1)}
|
|
1148
|
+
>
|
|
1149
|
+
{t('agent.retry')}
|
|
1150
|
+
</Button>
|
|
1151
|
+
</Center>
|
|
1152
|
+
) : (
|
|
1153
|
+
<ModernAgentConversation
|
|
1154
|
+
agentRunId={agentRunId}
|
|
1155
|
+
startWorkflow={startWorkflow}
|
|
1156
|
+
resetWorkflow={() => setAgentRunId(undefined)}
|
|
1157
|
+
onRestart={(run) => setAgentRunId(run.id)}
|
|
1158
|
+
sendMessageRef={messageRef}
|
|
1159
|
+
onMessage={(message) => {
|
|
1160
|
+
const details = message.details as Record<string, unknown> | undefined;
|
|
1161
|
+
if (!isArtifactRefreshEvent(details, draftPath)) return;
|
|
1162
|
+
const updateKey = `${message.timestamp}:${details?.path}:${details?.generation ?? ''}`;
|
|
1163
|
+
if (seenUpdatesRef.current.has(updateKey)) return;
|
|
1164
|
+
seenUpdatesRef.current.add(updateKey);
|
|
1165
|
+
setArtifactRefresh((current) => ({
|
|
1166
|
+
key: current.key + 1,
|
|
1167
|
+
details,
|
|
1168
|
+
}));
|
|
1169
|
+
}}
|
|
1170
|
+
onAgentWorkingChange={handleAgentWorkingChange}
|
|
1171
|
+
title={t('agent.documentEditing')}
|
|
1172
|
+
initialMessage={t('agent.documentEditingWelcome')}
|
|
1173
|
+
startButtonText={isStarting ? t('agent.startingAgent') : t('agent.startAgent')}
|
|
1174
|
+
placeholder={t('agent.documentEditingPlaceholder')}
|
|
1175
|
+
initialToolApprovalMode="full_control"
|
|
1176
|
+
hideObjectLinking
|
|
1177
|
+
hideHeader
|
|
1178
|
+
showRightPanel={false}
|
|
1179
|
+
fullWidth
|
|
1180
|
+
interactive
|
|
1181
|
+
/>
|
|
1182
|
+
)}
|
|
1183
|
+
</ResizablePanel>
|
|
1184
|
+
</ResizablePanelGroup>
|
|
1185
|
+
<ConfirmModal
|
|
1186
|
+
isOpen={showNewSessionConfirm}
|
|
1187
|
+
title={t('agent.newSessionDiscardTitle')}
|
|
1188
|
+
content={t('agent.newSessionDiscardDescription')}
|
|
1189
|
+
onConfirm={() => {
|
|
1190
|
+
setShowNewSessionConfirm(false);
|
|
1191
|
+
void handleStartNewSession();
|
|
1192
|
+
}}
|
|
1193
|
+
onCancel={() => setShowNewSessionConfirm(false)}
|
|
1194
|
+
/>
|
|
1195
|
+
<SaveVersionConfirmModal
|
|
1196
|
+
isOpen={showSaveConfirmation}
|
|
1197
|
+
onClose={() => setShowSaveConfirmation(false)}
|
|
1198
|
+
onConfirm={handleSave}
|
|
1199
|
+
isLoading={isSaving}
|
|
1200
|
+
/>
|
|
1201
|
+
</div>
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
export function DocumentEditingPanel({
|
|
1206
|
+
object,
|
|
1207
|
+
initialContent,
|
|
1208
|
+
onClose,
|
|
1209
|
+
onDocumentUpdated,
|
|
1210
|
+
sendMessageRef,
|
|
1211
|
+
model,
|
|
1212
|
+
startImmediately,
|
|
1213
|
+
}: DocumentEditingPanelProps) {
|
|
1214
|
+
const { t } = useUITranslation();
|
|
1215
|
+
return (
|
|
1216
|
+
<Modal
|
|
1217
|
+
isOpen
|
|
1218
|
+
onClose={onClose}
|
|
1219
|
+
size="full"
|
|
1220
|
+
noCloseButton
|
|
1221
|
+
disableCloseOnClickOutside
|
|
1222
|
+
className="gap-0 overflow-hidden p-0"
|
|
1223
|
+
description={t('agent.documentEditingWelcome')}
|
|
1224
|
+
>
|
|
1225
|
+
<DocumentEditingWorkspace
|
|
1226
|
+
object={object}
|
|
1227
|
+
initialContent={initialContent}
|
|
1228
|
+
onClose={onClose}
|
|
1229
|
+
onDocumentUpdated={onDocumentUpdated}
|
|
1230
|
+
sendMessageRef={sendMessageRef}
|
|
1231
|
+
model={model}
|
|
1232
|
+
startImmediately={startImmediately}
|
|
1233
|
+
/>
|
|
1234
|
+
</Modal>
|
|
1235
|
+
);
|
|
1236
|
+
}
|