@vertesia/ui 1.4.0 → 1.5.0-dev.20260713.151751Z
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/InputList.d.ts.map +1 -1
- package/lib/core/components/InputList.js +3 -2
- package/lib/core/components/InputList.js.map +1 -1
- package/lib/core/components/SelectList.d.ts.map +1 -1
- package/lib/core/components/SelectList.js +1 -1
- package/lib/core/components/SelectList.js.map +1 -1
- package/lib/core/components/TagsInput.d.ts.map +1 -1
- package/lib/core/components/TagsInput.js +36 -4
- package/lib/core/components/TagsInput.js.map +1 -1
- package/lib/core/components/popup/Popup.js +2 -1
- package/lib/core/components/popup/Popup.js.map +1 -1
- package/lib/core/components/popup/position.d.ts.map +1 -1
- package/lib/core/components/popup/position.js +3 -6
- package/lib/core/components/popup/position.js.map +1 -1
- package/lib/core/components/shadcn/badge.d.ts +2 -2
- package/lib/core/components/shadcn/badge.d.ts.map +1 -1
- package/lib/core/components/shadcn/badge.js +3 -0
- package/lib/core/components/shadcn/badge.js.map +1 -1
- package/lib/core/components/shadcn/breadcrumb.d.ts.map +1 -1
- package/lib/core/components/shadcn/breadcrumb.js +2 -2
- package/lib/core/components/shadcn/breadcrumb.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 -3
- package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/core/components/shadcn/resizeable.d.ts +1 -1
- package/lib/core/components/shadcn/resizeable.d.ts.map +1 -1
- package/lib/core/components/shadcn/resizeable.js +12 -2
- package/lib/core/components/shadcn/resizeable.js.map +1 -1
- package/lib/core/components/shadcn/selectBox.d.ts +7 -1
- package/lib/core/components/shadcn/selectBox.d.ts.map +1 -1
- package/lib/core/components/shadcn/selectBox.js +29 -12
- package/lib/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/core/components/table/index.d.ts.map +1 -1
- package/lib/core/components/table/index.js +1 -1
- package/lib/core/components/table/index.js.map +1 -1
- package/lib/core/hooks/useIntersectionObserver.d.ts.map +1 -1
- package/lib/core/hooks/useIntersectionObserver.js +3 -1
- package/lib/core/hooks/useIntersectionObserver.js.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.js +3 -6
- package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/features/agent/chat/AnimatedThinkingDots.d.ts.map +1 -1
- package/lib/features/agent/chat/AnimatedThinkingDots.js +1 -1
- package/lib/features/agent/chat/AnimatedThinkingDots.js.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.js +4 -3
- package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +56 -11
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +40 -31
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +3 -3
- package/lib/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +5 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -7
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.js +5 -5
- package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +4 -4
- package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +3 -3
- package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +156 -8
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
- package/lib/features/agent/chat/hooks/useFileProcessing.d.ts +1 -0
- package/lib/features/agent/chat/hooks/useFileProcessing.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useFileProcessing.js +37 -3
- package/lib/features/agent/chat/hooks/useFileProcessing.js.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.js +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/features/facets/InteractionsFacetsNav.d.ts +10 -1
- package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/InteractionsFacetsNav.js +14 -5
- package/lib/features/facets/InteractionsFacetsNav.js.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.js +12 -1
- package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
- package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/RunsFacetsNav.js +1 -1
- package/lib/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/features/magic-pdf/AnnotatedImageSlider.d.ts.map +1 -1
- package/lib/features/magic-pdf/AnnotatedImageSlider.js +1 -3
- package/lib/features/magic-pdf/AnnotatedImageSlider.js.map +1 -1
- package/lib/features/magic-pdf/MagicPdfProvider.js +2 -3
- package/lib/features/magic-pdf/MagicPdfProvider.js.map +1 -1
- package/lib/features/store/objects/DocumentSearchResults.d.ts +6 -2
- package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentSearchResults.js +6 -6
- package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +1 -1
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/components/DocumentIcon.d.ts.map +1 -1
- package/lib/features/store/objects/components/DocumentIcon.js +1 -1
- package/lib/features/store/objects/components/DocumentIcon.js.map +1 -1
- package/lib/features/store/objects/components/DocumentInput.js.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts +4 -4
- package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.js +1 -1
- package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
- package/lib/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
- package/lib/features/store/objects/selection/ObjectsActionContext.js +2 -25
- package/lib/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
- package/lib/features/store/objects/selection/ObjectsActionContextClass.d.ts +0 -2
- package/lib/features/store/objects/selection/ObjectsActionContextClass.d.ts.map +1 -1
- package/lib/features/store/objects/selection/ObjectsActionContextClass.js +1 -7
- package/lib/features/store/objects/selection/ObjectsActionContextClass.js.map +1 -1
- package/lib/features/store/objects/selection/ObjectsActionHooks.d.ts +0 -1
- package/lib/features/store/objects/selection/ObjectsActionHooks.d.ts.map +1 -1
- package/lib/features/store/objects/selection/ObjectsActionHooks.js +0 -10
- package/lib/features/store/objects/selection/ObjectsActionHooks.js.map +1 -1
- package/lib/features/store/objects/selection/SelectionActions.d.ts +4 -0
- package/lib/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
- package/lib/features/store/objects/selection/SelectionActions.js +4 -18
- package/lib/features/store/objects/selection/SelectionActions.js.map +1 -1
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.d.ts.map +1 -1
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js +16 -7
- package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
- package/lib/features/store/objects/selection/actions/StartWorkflowButton.d.ts +7 -0
- package/lib/features/store/objects/selection/actions/StartWorkflowButton.d.ts.map +1 -0
- package/lib/features/store/objects/selection/actions/StartWorkflowButton.js +51 -0
- package/lib/features/store/objects/selection/actions/StartWorkflowButton.js.map +1 -0
- package/lib/features/store/objects/selection/actions/index.d.ts +0 -1
- package/lib/features/store/objects/selection/actions/index.d.ts.map +1 -1
- package/lib/features/store/objects/selection/actions/index.js +0 -1
- package/lib/features/store/objects/selection/actions/index.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesSearch.js +55 -3
- package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts +5 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.js +4 -2
- package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/features/store/types/search/ObjectTypeSearchContext.js +1 -1
- package/lib/features/store/types/search/ObjectTypeSearchContext.js.map +1 -1
- package/lib/i18n/locales/ar.json +17 -0
- package/lib/i18n/locales/de.json +17 -0
- package/lib/i18n/locales/en.json +33 -0
- package/lib/i18n/locales/es.json +17 -0
- package/lib/i18n/locales/fr.json +17 -0
- package/lib/i18n/locales/it.json +17 -0
- package/lib/i18n/locales/ja.json +17 -0
- package/lib/i18n/locales/ko.json +17 -0
- package/lib/i18n/locales/pt.json +17 -0
- package/lib/i18n/locales/ru.json +17 -0
- package/lib/i18n/locales/tr.json +17 -0
- package/lib/i18n/locales/zh-TW.json +17 -0
- package/lib/i18n/locales/zh.json +17 -0
- package/lib/layout/Sidebar.d.ts +5 -1
- package/lib/layout/Sidebar.d.ts.map +1 -1
- package/lib/layout/Sidebar.js.map +1 -1
- package/lib/router/NestedRouterProvider.d.ts +1 -1
- package/lib/router/NestedRouterProvider.d.ts.map +1 -1
- package/lib/router/NestedRouterProvider.js +2 -2
- package/lib/router/NestedRouterProvider.js.map +1 -1
- package/lib/router/Redirect.d.ts +13 -0
- package/lib/router/Redirect.d.ts.map +1 -0
- package/lib/router/Redirect.js +20 -0
- package/lib/router/Redirect.js.map +1 -0
- package/lib/router/Router.d.ts.map +1 -1
- package/lib/router/Router.js +1 -2
- package/lib/router/Router.js.map +1 -1
- package/lib/router/index.d.ts +1 -0
- package/lib/router/index.d.ts.map +1 -1
- package/lib/router/index.js +1 -0
- package/lib/router/index.js.map +1 -1
- package/lib/session/DevSessionProvider.d.ts +8 -0
- package/lib/session/DevSessionProvider.d.ts.map +1 -0
- package/lib/session/DevSessionProvider.js +33 -0
- package/lib/session/DevSessionProvider.js.map +1 -0
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +16 -2
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/composable.d.ts +10 -1
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +38 -2
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/session/index.d.ts +1 -0
- package/lib/session/index.d.ts.map +1 -1
- package/lib/session/index.js +1 -0
- package/lib/session/index.js.map +1 -1
- package/lib/shell/VertesiaShell.d.ts +3 -1
- package/lib/shell/VertesiaShell.d.ts.map +1 -1
- package/lib/shell/VertesiaShell.js +5 -4
- package/lib/shell/VertesiaShell.js.map +1 -1
- package/lib/shell/login/SignInRestrictedEnvStep.d.ts +14 -0
- package/lib/shell/login/SignInRestrictedEnvStep.d.ts.map +1 -0
- package/lib/shell/login/SignInRestrictedEnvStep.js +50 -0
- package/lib/shell/login/SignInRestrictedEnvStep.js.map +1 -0
- package/lib/shell/login/SigninScreen.d.ts.map +1 -1
- package/lib/shell/login/SigninScreen.js +16 -3
- package/lib/shell/login/SigninScreen.js.map +1 -1
- package/lib/shell/login/productionUrl.d.ts +16 -0
- package/lib/shell/login/productionUrl.d.ts.map +1 -0
- package/lib/shell/login/productionUrl.js +19 -0
- package/lib/shell/login/productionUrl.js.map +1 -0
- package/lib/shell/login/signInUtils.d.ts.map +1 -1
- package/lib/shell/login/signInUtils.js +14 -1
- package/lib/shell/login/signInUtils.js.map +1 -1
- package/lib/vertesia-ui-core.js +95 -2
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +2 -2
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +454 -2
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +41 -2
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-layout.js +2 -2
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-router.js +2 -2
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js +2 -2
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +2 -2
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +9 -2
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/lib/widgets/json-view/JSONCode.d.ts.map +1 -1
- package/lib/widgets/json-view/JSONCode.js +1 -1
- package/lib/widgets/json-view/JSONCode.js.map +1 -1
- package/lib/widgets/json-view/JSONTable.d.ts.map +1 -1
- package/lib/widgets/json-view/JSONTable.js +1 -1
- package/lib/widgets/json-view/JSONTable.js.map +1 -1
- package/lib/widgets/markdown/ArtifactContentRenderer.d.ts.map +1 -1
- package/lib/widgets/markdown/ArtifactContentRenderer.js +1 -1
- package/lib/widgets/markdown/ArtifactContentRenderer.js.map +1 -1
- package/lib/widgets/markdown/CodeBlockPlaceholder.d.ts.map +1 -1
- package/lib/widgets/markdown/CodeBlockPlaceholder.js +1 -1
- package/lib/widgets/markdown/CodeBlockPlaceholder.js.map +1 -1
- package/lib/widgets/monacoEditor/foldingProviders.d.ts.map +1 -1
- package/lib/widgets/monacoEditor/foldingProviders.js +5 -10
- package/lib/widgets/monacoEditor/foldingProviders.js.map +1 -1
- package/lib/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
- package/lib/widgets/schema-editor/ManagedSchema.js +1 -2
- package/lib/widgets/schema-editor/ManagedSchema.js.map +1 -1
- package/lib/widgets/upload/UploadResultCategory.d.ts.map +1 -1
- package/lib/widgets/upload/UploadResultCategory.js +1 -1
- package/lib/widgets/upload/UploadResultCategory.js.map +1 -1
- package/lib/widgets/xml-viewer/components/TextElement/index.d.ts.map +1 -1
- package/lib/widgets/xml-viewer/components/TextElement/index.js +1 -1
- package/lib/widgets/xml-viewer/components/TextElement/index.js.map +1 -1
- package/package.json +38 -43
- package/src/core/components/InputList.tsx +5 -10
- package/src/core/components/SelectList.tsx +7 -2
- package/src/core/components/TagsInput.tsx +41 -4
- package/src/core/components/popup/Popup.tsx +3 -3
- package/src/core/components/popup/position.ts +3 -6
- package/src/core/components/shadcn/badge.tsx +3 -0
- package/src/core/components/shadcn/breadcrumb.tsx +2 -4
- package/src/core/components/shadcn/filters/filterBar.tsx +2 -3
- package/src/core/components/shadcn/resizeable.test.tsx +77 -0
- package/src/core/components/shadcn/resizeable.tsx +28 -2
- package/src/core/components/shadcn/selectBox.tsx +70 -36
- package/src/core/components/table/index.tsx +1 -2
- package/src/core/hooks/useIntersectionObserver.tsx +3 -1
- package/src/features/agent/chat/AgentRightPanel.tsx +5 -6
- package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -2
- package/src/features/agent/chat/AskUserWidget.test.tsx +49 -0
- package/src/features/agent/chat/AskUserWidget.tsx +32 -22
- package/src/features/agent/chat/ModernAgentConversation.test.tsx +198 -1
- package/src/features/agent/chat/ModernAgentConversation.tsx +62 -15
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +60 -34
- package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +3 -3
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +25 -0
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +5 -1
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +30 -30
- package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +5 -6
- package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +4 -5
- package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +3 -5
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +326 -42
- package/src/features/agent/chat/hooks/useFileProcessing.test.tsx +70 -0
- package/src/features/agent/chat/hooks/useFileProcessing.ts +37 -6
- package/src/features/facets/AgentRunnerFacetsNav.tsx +1 -2
- package/src/features/facets/InteractionsFacetsNav.tsx +30 -5
- package/src/features/facets/PromptsFacetsNav.tsx +13 -1
- package/src/features/facets/RunsFacetsNav.tsx +1 -2
- package/src/features/magic-pdf/AnnotatedImageSlider.tsx +1 -2
- package/src/features/magic-pdf/MagicPdfProvider.tsx +4 -4
- package/src/features/store/objects/DocumentSearchResults.tsx +11 -1
- package/src/features/store/objects/components/ContentOverview.tsx +1 -2
- package/src/features/store/objects/components/DocumentIcon.tsx +1 -2
- package/src/features/store/objects/components/DocumentInput.tsx +2 -2
- package/src/features/store/objects/search/DocumentSearchContext.test.ts +2 -2
- package/src/features/store/objects/search/DocumentSearchContext.ts +3 -3
- package/src/features/store/objects/selection/ObjectsActionContext.tsx +2 -27
- package/src/features/store/objects/selection/ObjectsActionContextClass.ts +1 -7
- package/src/features/store/objects/selection/ObjectsActionHooks.ts +0 -11
- package/src/features/store/objects/selection/SelectionActions.tsx +9 -34
- package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +40 -7
- package/src/features/store/objects/selection/actions/StartWorkflowButton.tsx +104 -0
- package/src/features/store/objects/selection/actions/index.ts +0 -1
- package/src/features/store/types/ContentObjectTypesSearch.tsx +110 -1
- package/src/features/store/types/ContentObjectTypesTable.tsx +42 -3
- package/src/features/store/types/search/ObjectTypeSearchContext.tsx +1 -1
- package/src/i18n/locales/ar.json +17 -0
- package/src/i18n/locales/de.json +17 -0
- package/src/i18n/locales/en.json +33 -0
- package/src/i18n/locales/es.json +17 -0
- package/src/i18n/locales/fr.json +17 -0
- package/src/i18n/locales/it.json +17 -0
- package/src/i18n/locales/ja.json +17 -0
- package/src/i18n/locales/ko.json +17 -0
- package/src/i18n/locales/pt.json +17 -0
- package/src/i18n/locales/ru.json +17 -0
- package/src/i18n/locales/tr.json +17 -0
- package/src/i18n/locales/zh-TW.json +17 -0
- package/src/i18n/locales/zh.json +17 -0
- package/src/layout/Sidebar.tsx +6 -1
- package/src/router/NestedRouterProvider.tsx +2 -2
- package/src/router/Redirect.tsx +29 -0
- package/src/router/Router.tsx +1 -2
- package/src/router/index.ts +1 -0
- package/src/session/DevSessionProvider.tsx +46 -0
- package/src/session/UserSessionProvider.tsx +18 -2
- package/src/session/auth/composable.ts +41 -3
- package/src/session/index.ts +1 -0
- package/src/shell/VertesiaShell.tsx +27 -14
- package/src/shell/login/SignInRestrictedEnvStep.tsx +87 -0
- package/src/shell/login/SigninScreen.tsx +29 -16
- package/src/shell/login/productionUrl.test.ts +19 -0
- package/src/shell/login/productionUrl.ts +18 -0
- package/src/shell/login/signInUtils.ts +14 -1
- package/src/widgets/json-view/JSONCode.tsx +1 -2
- package/src/widgets/json-view/JSONTable.tsx +1 -2
- package/src/widgets/markdown/ArtifactContentRenderer.tsx +4 -7
- package/src/widgets/markdown/CodeBlockPlaceholder.tsx +1 -2
- package/src/widgets/monacoEditor/foldingProviders.ts +10 -15
- package/src/widgets/schema-editor/ManagedSchema.ts +1 -2
- package/src/widgets/upload/UploadResultCategory.tsx +2 -3
- package/src/widgets/xml-viewer/components/TextElement/index.tsx +1 -2
- package/lib/features/store/objects/selection/actions/StartWorkflowComponent.d.ts +0 -4
- package/lib/features/store/objects/selection/actions/StartWorkflowComponent.d.ts.map +0 -1
- package/lib/features/store/objects/selection/actions/StartWorkflowComponent.js +0 -77
- package/lib/features/store/objects/selection/actions/StartWorkflowComponent.js.map +0 -1
- package/src/features/store/objects/selection/actions/StartWorkflowComponent.tsx +0 -127
|
@@ -104,6 +104,8 @@ const VARIANT_ICONS = {
|
|
|
104
104
|
success: CheckCircle,
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
+
const SCROLLABLE_PROMPT_CLASS = 'max-h-80 overflow-y-auto overscroll-contain pe-2';
|
|
108
|
+
|
|
107
109
|
/**
|
|
108
110
|
* AskUserWidget - A styled component for displaying agent prompts/questions to users
|
|
109
111
|
*
|
|
@@ -197,10 +199,14 @@ export function AskUserWidget({
|
|
|
197
199
|
if (answered) {
|
|
198
200
|
return (
|
|
199
201
|
<div className={cn('my-1.5 font-sans', className)}>
|
|
200
|
-
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
<div className={SCROLLABLE_PROMPT_CLASS}>
|
|
203
|
+
{compactQuestion}
|
|
204
|
+
{description && (
|
|
205
|
+
<p className={cn('mt-1 text-xs leading-5 text-muted', descriptionClassName)}>
|
|
206
|
+
{description}
|
|
207
|
+
</p>
|
|
208
|
+
)}
|
|
209
|
+
</div>
|
|
204
210
|
</div>
|
|
205
211
|
);
|
|
206
212
|
}
|
|
@@ -214,12 +220,14 @@ export function AskUserWidget({
|
|
|
214
220
|
<div className={cn('mt-1 flex-shrink-0 text-attention', iconClassName)}>{iconNode}</div>
|
|
215
221
|
)}
|
|
216
222
|
<div className="min-w-0 flex-1">
|
|
217
|
-
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
{
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
<div className={SCROLLABLE_PROMPT_CLASS}>
|
|
224
|
+
{compactQuestion}
|
|
225
|
+
{description && (
|
|
226
|
+
<p className={cn('mt-1 text-xs leading-5 text-muted', descriptionClassName)}>
|
|
227
|
+
{description}
|
|
228
|
+
</p>
|
|
229
|
+
)}
|
|
230
|
+
</div>
|
|
223
231
|
</div>
|
|
224
232
|
</div>
|
|
225
233
|
</div>
|
|
@@ -355,19 +363,21 @@ export function AskUserWidget({
|
|
|
355
363
|
{icon || <DefaultIcon className="size-5" />}
|
|
356
364
|
</div>
|
|
357
365
|
)}
|
|
358
|
-
<div className="
|
|
359
|
-
<div
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
<MarkdownRenderer>{question}</MarkdownRenderer>
|
|
363
|
-
</div>
|
|
364
|
-
{description && (
|
|
365
|
-
<p
|
|
366
|
-
className={`mt-1 text-sm text-gray-600 dark:text-gray-400 ${descriptionClassName || ''}`}
|
|
366
|
+
<div className="min-w-0 flex-1">
|
|
367
|
+
<div className={SCROLLABLE_PROMPT_CLASS}>
|
|
368
|
+
<div
|
|
369
|
+
className={`agent-ask-question prose prose-sm dark:prose-invert max-w-none text-gray-900 dark:text-gray-100 ${questionClassName || ''}`}
|
|
367
370
|
>
|
|
368
|
-
{
|
|
369
|
-
</
|
|
370
|
-
|
|
371
|
+
<MarkdownRenderer>{question}</MarkdownRenderer>
|
|
372
|
+
</div>
|
|
373
|
+
{description && (
|
|
374
|
+
<p
|
|
375
|
+
className={`mt-1 text-sm text-gray-600 dark:text-gray-400 ${descriptionClassName || ''}`}
|
|
376
|
+
>
|
|
377
|
+
{description}
|
|
378
|
+
</p>
|
|
379
|
+
)}
|
|
380
|
+
</div>
|
|
371
381
|
</div>
|
|
372
382
|
</div>
|
|
373
383
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
|
2
|
-
import { type AgentMessage, AgentMessageType } from '@vertesia/common';
|
|
2
|
+
import { type AgentMessage, AgentMessageType, type ConversationFile, FileProcessingStatus } from '@vertesia/common';
|
|
3
3
|
import type React from 'react';
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
5
|
import { renderWithProviders } from '../../../__tests__/test-utils.js';
|
|
@@ -245,6 +245,7 @@ describe('ModernAgentConversation send handling', () => {
|
|
|
245
245
|
hasProcessingFiles: false,
|
|
246
246
|
handleFileUpload: vi.fn(),
|
|
247
247
|
removeProcessingFile: vi.fn(),
|
|
248
|
+
clearProcessingFiles: vi.fn(),
|
|
248
249
|
});
|
|
249
250
|
});
|
|
250
251
|
|
|
@@ -285,6 +286,53 @@ describe('ModernAgentConversation send handling', () => {
|
|
|
285
286
|
expect(mocks.updateOptimisticMessageStatus).toHaveBeenCalledWith(expect.any(String), 'received');
|
|
286
287
|
});
|
|
287
288
|
|
|
289
|
+
it('binds ready uploaded files into the sent message and clears them after send', async () => {
|
|
290
|
+
const clearProcessingFiles = vi.fn();
|
|
291
|
+
const readyFile: ConversationFile = {
|
|
292
|
+
id: 'file-1',
|
|
293
|
+
name: 'report.pdf',
|
|
294
|
+
content_type: 'application/pdf',
|
|
295
|
+
size: 10,
|
|
296
|
+
status: FileProcessingStatus.READY,
|
|
297
|
+
artifact_path: 'files/report.pdf',
|
|
298
|
+
reference: 'artifact:files/report.pdf',
|
|
299
|
+
started_at: 1_000,
|
|
300
|
+
};
|
|
301
|
+
mocks.useFileProcessing.mockReturnValue({
|
|
302
|
+
processingFiles: new Map([[readyFile.id, readyFile]]),
|
|
303
|
+
hasProcessingFiles: false,
|
|
304
|
+
handleFileUpload: vi.fn(),
|
|
305
|
+
removeProcessingFile: vi.fn(),
|
|
306
|
+
clearProcessingFiles,
|
|
307
|
+
});
|
|
308
|
+
mockStreamState({
|
|
309
|
+
messages: [createMessage(AgentMessageType.COMPLETE, 'done')],
|
|
310
|
+
agentRunStatus: 'COMPLETED',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
renderConversation({ onRestart: vi.fn() });
|
|
314
|
+
|
|
315
|
+
fireEvent.click(screen.getByRole('button', { name: 'inline send' }));
|
|
316
|
+
|
|
317
|
+
await waitFor(() => {
|
|
318
|
+
expect(mocks.sendSignal).toHaveBeenCalledWith(
|
|
319
|
+
'agent-run-1',
|
|
320
|
+
'UserInput',
|
|
321
|
+
expect.objectContaining({
|
|
322
|
+
message: expect.stringContaining('Uploaded artifacts:'),
|
|
323
|
+
}),
|
|
324
|
+
);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const userInputCall = mocks.sendSignal.mock.calls.find((call) => call[1] === 'UserInput');
|
|
328
|
+
expect((userInputCall?.[2] as { message: string }).message).toContain(
|
|
329
|
+
'[report.pdf](artifact:files/report.pdf)',
|
|
330
|
+
);
|
|
331
|
+
await waitFor(() => {
|
|
332
|
+
expect(clearProcessingFiles).toHaveBeenCalledTimes(1);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
|
|
288
336
|
it('does not restart or send from a terminal run that cannot continue', () => {
|
|
289
337
|
mockStreamState({
|
|
290
338
|
messages: [createMessage(AgentMessageType.COMPLETE, 'done')],
|
|
@@ -425,6 +473,155 @@ describe('ModernAgentConversation send handling', () => {
|
|
|
425
473
|
expect(screen.queryByText('Switch to full control?')).toBeNull();
|
|
426
474
|
});
|
|
427
475
|
|
|
476
|
+
it('orders a follow-up user message after an in-flight approval mode change', async () => {
|
|
477
|
+
let resolveModeSignal: (() => void) | undefined;
|
|
478
|
+
mocks.retrieve.mockResolvedValue({
|
|
479
|
+
tool_approval_mode: 'ask',
|
|
480
|
+
interactive: true,
|
|
481
|
+
disabled_mcp_collections: undefined,
|
|
482
|
+
});
|
|
483
|
+
mocks.sendSignal.mockImplementation((_runId: string, signalName: string) => {
|
|
484
|
+
if (signalName === 'ToolApprovalModeChanged') {
|
|
485
|
+
return new Promise<void>((resolve) => {
|
|
486
|
+
resolveModeSignal = resolve;
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
return Promise.resolve({});
|
|
490
|
+
});
|
|
491
|
+
mockStreamState({
|
|
492
|
+
messages: [createMessage(AgentMessageType.REQUEST_INPUT, 'What should I do next?')],
|
|
493
|
+
isCompleted: false,
|
|
494
|
+
agentRunStatus: 'RUNNING',
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
renderConversation({ hideMessageInput: false, interactive: true, allowWorkflowControl: true });
|
|
498
|
+
|
|
499
|
+
const selector = await screen.findByRole('button', { name: 'Agent approval mode' });
|
|
500
|
+
fireEvent.pointerDown(selector, {
|
|
501
|
+
button: 0,
|
|
502
|
+
ctrlKey: false,
|
|
503
|
+
});
|
|
504
|
+
fireEvent.click(await screen.findByRole('menuitemradio', { name: /Full control/ }));
|
|
505
|
+
|
|
506
|
+
await waitFor(() => {
|
|
507
|
+
expect(mocks.sendSignal).toHaveBeenCalledWith('agent-run-1', 'ToolApprovalModeChanged', {
|
|
508
|
+
mode: 'full_control',
|
|
509
|
+
});
|
|
510
|
+
expect(resolveModeSignal).toBeDefined();
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
fireEvent.click(screen.getByRole('button', { name: 'composer send' }));
|
|
514
|
+
|
|
515
|
+
expect(mocks.sendSignal.mock.calls.some((call) => call[1] === 'UserInput')).toBe(false);
|
|
516
|
+
|
|
517
|
+
await act(async () => {
|
|
518
|
+
resolveModeSignal?.();
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
await waitFor(() => {
|
|
522
|
+
expect(mocks.sendSignal).toHaveBeenCalledWith(
|
|
523
|
+
'agent-run-1',
|
|
524
|
+
'UserInput',
|
|
525
|
+
expect.objectContaining({ message: 'follow up' }),
|
|
526
|
+
);
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
const modeCallIndex = mocks.sendSignal.mock.calls.findIndex((call) => call[1] === 'ToolApprovalModeChanged');
|
|
530
|
+
const userInputCallIndex = mocks.sendSignal.mock.calls.findIndex((call) => call[1] === 'UserInput');
|
|
531
|
+
expect(modeCallIndex).toBeGreaterThanOrEqual(0);
|
|
532
|
+
expect(userInputCallIndex).toBeGreaterThan(modeCallIndex);
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it('keeps a local approval mode change when stale run metadata loads later', async () => {
|
|
536
|
+
let resolveRetrieve: (run: {
|
|
537
|
+
tool_approval_mode: 'ask';
|
|
538
|
+
interactive: true;
|
|
539
|
+
disabled_mcp_collections: undefined;
|
|
540
|
+
}) => void = () => {};
|
|
541
|
+
mocks.retrieve.mockReturnValue(
|
|
542
|
+
new Promise((resolve) => {
|
|
543
|
+
resolveRetrieve = resolve;
|
|
544
|
+
}),
|
|
545
|
+
);
|
|
546
|
+
mockStreamState({
|
|
547
|
+
messages: [createMessage(AgentMessageType.ANSWER, 'still running')],
|
|
548
|
+
isCompleted: false,
|
|
549
|
+
agentRunStatus: 'RUNNING',
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
renderConversation({
|
|
553
|
+
hideMessageInput: false,
|
|
554
|
+
interactive: true,
|
|
555
|
+
allowWorkflowControl: true,
|
|
556
|
+
initialToolApprovalMode: 'ask',
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
expect(await screen.findByText('Ask for approval')).not.toBeNull();
|
|
560
|
+
fireEvent.pointerDown(screen.getByRole('button', { name: 'Agent approval mode' }), {
|
|
561
|
+
button: 0,
|
|
562
|
+
ctrlKey: false,
|
|
563
|
+
});
|
|
564
|
+
fireEvent.click(await screen.findByRole('menuitemradio', { name: /Full control/ }));
|
|
565
|
+
|
|
566
|
+
await waitFor(() => {
|
|
567
|
+
expect(mocks.sendSignal).toHaveBeenCalledWith('agent-run-1', 'ToolApprovalModeChanged', {
|
|
568
|
+
mode: 'full_control',
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
resolveRetrieve({
|
|
573
|
+
tool_approval_mode: 'ask',
|
|
574
|
+
interactive: true,
|
|
575
|
+
disabled_mcp_collections: undefined,
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
await waitFor(() => {
|
|
579
|
+
expect(screen.getByText('Full control')).not.toBeNull();
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('reverts the local approval mode when the change signal fails', async () => {
|
|
584
|
+
let rejectSignal: (error: Error) => void = () => {};
|
|
585
|
+
mocks.retrieve.mockResolvedValue({
|
|
586
|
+
tool_approval_mode: 'ask',
|
|
587
|
+
interactive: true,
|
|
588
|
+
disabled_mcp_collections: undefined,
|
|
589
|
+
});
|
|
590
|
+
mocks.sendSignal.mockReturnValueOnce(
|
|
591
|
+
new Promise((_resolve, reject) => {
|
|
592
|
+
rejectSignal = reject;
|
|
593
|
+
}),
|
|
594
|
+
);
|
|
595
|
+
mockStreamState({
|
|
596
|
+
messages: [createMessage(AgentMessageType.ANSWER, 'still running')],
|
|
597
|
+
isCompleted: false,
|
|
598
|
+
agentRunStatus: 'RUNNING',
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
renderConversation({ hideMessageInput: false, interactive: true, allowWorkflowControl: true });
|
|
602
|
+
|
|
603
|
+
const selector = await screen.findByRole('button', { name: 'Agent approval mode' });
|
|
604
|
+
expect(selector.textContent).toContain('Ask for approval');
|
|
605
|
+
fireEvent.pointerDown(selector, {
|
|
606
|
+
button: 0,
|
|
607
|
+
ctrlKey: false,
|
|
608
|
+
});
|
|
609
|
+
fireEvent.click(await screen.findByRole('menuitemradio', { name: /Full control/ }));
|
|
610
|
+
|
|
611
|
+
await waitFor(() => {
|
|
612
|
+
expect(mocks.sendSignal).toHaveBeenCalledWith('agent-run-1', 'ToolApprovalModeChanged', {
|
|
613
|
+
mode: 'full_control',
|
|
614
|
+
});
|
|
615
|
+
expect(selector.textContent).toContain('Full control');
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
rejectSignal(new Error('Signal failed'));
|
|
619
|
+
|
|
620
|
+
await waitFor(() => {
|
|
621
|
+
expect(selector.textContent).toContain('Ask for approval');
|
|
622
|
+
});
|
|
623
|
+
});
|
|
624
|
+
|
|
428
625
|
it('does not show a full-control fallback before active run mode metadata loads', () => {
|
|
429
626
|
mocks.retrieve.mockReturnValue(new Promise(() => {}));
|
|
430
627
|
mockStreamState({
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type CompletedWorkstreamEntry,
|
|
8
8
|
type ConversationFile,
|
|
9
9
|
type ConversationFileRef,
|
|
10
|
+
FileProcessingStatus,
|
|
10
11
|
type McpConnectUxConfig,
|
|
11
12
|
normalizeAgentToolApprovalMode,
|
|
12
13
|
type Plan,
|
|
@@ -1359,12 +1360,8 @@ function ModernAgentConversationInner({
|
|
|
1359
1360
|
updateDocumentTitle,
|
|
1360
1361
|
} = useDocumentPanel(messages);
|
|
1361
1362
|
|
|
1362
|
-
const { processingFiles, hasProcessingFiles, handleFileUpload, removeProcessingFile } =
|
|
1363
|
-
client,
|
|
1364
|
-
agentRunId,
|
|
1365
|
-
serverFileUpdates,
|
|
1366
|
-
toast,
|
|
1367
|
-
);
|
|
1363
|
+
const { processingFiles, hasProcessingFiles, handleFileUpload, removeProcessingFile, clearProcessingFiles } =
|
|
1364
|
+
useFileProcessing(client, agentRunId, serverFileUpdates, toast);
|
|
1368
1365
|
const canUploadFiles = interactive && !hideFileUpload;
|
|
1369
1366
|
|
|
1370
1367
|
const handleRemoveProcessingFile = useCallback(
|
|
@@ -1416,6 +1413,8 @@ function ModernAgentConversationInner({
|
|
|
1416
1413
|
const workstreamFetchFailedRef = useRef(false);
|
|
1417
1414
|
const dragCounterRef = useRef(0);
|
|
1418
1415
|
const pendingPlaybackScrollRef = useRef(false);
|
|
1416
|
+
const toolApprovalModeChangeVersionRef = useRef(0);
|
|
1417
|
+
const pendingToolApprovalModeChangeRef = useRef<Promise<void> | null>(null);
|
|
1419
1418
|
|
|
1420
1419
|
useEffect(() => {
|
|
1421
1420
|
setToolApprovalMode(initialResolvedToolApprovalMode);
|
|
@@ -1426,6 +1425,8 @@ function ModernAgentConversationInner({
|
|
|
1426
1425
|
isSendingRef.current = isSending;
|
|
1427
1426
|
const hasProcessingFilesRef = useRef(hasProcessingFiles);
|
|
1428
1427
|
hasProcessingFilesRef.current = hasProcessingFiles;
|
|
1428
|
+
const processingFilesRef = useRef(processingFiles);
|
|
1429
|
+
processingFilesRef.current = processingFiles;
|
|
1429
1430
|
|
|
1430
1431
|
const lastMainMessage = useMemo(() => {
|
|
1431
1432
|
const mainMessages = messages.filter((m) => (m.workstream_id || 'main') === 'main');
|
|
@@ -1909,6 +1910,13 @@ function ModernAgentConversationInner({
|
|
|
1909
1910
|
// Handlers
|
|
1910
1911
|
// ────────────────────────────────────────────
|
|
1911
1912
|
|
|
1913
|
+
const waitForPendingToolApprovalModeChange = useCallback(async () => {
|
|
1914
|
+
const pendingChange = pendingToolApprovalModeChangeRef.current;
|
|
1915
|
+
if (pendingChange) {
|
|
1916
|
+
await pendingChange;
|
|
1917
|
+
}
|
|
1918
|
+
}, []);
|
|
1919
|
+
|
|
1912
1920
|
// Send a message to the agent
|
|
1913
1921
|
const handleSendMessage = useCallback(
|
|
1914
1922
|
(message: string, inputMetadata?: Record<string, unknown>) => {
|
|
@@ -1942,6 +1950,24 @@ function ModernAgentConversationInner({
|
|
|
1942
1950
|
messageContent = [trimmed, '', 'Attachments:', ...lines].join('\n');
|
|
1943
1951
|
}
|
|
1944
1952
|
|
|
1953
|
+
// Bind ready uploaded files to this message: embed them as an "Uploaded artifacts:"
|
|
1954
|
+
// markdown block so they render underneath the sent bubble (parsed by
|
|
1955
|
+
// parseUserMessageAttachments) and get cleared from the composer on send.
|
|
1956
|
+
const uploadedArtifactLines = Array.from(processingFilesRef.current.values())
|
|
1957
|
+
.filter((file) => file.status === FileProcessingStatus.READY)
|
|
1958
|
+
.map((file) => {
|
|
1959
|
+
const href = file.reference?.startsWith('artifact:')
|
|
1960
|
+
? file.reference
|
|
1961
|
+
: file.artifact_path
|
|
1962
|
+
? `artifact:${file.artifact_path}`
|
|
1963
|
+
: undefined;
|
|
1964
|
+
return href ? `[${file.name}](${href})` : undefined;
|
|
1965
|
+
})
|
|
1966
|
+
.filter((line): line is string => Boolean(line));
|
|
1967
|
+
if (uploadedArtifactLines.length > 0) {
|
|
1968
|
+
messageContent = [messageContent, '', 'Uploaded artifacts:', ...uploadedArtifactLines].join('\n');
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1945
1971
|
const messageId = `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1946
1972
|
|
|
1947
1973
|
const optimisticMessage: AgentMessage = {
|
|
@@ -1973,6 +1999,7 @@ function ModernAgentConversationInner({
|
|
|
1973
1999
|
const markReceived = () => {
|
|
1974
2000
|
updateOptimisticMessageStatus(messageId, 'received');
|
|
1975
2001
|
onAttachmentsSent?.();
|
|
2002
|
+
clearProcessingFiles();
|
|
1976
2003
|
};
|
|
1977
2004
|
|
|
1978
2005
|
// When the workflow has already completed, restart it first so it resumes
|
|
@@ -1980,12 +2007,15 @@ function ModernAgentConversationInner({
|
|
|
1980
2007
|
// buffers the signal until the new run is ready to receive it. We reconnect
|
|
1981
2008
|
// the stream in place (rather than remounting via onRestart) so the existing
|
|
1982
2009
|
// timeline is preserved and the new exchange appends seamlessly at the bottom.
|
|
1983
|
-
const deliver =
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2010
|
+
const deliver = (async () => {
|
|
2011
|
+
await waitForPendingToolApprovalModeChange();
|
|
2012
|
+
if (isWorkflowTerminalRef.current) {
|
|
2013
|
+
await client.agents.restart(agentRunId);
|
|
2014
|
+
reconnectStream();
|
|
2015
|
+
}
|
|
2016
|
+
await sendUserInput();
|
|
2017
|
+
markReceived();
|
|
2018
|
+
})();
|
|
1989
2019
|
|
|
1990
2020
|
deliver
|
|
1991
2021
|
.catch((err) => {
|
|
@@ -2008,10 +2038,12 @@ function ModernAgentConversationInner({
|
|
|
2008
2038
|
getAttachedDocs,
|
|
2009
2039
|
getMessageContext,
|
|
2010
2040
|
onAttachmentsSent,
|
|
2041
|
+
clearProcessingFiles,
|
|
2011
2042
|
reconnectStream,
|
|
2012
2043
|
addOptimisticMessage,
|
|
2013
2044
|
updateOptimisticMessageStatus,
|
|
2014
2045
|
t,
|
|
2046
|
+
waitForPendingToolApprovalModeChange,
|
|
2015
2047
|
],
|
|
2016
2048
|
);
|
|
2017
2049
|
|
|
@@ -2040,12 +2072,16 @@ function ModernAgentConversationInner({
|
|
|
2040
2072
|
const [mcpDisabled, setMcpDisabled] = useState<string[] | undefined>(undefined);
|
|
2041
2073
|
useEffect(() => {
|
|
2042
2074
|
let cancelled = false;
|
|
2075
|
+
const requestVersion = toolApprovalModeChangeVersionRef.current;
|
|
2043
2076
|
client.agents
|
|
2044
2077
|
.retrieve(agentRunId)
|
|
2045
2078
|
.then((run) => {
|
|
2046
2079
|
if (!cancelled) {
|
|
2047
2080
|
setMcpDisabled(run.disabled_mcp_collections);
|
|
2048
|
-
if (
|
|
2081
|
+
if (
|
|
2082
|
+
toolApprovalModeChangeVersionRef.current === requestVersion &&
|
|
2083
|
+
(run.tool_approval_mode !== undefined || run.interactive !== undefined)
|
|
2084
|
+
) {
|
|
2049
2085
|
setToolApprovalMode(normalizeAgentToolApprovalMode(run.tool_approval_mode, run.interactive));
|
|
2050
2086
|
}
|
|
2051
2087
|
}
|
|
@@ -2081,10 +2117,14 @@ function ModernAgentConversationInner({
|
|
|
2081
2117
|
const handleToolApprovalModeChange = useCallback(
|
|
2082
2118
|
(mode: AgentToolApprovalMode) => {
|
|
2083
2119
|
const nextMode = normalizeAgentToolApprovalMode(mode, interactive);
|
|
2120
|
+
const previousMode = toolApprovalMode;
|
|
2121
|
+
toolApprovalModeChangeVersionRef.current += 1;
|
|
2084
2122
|
setToolApprovalMode(nextMode);
|
|
2085
|
-
client.agents
|
|
2123
|
+
const signalPromise = client.agents
|
|
2086
2124
|
.sendSignal(agentRunId, 'ToolApprovalModeChanged', { mode: nextMode })
|
|
2125
|
+
.then(() => undefined)
|
|
2087
2126
|
.catch((err: unknown) => {
|
|
2127
|
+
setToolApprovalMode((currentMode) => (currentMode === nextMode ? previousMode : currentMode));
|
|
2088
2128
|
toast({
|
|
2089
2129
|
status: 'error',
|
|
2090
2130
|
title: t('agent.approvalMode.changeFailed'),
|
|
@@ -2092,8 +2132,14 @@ function ModernAgentConversationInner({
|
|
|
2092
2132
|
duration: 3000,
|
|
2093
2133
|
});
|
|
2094
2134
|
});
|
|
2135
|
+
pendingToolApprovalModeChangeRef.current = signalPromise;
|
|
2136
|
+
void signalPromise.finally(() => {
|
|
2137
|
+
if (pendingToolApprovalModeChangeRef.current === signalPromise) {
|
|
2138
|
+
pendingToolApprovalModeChangeRef.current = null;
|
|
2139
|
+
}
|
|
2140
|
+
});
|
|
2095
2141
|
},
|
|
2096
|
-
[agentRunId, client, interactive, t, toast],
|
|
2142
|
+
[agentRunId, client, interactive, t, toast, toolApprovalMode],
|
|
2097
2143
|
);
|
|
2098
2144
|
|
|
2099
2145
|
// Drag and drop handlers for full-panel file upload
|
|
@@ -2418,6 +2464,7 @@ function ModernAgentConversationInner({
|
|
|
2418
2464
|
) : (
|
|
2419
2465
|
<AllMessagesMixed
|
|
2420
2466
|
messages={displayedMessages}
|
|
2467
|
+
workstreamSourceMessages={messages}
|
|
2421
2468
|
bottomRef={bottomRef as React.RefObject<HTMLDivElement>}
|
|
2422
2469
|
isCompleted={displayedIsCompleted}
|
|
2423
2470
|
plan={getActivePlan.plan}
|
|
@@ -2328,8 +2328,43 @@ class MessageErrorBoundary extends Component<{ children: ReactNode }, { hasError
|
|
|
2328
2328
|
}
|
|
2329
2329
|
}
|
|
2330
2330
|
|
|
2331
|
+
// Sort chronologically, drop document-panel events + hidden types, and dedupe adjacent
|
|
2332
|
+
// identical messages. Shared by the rendered transcript and the workstream tab derivation.
|
|
2333
|
+
function sortAndDedupeMessages(messages: AgentMessage[], hiddenMessageTypes?: AgentMessageType[]): AgentMessage[] {
|
|
2334
|
+
const filtered = messages.filter(
|
|
2335
|
+
(message) => !isDocumentPanelEventMessage(message) && !hiddenMessageTypes?.includes(message.type),
|
|
2336
|
+
);
|
|
2337
|
+
|
|
2338
|
+
const sorted = [...filtered].sort((a, b) => {
|
|
2339
|
+
const timeA = typeof a.timestamp === 'number' ? a.timestamp : new Date(a.timestamp).getTime();
|
|
2340
|
+
const timeB = typeof b.timestamp === 'number' ? b.timestamp : new Date(b.timestamp).getTime();
|
|
2341
|
+
return timeA - timeB;
|
|
2342
|
+
});
|
|
2343
|
+
|
|
2344
|
+
const deduped: AgentMessage[] = [];
|
|
2345
|
+
for (const msg of sorted) {
|
|
2346
|
+
const previous = deduped[deduped.length - 1];
|
|
2347
|
+
if (previous && shouldCollapseAdjacentRenderedMessage(previous, msg)) {
|
|
2348
|
+
continue;
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
if (previous && shouldDedupeAdjacentCompletedToolMessage(previous, msg)) {
|
|
2352
|
+
continue;
|
|
2353
|
+
}
|
|
2354
|
+
deduped.push(msg);
|
|
2355
|
+
}
|
|
2356
|
+
return deduped;
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2331
2359
|
interface AllMessagesMixedProps {
|
|
2332
2360
|
messages: AgentMessage[];
|
|
2361
|
+
/**
|
|
2362
|
+
* Full, workstream-unfiltered message set used to derive the workstream tab list, per-tab
|
|
2363
|
+
* counts, and completion status. Falls back to `messages` when omitted. The parent filters
|
|
2364
|
+
* `messages` down to the active workstream, so deriving the tab list from `messages` alone
|
|
2365
|
+
* makes the tabs collapse (and vanish once `main` is selected) as you navigate between them.
|
|
2366
|
+
*/
|
|
2367
|
+
workstreamSourceMessages?: AgentMessage[];
|
|
2333
2368
|
bottomRef: React.RefObject<HTMLDivElement>;
|
|
2334
2369
|
viewMode?: 'stacked' | 'sliding';
|
|
2335
2370
|
isCompleted?: boolean;
|
|
@@ -2397,6 +2432,7 @@ const SCROLL_THROTTLE_MS = 100; // Max 10 scrolls per second
|
|
|
2397
2432
|
|
|
2398
2433
|
function AllMessagesMixedComponent({
|
|
2399
2434
|
messages,
|
|
2435
|
+
workstreamSourceMessages,
|
|
2400
2436
|
bottomRef,
|
|
2401
2437
|
viewMode = 'stacked',
|
|
2402
2438
|
isCompleted = false,
|
|
@@ -2536,36 +2572,26 @@ function AllMessagesMixedComponent({
|
|
|
2536
2572
|
|
|
2537
2573
|
// Sort all messages chronologically and dedupe adjacent identical messages
|
|
2538
2574
|
// Low-signal messages are suppressed at the source (server-side) via shouldSuppressLowSignalMessage
|
|
2539
|
-
const sortedMessages = React.useMemo(
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
const sorted = [...filtered].sort((a, b) => {
|
|
2545
|
-
const timeA = typeof a.timestamp === 'number' ? a.timestamp : new Date(a.timestamp).getTime();
|
|
2546
|
-
const timeB = typeof b.timestamp === 'number' ? b.timestamp : new Date(b.timestamp).getTime();
|
|
2547
|
-
return timeA - timeB;
|
|
2548
|
-
});
|
|
2549
|
-
|
|
2550
|
-
const deduped: AgentMessage[] = [];
|
|
2551
|
-
for (const msg of sorted) {
|
|
2552
|
-
const previous = deduped[deduped.length - 1];
|
|
2553
|
-
if (previous && shouldCollapseAdjacentRenderedMessage(previous, msg)) {
|
|
2554
|
-
continue;
|
|
2555
|
-
}
|
|
2575
|
+
const sortedMessages = React.useMemo(
|
|
2576
|
+
() => sortAndDedupeMessages(messages, hiddenMessageTypes),
|
|
2577
|
+
[messages, hiddenMessageTypes],
|
|
2578
|
+
);
|
|
2556
2579
|
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2580
|
+
// The workstream tabs are navigation over the WHOLE conversation, so derive them from the
|
|
2581
|
+
// unfiltered source rather than `messages` (which the parent filters to the active workstream).
|
|
2582
|
+
// Falling back to `sortedMessages` keeps callers that don't pass the source working unchanged.
|
|
2583
|
+
const workstreamSourceSorted = React.useMemo(
|
|
2584
|
+
() =>
|
|
2585
|
+
workstreamSourceMessages
|
|
2586
|
+
? sortAndDedupeMessages(workstreamSourceMessages, hiddenMessageTypes)
|
|
2587
|
+
: sortedMessages,
|
|
2588
|
+
[workstreamSourceMessages, hiddenMessageTypes, sortedMessages],
|
|
2589
|
+
);
|
|
2564
2590
|
|
|
2565
2591
|
const workstreams = React.useMemo(() => {
|
|
2566
|
-
const extractedWorkstreams = extractWorkstreams(
|
|
2592
|
+
const extractedWorkstreams = extractWorkstreams(workstreamSourceSorted);
|
|
2567
2593
|
|
|
2568
|
-
|
|
2594
|
+
workstreamSourceSorted.forEach((message) => {
|
|
2569
2595
|
const details = getWorkstreamLaunchDetails(message) ?? getWorkstreamActivityDetails(message);
|
|
2570
2596
|
if (!details) return;
|
|
2571
2597
|
extractedWorkstreams.set(
|
|
@@ -2575,7 +2601,7 @@ function AllMessagesMixedComponent({
|
|
|
2575
2601
|
});
|
|
2576
2602
|
|
|
2577
2603
|
return extractedWorkstreams;
|
|
2578
|
-
}, [
|
|
2604
|
+
}, [workstreamSourceSorted]);
|
|
2579
2605
|
|
|
2580
2606
|
const activeWorkstreamName = React.useMemo(() => {
|
|
2581
2607
|
if (activeWorkstream === 'all') return undefined;
|
|
@@ -2616,17 +2642,17 @@ function AllMessagesMixedComponent({
|
|
|
2616
2642
|
}
|
|
2617
2643
|
}, [activeWorkstream, workstreams, setActiveWorkstream]);
|
|
2618
2644
|
|
|
2619
|
-
// Count messages per workstream
|
|
2645
|
+
// Count messages per workstream (from the full source so counts don't shrink to the active tab)
|
|
2620
2646
|
const workstreamCounts = React.useMemo(() => {
|
|
2621
2647
|
const counts = new Map<string, number>();
|
|
2622
|
-
counts.set('all',
|
|
2648
|
+
counts.set('all', workstreamSourceSorted.length);
|
|
2623
2649
|
|
|
2624
2650
|
// Count main messages
|
|
2625
|
-
const mainMessages = filterMessagesByWorkstream(
|
|
2651
|
+
const mainMessages = filterMessagesByWorkstream(workstreamSourceSorted, 'main');
|
|
2626
2652
|
counts.set('main', mainMessages.length);
|
|
2627
2653
|
|
|
2628
2654
|
// Count other workstreams
|
|
2629
|
-
|
|
2655
|
+
workstreamSourceSorted.forEach((msg) => {
|
|
2630
2656
|
const workstreamId = getWorkstreamId(msg);
|
|
2631
2657
|
if (workstreamId !== 'main') {
|
|
2632
2658
|
counts.set(workstreamId, (counts.get(workstreamId) || 0) + 1);
|
|
@@ -2634,7 +2660,7 @@ function AllMessagesMixedComponent({
|
|
|
2634
2660
|
});
|
|
2635
2661
|
|
|
2636
2662
|
return counts;
|
|
2637
|
-
}, [
|
|
2663
|
+
}, [workstreamSourceSorted]);
|
|
2638
2664
|
|
|
2639
2665
|
// Filter messages based on active workstream
|
|
2640
2666
|
const displayMessages = React.useMemo(() => {
|
|
@@ -2869,7 +2895,7 @@ function AllMessagesMixedComponent({
|
|
|
2869
2895
|
// Group messages by workstream
|
|
2870
2896
|
const workstreamMessages = new Map<string, AgentMessage[]>();
|
|
2871
2897
|
|
|
2872
|
-
|
|
2898
|
+
workstreamSourceSorted.forEach((message) => {
|
|
2873
2899
|
const workstreamId = getWorkstreamId(message);
|
|
2874
2900
|
if (!workstreamMessages.has(workstreamId)) {
|
|
2875
2901
|
workstreamMessages.set(workstreamId, []);
|
|
@@ -2905,7 +2931,7 @@ function AllMessagesMixedComponent({
|
|
|
2905
2931
|
}
|
|
2906
2932
|
|
|
2907
2933
|
return statusMap;
|
|
2908
|
-
}, [
|
|
2934
|
+
}, [workstreamSourceSorted]);
|
|
2909
2935
|
|
|
2910
2936
|
return (
|
|
2911
2937
|
<div
|
|
@@ -127,9 +127,9 @@ function InlineSlidingPlanPanelComponent({
|
|
|
127
127
|
: `task-${taskGoal}-${task.status || 'pending'}`;
|
|
128
128
|
|
|
129
129
|
let status: 'pending' | 'in_progress' | 'completed' | 'skipped' = task.status || 'pending';
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
status =
|
|
130
|
+
const wsStatus = workstreamStatus.get(taskId);
|
|
131
|
+
if (wsStatus !== undefined) {
|
|
132
|
+
status = wsStatus;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
let StatusIcon = Circle;
|