@vertesia/ui 0.80.0-dev-20251118 → 0.80.0
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 +105 -0
- package/lib/esm/core/components/MenuList.js +2 -5
- package/lib/esm/core/components/MenuList.js.map +1 -1
- package/lib/esm/core/components/MessageBox.js +1 -1
- package/lib/esm/core/components/MessageBox.js.map +1 -1
- package/lib/esm/core/components/TagsInput.js +194 -0
- package/lib/esm/core/components/TagsInput.js.map +1 -0
- package/lib/esm/core/components/index.js +2 -1
- package/lib/esm/core/components/index.js.map +1 -1
- package/lib/esm/core/components/shadcn/dialog.js +16 -2
- package/lib/esm/core/components/shadcn/dialog.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filter/SelectFilter.js +6 -9
- package/lib/esm/core/components/shadcn/filters/filter/SelectFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/popover.js +1 -1
- package/lib/esm/core/components/shadcn/popover.js.map +1 -1
- package/lib/esm/core/components/shadcn/selectBox.js +23 -5
- package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/esm/core/components/shadcn/tabs.js +3 -3
- package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
- package/lib/esm/env/index.js +4 -1
- package/lib/esm/env/index.js.map +1 -1
- package/lib/esm/features/agent/chat/AgentChart.js +184 -0
- package/lib/esm/features/agent/chat/AgentChart.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +87 -10
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +6 -2
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +4 -4
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +4 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js +12 -4
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +60 -56
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/esm/features/agent/chat/index.js +1 -0
- package/lib/esm/features/agent/chat/index.js.map +1 -1
- package/lib/esm/features/agent/createChartTool.js +354 -0
- package/lib/esm/features/agent/createChartTool.js.map +1 -0
- package/lib/esm/features/agent/examples.js +295 -0
- package/lib/esm/features/agent/examples.js.map +1 -0
- package/lib/esm/features/agent/index.js +2 -0
- package/lib/esm/features/agent/index.js.map +1 -1
- package/lib/esm/features/agent/visualization.js +165 -0
- package/lib/esm/features/agent/visualization.js.map +1 -0
- package/lib/esm/features/facets/CollectionsFacetsNav.js +5 -1
- package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/esm/features/index.js +1 -0
- package/lib/esm/features/index.js.map +1 -1
- package/lib/esm/features/layout/GenericPageNavHeader.js +14 -4
- package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
- package/lib/esm/features/magic-pdf/AnnotatedImageSlider.js +268 -0
- package/lib/esm/features/magic-pdf/AnnotatedImageSlider.js.map +1 -0
- package/lib/esm/features/magic-pdf/DownloadPopover.js +11 -11
- package/lib/esm/features/magic-pdf/DownloadPopover.js.map +1 -1
- package/lib/esm/features/magic-pdf/ExtractedContentView.js +77 -0
- package/lib/esm/features/magic-pdf/ExtractedContentView.js.map +1 -0
- package/lib/esm/features/magic-pdf/MagicPdfProvider.js +242 -0
- package/lib/esm/features/magic-pdf/MagicPdfProvider.js.map +1 -0
- package/lib/esm/features/magic-pdf/MagicPdfView.js +41 -47
- package/lib/esm/features/magic-pdf/MagicPdfView.js.map +1 -1
- package/lib/esm/features/pdf-viewer/PdfPageRenderer.js +261 -0
- package/lib/esm/features/pdf-viewer/PdfPageRenderer.js.map +1 -0
- package/lib/esm/features/pdf-viewer/PdfPageSlider.js +276 -0
- package/lib/esm/features/pdf-viewer/PdfPageSlider.js.map +1 -0
- package/lib/esm/features/pdf-viewer/SimplePdfViewer.js +71 -0
- package/lib/esm/features/pdf-viewer/SimplePdfViewer.js.map +1 -0
- package/lib/esm/features/pdf-viewer/index.js +4 -0
- package/lib/esm/features/pdf-viewer/index.js.map +1 -0
- package/lib/esm/features/store/collections/EditCollectionView.js +19 -10
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/SelectCollection.js +104 -39
- package/lib/esm/features/store/collections/SelectCollection.js.map +1 -1
- package/lib/esm/features/store/collections/SharedPropsEditor.js +39 -0
- package/lib/esm/features/store/collections/SharedPropsEditor.js.map +1 -0
- package/lib/esm/features/store/collections/SyncMemberHeadsToggle.js +35 -0
- package/lib/esm/features/store/collections/SyncMemberHeadsToggle.js.map +1 -0
- package/lib/esm/features/store/collections/index.js +2 -0
- package/lib/esm/features/store/collections/index.js.map +1 -1
- package/lib/esm/features/store/objects/DocumentSearchResults.js +0 -7
- package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/esm/features/store/objects/components/ContentOverview.js +273 -83
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js +153 -0
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js.map +1 -0
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +3 -3
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
- package/lib/esm/features/store/objects/layout/renderers.js +13 -0
- package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js +10 -9
- package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
- package/lib/esm/features/utils/index.js +2 -0
- package/lib/esm/features/utils/index.js.map +1 -1
- package/lib/esm/features/utils/mimeType.js +8 -0
- package/lib/esm/features/utils/mimeType.js.map +1 -1
- package/lib/esm/features/utils/print.js +181 -0
- package/lib/esm/features/utils/print.js.map +1 -0
- package/lib/esm/features/utils/workflowStatus.js +43 -0
- package/lib/esm/features/utils/workflowStatus.js.map +1 -0
- package/lib/esm/router/HistoryNavigator.js +22 -2
- package/lib/esm/router/HistoryNavigator.js.map +1 -1
- package/lib/esm/session/UserSessionProvider.js +2 -2
- package/lib/esm/session/UserSessionProvider.js.map +1 -1
- package/lib/esm/shell/apps/AppProjectSelector.js +2 -2
- package/lib/esm/shell/apps/AppProjectSelector.js.map +1 -1
- package/lib/esm/shell/login/UserInfo.js +2 -1
- package/lib/esm/shell/login/UserInfo.js.map +1 -1
- package/lib/esm/shell/login/UserSessionMenu.js +7 -1
- package/lib/esm/shell/login/UserSessionMenu.js.map +1 -1
- package/lib/esm/widgets/form/Form.js +6 -2
- package/lib/esm/widgets/form/Form.js.map +1 -1
- package/lib/esm/widgets/markdown/MarkdownRenderer.js +226 -4
- package/lib/esm/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/esm/widgets/schema-editor/ManagedSchema.js +0 -3
- package/lib/esm/widgets/schema-editor/ManagedSchema.js.map +1 -1
- package/lib/esm/widgets/schema-editor/json-schema4-utils.js +1 -1
- package/lib/esm/widgets/schema-editor/json-schema4-utils.js.map +1 -1
- package/lib/esm/widgets/xml-viewer/components/XMLViewer.js +18 -9
- package/lib/esm/widgets/xml-viewer/components/XMLViewer.js.map +1 -1
- package/lib/esm/widgets/xml-viewer/constants/index.js +10 -0
- package/lib/esm/widgets/xml-viewer/constants/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/MessageBox.d.ts.map +1 -1
- package/lib/types/core/components/TagsInput.d.ts +16 -0
- package/lib/types/core/components/TagsInput.d.ts.map +1 -0
- package/lib/types/core/components/index.d.ts +2 -1
- package/lib/types/core/components/index.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/dialog.d.ts +2 -1
- package/lib/types/core/components/shadcn/dialog.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/popover.d.ts +7 -0
- package/lib/types/core/components/shadcn/popover.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/selectBox.d.ts +5 -1
- package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/tabs.d.ts +3 -1
- package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/types/env/index.d.ts +2 -0
- package/lib/types/env/index.d.ts.map +1 -1
- package/lib/types/features/agent/chat/AgentChart.d.ts +48 -0
- package/lib/types/features/agent/chat/AgentChart.d.ts.map +1 -0
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +3 -2
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts +2 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts +4 -2
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +2 -4
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/types/features/agent/chat/index.d.ts +1 -0
- package/lib/types/features/agent/chat/index.d.ts.map +1 -1
- package/lib/types/features/agent/createChartTool.d.ts +178 -0
- package/lib/types/features/agent/createChartTool.d.ts.map +1 -0
- package/lib/types/features/agent/examples.d.ts +59 -0
- package/lib/types/features/agent/examples.d.ts.map +1 -0
- package/lib/types/features/agent/index.d.ts +2 -0
- package/lib/types/features/agent/index.d.ts.map +1 -1
- package/lib/types/features/agent/visualization.d.ts +95 -0
- package/lib/types/features/agent/visualization.d.ts.map +1 -0
- package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/index.d.ts +1 -0
- package/lib/types/features/index.d.ts.map +1 -1
- package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
- package/lib/types/features/magic-pdf/AnnotatedImageSlider.d.ts +13 -0
- package/lib/types/features/magic-pdf/AnnotatedImageSlider.d.ts.map +1 -0
- package/lib/types/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
- package/lib/types/features/magic-pdf/ExtractedContentView.d.ts +8 -0
- package/lib/types/features/magic-pdf/ExtractedContentView.d.ts.map +1 -0
- package/lib/types/features/magic-pdf/MagicPdfProvider.d.ts +58 -0
- package/lib/types/features/magic-pdf/MagicPdfProvider.d.ts.map +1 -0
- package/lib/types/features/magic-pdf/MagicPdfView.d.ts +1 -1
- package/lib/types/features/magic-pdf/MagicPdfView.d.ts.map +1 -1
- package/lib/types/features/pdf-viewer/PdfPageRenderer.d.ts +83 -0
- package/lib/types/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -0
- package/lib/types/features/pdf-viewer/PdfPageSlider.d.ts +29 -0
- package/lib/types/features/pdf-viewer/PdfPageSlider.d.ts.map +1 -0
- package/lib/types/features/pdf-viewer/SimplePdfViewer.d.ts +19 -0
- package/lib/types/features/pdf-viewer/SimplePdfViewer.d.ts.map +1 -0
- package/lib/types/features/pdf-viewer/index.d.ts +4 -0
- package/lib/types/features/pdf-viewer/index.d.ts.map +1 -0
- package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/collections/SelectCollection.d.ts +2 -1
- package/lib/types/features/store/collections/SelectCollection.d.ts.map +1 -1
- package/lib/types/features/store/collections/SharedPropsEditor.d.ts +7 -0
- package/lib/types/features/store/collections/SharedPropsEditor.d.ts.map +1 -0
- package/lib/types/features/store/collections/SyncMemberHeadsToggle.d.ts +7 -0
- package/lib/types/features/store/collections/SyncMemberHeadsToggle.d.ts.map +1 -0
- package/lib/types/features/store/collections/index.d.ts +2 -0
- package/lib/types/features/store/collections/index.d.ts.map +1 -1
- package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts +30 -0
- package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -0
- package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/types/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
- package/lib/types/features/utils/index.d.ts +2 -0
- package/lib/types/features/utils/index.d.ts.map +1 -1
- package/lib/types/features/utils/mimeType.d.ts +1 -0
- package/lib/types/features/utils/mimeType.d.ts.map +1 -1
- package/lib/types/features/utils/print.d.ts +10 -0
- package/lib/types/features/utils/print.d.ts.map +1 -0
- package/lib/types/features/utils/workflowStatus.d.ts +10 -0
- package/lib/types/features/utils/workflowStatus.d.ts.map +1 -0
- package/lib/types/router/HistoryNavigator.d.ts +3 -0
- package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
- package/lib/types/shell/login/UserInfo.d.ts.map +1 -1
- package/lib/types/shell/login/UserSessionMenu.d.ts.map +1 -1
- package/lib/types/widgets/form/Form.d.ts.map +1 -1
- package/lib/types/widgets/markdown/MarkdownRenderer.d.ts +5 -1
- package/lib/types/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/types/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
- package/lib/types/widgets/xml-viewer/components/XMLViewer.d.ts.map +1 -1
- package/lib/types/widgets/xml-viewer/constants/index.d.ts +10 -0
- package/lib/types/widgets/xml-viewer/constants/index.d.ts.map +1 -1
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-layout.js +1 -1
- package/lib/vertesia-ui-layout.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 +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +173 -170
- package/src/core/components/MenuList.tsx +3 -6
- package/src/core/components/MessageBox.tsx +7 -2
- package/src/core/components/SelectBox.tsx +1 -1
- package/src/core/components/shadcn/dialog.tsx +19 -1
- package/src/core/components/shadcn/filters/filter/SelectFilter.tsx +31 -31
- package/src/core/components/shadcn/filters/filterBar.tsx +1 -0
- package/src/core/components/shadcn/selectBox.tsx +32 -6
- package/src/core/components/shadcn/tabs.tsx +3 -2
- package/src/env/index.ts +6 -1
- package/src/features/agent/CHART_INSTRUCTIONS.md +228 -0
- package/src/features/agent/chat/AgentChart.tsx +601 -0
- package/src/features/agent/chat/ModernAgentConversation.tsx +123 -11
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +8 -2
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +12 -2
- package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +6 -1
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +15 -10
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +122 -87
- package/src/features/agent/chat/index.ts +1 -0
- package/src/features/agent/createChartTool.ts +364 -0
- package/src/features/agent/examples.ts +321 -0
- package/src/features/agent/index.ts +2 -0
- package/src/features/agent/visualization.ts +227 -0
- package/src/features/facets/CollectionsFacetsNav.tsx +5 -1
- package/src/features/index.ts +1 -0
- package/src/features/layout/GenericPageNavHeader.tsx +15 -4
- package/src/features/magic-pdf/AnnotatedImageSlider.tsx +482 -0
- package/src/features/magic-pdf/DownloadPopover.tsx +45 -40
- package/src/features/magic-pdf/ExtractedContentView.tsx +132 -0
- package/src/features/magic-pdf/MagicPdfProvider.tsx +297 -0
- package/src/features/magic-pdf/MagicPdfView.tsx +184 -91
- package/src/features/pdf-viewer/PdfPageRenderer.tsx +612 -0
- package/src/features/pdf-viewer/PdfPageSlider.tsx +473 -0
- package/src/features/pdf-viewer/SimplePdfViewer.tsx +142 -0
- package/src/features/pdf-viewer/index.ts +3 -0
- package/src/features/store/collections/EditCollectionView.tsx +3 -5
- package/src/features/store/collections/SharedPropsEditor.tsx +1 -2
- package/src/features/store/objects/DocumentSearchResults.tsx +0 -7
- package/src/features/store/objects/components/ContentOverview.tsx +677 -210
- package/src/features/store/objects/components/useContentPanelHooks.ts +169 -0
- package/src/features/store/objects/layout/DocumentTableColumn.tsx +3 -3
- package/src/features/store/objects/layout/knowledge.md +1 -0
- package/src/features/store/objects/layout/renderers.tsx +25 -0
- package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +1 -3
- package/src/features/utils/index.ts +3 -1
- package/src/features/utils/mimeType.ts +10 -1
- package/src/features/utils/print.ts +189 -0
- package/src/features/utils/workflowStatus.ts +44 -0
- package/src/router/HistoryNavigator.ts +30 -2
- package/src/session/UserSessionProvider.tsx +2 -2
- package/src/shell/login/UserInfo.tsx +2 -0
- package/src/shell/login/UserSessionMenu.tsx +12 -1
- package/src/widgets/form/Form.tsx +8 -3
- package/src/widgets/markdown/MarkdownRenderer.tsx +350 -6
- package/src/widgets/schema-editor/ManagedSchema.ts +0 -3
- package/src/widgets/schema-editor/json-schema4-utils.ts +1 -1
- package/src/widgets/xml-viewer/components/XMLViewer.tsx +22 -10
- package/src/widgets/xml-viewer/constants/index.ts +11 -0
- package/lib/esm/features/magic-pdf/PageSlider.js +0 -70
- package/lib/esm/features/magic-pdf/PageSlider.js.map +0 -1
- package/lib/esm/features/magic-pdf/PdfPageProvider.js +0 -188
- package/lib/esm/features/magic-pdf/PdfPageProvider.js.map +0 -1
- package/lib/esm/features/magic-pdf/TextPageView.js +0 -62
- package/lib/esm/features/magic-pdf/TextPageView.js.map +0 -1
- package/lib/esm/features/magic-pdf/useResizeOnDrag.js +0 -34
- package/lib/esm/features/magic-pdf/useResizeOnDrag.js.map +0 -1
- package/lib/types/features/magic-pdf/PageSlider.d.ts +0 -9
- package/lib/types/features/magic-pdf/PageSlider.d.ts.map +0 -1
- package/lib/types/features/magic-pdf/PdfPageProvider.d.ts +0 -39
- package/lib/types/features/magic-pdf/PdfPageProvider.d.ts.map +0 -1
- package/lib/types/features/magic-pdf/TextPageView.d.ts +0 -8
- package/lib/types/features/magic-pdf/TextPageView.d.ts.map +0 -1
- package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts +0 -9
- package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts.map +0 -1
- package/src/features/magic-pdf/PageSlider.tsx +0 -142
- package/src/features/magic-pdf/PdfPageProvider.tsx +0 -310
- package/src/features/magic-pdf/TextPageView.tsx +0 -91
- package/src/features/magic-pdf/useResizeOnDrag.ts +0 -42
|
@@ -3,7 +3,7 @@ import { Bot, Cpu, SendIcon, XIcon } from "lucide-react";
|
|
|
3
3
|
import { useUserSession } from "@vertesia/ui/session";
|
|
4
4
|
import { AsyncExecutionResult, VertesiaClient } from "@vertesia/client";
|
|
5
5
|
import { AgentMessage, AgentMessageType, Plan, UserInputSignal } from "@vertesia/common";
|
|
6
|
-
import { Button, MessageBox, Spinner, useToast } from "@vertesia/ui/core";
|
|
6
|
+
import { Button, MessageBox, Spinner, useToast, VModal, VModalBody, VModalFooter, VModalTitle } from "@vertesia/ui/core";
|
|
7
7
|
|
|
8
8
|
import { AnimatedThinkingDots, PulsatingCircle } from "./AnimatedThinkingDots";
|
|
9
9
|
import AllMessagesMixed from "./ModernAgentOutput/AllMessagesMixed";
|
|
@@ -17,6 +17,50 @@ type StartWorkflowFn = (
|
|
|
17
17
|
initialMessage?: string,
|
|
18
18
|
) => Promise<{ run_id: string; workflow_id: string } | undefined>;
|
|
19
19
|
|
|
20
|
+
function printElementToPdf(sourceElement: HTMLElement, title: string): boolean {
|
|
21
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Use a hidden iframe to avoid opening a new window
|
|
26
|
+
const iframe = document.createElement("iframe");
|
|
27
|
+
iframe.style.position = "fixed";
|
|
28
|
+
iframe.style.right = "0";
|
|
29
|
+
iframe.style.bottom = "0";
|
|
30
|
+
iframe.style.width = "0";
|
|
31
|
+
iframe.style.height = "0";
|
|
32
|
+
iframe.style.border = "0";
|
|
33
|
+
iframe.style.visibility = "hidden";
|
|
34
|
+
document.body.appendChild(iframe);
|
|
35
|
+
|
|
36
|
+
const iframeWindow = iframe.contentWindow;
|
|
37
|
+
if (!iframeWindow) {
|
|
38
|
+
iframe.parentNode?.removeChild(iframe);
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const doc = iframeWindow.document;
|
|
43
|
+
doc.open();
|
|
44
|
+
doc.write(`<!doctype html><html><head><title>${title}</title></head><body></body></html>`);
|
|
45
|
+
doc.close();
|
|
46
|
+
doc.title = title;
|
|
47
|
+
|
|
48
|
+
const styles = document.querySelectorAll<HTMLLinkElement | HTMLStyleElement>("link[rel=\"stylesheet\"], style");
|
|
49
|
+
styles.forEach((node) => {
|
|
50
|
+
doc.head.appendChild(node.cloneNode(true));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
doc.body.innerHTML = sourceElement.innerHTML;
|
|
54
|
+
iframeWindow.focus();
|
|
55
|
+
iframeWindow.print();
|
|
56
|
+
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
iframe.parentNode?.removeChild(iframe);
|
|
59
|
+
}, 1000);
|
|
60
|
+
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
20
64
|
interface ModernAgentConversationProps {
|
|
21
65
|
run?: AsyncExecutionResult | { workflow_id: string; run_id: string };
|
|
22
66
|
title?: string;
|
|
@@ -248,9 +292,9 @@ function ModernAgentConversationInner({
|
|
|
248
292
|
}: ModernAgentConversationProps & { run: AsyncExecutionResult }) {
|
|
249
293
|
const { client } = useUserSession();
|
|
250
294
|
const bottomRef = useRef<HTMLDivElement | null>(null);
|
|
295
|
+
const conversationRef = useRef<HTMLDivElement | null>(null);
|
|
251
296
|
const [messages, setMessages] = useState<AgentMessage[]>([]);
|
|
252
297
|
const [isCompleted, setIsCompleted] = useState(false);
|
|
253
|
-
const [inputValue, setInputValue] = useState<string>("");
|
|
254
298
|
const [isSending, setIsSending] = useState(false);
|
|
255
299
|
const [viewMode, setViewMode] = useState<"stacked" | "sliding">("sliding");
|
|
256
300
|
const [showSlidingPanel, setShowSlidingPanel] = useState<boolean>(!isModal);
|
|
@@ -486,16 +530,15 @@ function ModernAgentConversationInner({
|
|
|
486
530
|
}, [messages, plans, activePlanIndex]);
|
|
487
531
|
|
|
488
532
|
// Send a message to the agent
|
|
489
|
-
const handleSendMessage = () => {
|
|
490
|
-
const
|
|
491
|
-
if (!
|
|
533
|
+
const handleSendMessage = (message: string) => {
|
|
534
|
+
const trimmed = message.trim();
|
|
535
|
+
if (!trimmed || isSending) return;
|
|
492
536
|
|
|
493
537
|
setIsSending(true);
|
|
494
|
-
setInputValue("");
|
|
495
538
|
|
|
496
539
|
client.store.workflows
|
|
497
540
|
.sendSignal(run.workflowId, run.runId, "UserInput", {
|
|
498
|
-
message,
|
|
541
|
+
message: trimmed,
|
|
499
542
|
} as UserInputSignal)
|
|
500
543
|
.then(() => {
|
|
501
544
|
setIsCompleted(false);
|
|
@@ -583,12 +626,63 @@ function ModernAgentConversationInner({
|
|
|
583
626
|
});
|
|
584
627
|
};
|
|
585
628
|
|
|
629
|
+
const [isPdfModalOpen, setIsPdfModalOpen] = useState(false);
|
|
630
|
+
|
|
631
|
+
const exportConversationPdf = () => {
|
|
632
|
+
if (!conversationRef.current) {
|
|
633
|
+
toast({
|
|
634
|
+
status: "error",
|
|
635
|
+
title: "PDF export failed",
|
|
636
|
+
description: "No conversation content available to export",
|
|
637
|
+
duration: 3000,
|
|
638
|
+
});
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
setIsPdfModalOpen(true);
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
const handleConfirmExportPdf = () => {
|
|
645
|
+
if (!conversationRef.current) {
|
|
646
|
+
toast({
|
|
647
|
+
status: "error",
|
|
648
|
+
title: "PDF export failed",
|
|
649
|
+
description: "No conversation content available to export",
|
|
650
|
+
duration: 3000,
|
|
651
|
+
});
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const pdfTitle = `${actualTitle} - ${run.runId}`;
|
|
656
|
+
const success = printElementToPdf(conversationRef.current, pdfTitle);
|
|
657
|
+
|
|
658
|
+
if (!success) {
|
|
659
|
+
toast({
|
|
660
|
+
status: "error",
|
|
661
|
+
title: "PDF export failed",
|
|
662
|
+
description: "Unable to open print preview",
|
|
663
|
+
duration: 4000,
|
|
664
|
+
});
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
toast({
|
|
669
|
+
status: "success",
|
|
670
|
+
title: "PDF export ready",
|
|
671
|
+
description: "Use your browser's Print dialog to save as PDF",
|
|
672
|
+
duration: 4000,
|
|
673
|
+
});
|
|
674
|
+
setIsPdfModalOpen(false);
|
|
675
|
+
};
|
|
676
|
+
|
|
586
677
|
return (
|
|
587
678
|
<div className="flex gap-2 h-full">
|
|
588
679
|
{/* Conversation Area - responsive width based on panel visibility */}
|
|
589
|
-
<div
|
|
680
|
+
<div
|
|
681
|
+
ref={conversationRef}
|
|
682
|
+
className={`flex flex-col h-full min-h-0 border-0 ${
|
|
590
683
|
showSlidingPanel ? 'lg:w-2/3 flex-1' : `flex-1 mx-auto ${!isModal ? 'max-w-4xl' : ''}`
|
|
591
|
-
}`}
|
|
684
|
+
}`}
|
|
685
|
+
>
|
|
592
686
|
<Header
|
|
593
687
|
title={actualTitle}
|
|
594
688
|
isCompleted={isCompleted}
|
|
@@ -609,6 +703,7 @@ function ModernAgentConversationInner({
|
|
|
609
703
|
onDownload={downloadConversation}
|
|
610
704
|
onCopyRunId={copyRunId}
|
|
611
705
|
resetWorkflow={resetWorkflow}
|
|
706
|
+
onExportPdf={exportConversationPdf}
|
|
612
707
|
/>
|
|
613
708
|
|
|
614
709
|
{messages.length === 0 && !isCompleted ? (
|
|
@@ -664,8 +759,6 @@ function ModernAgentConversationInner({
|
|
|
664
759
|
</MessageBox>
|
|
665
760
|
) : showInput && (
|
|
666
761
|
<MessageInput
|
|
667
|
-
value={inputValue}
|
|
668
|
-
onChange={setInputValue}
|
|
669
762
|
onSend={handleSendMessage}
|
|
670
763
|
disabled={false}
|
|
671
764
|
isSending={isSending}
|
|
@@ -690,6 +783,25 @@ function ModernAgentConversationInner({
|
|
|
690
783
|
/>
|
|
691
784
|
</div>
|
|
692
785
|
)}
|
|
786
|
+
<VModal isOpen={isPdfModalOpen} onClose={() => setIsPdfModalOpen(false)}>
|
|
787
|
+
<VModalTitle>Export conversation as PDF</VModalTitle>
|
|
788
|
+
<VModalBody>
|
|
789
|
+
<p className="mb-2">
|
|
790
|
+
This will open your browser's print dialog with the current conversation.
|
|
791
|
+
</p>
|
|
792
|
+
<p className="text-sm text-muted">
|
|
793
|
+
To save a PDF, choose "Save as PDF" or a similar option in the print dialog.
|
|
794
|
+
</p>
|
|
795
|
+
</VModalBody>
|
|
796
|
+
<VModalFooter align="right">
|
|
797
|
+
<Button variant="ghost" size="sm" onClick={() => setIsPdfModalOpen(false)}>
|
|
798
|
+
Cancel
|
|
799
|
+
</Button>
|
|
800
|
+
<Button size="sm" onClick={handleConfirmExportPdf}>
|
|
801
|
+
Open print dialog
|
|
802
|
+
</Button>
|
|
803
|
+
</VModalFooter>
|
|
804
|
+
</VModal>
|
|
693
805
|
</div>
|
|
694
806
|
);
|
|
695
807
|
}
|
|
@@ -19,7 +19,7 @@ interface AllMessagesMixedProps {
|
|
|
19
19
|
taskLabels?: Map<string, string>; // Maps task IDs to more descriptive labels
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
function AllMessagesMixedComponent({
|
|
23
23
|
messages,
|
|
24
24
|
bottomRef,
|
|
25
25
|
viewMode = 'stacked',
|
|
@@ -167,11 +167,13 @@ export default function AllMessagesMixed({
|
|
|
167
167
|
<>
|
|
168
168
|
{/* Get all messages to display in sliding view */}
|
|
169
169
|
{(() => {
|
|
170
|
-
// First get all permanent messages (ANSWER, QUESTION, COMPLETE, REQUEST_INPUT, TERMINATED)
|
|
170
|
+
// First get all permanent messages (ANSWER, QUESTION, COMPLETE, REQUEST_INPUT, IDLE, TERMINATED)
|
|
171
171
|
const permanentMessages = displayMessages.filter(msg =>
|
|
172
172
|
msg.type === AgentMessageType.ANSWER ||
|
|
173
173
|
msg.type === AgentMessageType.QUESTION ||
|
|
174
174
|
msg.type === AgentMessageType.COMPLETE ||
|
|
175
|
+
msg.type === AgentMessageType.IDLE ||
|
|
176
|
+
msg.type === AgentMessageType.REQUEST_INPUT ||
|
|
175
177
|
msg.type === AgentMessageType.TERMINATED
|
|
176
178
|
);
|
|
177
179
|
|
|
@@ -225,3 +227,7 @@ export default function AllMessagesMixed({
|
|
|
225
227
|
</div>
|
|
226
228
|
);
|
|
227
229
|
}
|
|
230
|
+
|
|
231
|
+
const AllMessagesMixed = React.memo(AllMessagesMixedComponent);
|
|
232
|
+
|
|
233
|
+
export default AllMessagesMixed;
|
|
@@ -19,6 +19,7 @@ interface HeaderProps {
|
|
|
19
19
|
onDownload?: () => void;
|
|
20
20
|
onCopyRunId?: () => void;
|
|
21
21
|
resetWorkflow?: () => void;
|
|
22
|
+
onExportPdf?: () => void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export default function Header({
|
|
@@ -33,7 +34,8 @@ export default function Header({
|
|
|
33
34
|
onTogglePlanPanel,
|
|
34
35
|
onDownload,
|
|
35
36
|
onCopyRunId,
|
|
36
|
-
resetWorkflow
|
|
37
|
+
resetWorkflow,
|
|
38
|
+
onExportPdf,
|
|
37
39
|
}: HeaderProps) {
|
|
38
40
|
return (
|
|
39
41
|
<PayloadBuilderProvider>
|
|
@@ -84,6 +86,7 @@ export default function Header({
|
|
|
84
86
|
onDownload={onDownload}
|
|
85
87
|
onCopyRunId={onCopyRunId}
|
|
86
88
|
resetWorkflow={resetWorkflow}
|
|
89
|
+
onExportPdf={onExportPdf}
|
|
87
90
|
/>
|
|
88
91
|
{onClose && !isModal && (
|
|
89
92
|
<Button size="xs" variant="ghost" onClick={onClose}>
|
|
@@ -102,7 +105,8 @@ function MoreDropdown({
|
|
|
102
105
|
onClose,
|
|
103
106
|
onDownload,
|
|
104
107
|
onCopyRunId,
|
|
105
|
-
resetWorkflow
|
|
108
|
+
resetWorkflow,
|
|
109
|
+
onExportPdf,
|
|
106
110
|
}: {
|
|
107
111
|
run: AsyncExecutionResult;
|
|
108
112
|
isModal: boolean;
|
|
@@ -110,6 +114,7 @@ function MoreDropdown({
|
|
|
110
114
|
onDownload?: () => void;
|
|
111
115
|
onCopyRunId?: () => void;
|
|
112
116
|
resetWorkflow?: () => void;
|
|
117
|
+
onExportPdf?: () => void;
|
|
113
118
|
}) {
|
|
114
119
|
const toast = useToast();
|
|
115
120
|
const { client } = useUserSession();
|
|
@@ -191,6 +196,11 @@ function MoreDropdown({
|
|
|
191
196
|
<DownloadCloudIcon className="size-3.5 mr-2 text-muted" /> Download
|
|
192
197
|
Conversation
|
|
193
198
|
</CommandItem>
|
|
199
|
+
{onExportPdf && (
|
|
200
|
+
<CommandItem className="text-xs" onSelect={onExportPdf}>
|
|
201
|
+
<DownloadCloudIcon className="size-3.5 mr-2 text-muted" /> Export as PDF
|
|
202
|
+
</CommandItem>
|
|
203
|
+
)}
|
|
194
204
|
{onClose && isModal && (
|
|
195
205
|
<CommandItem className="text-xs" onSelect={onClose}>
|
|
196
206
|
<XIcon className="size-3.5 mr-2 text-muted" /> Close
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Plan } from "@vertesia/common";
|
|
2
2
|
import { Badge, Button } from "@vertesia/ui/core";
|
|
3
3
|
import { AlertCircle, CheckCircle, Circle, Clock, X } from "lucide-react";
|
|
4
|
+
import React from "react";
|
|
4
5
|
|
|
5
6
|
interface InlinePlanPanelProps {
|
|
6
7
|
plan: Plan;
|
|
@@ -12,7 +13,7 @@ interface InlinePlanPanelProps {
|
|
|
12
13
|
onChangePlan?: (index: number) => void;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
function InlineSlidingPlanPanelComponent({
|
|
16
17
|
plan,
|
|
17
18
|
workstreamStatus,
|
|
18
19
|
isOpen,
|
|
@@ -264,3 +265,7 @@ export default function InlineSlidingPlanPanel({
|
|
|
264
265
|
</div>
|
|
265
266
|
);
|
|
266
267
|
}
|
|
268
|
+
|
|
269
|
+
const InlineSlidingPlanPanel = React.memo(InlineSlidingPlanPanelComponent);
|
|
270
|
+
|
|
271
|
+
export default InlineSlidingPlanPanel;
|
|
@@ -4,9 +4,7 @@ import React, { useEffect, useRef, useState } from "react";
|
|
|
4
4
|
import { SelectDocument } from "../../../store";
|
|
5
5
|
|
|
6
6
|
interface MessageInputProps {
|
|
7
|
-
|
|
8
|
-
onChange: (v: string) => void;
|
|
9
|
-
onSend: () => void;
|
|
7
|
+
onSend: (message: string) => void;
|
|
10
8
|
disabled?: boolean;
|
|
11
9
|
isSending?: boolean;
|
|
12
10
|
isCompleted?: boolean;
|
|
@@ -15,8 +13,6 @@ interface MessageInputProps {
|
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
export default function MessageInput({
|
|
18
|
-
value,
|
|
19
|
-
onChange,
|
|
20
16
|
onSend,
|
|
21
17
|
disabled = false,
|
|
22
18
|
isSending = false,
|
|
@@ -25,16 +21,25 @@ export default function MessageInput({
|
|
|
25
21
|
placeholder = "Type your message..."
|
|
26
22
|
}: MessageInputProps) {
|
|
27
23
|
const ref = useRef<HTMLInputElement | null>(null);
|
|
24
|
+
const [value, setValue] = useState("");
|
|
28
25
|
const [isObjectModalOpen, setIsObjectModalOpen] = useState(false);
|
|
29
26
|
|
|
30
27
|
useEffect(() => {
|
|
31
28
|
if (!disabled && isCompleted) ref.current?.focus();
|
|
32
29
|
}, [disabled, isCompleted]);
|
|
33
30
|
|
|
31
|
+
const handleSend = () => {
|
|
32
|
+
const message = value.trim();
|
|
33
|
+
if (!message || disabled || isSending) return;
|
|
34
|
+
|
|
35
|
+
onSend(message);
|
|
36
|
+
setValue("");
|
|
37
|
+
};
|
|
38
|
+
|
|
34
39
|
const keyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
35
40
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
36
41
|
e.preventDefault();
|
|
37
|
-
|
|
42
|
+
handleSend();
|
|
38
43
|
}
|
|
39
44
|
};
|
|
40
45
|
|
|
@@ -50,7 +55,7 @@ export default function MessageInput({
|
|
|
50
55
|
const newValue = currentValue.substring(0, cursorPos) + markdownLink + currentValue.substring(cursorPos);
|
|
51
56
|
|
|
52
57
|
// Update the input value
|
|
53
|
-
|
|
58
|
+
setValue(newValue);
|
|
54
59
|
|
|
55
60
|
// Close the modal
|
|
56
61
|
setIsObjectModalOpen(false);
|
|
@@ -74,7 +79,7 @@ export default function MessageInput({
|
|
|
74
79
|
ref={ref}
|
|
75
80
|
value={value}
|
|
76
81
|
onKeyDown={keyDown}
|
|
77
|
-
onChange={
|
|
82
|
+
onChange={setValue}
|
|
78
83
|
disabled={disabled || isSending}
|
|
79
84
|
placeholder={placeholder}
|
|
80
85
|
className="pr-12 py-2.5"
|
|
@@ -90,7 +95,7 @@ export default function MessageInput({
|
|
|
90
95
|
</Button>
|
|
91
96
|
</div>
|
|
92
97
|
<Button
|
|
93
|
-
onClick={
|
|
98
|
+
onClick={handleSend}
|
|
94
99
|
disabled={disabled || isSending || !value.trim()}
|
|
95
100
|
className="px-4 py-2.5"
|
|
96
101
|
>
|
|
@@ -122,4 +127,4 @@ export default function MessageInput({
|
|
|
122
127
|
</VModal>
|
|
123
128
|
</div>
|
|
124
129
|
);
|
|
125
|
-
}
|
|
130
|
+
}
|
|
@@ -2,11 +2,10 @@ import { AgentMessage, AgentMessageType } from "@vertesia/common";
|
|
|
2
2
|
import { Badge, Button, useToast } from "@vertesia/ui/core";
|
|
3
3
|
import { NavLink } from "@vertesia/ui/router";
|
|
4
4
|
import { useUserSession } from "@vertesia/ui/session";
|
|
5
|
+
import { MarkdownRenderer } from "@vertesia/ui/widgets";
|
|
5
6
|
import dayjs from "dayjs";
|
|
6
7
|
import { AlertCircle, Bot, CheckCircle, Clock, CopyIcon, Info, MessageSquare, User } from "lucide-react";
|
|
7
8
|
import React, { useEffect, useState } from "react";
|
|
8
|
-
import Markdown from "react-markdown";
|
|
9
|
-
import remarkGfm from "remark-gfm";
|
|
10
9
|
import { AnimatedThinkingDots, PulsatingCircle } from "../AnimatedThinkingDots";
|
|
11
10
|
import { ThinkingMessages } from "../WaitingMessages";
|
|
12
11
|
import { getWorkstreamId } from "./utils";
|
|
@@ -100,46 +99,17 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
|
|
|
100
99
|
|
|
101
100
|
const messageStyles = getMessageStyles();
|
|
102
101
|
|
|
103
|
-
// Convert links in the content
|
|
102
|
+
// Convert links in the content.
|
|
103
|
+
// Special schemes like store:, collection:, image:, and artifact:
|
|
104
|
+
// are now handled centrally in MarkdownRenderer, so this function
|
|
105
|
+
// only preserves the async shape for backwards compatibility.
|
|
104
106
|
const convertLinks = async (content: string | object): Promise<string | object> => {
|
|
105
107
|
// If content is not a string, return it as is
|
|
106
108
|
if (typeof content !== "string") {
|
|
107
109
|
return content;
|
|
108
110
|
}
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// First, handle store and collection links
|
|
113
|
-
processedContent = processedContent.replace(/\[([^\]]+)\]\((store|collection):([a-f\d]{24})\)/gi, (_, text, type, id) => {
|
|
114
|
-
const path = type === 'store' ? 'objects' : 'collections';
|
|
115
|
-
return `[${text}](/store/${path}/${id})`;
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Then, handle image links by finding all image:<gcspath> patterns
|
|
119
|
-
const imageRegex = /!\[([^\]]*)\]\(image:([^)]+)\)/g;
|
|
120
|
-
const imageMatches = Array.from(processedContent.matchAll(imageRegex));
|
|
121
|
-
|
|
122
|
-
// Process all image URLs in parallel
|
|
123
|
-
const imageReplacements = await Promise.all(
|
|
124
|
-
imageMatches.map(async (match) => {
|
|
125
|
-
const [fullMatch, altText, gcsPath] = match;
|
|
126
|
-
try {
|
|
127
|
-
const response = await client.files.getDownloadUrl(gcsPath);
|
|
128
|
-
return { fullMatch, replacement: `` };
|
|
129
|
-
} catch (error) {
|
|
130
|
-
console.error(`Failed to get download URL for image: ${gcsPath}`, error);
|
|
131
|
-
// Return original on error
|
|
132
|
-
return { fullMatch, replacement: fullMatch };
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
// Apply all replacements
|
|
138
|
-
for (const { fullMatch, replacement } of imageReplacements) {
|
|
139
|
-
processedContent = processedContent.replace(fullMatch, replacement);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return processedContent;
|
|
112
|
+
return content;
|
|
143
113
|
};
|
|
144
114
|
|
|
145
115
|
// Get the message content to display with thinking message replacement
|
|
@@ -254,10 +224,12 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
|
|
|
254
224
|
}
|
|
255
225
|
|
|
256
226
|
// Handle string content with markdown - content is already processed
|
|
227
|
+
const runId = (message as any).workflow_run_id as string | undefined;
|
|
228
|
+
|
|
257
229
|
return (
|
|
258
230
|
<div className="vprose prose-sm">
|
|
259
|
-
<
|
|
260
|
-
|
|
231
|
+
<MarkdownRenderer
|
|
232
|
+
artifactRunId={runId}
|
|
261
233
|
components={{
|
|
262
234
|
a: ({ node, ref, ...props }: { node?: any; ref?: any; href?: string; children?: React.ReactNode }) => {
|
|
263
235
|
const href = props.href || "";
|
|
@@ -289,62 +261,78 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
|
|
|
289
261
|
/>
|
|
290
262
|
);
|
|
291
263
|
},
|
|
292
|
-
code: ({
|
|
293
|
-
node,
|
|
294
|
-
ref,
|
|
295
|
-
className,
|
|
296
|
-
children,
|
|
297
|
-
...props
|
|
298
|
-
}: {
|
|
299
|
-
node?: any;
|
|
300
|
-
ref?: any;
|
|
301
|
-
className?: string;
|
|
302
|
-
children?: React.ReactNode;
|
|
303
|
-
}) => {
|
|
304
|
-
const match = /language-(\w+)/.exec(className || "");
|
|
305
|
-
const isInline = !match;
|
|
306
|
-
const language = match ? match[1] : "";
|
|
307
|
-
|
|
308
|
-
// Keep only the language indicator logic here, styling moved to CSS
|
|
309
|
-
return (
|
|
310
|
-
<>
|
|
311
|
-
{!isInline && language && (
|
|
312
|
-
<div className="code-language-indicator">
|
|
313
|
-
{language}
|
|
314
|
-
</div>
|
|
315
|
-
)}
|
|
316
|
-
<code {...props}>
|
|
317
|
-
{children}
|
|
318
|
-
</code>
|
|
319
|
-
</>
|
|
320
|
-
);
|
|
321
|
-
},
|
|
322
|
-
// Remove 'node' and 'ref' from props
|
|
323
|
-
p: ({ node, ref, ...props }) => <p {...props} />,
|
|
324
|
-
strong: ({ node, ref, ...props }) => <strong {...props} />,
|
|
325
|
-
em: ({ node, ref, ...props }) => <em {...props} />,
|
|
326
|
-
pre: ({ node, ref, ...props }) => <pre {...props} />,
|
|
327
|
-
h1: ({ node, ref, ...props }) => <h1 {...props} />,
|
|
328
|
-
h2: ({ node, ref, ...props }) => <h2 {...props} />,
|
|
329
|
-
h3: ({ node, ref, ...props }) => <h3 {...props} />,
|
|
330
|
-
li: ({ node, ref, ...props }) => <li {...props} />,
|
|
331
|
-
ul: ({ node, ref, ...props }) => <ul {...props} />,
|
|
332
|
-
ol: ({ node, ref, ...props }) => <ol {...props} />,
|
|
333
|
-
blockquote: ({ node, ref, ...props }) => <blockquote {...props} />,
|
|
334
|
-
hr: ({ node, ref, ...props }) => <hr {...props} />,
|
|
335
|
-
table: ({ node, ref, ...props }) => <div className="overflow-x-auto"><table {...props} /></div>,
|
|
336
|
-
th: ({ node, ref, ...props }) => <th {...props} />,
|
|
337
|
-
td: ({ node, ref, ...props }) => <td {...props} />,
|
|
338
264
|
}}
|
|
339
265
|
>
|
|
340
266
|
{content as string}
|
|
341
|
-
</
|
|
267
|
+
</MarkdownRenderer>
|
|
342
268
|
</div>
|
|
343
269
|
);
|
|
344
270
|
};
|
|
345
271
|
|
|
346
272
|
const messageContent = getMessageContent();
|
|
347
273
|
|
|
274
|
+
// Resolve artifacts from tool details (e.g. execute_shell.outputFiles)
|
|
275
|
+
const [artifactLinks, setArtifactLinks] = useState<
|
|
276
|
+
{ displayName: string; artifactPath: string; url: string; isImage: boolean }[]
|
|
277
|
+
>([]);
|
|
278
|
+
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
const loadArtifacts = async () => {
|
|
281
|
+
const runId = (message as any).workflow_run_id as string | undefined;
|
|
282
|
+
const details = message.details as any;
|
|
283
|
+
const outputFiles: unknown = details && details.outputFiles;
|
|
284
|
+
|
|
285
|
+
if (!runId || !Array.isArray(outputFiles) || outputFiles.length === 0) {
|
|
286
|
+
setArtifactLinks([]);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const entries = await Promise.all(
|
|
292
|
+
outputFiles.map(async (name: unknown) => {
|
|
293
|
+
if (typeof name !== "string" || !name.trim()) return null;
|
|
294
|
+
const trimmed = name.trim();
|
|
295
|
+
// execute_shell returns relative paths like "result.csv" or "plots/chart.png"
|
|
296
|
+
// canonical artifact name is under out/
|
|
297
|
+
const artifactPath =
|
|
298
|
+
trimmed.startsWith("out/") || trimmed.startsWith("files/") || trimmed.startsWith("scripts/")
|
|
299
|
+
? trimmed
|
|
300
|
+
: `out/${trimmed}`;
|
|
301
|
+
|
|
302
|
+
const ext = artifactPath.split(".").pop()?.toLowerCase() || "";
|
|
303
|
+
const imageExtensions = new Set(["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg"]);
|
|
304
|
+
const isImage = imageExtensions.has(ext);
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
const disposition = isImage ? "inline" : "attachment";
|
|
308
|
+
const { url } = await client.files.getArtifactDownloadUrl(runId, artifactPath, disposition);
|
|
309
|
+
return {
|
|
310
|
+
displayName: trimmed,
|
|
311
|
+
artifactPath,
|
|
312
|
+
url,
|
|
313
|
+
isImage,
|
|
314
|
+
};
|
|
315
|
+
} catch (err) {
|
|
316
|
+
console.error(`Failed to resolve artifact URL for ${artifactPath}`, err);
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}),
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
setArtifactLinks(
|
|
323
|
+
entries.filter(
|
|
324
|
+
(e): e is { displayName: string; artifactPath: string; url: string; isImage: boolean } => !!e,
|
|
325
|
+
),
|
|
326
|
+
);
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.error("Error loading artifact URLs from message details", error);
|
|
329
|
+
setArtifactLinks([]);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
loadArtifacts();
|
|
334
|
+
}, [message.details, message.timestamp, client]);
|
|
335
|
+
|
|
348
336
|
// Process content with image URL resolution when component mounts or message changes
|
|
349
337
|
useEffect(() => {
|
|
350
338
|
const processContent = async () => {
|
|
@@ -507,7 +495,7 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
|
|
|
507
495
|
)}
|
|
508
496
|
</div>
|
|
509
497
|
|
|
510
|
-
<div className="flex items-center gap-2">
|
|
498
|
+
<div className="flex items-center gap-2 print:hidden">
|
|
511
499
|
<span className="text-xs text-muted">
|
|
512
500
|
{dayjs(message.timestamp).format("HH:mm:ss")}
|
|
513
501
|
</span>
|
|
@@ -537,9 +525,56 @@ export default function MessageItem({ message, showPulsatingCircle = false }: Me
|
|
|
537
525
|
</div>
|
|
538
526
|
)}
|
|
539
527
|
|
|
528
|
+
{/* Auto-surfaced artifacts from tool details (e.g. execute_shell.outputFiles) */}
|
|
529
|
+
{artifactLinks.length > 0 && (
|
|
530
|
+
<div className="mt-3 text-xs">
|
|
531
|
+
<div className="font-medium text-muted mb-1">Artifacts</div>
|
|
532
|
+
|
|
533
|
+
{/* Inline previews for image artifacts */}
|
|
534
|
+
{artifactLinks.some(a => a.isImage) && (
|
|
535
|
+
<div className="mb-2 flex flex-wrap gap-3">
|
|
536
|
+
{artifactLinks
|
|
537
|
+
.filter(a => a.isImage)
|
|
538
|
+
.map(({ displayName, artifactPath, url }) => (
|
|
539
|
+
<div
|
|
540
|
+
key={`${artifactPath}-preview`}
|
|
541
|
+
className="max-w-xs cursor-pointer"
|
|
542
|
+
onClick={() => window.open(url, "_blank")}
|
|
543
|
+
>
|
|
544
|
+
<img
|
|
545
|
+
src={url}
|
|
546
|
+
alt={displayName}
|
|
547
|
+
className="max-w-full h-auto rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
|
548
|
+
/>
|
|
549
|
+
<div className="mt-1 text-[11px] text-muted truncate">
|
|
550
|
+
{displayName}
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
))}
|
|
554
|
+
</div>
|
|
555
|
+
)}
|
|
556
|
+
|
|
557
|
+
{/* Buttons for all artifacts (files and images) */}
|
|
558
|
+
<div className="flex flex-wrap gap-2 print:hidden">
|
|
559
|
+
{artifactLinks.map(({ displayName, artifactPath, url }) => (
|
|
560
|
+
<Button
|
|
561
|
+
key={artifactPath + url}
|
|
562
|
+
variant="outline"
|
|
563
|
+
size="xs"
|
|
564
|
+
className="px-2 py-1 text-xs"
|
|
565
|
+
onClick={() => window.open(url, "_blank")}
|
|
566
|
+
title={artifactPath}
|
|
567
|
+
>
|
|
568
|
+
{displayName}
|
|
569
|
+
</Button>
|
|
570
|
+
))}
|
|
571
|
+
</div>
|
|
572
|
+
</div>
|
|
573
|
+
)}
|
|
574
|
+
|
|
540
575
|
{/* Optional details section */}
|
|
541
576
|
{message.details && (
|
|
542
|
-
<div className="mt-2">
|
|
577
|
+
<div className="mt-2 print:hidden">
|
|
543
578
|
<button
|
|
544
579
|
onClick={() => setShowDetails(!showDetails)}
|
|
545
580
|
className="text-xs text-muted flex items-center"
|