@vertesia/ui 1.4.0-dev.20260615.051508Z → 1.4.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/lib/core/components/shadcn/dropdown.d.ts.map +1 -1
- package/lib/core/components/shadcn/dropdown.js +6 -2
- package/lib/core/components/shadcn/dropdown.js.map +1 -1
- package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/core/components/shadcn/filters/filterBar.js +9 -2
- package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/core/components/shadcn/modal/ConfirmModal.d.ts +16 -1
- package/lib/core/components/shadcn/modal/ConfirmModal.d.ts.map +1 -1
- package/lib/core/components/shadcn/modal/ConfirmModal.js +25 -3
- package/lib/core/components/shadcn/modal/ConfirmModal.js.map +1 -1
- package/lib/core/components/shadcn/modal/dialog.js +1 -1
- package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
- package/lib/core/components/shadcn/popover.d.ts.map +1 -1
- package/lib/core/components/shadcn/popover.js +3 -1
- package/lib/core/components/shadcn/popover.js.map +1 -1
- package/lib/core/components/shadcn/switch.js +3 -3
- package/lib/core/components/shadcn/switch.js.map +1 -1
- package/lib/core/components/shadcn/tabs.js +1 -1
- package/lib/core/components/shadcn/tabs.js.map +1 -1
- package/lib/core/components/shadcn/tooltip.d.ts.map +1 -1
- package/lib/core/components/shadcn/tooltip.js +3 -1
- package/lib/core/components/shadcn/tooltip.js.map +1 -1
- package/lib/env/index.d.ts +0 -19
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +0 -6
- package/lib/env/index.js.map +1 -1
- package/lib/features/agent/PayloadBuilder.d.ts +4 -0
- package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
- package/lib/features/agent/PayloadBuilder.js +16 -0
- package/lib/features/agent/PayloadBuilder.js.map +1 -1
- package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts +10 -0
- package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts.map +1 -0
- package/lib/features/agent/chat/AgentApprovalModeSelector.js +50 -0
- package/lib/features/agent/chat/AgentApprovalModeSelector.js.map +1 -0
- package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts +2 -1
- package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentChatFixtureReplay.js +3 -3
- package/lib/features/agent/chat/AgentChatFixtureReplay.js.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +5 -2
- package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRequestInputOverlay.js +41 -7
- package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/features/agent/chat/AgentRightPanel.js +133 -12
- package/lib/features/agent/chat/AgentRightPanel.js.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/ArtifactsTab.d.ts.map +1 -1
- package/lib/features/agent/chat/ArtifactsTab.js +11 -65
- package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
- package/lib/features/agent/chat/AskUserWidget.d.ts +3 -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 +10 -2
- package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentConversation.js +526 -117
- package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts +8 -0
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +19 -0
- package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -2
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +551 -92
- package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +7 -6
- package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/Header.js +2 -2
- package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts +8 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js +61 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js.map +1 -0
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +15 -2
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +28 -38
- package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -2
- package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +2 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts +5 -0
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +59 -4
- package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +2 -2
- package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +9 -0
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +180 -0
- package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
- package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
- package/lib/features/agent/chat/ModernAgentOutput/utils.js +92 -2
- package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
- package/lib/features/agent/chat/clipboardFiles.d.ts +15 -0
- package/lib/features/agent/chat/clipboardFiles.d.ts.map +1 -0
- package/lib/features/agent/chat/clipboardFiles.js +35 -0
- package/lib/features/agent/chat/clipboardFiles.js.map +1 -0
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts +6 -0
- package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useAgentStream.js +218 -37
- package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/features/agent/chat/hooks/useArtifacts.d.ts +1 -8
- package/lib/features/agent/chat/hooks/useArtifacts.d.ts.map +1 -1
- package/lib/features/agent/chat/hooks/useArtifacts.js +10 -28
- package/lib/features/agent/chat/hooks/useArtifacts.js.map +1 -1
- package/lib/features/agent/chat/index.d.ts +2 -1
- package/lib/features/agent/chat/index.d.ts.map +1 -1
- package/lib/features/agent/chat/index.js +2 -1
- package/lib/features/agent/chat/index.js.map +1 -1
- package/lib/features/agent/chat/workstreams.d.ts +1 -0
- package/lib/features/agent/chat/workstreams.d.ts.map +1 -1
- package/lib/features/agent/chat/workstreams.js +28 -0
- package/lib/features/agent/chat/workstreams.js.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts +10 -1
- package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/AgentRunnerFacetsNav.js +6 -3
- package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.d.ts +10 -1
- package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/CollectionsFacetsNav.js +14 -5
- package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts +10 -1
- package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/PromptsFacetsNav.js +14 -5
- package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
- package/lib/features/facets/RunsFacetsNav.d.ts +10 -1
- package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/features/facets/RunsFacetsNav.js +14 -5
- package/lib/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/features/index.d.ts +0 -1
- package/lib/features/index.d.ts.map +1 -1
- package/lib/features/index.js +0 -1
- package/lib/features/index.js.map +1 -1
- package/lib/features/oauth/McpConnectionsButton.d.ts +30 -0
- package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -0
- package/lib/features/oauth/McpConnectionsButton.js +70 -0
- package/lib/features/oauth/McpConnectionsButton.js.map +1 -0
- package/lib/features/oauth/McpConnectionsDialog.d.ts +25 -0
- package/lib/features/oauth/McpConnectionsDialog.d.ts.map +1 -0
- package/lib/features/oauth/McpConnectionsDialog.js +26 -0
- package/lib/features/oauth/McpConnectionsDialog.js.map +1 -0
- package/lib/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -1
- package/lib/features/oauth/RemoteMcpConnectionButton.js +14 -6
- package/lib/features/oauth/RemoteMcpConnectionButton.js.map +1 -1
- package/lib/features/oauth/index.d.ts +3 -0
- package/lib/features/oauth/index.d.ts.map +1 -1
- package/lib/features/oauth/index.js +3 -0
- package/lib/features/oauth/index.js.map +1 -1
- package/lib/features/oauth/useMcpConnections.d.ts +44 -0
- package/lib/features/oauth/useMcpConnections.d.ts.map +1 -0
- package/lib/features/oauth/useMcpConnections.js +168 -0
- package/lib/features/oauth/useMcpConnections.js.map +1 -0
- package/lib/features/permissions/UserPermissionsProvider.d.ts +4 -6
- package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
- package/lib/features/permissions/UserPermissionsProvider.js +40 -42
- package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
- package/lib/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentPreviewPanel.js +2 -1
- package/lib/features/store/objects/DocumentPreviewPanel.js.map +1 -1
- package/lib/features/store/objects/DocumentQuickFilter.d.ts +23 -0
- package/lib/features/store/objects/DocumentQuickFilter.d.ts.map +1 -0
- package/lib/features/store/objects/DocumentQuickFilter.js +30 -0
- package/lib/features/store/objects/DocumentQuickFilter.js.map +1 -0
- package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentSearchResults.js +17 -1
- package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +17 -74
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +7 -1
- package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
- package/lib/features/store/objects/layout/DocumentTableColumn.js +27 -3
- package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
- package/lib/features/store/objects/layout/documentLayout.js +1 -1
- package/lib/features/store/objects/layout/renderers.d.ts +2 -1
- package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/features/store/objects/layout/renderers.js +27 -20
- package/lib/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesSearch.js +4 -1
- package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts +2 -1
- package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
- package/lib/features/store/types/ContentObjectTypesTable.js +8 -3
- package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/i18n/instance.d.ts.map +1 -1
- package/lib/i18n/instance.js +1 -0
- package/lib/i18n/instance.js.map +1 -1
- package/lib/i18n/locales/ar.json +72 -45
- package/lib/i18n/locales/de.json +65 -34
- package/lib/i18n/locales/en.json +63 -47
- package/lib/i18n/locales/es.json +65 -35
- package/lib/i18n/locales/fr.json +65 -35
- package/lib/i18n/locales/it.json +72 -42
- package/lib/i18n/locales/ja.json +72 -41
- package/lib/i18n/locales/ko.json +72 -41
- package/lib/i18n/locales/pt.json +72 -42
- package/lib/i18n/locales/ru.json +72 -43
- package/lib/i18n/locales/tr.json +72 -41
- package/lib/i18n/locales/zh-TW.json +72 -41
- package/lib/i18n/locales/zh.json +72 -41
- package/lib/session/UserSession.d.ts +0 -6
- package/lib/session/UserSession.d.ts.map +1 -1
- package/lib/session/UserSession.js +0 -15
- package/lib/session/UserSession.js.map +1 -1
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +39 -98
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/composable.d.ts.map +1 -1
- package/lib/session/auth/composable.js +3 -33
- package/lib/session/auth/composable.js.map +1 -1
- package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
- package/lib/shell/login/SignInPrimitives.js +3 -2
- package/lib/shell/login/SignInPrimitives.js.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-i18n.js +1 -1
- package/lib/vertesia-ui-i18n.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/lib/widgets/schema-editor/editor/Editable.js +1 -1
- package/lib/widgets/schema-editor/editor/Editable.js.map +1 -1
- package/llms.txt +70 -70
- package/package.json +35 -32
- package/src/core/components/shadcn/dropdown.tsx +2 -0
- package/src/core/components/shadcn/filters/filterBar.tsx +9 -2
- package/src/core/components/shadcn/modal/ConfirmModal.tsx +65 -3
- package/src/core/components/shadcn/modal/dialog.tsx +1 -1
- package/src/core/components/shadcn/popover.tsx +1 -0
- package/src/core/components/shadcn/switch.tsx +4 -4
- package/src/core/components/shadcn/tabs.tsx +1 -1
- package/src/core/components/shadcn/tooltip.tsx +1 -0
- package/src/env/index.ts +0 -24
- package/src/features/agent/PayloadBuilder.tsx +18 -0
- package/src/features/agent/chat/AgentApprovalModeSelector.tsx +130 -0
- package/src/features/agent/chat/AgentChatFixtureReplay.test.tsx +22 -2
- package/src/features/agent/chat/AgentChatFixtureReplay.tsx +33 -27
- package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +122 -0
- package/src/features/agent/chat/AgentRequestInputOverlay.tsx +91 -17
- package/src/features/agent/chat/AgentRightPanel.tsx +238 -50
- package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -1
- package/src/features/agent/chat/ArtifactsTab.tsx +21 -155
- package/src/features/agent/chat/AskUserWidget.tsx +6 -2
- package/src/features/agent/chat/ModernAgentConversation.test.tsx +1157 -47
- package/src/features/agent/chat/ModernAgentConversation.tsx +703 -136
- package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +74 -0
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +1420 -126
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +934 -111
- package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +31 -40
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +28 -28
- package/src/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.tsx +83 -0
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +38 -2
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +121 -98
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +7 -1
- package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +3 -3
- package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +82 -2
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +2 -2
- package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +216 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +149 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.ts +103 -2
- package/src/features/agent/chat/clipboardFiles.ts +33 -0
- package/src/features/agent/chat/hooks/useAgentStream.test.tsx +355 -4
- package/src/features/agent/chat/hooks/useAgentStream.ts +270 -43
- package/src/features/agent/chat/hooks/useArtifacts.ts +11 -44
- package/src/features/agent/chat/index.ts +10 -1
- package/src/features/agent/chat/workstreams.ts +42 -0
- package/src/features/facets/AgentRunnerFacetsNav.tsx +23 -3
- package/src/features/facets/CollectionsFacetsNav.tsx +30 -5
- package/src/features/facets/PromptsFacetsNav.tsx +30 -5
- package/src/features/facets/RunsFacetsNav.tsx +32 -5
- package/src/features/index.ts +0 -1
- package/src/features/oauth/McpConnectionsButton.test.tsx +248 -0
- package/src/features/oauth/McpConnectionsButton.tsx +269 -0
- package/src/features/oauth/McpConnectionsDialog.tsx +142 -0
- package/src/features/oauth/RemoteMcpConnectionButton.tsx +37 -14
- package/src/features/oauth/index.ts +3 -0
- package/src/features/oauth/useMcpConnections.test.ts +94 -0
- package/src/features/oauth/useMcpConnections.ts +210 -0
- package/src/features/permissions/UserPermissionsProvider.tsx +41 -59
- package/src/features/store/objects/DocumentPreviewPanel.tsx +4 -2
- package/src/features/store/objects/DocumentQuickFilter.tsx +72 -0
- package/src/features/store/objects/DocumentSearchResults.tsx +30 -11
- package/src/features/store/objects/components/ContentOverview.tsx +30 -99
- package/src/features/store/objects/layout/DocumentTableColumn.tsx +29 -4
- package/src/features/store/objects/layout/documentLayout.tsx +1 -1
- package/src/features/store/objects/layout/renderers.tsx +80 -20
- package/src/features/store/types/ContentObjectTypesSearch.tsx +7 -1
- package/src/features/store/types/ContentObjectTypesTable.tsx +34 -4
- package/src/i18n/instance.ts +1 -0
- package/src/i18n/locales/ar.json +72 -45
- package/src/i18n/locales/de.json +65 -34
- package/src/i18n/locales/en.json +63 -47
- package/src/i18n/locales/es.json +65 -35
- package/src/i18n/locales/fr.json +65 -35
- package/src/i18n/locales/it.json +72 -42
- package/src/i18n/locales/ja.json +72 -41
- package/src/i18n/locales/ko.json +72 -41
- package/src/i18n/locales/pt.json +72 -42
- package/src/i18n/locales/ru.json +72 -43
- package/src/i18n/locales/tr.json +72 -41
- package/src/i18n/locales/zh-TW.json +72 -41
- package/src/i18n/locales/zh.json +72 -41
- package/src/i18n/rtl.test.ts +57 -1
- package/src/session/UserSession.ts +0 -16
- package/src/session/UserSessionProvider.tsx +51 -123
- package/src/session/auth/composable.ts +3 -34
- package/src/shell/login/SignInPrimitives.tsx +3 -2
- package/src/widgets/schema-editor/editor/Editable.tsx +1 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts +0 -73
- package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +0 -1
- package/lib/features/document-viewer/UniversalDocumentViewer.js +0 -415
- package/lib/features/document-viewer/UniversalDocumentViewer.js.map +0 -1
- package/lib/features/document-viewer/index.d.ts +0 -2
- package/lib/features/document-viewer/index.d.ts.map +0 -1
- package/lib/features/document-viewer/index.js +0 -2
- package/lib/features/document-viewer/index.js.map +0 -1
- package/src/features/document-viewer/UniversalDocumentViewer.test.tsx +0 -123
- package/src/features/document-viewer/UniversalDocumentViewer.tsx +0 -746
- package/src/features/document-viewer/index.ts +0 -1
- package/src/session/auth/composable.test.ts +0 -79
|
@@ -100,6 +100,70 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
100
100
|
vi.useRealTimers();
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
+
it('renders delivery status on user bubbles in summary view', () => {
|
|
104
|
+
renderSummary([
|
|
105
|
+
makeMessage({
|
|
106
|
+
timestamp: 1_000,
|
|
107
|
+
type: AgentMessageType.QUESTION,
|
|
108
|
+
message: 'Find Japan news.',
|
|
109
|
+
details: {
|
|
110
|
+
_deliveryStatus: 'consumed',
|
|
111
|
+
ack: 'message-1',
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
expect(screen.getByLabelText('Message consumed')).not.toBeNull();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('renders delivery status on user messages in stacked view', () => {
|
|
120
|
+
renderStacked([
|
|
121
|
+
makeMessage({
|
|
122
|
+
timestamp: 1_000,
|
|
123
|
+
type: AgentMessageType.QUESTION,
|
|
124
|
+
message: 'Find Japan news.',
|
|
125
|
+
details: {
|
|
126
|
+
_deliveryStatus: 'sending',
|
|
127
|
+
_messageId: 'message-1',
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
expect(screen.getByLabelText('Sending message')).not.toBeNull();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('renders an acked stop marker as a right-aligned consumed status row', () => {
|
|
136
|
+
renderSummary(
|
|
137
|
+
[
|
|
138
|
+
makeMessage({
|
|
139
|
+
timestamp: 2_000,
|
|
140
|
+
type: AgentMessageType.THOUGHT,
|
|
141
|
+
message: 'Searching',
|
|
142
|
+
details: {
|
|
143
|
+
tool: 'web_search',
|
|
144
|
+
tool_status: 'running',
|
|
145
|
+
tool_run_id: 'tool-1',
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
makeMessage({
|
|
149
|
+
timestamp: 77_000,
|
|
150
|
+
type: AgentMessageType.IDLE,
|
|
151
|
+
message: 'Stopped. Waiting for your command...',
|
|
152
|
+
details: {
|
|
153
|
+
ack: 'stop-1',
|
|
154
|
+
status_reason: 'user_stopped',
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
],
|
|
158
|
+
true,
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
expect(screen.getByTestId('summary-stopped-message')).not.toBeNull();
|
|
162
|
+
expect(screen.getByText('You stopped after 1m 15s')).not.toBeNull();
|
|
163
|
+
expect(screen.getByLabelText('Message consumed')).not.toBeNull();
|
|
164
|
+
expect(screen.queryByText('Stopped. Waiting for your command...')).toBeNull();
|
|
165
|
+
});
|
|
166
|
+
|
|
103
167
|
it('renders completed tool activity as a collapsed Worked row that expands to tool details', () => {
|
|
104
168
|
renderSummary(
|
|
105
169
|
[
|
|
@@ -138,16 +202,111 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
138
202
|
fireEvent.click(workedRow);
|
|
139
203
|
|
|
140
204
|
expect(workedRow.getAttribute('aria-expanded')).toBe('true');
|
|
141
|
-
expect(screen.
|
|
205
|
+
expect(screen.queryByText('Search')).toBeNull();
|
|
142
206
|
expect(screen.getByText('Japan news')).not.toBeNull();
|
|
143
207
|
|
|
144
|
-
const toolRow = screen.getByRole('button', { name: /
|
|
208
|
+
const toolRow = screen.getByRole('button', { name: /Japan news/ });
|
|
145
209
|
expect(toolRow.getAttribute('aria-expanded')).toBe('false');
|
|
146
210
|
fireEvent.click(toolRow);
|
|
147
211
|
|
|
212
|
+
expect(screen.getByText('Tool')).not.toBeNull();
|
|
213
|
+
expect(screen.getByText('web_search_serper')).not.toBeNull();
|
|
214
|
+
expect(screen.getByText('Time')).not.toBeNull();
|
|
148
215
|
expect(screen.getByText('Found 5 results')).not.toBeNull();
|
|
149
216
|
});
|
|
150
217
|
|
|
218
|
+
it('keeps same-iteration tool detail panels matched to their own tool identity', () => {
|
|
219
|
+
renderSummary(
|
|
220
|
+
[
|
|
221
|
+
makeMessage({
|
|
222
|
+
timestamp: 1_000,
|
|
223
|
+
type: AgentMessageType.QUESTION,
|
|
224
|
+
message: 'Launch France and Japan news workstreams.',
|
|
225
|
+
}),
|
|
226
|
+
makeMessage({
|
|
227
|
+
timestamp: 2_000,
|
|
228
|
+
message:
|
|
229
|
+
'Updating the project plan to mark both workstream launches as completed and the monitoring phase as in-progress...',
|
|
230
|
+
details: {
|
|
231
|
+
event_class: 'activity',
|
|
232
|
+
tool: 'update_plan',
|
|
233
|
+
tool_run_id: 'update_plan',
|
|
234
|
+
tool_use_id: 'update_plan',
|
|
235
|
+
tool_iteration: 7,
|
|
236
|
+
tool_status: 'running',
|
|
237
|
+
tool_event: 'started',
|
|
238
|
+
activity_group_id: 'activity-7',
|
|
239
|
+
message_to_human:
|
|
240
|
+
'Updating the project plan to mark both workstream launches as completed and the monitoring phase as in-progress...',
|
|
241
|
+
},
|
|
242
|
+
}),
|
|
243
|
+
makeMessage({
|
|
244
|
+
timestamp: 2_500,
|
|
245
|
+
message: 'Launching the Japan news headline gathering workstream...',
|
|
246
|
+
details: {
|
|
247
|
+
event_class: 'activity',
|
|
248
|
+
tool: 'launch_workstream',
|
|
249
|
+
tool_run_id: 'launch_workstream',
|
|
250
|
+
tool_use_id: 'launch_workstream',
|
|
251
|
+
tool_iteration: 7,
|
|
252
|
+
tool_status: 'running',
|
|
253
|
+
tool_event: 'started',
|
|
254
|
+
activity_group_id: 'activity-7',
|
|
255
|
+
message_to_human: 'Launching the Japan news headline gathering workstream...',
|
|
256
|
+
},
|
|
257
|
+
}),
|
|
258
|
+
makeMessage({
|
|
259
|
+
timestamp: 3_000,
|
|
260
|
+
type: AgentMessageType.UPDATE,
|
|
261
|
+
message: 'Updating 3 tasks of our plan.',
|
|
262
|
+
details: {
|
|
263
|
+
updates: [
|
|
264
|
+
{ task_id: 1, status: 'completed' },
|
|
265
|
+
{ task_id: 2, status: 'completed' },
|
|
266
|
+
{ task_id: 3, status: 'in_progress' },
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
}),
|
|
270
|
+
makeMessage({
|
|
271
|
+
timestamp: 3_001,
|
|
272
|
+
type: AgentMessageType.PLAN,
|
|
273
|
+
message:
|
|
274
|
+
'Both news workstreams (France and Japan) have been successfully launched. We are now entering the monitoring phase.',
|
|
275
|
+
details: {
|
|
276
|
+
plan: [
|
|
277
|
+
{ id: 1, status: 'completed', goal: 'Launch France workstream' },
|
|
278
|
+
{ id: 2, status: 'completed', goal: 'Launch Japan workstream' },
|
|
279
|
+
{ id: 3, status: 'in_progress', goal: 'Monitor both workstreams' },
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
makeMessage({
|
|
284
|
+
timestamp: 4_000,
|
|
285
|
+
type: AgentMessageType.ANSWER,
|
|
286
|
+
message: 'Done.',
|
|
287
|
+
}),
|
|
288
|
+
],
|
|
289
|
+
true,
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for\s*2s/ }));
|
|
293
|
+
|
|
294
|
+
const updatePlanRow = screen.getByRole('button', { name: /Updating the project plan/ });
|
|
295
|
+
expect(screen.queryByRole('button', { name: /Updating 3 tasks/ })).toBeNull();
|
|
296
|
+
expect(screen.queryByRole('button', { name: /Both news workstreams/ })).toBeNull();
|
|
297
|
+
|
|
298
|
+
fireEvent.click(updatePlanRow);
|
|
299
|
+
|
|
300
|
+
expect(screen.getByText('update_plan')).not.toBeNull();
|
|
301
|
+
expect(screen.queryByText('launch_workstream')).toBeNull();
|
|
302
|
+
expect(screen.getByText(/"updates"/)).not.toBeNull();
|
|
303
|
+
|
|
304
|
+
const launchWorkstreamRow = screen.getByRole('button', { name: /Launching the Japan news/ });
|
|
305
|
+
fireEvent.click(launchWorkstreamRow);
|
|
306
|
+
|
|
307
|
+
expect(screen.getByText('launch_workstream')).not.toBeNull();
|
|
308
|
+
});
|
|
309
|
+
|
|
151
310
|
it('renders active tool activity as an expanded Working row', () => {
|
|
152
311
|
renderSummary([
|
|
153
312
|
makeMessage({
|
|
@@ -169,11 +328,11 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
169
328
|
|
|
170
329
|
const workingRow = screen.getByRole('button', { name: /Working\s*for\s*1s/ });
|
|
171
330
|
expect(workingRow.getAttribute('aria-expanded')).toBe('true');
|
|
172
|
-
expect(screen.
|
|
331
|
+
expect(screen.queryByText('Bash')).toBeNull();
|
|
173
332
|
expect(screen.getByText('Running build')).not.toBeNull();
|
|
174
333
|
expect(screen.queryByText('$ pnpm run build')).toBeNull();
|
|
175
334
|
|
|
176
|
-
const toolRow = screen.getByRole('button', { name: /
|
|
335
|
+
const toolRow = screen.getByRole('button', { name: /Running build/ });
|
|
177
336
|
fireEvent.click(toolRow);
|
|
178
337
|
|
|
179
338
|
expect(screen.queryByText('Shell')).toBeNull();
|
|
@@ -181,6 +340,164 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
181
340
|
expect(screen.queryByText('Running')).toBeNull();
|
|
182
341
|
});
|
|
183
342
|
|
|
343
|
+
it('keeps a pending tool approval prompt inside the active work row', () => {
|
|
344
|
+
const onSendMessage = vi.fn();
|
|
345
|
+
|
|
346
|
+
renderSummary(
|
|
347
|
+
[
|
|
348
|
+
makeMessage({
|
|
349
|
+
timestamp: Date.now() - 4_000,
|
|
350
|
+
type: AgentMessageType.QUESTION,
|
|
351
|
+
message: 'Create a news report.',
|
|
352
|
+
}),
|
|
353
|
+
makeMessage({
|
|
354
|
+
timestamp: Date.now() - 3_000,
|
|
355
|
+
message: 'Creating document from artifact...',
|
|
356
|
+
details: {
|
|
357
|
+
event_class: 'activity',
|
|
358
|
+
tool: 'create_document',
|
|
359
|
+
tool_run_id: 'create_document',
|
|
360
|
+
tool_use_id: 'create_document',
|
|
361
|
+
tool_status: 'running',
|
|
362
|
+
tool_event: 'started',
|
|
363
|
+
activity_group_id: 'activity-approval',
|
|
364
|
+
message_to_human: 'Creating document from artifact...',
|
|
365
|
+
},
|
|
366
|
+
}),
|
|
367
|
+
makeMessage({
|
|
368
|
+
timestamp: Date.now() - 1_000,
|
|
369
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
370
|
+
message: 'Approve Create Document: name News Headlines Today?',
|
|
371
|
+
details: {
|
|
372
|
+
tool_approval: {
|
|
373
|
+
approval_key: 'create_document:name:News Headlines Today',
|
|
374
|
+
tool_name: 'create_document',
|
|
375
|
+
tool_title: 'Create Document',
|
|
376
|
+
target: 'name:News Headlines Today',
|
|
377
|
+
},
|
|
378
|
+
ux: {
|
|
379
|
+
options: [
|
|
380
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
381
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
382
|
+
{ id: 'deny', label: 'Deny' },
|
|
383
|
+
],
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
}),
|
|
387
|
+
],
|
|
388
|
+
false,
|
|
389
|
+
new Map(),
|
|
390
|
+
{ onSendMessage },
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
expect(screen.queryByRole('button', { name: /Worked\s*for/ })).toBeNull();
|
|
394
|
+
const workingRow = screen.getByRole('button', { name: /Working\s*for/ });
|
|
395
|
+
expect(workingRow.getAttribute('aria-expanded')).toBe('true');
|
|
396
|
+
expect(screen.getByText('Creating document from artifact...')).not.toBeNull();
|
|
397
|
+
expect(screen.getByText('Approve Create Document: News Headlines Today?')).not.toBeNull();
|
|
398
|
+
expect(screen.queryByText('Approve Create Document: name News Headlines Today?')).toBeNull();
|
|
399
|
+
|
|
400
|
+
fireEvent.click(screen.getByRole('button', { name: /Allow once/ }));
|
|
401
|
+
|
|
402
|
+
expect(onSendMessage).toHaveBeenCalledWith('allow_once');
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('keeps an approved tool approval continuation in the same active work row', () => {
|
|
406
|
+
renderSummary(
|
|
407
|
+
[
|
|
408
|
+
makeMessage({
|
|
409
|
+
timestamp: 1_000,
|
|
410
|
+
type: AgentMessageType.QUESTION,
|
|
411
|
+
message: 'Create a news report.',
|
|
412
|
+
}),
|
|
413
|
+
makeMessage({
|
|
414
|
+
timestamp: 2_000,
|
|
415
|
+
message: 'Creating the permanent news report document in the project repository...',
|
|
416
|
+
details: {
|
|
417
|
+
event_class: 'activity',
|
|
418
|
+
tool: 'create_document',
|
|
419
|
+
tool_run_id: 'create_document',
|
|
420
|
+
tool_use_id: 'create_document',
|
|
421
|
+
tool_status: 'running',
|
|
422
|
+
tool_event: 'started',
|
|
423
|
+
activity_group_id: 'activity-approval',
|
|
424
|
+
message_to_human: 'Creating the permanent news report document in the project repository...',
|
|
425
|
+
},
|
|
426
|
+
}),
|
|
427
|
+
makeMessage({
|
|
428
|
+
timestamp: 3_000,
|
|
429
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
430
|
+
message: 'Approve Create Document: Japan Daily News Report - June 22, 2026?',
|
|
431
|
+
details: {
|
|
432
|
+
tool_approval: {
|
|
433
|
+
approval_key: 'create_document:name:Japan Daily News Report - June 22, 2026',
|
|
434
|
+
tool_name: 'create_document',
|
|
435
|
+
tool_title: 'Create Document',
|
|
436
|
+
target: 'name:Japan Daily News Report - June 22, 2026',
|
|
437
|
+
},
|
|
438
|
+
ux: {
|
|
439
|
+
options: [
|
|
440
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
441
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
442
|
+
{ id: 'deny', label: 'Deny' },
|
|
443
|
+
],
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
}),
|
|
447
|
+
makeMessage({
|
|
448
|
+
timestamp: 4_000,
|
|
449
|
+
type: AgentMessageType.QUESTION,
|
|
450
|
+
message: 'allow_for_run',
|
|
451
|
+
}),
|
|
452
|
+
],
|
|
453
|
+
false,
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
expect(screen.queryByRole('button', { name: /Worked\s*for/ })).toBeNull();
|
|
457
|
+
expect(screen.getAllByRole('button', { name: /Working\s*for/ })).toHaveLength(1);
|
|
458
|
+
expect(
|
|
459
|
+
screen.getByText('Creating the permanent news report document in the project repository...'),
|
|
460
|
+
).not.toBeNull();
|
|
461
|
+
expect(screen.queryByText('Approve Create Document: Japan Daily News Report - June 22, 2026?')).toBeNull();
|
|
462
|
+
expect(screen.queryByText('allow_for_run')).toBeNull();
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
it('expands tool rows that only have metadata', () => {
|
|
466
|
+
renderSummary(
|
|
467
|
+
[
|
|
468
|
+
makeMessage({
|
|
469
|
+
timestamp: 1_000,
|
|
470
|
+
type: AgentMessageType.QUESTION,
|
|
471
|
+
message: 'Warm the cache.',
|
|
472
|
+
}),
|
|
473
|
+
makeMessage({
|
|
474
|
+
timestamp: 2_000,
|
|
475
|
+
message: 'Loading cache',
|
|
476
|
+
details: {
|
|
477
|
+
tool: 'cache_loader',
|
|
478
|
+
tool_status: 'completed',
|
|
479
|
+
tool_run_id: 'tool-cache',
|
|
480
|
+
},
|
|
481
|
+
}),
|
|
482
|
+
],
|
|
483
|
+
true,
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
487
|
+
|
|
488
|
+
const toolRow = screen.getByRole('button', { name: /Loading cache/ });
|
|
489
|
+
expect(toolRow.getAttribute('aria-expanded')).toBe('false');
|
|
490
|
+
expect(screen.queryByText('cache_loader')).toBeNull();
|
|
491
|
+
|
|
492
|
+
fireEvent.click(toolRow);
|
|
493
|
+
|
|
494
|
+
expect(toolRow.getAttribute('aria-expanded')).toBe('true');
|
|
495
|
+
expect(screen.getByText('Tool')).not.toBeNull();
|
|
496
|
+
expect(screen.getByText('cache_loader')).not.toBeNull();
|
|
497
|
+
expect(screen.getByText('Time')).not.toBeNull();
|
|
498
|
+
expect(screen.queryByRole('button', { name: 'Copy tool details' })).toBeNull();
|
|
499
|
+
});
|
|
500
|
+
|
|
184
501
|
it('renders workstream launch events as inline workstream rows', () => {
|
|
185
502
|
renderSummary(
|
|
186
503
|
[
|
|
@@ -205,6 +522,17 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
205
522
|
child_workflow_run_id: 'run-qa-tasks',
|
|
206
523
|
},
|
|
207
524
|
}),
|
|
525
|
+
makeMessage({
|
|
526
|
+
timestamp: 3_000,
|
|
527
|
+
type: AgentMessageType.ANSWER,
|
|
528
|
+
message: 'Main agent response.',
|
|
529
|
+
}),
|
|
530
|
+
makeMessage({
|
|
531
|
+
timestamp: 4_000,
|
|
532
|
+
type: AgentMessageType.ANSWER,
|
|
533
|
+
message: 'Workstream-only result.',
|
|
534
|
+
workstream_id: 'qa_tasks',
|
|
535
|
+
}),
|
|
208
536
|
],
|
|
209
537
|
true,
|
|
210
538
|
);
|
|
@@ -212,87 +540,188 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
212
540
|
expect(screen.getByText('Workstreams')).not.toBeNull();
|
|
213
541
|
expect(screen.getByText('QA Tasks')).not.toBeNull();
|
|
214
542
|
expect(screen.getByText('Browser Agent')).not.toBeNull();
|
|
543
|
+
expect(screen.queryByText('Workstream-only result.')).toBeNull();
|
|
544
|
+
|
|
545
|
+
fireEvent.click(screen.getByRole('button', { name: /QA Tasks/ }));
|
|
546
|
+
|
|
547
|
+
expect(screen.getByRole('button', { name: 'Back to main agent' })).not.toBeNull();
|
|
548
|
+
expect(screen.getByText('Workstream-only result.')).not.toBeNull();
|
|
549
|
+
expect(screen.queryByText('Main agent response.')).toBeNull();
|
|
550
|
+
expect(screen.queryByText('Workstreams')).toBeNull();
|
|
551
|
+
|
|
552
|
+
fireEvent.click(screen.getByRole('button', { name: 'Back to main agent' }));
|
|
553
|
+
|
|
554
|
+
expect(screen.getByText('Main agent response.')).not.toBeNull();
|
|
215
555
|
});
|
|
216
556
|
|
|
217
|
-
it('
|
|
557
|
+
it('renders first child workflow activity as a workstream row when the launch event is missing', () => {
|
|
218
558
|
renderSummary(
|
|
219
559
|
[
|
|
220
560
|
makeMessage({
|
|
221
561
|
timestamp: 1_000,
|
|
222
562
|
type: AgentMessageType.QUESTION,
|
|
223
|
-
message: '
|
|
563
|
+
message: 'Check the app.',
|
|
224
564
|
}),
|
|
225
565
|
makeMessage({
|
|
226
566
|
timestamp: 2_000,
|
|
227
|
-
type: AgentMessageType.THOUGHT,
|
|
228
|
-
message: 'I am generating the image with a specialist agent.',
|
|
229
|
-
details: {
|
|
230
|
-
streamed: true,
|
|
231
|
-
},
|
|
232
|
-
}),
|
|
233
|
-
makeMessage({
|
|
234
|
-
timestamp: 3_000,
|
|
235
567
|
type: AgentMessageType.UPDATE,
|
|
236
|
-
message: '
|
|
237
|
-
workstream_id: '
|
|
568
|
+
message: 'Browser agent started.',
|
|
569
|
+
workstream_id: 'legacy_browser',
|
|
238
570
|
details: {
|
|
239
571
|
event_class: 'activity',
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
interaction: 'ImageGeneratorAgent',
|
|
572
|
+
workstream_id: 'legacy_browser',
|
|
573
|
+
interaction: 'sys:BrowserAgent',
|
|
574
|
+
child_workflow_id: 'workstream:legacy_browser',
|
|
575
|
+
child_workflow_run_id: 'run-legacy-browser',
|
|
245
576
|
},
|
|
246
577
|
}),
|
|
247
578
|
makeMessage({
|
|
248
|
-
timestamp:
|
|
579
|
+
timestamp: 3_000,
|
|
249
580
|
type: AgentMessageType.ANSWER,
|
|
250
|
-
message: '
|
|
251
|
-
workstream_id: 'ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6',
|
|
252
|
-
details: {
|
|
253
|
-
event_class: 'user_content',
|
|
254
|
-
streamed: true,
|
|
255
|
-
},
|
|
581
|
+
message: 'Main agent response.',
|
|
256
582
|
}),
|
|
257
583
|
makeMessage({
|
|
258
|
-
timestamp:
|
|
584
|
+
timestamp: 4_000,
|
|
259
585
|
type: AgentMessageType.ANSWER,
|
|
260
|
-
message: '
|
|
261
|
-
workstream_id: '
|
|
586
|
+
message: 'Legacy workstream-only result.',
|
|
587
|
+
workstream_id: 'legacy_browser',
|
|
262
588
|
}),
|
|
263
589
|
],
|
|
264
590
|
true,
|
|
265
|
-
new Map([
|
|
266
|
-
[
|
|
267
|
-
'stream-json',
|
|
268
|
-
{
|
|
269
|
-
text: '{"generated_images":["store:object-2"]}',
|
|
270
|
-
workstreamId: 'ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6',
|
|
271
|
-
isComplete: true,
|
|
272
|
-
startTimestamp: 4_500,
|
|
273
|
-
},
|
|
274
|
-
],
|
|
275
|
-
]),
|
|
276
591
|
);
|
|
277
592
|
|
|
278
|
-
expect(screen.getByText('
|
|
279
|
-
expect(screen.getByText('
|
|
280
|
-
expect(screen.getByText('
|
|
281
|
-
expect(screen.queryByText(
|
|
282
|
-
|
|
593
|
+
expect(screen.getByText('Workstreams')).not.toBeNull();
|
|
594
|
+
expect(screen.getByText('Legacy Browser')).not.toBeNull();
|
|
595
|
+
expect(screen.getByText('Browser Agent')).not.toBeNull();
|
|
596
|
+
expect(screen.queryByText('Legacy workstream-only result.')).toBeNull();
|
|
597
|
+
|
|
598
|
+
fireEvent.click(screen.getByRole('button', { name: /Legacy Browser/ }));
|
|
599
|
+
|
|
600
|
+
expect(screen.getByRole('button', { name: 'Back to main agent' })).not.toBeNull();
|
|
601
|
+
expect(screen.getByText('Legacy workstream-only result.')).not.toBeNull();
|
|
602
|
+
expect(screen.queryByText('Main agent response.')).toBeNull();
|
|
603
|
+
expect(screen.queryByText('Workstreams')).toBeNull();
|
|
283
604
|
});
|
|
284
605
|
|
|
285
|
-
it('
|
|
606
|
+
it('does not render a failed pre-launch workstream activity as a clickable workstream row', () => {
|
|
286
607
|
renderSummary(
|
|
287
608
|
[
|
|
288
609
|
makeMessage({
|
|
289
610
|
timestamp: 1_000,
|
|
290
611
|
type: AgentMessageType.QUESTION,
|
|
291
|
-
message:
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
612
|
+
message: 'Create a bookmark.',
|
|
613
|
+
}),
|
|
614
|
+
makeMessage({
|
|
615
|
+
timestamp: 2_000,
|
|
616
|
+
type: AgentMessageType.UPDATE,
|
|
617
|
+
message: 'Provisioning browser sandbox for "Create Bookmark"...',
|
|
618
|
+
workstream_id: 'create_bookmark',
|
|
619
|
+
details: {
|
|
620
|
+
event_class: 'activity',
|
|
621
|
+
workstream_id: 'create_bookmark',
|
|
622
|
+
},
|
|
623
|
+
}),
|
|
624
|
+
makeMessage({
|
|
625
|
+
timestamp: 3_000,
|
|
626
|
+
type: AgentMessageType.ERROR,
|
|
627
|
+
message: 'Failed to provision browser sandbox: Request failed with status code 502',
|
|
628
|
+
workstream_id: 'create_bookmark',
|
|
629
|
+
details: {
|
|
630
|
+
event_class: 'activity',
|
|
631
|
+
workstream_id: 'create_bookmark',
|
|
632
|
+
},
|
|
633
|
+
}),
|
|
634
|
+
],
|
|
635
|
+
true,
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
expect(screen.queryByText('Workstreams')).toBeNull();
|
|
639
|
+
expect(screen.queryByText('Create Bookmark')).toBeNull();
|
|
640
|
+
expect(screen.queryByText('Error')).toBeNull();
|
|
641
|
+
expect(screen.queryByRole('button', { name: /Work needs attention/ })).toBeNull();
|
|
642
|
+
expect(screen.getByRole('button', { name: /Working/ })).not.toBeNull();
|
|
643
|
+
expect(screen.getByText(/Failed to provision browser sandbox/)).not.toBeNull();
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
it('suppresses JSON-only child workstream results in summary view', () => {
|
|
647
|
+
renderSummary(
|
|
648
|
+
[
|
|
649
|
+
makeMessage({
|
|
650
|
+
timestamp: 1_000,
|
|
651
|
+
type: AgentMessageType.QUESTION,
|
|
652
|
+
message: 'Generate a picture.',
|
|
653
|
+
}),
|
|
654
|
+
makeMessage({
|
|
655
|
+
timestamp: 2_000,
|
|
656
|
+
type: AgentMessageType.THOUGHT,
|
|
657
|
+
message: 'I am generating the image with a specialist agent.',
|
|
658
|
+
details: {
|
|
659
|
+
streamed: true,
|
|
660
|
+
},
|
|
661
|
+
}),
|
|
662
|
+
makeMessage({
|
|
663
|
+
timestamp: 3_000,
|
|
664
|
+
type: AgentMessageType.UPDATE,
|
|
665
|
+
message: 'Workstream "ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6" launched',
|
|
666
|
+
workstream_id: 'ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6',
|
|
667
|
+
details: {
|
|
668
|
+
event_class: 'activity',
|
|
669
|
+
workstream_event: 'launched',
|
|
670
|
+
launch_id: 'launch-1',
|
|
671
|
+
workstream_id: 'ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6',
|
|
672
|
+
kind: 'agent',
|
|
673
|
+
interaction: 'ImageGeneratorAgent',
|
|
674
|
+
},
|
|
675
|
+
}),
|
|
676
|
+
makeMessage({
|
|
677
|
+
timestamp: 4_000,
|
|
678
|
+
type: AgentMessageType.ANSWER,
|
|
679
|
+
message: '{"generated_images":["store:object-1"]}',
|
|
680
|
+
workstream_id: 'ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6',
|
|
681
|
+
details: {
|
|
682
|
+
event_class: 'user_content',
|
|
683
|
+
streamed: true,
|
|
684
|
+
},
|
|
685
|
+
}),
|
|
686
|
+
makeMessage({
|
|
687
|
+
timestamp: 5_000,
|
|
688
|
+
type: AgentMessageType.ANSWER,
|
|
689
|
+
message: 'I saved the generated image as a content object.',
|
|
690
|
+
workstream_id: 'main',
|
|
691
|
+
}),
|
|
692
|
+
],
|
|
693
|
+
true,
|
|
694
|
+
new Map([
|
|
695
|
+
[
|
|
696
|
+
'stream-json',
|
|
697
|
+
{
|
|
698
|
+
text: '{"generated_images":["store:object-2"]}',
|
|
699
|
+
workstreamId: 'ImageGeneratorAgent-16b7f73a-8e8e-40b7-b891-cb47a78c38c6',
|
|
700
|
+
isComplete: true,
|
|
701
|
+
startTimestamp: 4_500,
|
|
702
|
+
},
|
|
703
|
+
],
|
|
704
|
+
]),
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
expect(screen.getByText('Generate a picture.')).not.toBeNull();
|
|
708
|
+
expect(screen.getByText('Image Generator Agent')).not.toBeNull();
|
|
709
|
+
expect(screen.getByText('I saved the generated image as a content object.')).not.toBeNull();
|
|
710
|
+
expect(screen.queryByText(/generated_images/)).toBeNull();
|
|
711
|
+
expect(screen.queryByText(/store:object/)).toBeNull();
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it('renders question attachment markdown as a store object link in summary view', () => {
|
|
715
|
+
renderSummary(
|
|
716
|
+
[
|
|
717
|
+
makeMessage({
|
|
718
|
+
timestamp: 1_000,
|
|
719
|
+
type: AgentMessageType.QUESTION,
|
|
720
|
+
message: [
|
|
721
|
+
'what is in this image?',
|
|
722
|
+
'',
|
|
723
|
+
'Attachments:',
|
|
724
|
+
'[tokyo-tower_1 (1).jpg](/store/objects/6a17fc9544c9629943624589)',
|
|
296
725
|
].join('\n'),
|
|
297
726
|
}),
|
|
298
727
|
],
|
|
@@ -429,16 +858,82 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
429
858
|
const workedRow = screen.getByRole('button', { name: /Worked\s*for\s*1s/ });
|
|
430
859
|
fireEvent.click(workedRow);
|
|
431
860
|
|
|
432
|
-
expect(screen.getByRole('button', { name: /
|
|
861
|
+
expect(screen.getByRole('button', { name: /Running production build preflight/ })).not.toBeNull();
|
|
433
862
|
expect(screen.queryByRole('button', { name: /\$ cd \/home\/daytona\/src/ })).toBeNull();
|
|
434
863
|
|
|
435
|
-
fireEvent.click(screen.getByRole('button', { name: /
|
|
864
|
+
fireEvent.click(screen.getByRole('button', { name: /Running production build preflight/ }));
|
|
436
865
|
|
|
437
866
|
expect(screen.getByText('$ cd /home/daytona/src && pnpm run build completed successfully')).not.toBeNull();
|
|
438
867
|
expect(screen.getByText('Build output')).not.toBeNull();
|
|
439
868
|
expect(screen.queryByText('Success')).toBeNull();
|
|
440
869
|
});
|
|
441
870
|
|
|
871
|
+
it('merges legacy plan update rows with the preceding update_plan tool row', () => {
|
|
872
|
+
renderSummary(
|
|
873
|
+
[
|
|
874
|
+
makeMessage({
|
|
875
|
+
timestamp: 1_000,
|
|
876
|
+
type: AgentMessageType.QUESTION,
|
|
877
|
+
message: 'What are the news headlines in France today?',
|
|
878
|
+
}),
|
|
879
|
+
makeMessage({
|
|
880
|
+
timestamp: 2_000,
|
|
881
|
+
message: "Updating the plan and performing a Google web search for today's headlines in France.",
|
|
882
|
+
details: {
|
|
883
|
+
event_class: 'activity',
|
|
884
|
+
tool: 'update_plan',
|
|
885
|
+
tool_run_id: 'update_plan',
|
|
886
|
+
tool_status: 'running',
|
|
887
|
+
tool_event: 'started',
|
|
888
|
+
activity_group_id: 'activity-4',
|
|
889
|
+
message_to_human:
|
|
890
|
+
"Updating the plan and performing a Google web search for today's headlines in France.",
|
|
891
|
+
},
|
|
892
|
+
}),
|
|
893
|
+
makeMessage({
|
|
894
|
+
timestamp: 3_000,
|
|
895
|
+
type: AgentMessageType.UPDATE,
|
|
896
|
+
message: 'Updating 2 tasks of our plan.',
|
|
897
|
+
details: {
|
|
898
|
+
updates: [
|
|
899
|
+
{ task_id: 1, status: 'completed' },
|
|
900
|
+
{ task_id: 2, status: 'in_progress' },
|
|
901
|
+
],
|
|
902
|
+
},
|
|
903
|
+
}),
|
|
904
|
+
makeMessage({
|
|
905
|
+
timestamp: 4_000,
|
|
906
|
+
type: AgentMessageType.PLAN,
|
|
907
|
+
message:
|
|
908
|
+
'Task 1 (Learn the web search skill) has been completed successfully. Now commencing Task 2.',
|
|
909
|
+
details: {
|
|
910
|
+
plan: [
|
|
911
|
+
{ id: 1, goal: 'Learn the web search skill', status: 'completed' },
|
|
912
|
+
{ id: 2, goal: "Search for today's headlines in France", status: 'in_progress' },
|
|
913
|
+
],
|
|
914
|
+
},
|
|
915
|
+
}),
|
|
916
|
+
],
|
|
917
|
+
true,
|
|
918
|
+
);
|
|
919
|
+
|
|
920
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
921
|
+
|
|
922
|
+
const planRow = screen.getByRole('button', {
|
|
923
|
+
name: /Updating the plan and performing a Google web search/,
|
|
924
|
+
});
|
|
925
|
+
expect(planRow).not.toBeNull();
|
|
926
|
+
expect(screen.queryByRole('button', { name: /Updating 2 tasks of our plan/ })).toBeNull();
|
|
927
|
+
expect(screen.queryByRole('button', { name: /Task 1 \(Learn the web search skill\)/ })).toBeNull();
|
|
928
|
+
|
|
929
|
+
fireEvent.click(planRow);
|
|
930
|
+
|
|
931
|
+
expect(screen.getByText('update_plan')).not.toBeNull();
|
|
932
|
+
expect(screen.getByText('Started')).not.toBeNull();
|
|
933
|
+
expect(screen.getByText('Ended')).not.toBeNull();
|
|
934
|
+
expect(screen.getByText('Duration')).not.toBeNull();
|
|
935
|
+
});
|
|
936
|
+
|
|
442
937
|
it('copies expanded tool details without requiring the parent row click target', () => {
|
|
443
938
|
const writeText = vi.fn().mockResolvedValue(undefined);
|
|
444
939
|
Object.defineProperty(navigator, 'clipboard', {
|
|
@@ -454,105 +949,610 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
454
949
|
message: 'Find Japan news.',
|
|
455
950
|
}),
|
|
456
951
|
makeMessage({
|
|
457
|
-
timestamp: 2_000,
|
|
458
|
-
message: 'Searching for Japan news',
|
|
952
|
+
timestamp: 2_000,
|
|
953
|
+
message: 'Searching for Japan news',
|
|
954
|
+
details: {
|
|
955
|
+
tool: 'web_search_serper',
|
|
956
|
+
tool_status: 'completed',
|
|
957
|
+
tool_run_id: 'tool-1',
|
|
958
|
+
query: 'Japan news',
|
|
959
|
+
output: 'Found 5 results',
|
|
960
|
+
},
|
|
961
|
+
}),
|
|
962
|
+
],
|
|
963
|
+
true,
|
|
964
|
+
);
|
|
965
|
+
|
|
966
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
967
|
+
fireEvent.click(screen.getByRole('button', { name: /Japan news/ }));
|
|
968
|
+
fireEvent.click(screen.getByRole('button', { name: 'Copy tool details' }));
|
|
969
|
+
|
|
970
|
+
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('Tool: web_search_serper'));
|
|
971
|
+
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('Found 5 results'));
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
it('does not expand tool error details by default', () => {
|
|
975
|
+
renderSummary(
|
|
976
|
+
[
|
|
977
|
+
makeMessage({
|
|
978
|
+
timestamp: 1_000,
|
|
979
|
+
type: AgentMessageType.QUESTION,
|
|
980
|
+
message: 'Publish the app.',
|
|
981
|
+
}),
|
|
982
|
+
makeMessage({
|
|
983
|
+
timestamp: 2_000,
|
|
984
|
+
message: 'Publishing app...',
|
|
985
|
+
details: {
|
|
986
|
+
activity_group_id: 'activity-10',
|
|
987
|
+
tool: 'app_publish',
|
|
988
|
+
tool_run_id: 'publish-wrapper',
|
|
989
|
+
tool_status: 'running',
|
|
990
|
+
},
|
|
991
|
+
}),
|
|
992
|
+
makeMessage({
|
|
993
|
+
timestamp: 3_000,
|
|
994
|
+
type: AgentMessageType.ERROR,
|
|
995
|
+
message: 'App publish blocked until preview validation passes',
|
|
996
|
+
details: {
|
|
997
|
+
activity_group_id: 'activity-10',
|
|
998
|
+
tool: 'app_publish',
|
|
999
|
+
tool_run_id: 'publish-progress',
|
|
1000
|
+
tool_status: 'error',
|
|
1001
|
+
},
|
|
1002
|
+
}),
|
|
1003
|
+
],
|
|
1004
|
+
true,
|
|
1005
|
+
);
|
|
1006
|
+
|
|
1007
|
+
expect(screen.queryByRole('button', { name: /Work needs attention/ })).toBeNull();
|
|
1008
|
+
const workRow = screen.getByRole('button', { name: /Worked\s*for\s*1s/ });
|
|
1009
|
+
fireEvent.click(workRow);
|
|
1010
|
+
|
|
1011
|
+
const toolRow = screen.getByRole('button', { name: /Publishing app/ });
|
|
1012
|
+
expect(toolRow.getAttribute('aria-expanded')).toBe('false');
|
|
1013
|
+
expect(screen.queryByText('App publish blocked until preview validation passes')).toBeNull();
|
|
1014
|
+
|
|
1015
|
+
fireEvent.click(toolRow);
|
|
1016
|
+
|
|
1017
|
+
expect(screen.getByText('App publish blocked until preview validation passes')).not.toBeNull();
|
|
1018
|
+
});
|
|
1019
|
+
|
|
1020
|
+
it('marks denied tool approvals as error rows with expandable approval details', () => {
|
|
1021
|
+
renderSummary(
|
|
1022
|
+
[
|
|
1023
|
+
makeMessage({
|
|
1024
|
+
timestamp: 1_000,
|
|
1025
|
+
type: AgentMessageType.QUESTION,
|
|
1026
|
+
message: 'Create a document.',
|
|
1027
|
+
}),
|
|
1028
|
+
makeMessage({
|
|
1029
|
+
timestamp: 2_000,
|
|
1030
|
+
message: 'Writing the document to a temporary markdown file...',
|
|
1031
|
+
details: {
|
|
1032
|
+
event_class: 'activity',
|
|
1033
|
+
activity_group_id: 'activity-approval-1',
|
|
1034
|
+
tool: 'write_artifact',
|
|
1035
|
+
tool_run_id: 'write-1',
|
|
1036
|
+
tool_use_id: 'write-1',
|
|
1037
|
+
tool_status: 'running',
|
|
1038
|
+
tool_event: 'started',
|
|
1039
|
+
message_to_human: 'Writing the document to a temporary markdown file...',
|
|
1040
|
+
},
|
|
1041
|
+
}),
|
|
1042
|
+
makeMessage({
|
|
1043
|
+
timestamp: 3_000,
|
|
1044
|
+
message: 'User declined to use Write Artifact.',
|
|
1045
|
+
details: {
|
|
1046
|
+
event_class: 'activity',
|
|
1047
|
+
activity_group_id: 'activity-approval-1',
|
|
1048
|
+
tool: 'write_artifact',
|
|
1049
|
+
tool_run_id: 'write-1',
|
|
1050
|
+
tool_use_id: 'write-1',
|
|
1051
|
+
tool_status: 'error',
|
|
1052
|
+
tool_event: 'failed',
|
|
1053
|
+
approval_decision: 'denied',
|
|
1054
|
+
approval_request: {
|
|
1055
|
+
tool_name: 'write_artifact',
|
|
1056
|
+
tool_title: 'Write Artifact',
|
|
1057
|
+
target: 'name:quotes.md',
|
|
1058
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1059
|
+
},
|
|
1060
|
+
input: {
|
|
1061
|
+
name: 'quotes.md',
|
|
1062
|
+
type: 'file',
|
|
1063
|
+
},
|
|
1064
|
+
observation: 'The user declined this tool action.',
|
|
1065
|
+
},
|
|
1066
|
+
}),
|
|
1067
|
+
],
|
|
1068
|
+
true,
|
|
1069
|
+
);
|
|
1070
|
+
|
|
1071
|
+
expect(screen.queryByRole('button', { name: /Work needs attention\s*for/ })).toBeNull();
|
|
1072
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
1073
|
+
|
|
1074
|
+
expect(screen.queryByRole('button', { name: /User declined to use Write Artifact/ })).toBeNull();
|
|
1075
|
+
const deniedRow = screen.getByRole('button', { name: /Writing the document.*Declined by user/ });
|
|
1076
|
+
expect(deniedRow.getAttribute('aria-expanded')).toBe('false');
|
|
1077
|
+
|
|
1078
|
+
fireEvent.click(deniedRow);
|
|
1079
|
+
|
|
1080
|
+
expect(screen.queryByText('Decision')).toBeNull();
|
|
1081
|
+
expect(screen.queryByText('denied')).toBeNull();
|
|
1082
|
+
expect(screen.queryByText('Approval request')).toBeNull();
|
|
1083
|
+
expect(screen.getAllByText(/quotes\.md/).length).toBeGreaterThan(0);
|
|
1084
|
+
const deniedMessage = screen.getByText('The user declined this tool action.');
|
|
1085
|
+
expect(deniedMessage.className).toContain('text-destructive');
|
|
1086
|
+
});
|
|
1087
|
+
|
|
1088
|
+
it('does not split a denied approval into separate worked and attention rows', () => {
|
|
1089
|
+
renderSummary(
|
|
1090
|
+
[
|
|
1091
|
+
makeMessage({
|
|
1092
|
+
timestamp: 1_000,
|
|
1093
|
+
type: AgentMessageType.QUESTION,
|
|
1094
|
+
message: 'Create a document.',
|
|
1095
|
+
}),
|
|
1096
|
+
makeMessage({
|
|
1097
|
+
timestamp: 2_000,
|
|
1098
|
+
message: 'Writing the document to a temporary markdown file...',
|
|
1099
|
+
details: {
|
|
1100
|
+
event_class: 'activity',
|
|
1101
|
+
activity_group_id: 'activity-approval-2',
|
|
1102
|
+
tool: 'write_artifact',
|
|
1103
|
+
tool_run_id: 'write-2',
|
|
1104
|
+
tool_use_id: 'write-2',
|
|
1105
|
+
tool_status: 'running',
|
|
1106
|
+
tool_event: 'started',
|
|
1107
|
+
message_to_human: 'Writing the document to a temporary markdown file...',
|
|
1108
|
+
},
|
|
1109
|
+
}),
|
|
1110
|
+
makeMessage({
|
|
1111
|
+
timestamp: 3_000,
|
|
1112
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1113
|
+
message: 'Approve Write Artifact: quotes.md?',
|
|
1114
|
+
details: {
|
|
1115
|
+
tool_approval: {
|
|
1116
|
+
tool_name: 'write_artifact',
|
|
1117
|
+
tool_title: 'Write Artifact',
|
|
1118
|
+
action_summary: 'Write Artifact: quotes.md',
|
|
1119
|
+
target: 'name:quotes.md',
|
|
1120
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1121
|
+
input: {
|
|
1122
|
+
name: 'quotes.md',
|
|
1123
|
+
type: 'file',
|
|
1124
|
+
},
|
|
1125
|
+
},
|
|
1126
|
+
ux: {
|
|
1127
|
+
options: [
|
|
1128
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1129
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1130
|
+
{ id: 'deny', label: 'Deny' },
|
|
1131
|
+
],
|
|
1132
|
+
},
|
|
1133
|
+
},
|
|
1134
|
+
}),
|
|
1135
|
+
makeMessage({
|
|
1136
|
+
timestamp: 4_000,
|
|
1137
|
+
type: AgentMessageType.QUESTION,
|
|
1138
|
+
message: 'deny',
|
|
1139
|
+
}),
|
|
1140
|
+
makeMessage({
|
|
1141
|
+
timestamp: 5_000,
|
|
1142
|
+
message: 'User declined to use Write Artifact.',
|
|
1143
|
+
details: {
|
|
1144
|
+
event_class: 'activity',
|
|
1145
|
+
activity_group_id: 'activity-approval-2',
|
|
1146
|
+
tool: 'write_artifact',
|
|
1147
|
+
tool_run_id: 'write-2',
|
|
1148
|
+
tool_use_id: 'write-2',
|
|
1149
|
+
tool_status: 'error',
|
|
1150
|
+
tool_event: 'failed',
|
|
1151
|
+
approval_decision: 'denied',
|
|
1152
|
+
approval_request: {
|
|
1153
|
+
tool_name: 'write_artifact',
|
|
1154
|
+
tool_title: 'Write Artifact',
|
|
1155
|
+
target: 'name:quotes.md',
|
|
1156
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1157
|
+
},
|
|
1158
|
+
input: {
|
|
1159
|
+
name: 'quotes.md',
|
|
1160
|
+
type: 'file',
|
|
1161
|
+
},
|
|
1162
|
+
observation: 'The user declined this tool action.',
|
|
1163
|
+
},
|
|
1164
|
+
}),
|
|
1165
|
+
],
|
|
1166
|
+
true,
|
|
1167
|
+
);
|
|
1168
|
+
|
|
1169
|
+
expect(screen.queryByText('Approve Write Artifact: quotes.md?')).toBeNull();
|
|
1170
|
+
expect(screen.queryByText('deny')).toBeNull();
|
|
1171
|
+
expect(screen.queryByRole('button', { name: /Work needs attention\s*for/ })).toBeNull();
|
|
1172
|
+
|
|
1173
|
+
const workRows = screen.getAllByRole('button', { name: /Worked\s*for/ });
|
|
1174
|
+
expect(workRows).toHaveLength(1);
|
|
1175
|
+
fireEvent.click(workRows[0]);
|
|
1176
|
+
|
|
1177
|
+
expect(screen.queryByRole('button', { name: /User declined to use Write Artifact/ })).toBeNull();
|
|
1178
|
+
expect(screen.getByRole('button', { name: /Writing the document.*Declined by user/ })).not.toBeNull();
|
|
1179
|
+
});
|
|
1180
|
+
|
|
1181
|
+
it('renders a compact denied tool row for legacy approvals without lifecycle events', () => {
|
|
1182
|
+
renderSummary(
|
|
1183
|
+
[
|
|
1184
|
+
makeMessage({
|
|
1185
|
+
timestamp: 1_000,
|
|
1186
|
+
type: AgentMessageType.QUESTION,
|
|
1187
|
+
message: 'Create a document.',
|
|
1188
|
+
}),
|
|
1189
|
+
makeMessage({
|
|
1190
|
+
timestamp: 2_000,
|
|
1191
|
+
message: 'Writing the document to a temporary markdown file...',
|
|
1192
|
+
details: {
|
|
1193
|
+
event_class: 'activity',
|
|
1194
|
+
activity_group_id: 'activity-legacy-approval',
|
|
1195
|
+
tool: 'write_artifact',
|
|
1196
|
+
tool_run_id: 'write-legacy-1',
|
|
1197
|
+
tool_status: 'running',
|
|
1198
|
+
tool_event: 'started',
|
|
1199
|
+
},
|
|
1200
|
+
}),
|
|
1201
|
+
makeMessage({
|
|
1202
|
+
timestamp: 3_000,
|
|
1203
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1204
|
+
message: 'Approve Write Artifact: quotes.md?',
|
|
1205
|
+
details: {
|
|
1206
|
+
tool_approval: {
|
|
1207
|
+
tool_name: 'write_artifact',
|
|
1208
|
+
tool_title: 'Write Artifact',
|
|
1209
|
+
action_summary: 'Write Artifact: quotes.md',
|
|
1210
|
+
target: 'name:quotes.md',
|
|
1211
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1212
|
+
input: {
|
|
1213
|
+
name: 'quotes.md',
|
|
1214
|
+
type: 'file',
|
|
1215
|
+
},
|
|
1216
|
+
},
|
|
1217
|
+
ux: {
|
|
1218
|
+
options: [
|
|
1219
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1220
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1221
|
+
{ id: 'deny', label: 'Deny' },
|
|
1222
|
+
],
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
}),
|
|
1226
|
+
makeMessage({
|
|
1227
|
+
timestamp: 4_000,
|
|
1228
|
+
type: AgentMessageType.QUESTION,
|
|
1229
|
+
message: 'deny',
|
|
1230
|
+
}),
|
|
1231
|
+
],
|
|
1232
|
+
true,
|
|
1233
|
+
);
|
|
1234
|
+
|
|
1235
|
+
expect(screen.queryByText('Approve Write Artifact: quotes.md?')).toBeNull();
|
|
1236
|
+
expect(screen.queryByText('deny')).toBeNull();
|
|
1237
|
+
|
|
1238
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
1239
|
+
const deniedRow = screen.getByRole('button', { name: /Write Artifact.*Declined by user/ });
|
|
1240
|
+
fireEvent.click(deniedRow);
|
|
1241
|
+
|
|
1242
|
+
expect(screen.queryByText('Decision')).toBeNull();
|
|
1243
|
+
expect(screen.queryByText('denied')).toBeNull();
|
|
1244
|
+
expect(screen.queryByText('Approval request')).toBeNull();
|
|
1245
|
+
expect(screen.getAllByText(/quotes\.md/).length).toBeGreaterThan(0);
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1248
|
+
it('renders pending ask options compactly in summary view', () => {
|
|
1249
|
+
renderSummary([
|
|
1250
|
+
makeMessage({
|
|
1251
|
+
timestamp: 1_000,
|
|
1252
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1253
|
+
message: 'What is your favorite color?',
|
|
1254
|
+
details: {
|
|
1255
|
+
ux: {
|
|
1256
|
+
options: [
|
|
1257
|
+
{ id: 'red', label: 'Red', description: 'The color of fire and passion' },
|
|
1258
|
+
{ id: 'blue', label: 'Blue', description: 'The color of the sky and ocean' },
|
|
1259
|
+
],
|
|
1260
|
+
},
|
|
1261
|
+
},
|
|
1262
|
+
}),
|
|
1263
|
+
]);
|
|
1264
|
+
|
|
1265
|
+
expect(screen.getByText('What is your favorite color?')).not.toBeNull();
|
|
1266
|
+
expect(screen.getByRole('button', { name: /Blue\s*The color of the sky and ocean/ })).not.toBeNull();
|
|
1267
|
+
});
|
|
1268
|
+
|
|
1269
|
+
it('renders legacy field-prefixed tool approval prompts with a friendly target in summary view', () => {
|
|
1270
|
+
renderSummary([
|
|
1271
|
+
makeMessage({
|
|
1272
|
+
timestamp: 1_000,
|
|
1273
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1274
|
+
message: 'Approve Create Document: name News Headlines Today?',
|
|
1275
|
+
details: {
|
|
1276
|
+
tool_approval: {
|
|
1277
|
+
approval_key: 'create_document:name:News Headlines Today',
|
|
1278
|
+
tool_name: 'create_document',
|
|
1279
|
+
tool_title: 'Create Document',
|
|
1280
|
+
target: 'name:News Headlines Today',
|
|
1281
|
+
},
|
|
1282
|
+
ux: {
|
|
1283
|
+
options: [
|
|
1284
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1285
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1286
|
+
{ id: 'deny', label: 'Deny' },
|
|
1287
|
+
],
|
|
1288
|
+
},
|
|
1289
|
+
},
|
|
1290
|
+
}),
|
|
1291
|
+
]);
|
|
1292
|
+
|
|
1293
|
+
expect(screen.getByText('Approve Create Document: News Headlines Today?')).not.toBeNull();
|
|
1294
|
+
expect(screen.queryByText('Approve Create Document: name News Headlines Today?')).toBeNull();
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1297
|
+
it('keeps only the ask question after the user answers in summary view', () => {
|
|
1298
|
+
renderSummary(
|
|
1299
|
+
[
|
|
1300
|
+
makeMessage({
|
|
1301
|
+
timestamp: 1_000,
|
|
1302
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1303
|
+
message: 'What is your favorite color?',
|
|
1304
|
+
details: {
|
|
1305
|
+
ux: {
|
|
1306
|
+
options: [
|
|
1307
|
+
{ id: 'red', label: 'Red', description: 'The color of fire and passion' },
|
|
1308
|
+
{ id: 'blue', label: 'Blue', description: 'The color of the sky and ocean' },
|
|
1309
|
+
],
|
|
1310
|
+
},
|
|
1311
|
+
},
|
|
1312
|
+
}),
|
|
1313
|
+
makeMessage({
|
|
1314
|
+
timestamp: 2_000,
|
|
1315
|
+
type: AgentMessageType.QUESTION,
|
|
1316
|
+
message: 'blue',
|
|
1317
|
+
}),
|
|
1318
|
+
],
|
|
1319
|
+
true,
|
|
1320
|
+
);
|
|
1321
|
+
|
|
1322
|
+
expect(screen.getByText('What is your favorite color?')).not.toBeNull();
|
|
1323
|
+
expect(screen.getByText('blue')).not.toBeNull();
|
|
1324
|
+
expect(screen.queryByText('The color of the sky and ocean')).toBeNull();
|
|
1325
|
+
expect(screen.queryByRole('button', { name: /Blue/ })).toBeNull();
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
it('hides denied tool approval prompts when the stream contains a denied tool event', () => {
|
|
1329
|
+
renderSummary(
|
|
1330
|
+
[
|
|
1331
|
+
makeMessage({
|
|
1332
|
+
timestamp: 1_000,
|
|
1333
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1334
|
+
message: 'Approve Write Artifact for japan_news_2026_06_21.md?',
|
|
1335
|
+
details: {
|
|
1336
|
+
tool_approval: {
|
|
1337
|
+
approval_key: 'write_artifact:name:japan_news_2026_06_21.md',
|
|
1338
|
+
tool_name: 'write_artifact',
|
|
1339
|
+
tool_title: 'Write Artifact',
|
|
1340
|
+
target: 'name:japan_news_2026_06_21.md',
|
|
1341
|
+
input: {
|
|
1342
|
+
name: 'japan_news_2026_06_21.md',
|
|
1343
|
+
content_ref: {
|
|
1344
|
+
display_ref: 'artifact:tool-inputs/write_artifact/write_artifact.txt',
|
|
1345
|
+
},
|
|
1346
|
+
},
|
|
1347
|
+
},
|
|
1348
|
+
ux: {
|
|
1349
|
+
options: [
|
|
1350
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1351
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1352
|
+
{ id: 'deny', label: 'Deny' },
|
|
1353
|
+
],
|
|
1354
|
+
},
|
|
1355
|
+
},
|
|
1356
|
+
}),
|
|
1357
|
+
makeMessage({
|
|
1358
|
+
timestamp: 2_000,
|
|
1359
|
+
type: AgentMessageType.QUESTION,
|
|
1360
|
+
message: 'deny',
|
|
1361
|
+
}),
|
|
1362
|
+
makeMessage({
|
|
1363
|
+
timestamp: 3_000,
|
|
1364
|
+
type: AgentMessageType.THOUGHT,
|
|
1365
|
+
message: 'User declined to use Write Artifact.',
|
|
1366
|
+
details: {
|
|
1367
|
+
event_class: 'activity',
|
|
1368
|
+
tool: 'write_artifact',
|
|
1369
|
+
tool_run_id: 'tool-run-1',
|
|
1370
|
+
tool_use_id: 'tool-use-1',
|
|
1371
|
+
tool_status: 'error',
|
|
1372
|
+
tool_event: 'failed',
|
|
1373
|
+
activity_group_id: 'activity-1',
|
|
1374
|
+
observation: 'User declined to use Write Artifact.',
|
|
1375
|
+
approval_decision: 'denied',
|
|
1376
|
+
approval_request: {
|
|
1377
|
+
approval_key: 'write_artifact:name:japan_news_2026_06_21.md',
|
|
1378
|
+
tool_name: 'write_artifact',
|
|
1379
|
+
tool_title: 'Write Artifact',
|
|
1380
|
+
target: 'name:japan_news_2026_06_21.md',
|
|
1381
|
+
},
|
|
1382
|
+
input: {
|
|
1383
|
+
name: 'japan_news_2026_06_21.md',
|
|
1384
|
+
content_ref: {
|
|
1385
|
+
display_ref: 'artifact:tool-inputs/write_artifact/write_artifact.txt',
|
|
1386
|
+
},
|
|
1387
|
+
},
|
|
1388
|
+
},
|
|
1389
|
+
}),
|
|
1390
|
+
makeMessage({
|
|
1391
|
+
timestamp: 3_500,
|
|
1392
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1393
|
+
message: 'Approve Create Document: Japan News Headlines?',
|
|
1394
|
+
details: {
|
|
1395
|
+
tool_approval: {
|
|
1396
|
+
approval_key: 'create_document:name:Japan News Headlines',
|
|
1397
|
+
tool_name: 'create_document',
|
|
1398
|
+
tool_title: 'Create Document',
|
|
1399
|
+
target: 'name:Japan News Headlines',
|
|
1400
|
+
input: {
|
|
1401
|
+
name: 'Japan News Headlines',
|
|
1402
|
+
source: 'artifact:files/japan_news_2026_06_21.md',
|
|
1403
|
+
},
|
|
1404
|
+
},
|
|
1405
|
+
ux: {
|
|
1406
|
+
options: [
|
|
1407
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1408
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1409
|
+
{ id: 'deny', label: 'Deny' },
|
|
1410
|
+
],
|
|
1411
|
+
},
|
|
1412
|
+
},
|
|
1413
|
+
}),
|
|
1414
|
+
makeMessage({
|
|
1415
|
+
timestamp: 4_000,
|
|
1416
|
+
type: AgentMessageType.THOUGHT,
|
|
1417
|
+
message: 'Cancelled Create Document after denial.',
|
|
459
1418
|
details: {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
tool_run_id: 'tool-
|
|
463
|
-
|
|
464
|
-
|
|
1419
|
+
event_class: 'activity',
|
|
1420
|
+
tool: 'create_document',
|
|
1421
|
+
tool_run_id: 'tool-run-2',
|
|
1422
|
+
tool_use_id: 'tool-use-2',
|
|
1423
|
+
tool_status: 'error',
|
|
1424
|
+
tool_event: 'failed',
|
|
1425
|
+
activity_group_id: 'activity-1',
|
|
1426
|
+
observation: 'Tool execution was cancelled because another tool action was denied.',
|
|
1427
|
+
approval_decision: 'cancelled_after_denial',
|
|
1428
|
+
approval_request: {
|
|
1429
|
+
approval_key: 'create_document:name:Japan News Headlines',
|
|
1430
|
+
tool_name: 'create_document',
|
|
1431
|
+
tool_title: 'Create Document',
|
|
1432
|
+
target: 'name:Japan News Headlines',
|
|
1433
|
+
},
|
|
1434
|
+
input: {
|
|
1435
|
+
name: 'Japan News Headlines',
|
|
1436
|
+
source: 'artifact:files/japan_news_2026_06_21.md',
|
|
1437
|
+
},
|
|
465
1438
|
},
|
|
466
1439
|
}),
|
|
467
1440
|
],
|
|
468
1441
|
true,
|
|
469
1442
|
);
|
|
470
1443
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
1444
|
+
expect(screen.queryByText('Approve Write Artifact for japan_news_2026_06_21.md?')).toBeNull();
|
|
1445
|
+
expect(screen.queryByText('Approve Create Document: Japan News Headlines?')).toBeNull();
|
|
1446
|
+
expect(screen.queryByText('deny')).toBeNull();
|
|
474
1447
|
|
|
475
|
-
expect(
|
|
1448
|
+
expect(screen.queryByRole('button', { name: /Work needs attention/ })).toBeNull();
|
|
1449
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked/ }));
|
|
1450
|
+
fireEvent.click(screen.getByRole('button', { name: /Write Artifact/ }));
|
|
1451
|
+
|
|
1452
|
+
expect(screen.getByText('Declined by user')).not.toBeNull();
|
|
1453
|
+
expect(screen.getAllByText(/japan_news_2026_06_21\.md/).length).toBeGreaterThan(0);
|
|
1454
|
+
expect(screen.getByText('Cancelled after denial')).not.toBeNull();
|
|
1455
|
+
fireEvent.click(screen.getByRole('button', { name: /Create Document.*Cancelled after denial/ }));
|
|
1456
|
+
expect(screen.getAllByText(/Japan News Headlines/).length).toBeGreaterThan(0);
|
|
476
1457
|
});
|
|
477
1458
|
|
|
478
|
-
it('
|
|
1459
|
+
it('hides a commented approval denial prompt while keeping the user comment visible', () => {
|
|
479
1460
|
renderSummary(
|
|
480
1461
|
[
|
|
481
1462
|
makeMessage({
|
|
482
1463
|
timestamp: 1_000,
|
|
483
|
-
type: AgentMessageType.
|
|
484
|
-
message: '
|
|
1464
|
+
type: AgentMessageType.REQUEST_INPUT,
|
|
1465
|
+
message: 'Approve Write Artifact: quotes.md?',
|
|
1466
|
+
details: {
|
|
1467
|
+
tool_approval: {
|
|
1468
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1469
|
+
tool_name: 'write_artifact',
|
|
1470
|
+
tool_title: 'Write Artifact',
|
|
1471
|
+
target: 'name:quotes.md',
|
|
1472
|
+
input: {
|
|
1473
|
+
name: 'quotes.md',
|
|
1474
|
+
type: 'file',
|
|
1475
|
+
},
|
|
1476
|
+
},
|
|
1477
|
+
ux: {
|
|
1478
|
+
options: [
|
|
1479
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1480
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1481
|
+
{ id: 'deny', label: 'Deny' },
|
|
1482
|
+
],
|
|
1483
|
+
free_response: {
|
|
1484
|
+
placeholder: 'No, and tell the agent what to do differently',
|
|
1485
|
+
submit_label: 'Submit',
|
|
1486
|
+
metadata: {
|
|
1487
|
+
tool_approval_response: {
|
|
1488
|
+
decision: 'deny_with_feedback',
|
|
1489
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1490
|
+
},
|
|
1491
|
+
},
|
|
1492
|
+
},
|
|
1493
|
+
},
|
|
1494
|
+
},
|
|
485
1495
|
}),
|
|
486
1496
|
makeMessage({
|
|
487
1497
|
timestamp: 2_000,
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
activity_group_id: 'activity-10',
|
|
491
|
-
tool: 'app_publish',
|
|
492
|
-
tool_run_id: 'publish-wrapper',
|
|
493
|
-
tool_status: 'running',
|
|
494
|
-
},
|
|
1498
|
+
type: AgentMessageType.QUESTION,
|
|
1499
|
+
message: 'Do not write a file. Put the summary in chat.',
|
|
495
1500
|
}),
|
|
496
1501
|
makeMessage({
|
|
497
1502
|
timestamp: 3_000,
|
|
498
|
-
type: AgentMessageType.
|
|
499
|
-
message: '
|
|
1503
|
+
type: AgentMessageType.THOUGHT,
|
|
1504
|
+
message: 'User declined to use Write Artifact.',
|
|
500
1505
|
details: {
|
|
501
|
-
|
|
502
|
-
tool: '
|
|
503
|
-
tool_run_id: '
|
|
1506
|
+
event_class: 'activity',
|
|
1507
|
+
tool: 'write_artifact',
|
|
1508
|
+
tool_run_id: 'tool-run-1',
|
|
1509
|
+
tool_use_id: 'tool-use-1',
|
|
504
1510
|
tool_status: 'error',
|
|
1511
|
+
tool_event: 'failed',
|
|
1512
|
+
activity_group_id: 'activity-1',
|
|
1513
|
+
observation: 'User declined to use Write Artifact and provided new instructions.',
|
|
1514
|
+
approval_decision: 'denied_with_feedback',
|
|
1515
|
+
approval_request: {
|
|
1516
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1517
|
+
tool_name: 'write_artifact',
|
|
1518
|
+
tool_title: 'Write Artifact',
|
|
1519
|
+
target: 'name:quotes.md',
|
|
1520
|
+
},
|
|
1521
|
+
input: {
|
|
1522
|
+
name: 'quotes.md',
|
|
1523
|
+
type: 'file',
|
|
1524
|
+
},
|
|
505
1525
|
},
|
|
506
1526
|
}),
|
|
507
1527
|
],
|
|
508
1528
|
true,
|
|
509
1529
|
);
|
|
510
1530
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
expect(toolRow.getAttribute('aria-expanded')).toBe('false');
|
|
516
|
-
expect(screen.queryByText('App publish blocked until preview validation passes')).toBeNull();
|
|
517
|
-
|
|
518
|
-
fireEvent.click(toolRow);
|
|
519
|
-
|
|
520
|
-
expect(screen.getByText('App publish blocked until preview validation passes')).not.toBeNull();
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
it('renders pending ask options compactly in summary view', () => {
|
|
524
|
-
renderSummary([
|
|
525
|
-
makeMessage({
|
|
526
|
-
timestamp: 1_000,
|
|
527
|
-
type: AgentMessageType.REQUEST_INPUT,
|
|
528
|
-
message: 'What is your favorite color?',
|
|
529
|
-
details: {
|
|
530
|
-
ux: {
|
|
531
|
-
options: [
|
|
532
|
-
{ id: 'red', label: 'Red', description: 'The color of fire and passion' },
|
|
533
|
-
{ id: 'blue', label: 'Blue', description: 'The color of the sky and ocean' },
|
|
534
|
-
],
|
|
535
|
-
},
|
|
536
|
-
},
|
|
537
|
-
}),
|
|
538
|
-
]);
|
|
539
|
-
|
|
540
|
-
expect(screen.getByText('What is your favorite color?')).not.toBeNull();
|
|
541
|
-
expect(screen.getByRole('button', { name: /Blue\s*The color of the sky and ocean/ })).not.toBeNull();
|
|
1531
|
+
expect(screen.queryByText('Approve Write Artifact: quotes.md?')).toBeNull();
|
|
1532
|
+
expect(screen.getByText('Do not write a file. Put the summary in chat.')).not.toBeNull();
|
|
1533
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked/ }));
|
|
1534
|
+
expect(screen.getByRole('button', { name: /Write Artifact.*Declined by user/ })).not.toBeNull();
|
|
542
1535
|
});
|
|
543
1536
|
|
|
544
|
-
it('
|
|
1537
|
+
it('hides a commented approval denial prompt immediately from response metadata', () => {
|
|
545
1538
|
renderSummary(
|
|
546
1539
|
[
|
|
547
1540
|
makeMessage({
|
|
548
1541
|
timestamp: 1_000,
|
|
549
1542
|
type: AgentMessageType.REQUEST_INPUT,
|
|
550
|
-
message: '
|
|
1543
|
+
message: 'Approve Write Artifact: quotes.md?',
|
|
551
1544
|
details: {
|
|
1545
|
+
tool_approval: {
|
|
1546
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1547
|
+
tool_name: 'write_artifact',
|
|
1548
|
+
tool_title: 'Write Artifact',
|
|
1549
|
+
target: 'name:quotes.md',
|
|
1550
|
+
},
|
|
552
1551
|
ux: {
|
|
553
1552
|
options: [
|
|
554
|
-
{ id: '
|
|
555
|
-
{ id: '
|
|
1553
|
+
{ id: 'allow_once', label: 'Allow once' },
|
|
1554
|
+
{ id: 'allow_for_run', label: 'Allow this action for this run' },
|
|
1555
|
+
{ id: 'deny', label: 'Deny' },
|
|
556
1556
|
],
|
|
557
1557
|
},
|
|
558
1558
|
},
|
|
@@ -560,16 +1560,20 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
560
1560
|
makeMessage({
|
|
561
1561
|
timestamp: 2_000,
|
|
562
1562
|
type: AgentMessageType.QUESTION,
|
|
563
|
-
message: '
|
|
1563
|
+
message: 'Do not write a file. Put the summary in chat.',
|
|
1564
|
+
details: {
|
|
1565
|
+
tool_approval_response: {
|
|
1566
|
+
decision: 'deny_with_feedback',
|
|
1567
|
+
approval_key: 'write_artifact:name:quotes.md',
|
|
1568
|
+
},
|
|
1569
|
+
},
|
|
564
1570
|
}),
|
|
565
1571
|
],
|
|
566
|
-
|
|
1572
|
+
false,
|
|
567
1573
|
);
|
|
568
1574
|
|
|
569
|
-
expect(screen.
|
|
570
|
-
expect(screen.getByText('
|
|
571
|
-
expect(screen.queryByText('The color of the sky and ocean')).toBeNull();
|
|
572
|
-
expect(screen.queryByRole('button', { name: /Blue/ })).toBeNull();
|
|
1575
|
+
expect(screen.queryByText('Approve Write Artifact: quotes.md?')).toBeNull();
|
|
1576
|
+
expect(screen.getByText('Do not write a file. Put the summary in chat.')).not.toBeNull();
|
|
573
1577
|
});
|
|
574
1578
|
|
|
575
1579
|
it('does not duplicate the initial request once the persisted user prompt is present', () => {
|
|
@@ -625,7 +1629,7 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
625
1629
|
expect(screen.queryByRole('button', { name: /Blue/ })).toBeNull();
|
|
626
1630
|
});
|
|
627
1631
|
|
|
628
|
-
it('renders thought prose
|
|
1632
|
+
it('renders thought prose as a collapsed subsection inside expanded work details', () => {
|
|
629
1633
|
renderSummary(
|
|
630
1634
|
[
|
|
631
1635
|
makeMessage({
|
|
@@ -670,7 +1674,7 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
670
1674
|
const workedRow = screen.getByRole('button', { name: /Worked\s*for\s*3s/ });
|
|
671
1675
|
fireEvent.click(workedRow);
|
|
672
1676
|
|
|
673
|
-
expect(screen.
|
|
1677
|
+
expect(screen.queryByRole('button', { name: /Thought: The form source is better than the UI/ })).toBeNull();
|
|
674
1678
|
expect(
|
|
675
1679
|
screen.getByText('The form source is better than the UI, so I will inspect the serialization path.'),
|
|
676
1680
|
).not.toBeNull();
|
|
@@ -678,7 +1682,74 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
678
1682
|
expect(screen.getByText('allowed_scopes')).not.toBeNull();
|
|
679
1683
|
});
|
|
680
1684
|
|
|
681
|
-
it('
|
|
1685
|
+
it('collapses very long thought prose inside expanded work details', () => {
|
|
1686
|
+
const longThought = [
|
|
1687
|
+
'Thinking through the best approach for this complex multi-repo release note generation problem...',
|
|
1688
|
+
'',
|
|
1689
|
+
'Grant is asking me to help design a prompt strategy for release notes from GitHub repos.',
|
|
1690
|
+
'This is a meta-task, so I need to help him think through the best approach and craft effective prompts.',
|
|
1691
|
+
'',
|
|
1692
|
+
'Key challenges:',
|
|
1693
|
+
'',
|
|
1694
|
+
'1. Multi-repo complexity: 3 repos with a dependency chain.',
|
|
1695
|
+
'2. Filtering logic: exclude chores and infrastructure changes unless user-facing.',
|
|
1696
|
+
'3. Deduplication: fixes and improvements should roll into the relevant feature.',
|
|
1697
|
+
'4. Progressive document building: preserve context without overloading a single step.',
|
|
1698
|
+
'5. Review loop: make sure final release notes are concise and audience-ready.',
|
|
1699
|
+
'',
|
|
1700
|
+
'Daily changelog approach has natural organization by time, but it creates rework.',
|
|
1701
|
+
'Feature list approach is more aligned with release notes, but needs stronger discovery.',
|
|
1702
|
+
'The best option is likely a hybrid: gather structured daily facts, then synthesize by feature.',
|
|
1703
|
+
].join('\n');
|
|
1704
|
+
|
|
1705
|
+
renderSummary(
|
|
1706
|
+
[
|
|
1707
|
+
makeMessage({
|
|
1708
|
+
timestamp: 1_000,
|
|
1709
|
+
type: AgentMessageType.QUESTION,
|
|
1710
|
+
message: 'Plan release notes.',
|
|
1711
|
+
}),
|
|
1712
|
+
makeMessage({
|
|
1713
|
+
timestamp: 2_000,
|
|
1714
|
+
type: AgentMessageType.THOUGHT,
|
|
1715
|
+
message: longThought,
|
|
1716
|
+
}),
|
|
1717
|
+
makeMessage({
|
|
1718
|
+
timestamp: 3_000,
|
|
1719
|
+
message: 'Reading commits',
|
|
1720
|
+
details: {
|
|
1721
|
+
tool: 'read_file',
|
|
1722
|
+
tool_status: 'completed',
|
|
1723
|
+
tool_run_id: 'tool-1',
|
|
1724
|
+
path: 'CHANGELOG.md',
|
|
1725
|
+
},
|
|
1726
|
+
}),
|
|
1727
|
+
],
|
|
1728
|
+
true,
|
|
1729
|
+
);
|
|
1730
|
+
|
|
1731
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
1732
|
+
|
|
1733
|
+
const showMoreButton = screen.getByRole('button', { name: /Show more/ });
|
|
1734
|
+
const prose = screen.getByTestId('summary-thought-prose');
|
|
1735
|
+
expect(showMoreButton.getAttribute('aria-expanded')).toBe('false');
|
|
1736
|
+
expect(prose.getAttribute('class') ?? '').toContain('[-webkit-line-clamp:6]');
|
|
1737
|
+
expect(showMoreButton.getAttribute('class') ?? '').not.toContain('focus-visible:underline');
|
|
1738
|
+
expect(showMoreButton.getAttribute('class') ?? '').not.toContain('underline-offset');
|
|
1739
|
+
expect(Boolean(prose.compareDocumentPosition(showMoreButton) & Node.DOCUMENT_POSITION_FOLLOWING)).toBe(true);
|
|
1740
|
+
expect(screen.getByText(/Thinking through the best approach/)).not.toBeNull();
|
|
1741
|
+
expect(screen.getByText('CHANGELOG.md')).not.toBeNull();
|
|
1742
|
+
|
|
1743
|
+
fireEvent.click(showMoreButton);
|
|
1744
|
+
|
|
1745
|
+
const showLessButton = screen.getByRole('button', { name: /Show less/ });
|
|
1746
|
+
expect(showLessButton.getAttribute('aria-expanded')).toBe('true');
|
|
1747
|
+
expect(showLessButton.getAttribute('class') ?? '').not.toContain('sticky');
|
|
1748
|
+
expect(prose.getAttribute('class') ?? '').not.toContain('[-webkit-line-clamp:6]');
|
|
1749
|
+
expect(screen.getByText(/Feature list approach is more aligned/)).not.toBeNull();
|
|
1750
|
+
});
|
|
1751
|
+
|
|
1752
|
+
it('renders legacy think tool rows as plain preamble prose in expanded summary work details', () => {
|
|
682
1753
|
renderSummary(
|
|
683
1754
|
[
|
|
684
1755
|
makeMessage({
|
|
@@ -720,8 +1791,121 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
720
1791
|
fireEvent.click(workedRow);
|
|
721
1792
|
|
|
722
1793
|
expect(screen.getByText('Searching for the latest news headlines from Japan...')).not.toBeNull();
|
|
1794
|
+
expect(
|
|
1795
|
+
screen.queryByRole('button', { name: /Thought: Searching for the latest news headlines from Japan/ }),
|
|
1796
|
+
).toBeNull();
|
|
723
1797
|
expect(screen.queryByRole('button', { name: /Tool\s+Searching for/ })).toBeNull();
|
|
724
|
-
expect(screen.getByRole('button', { name: /
|
|
1798
|
+
expect(screen.getByRole('button', { name: /Updating 1 tasks of our plan/ })).not.toBeNull();
|
|
1799
|
+
});
|
|
1800
|
+
|
|
1801
|
+
it('renders long tool preambles as plain prose with show more inside expanded summary work details', () => {
|
|
1802
|
+
const longPreamble = [
|
|
1803
|
+
'I will now activate the web search skill so that I can look up live French news headlines.',
|
|
1804
|
+
'Then I will update the plan and proceed to search for current news headlines in France.',
|
|
1805
|
+
'After that I will compare French and international sources before giving a concise summary.',
|
|
1806
|
+
'This should keep the tool work visible without turning this preamble into a tool row.',
|
|
1807
|
+
'I will also keep the answer scoped to the current date and avoid stale coverage.',
|
|
1808
|
+
'Next I will verify that the sources are current enough for the requested headline summary.',
|
|
1809
|
+
'Finally I will present the findings as regular assistant prose instead of another tool row.',
|
|
1810
|
+
].join('\n');
|
|
1811
|
+
|
|
1812
|
+
renderSummary(
|
|
1813
|
+
[
|
|
1814
|
+
makeMessage({
|
|
1815
|
+
timestamp: 1_000,
|
|
1816
|
+
type: AgentMessageType.QUESTION,
|
|
1817
|
+
message: 'What are the news headlines in France today?',
|
|
1818
|
+
}),
|
|
1819
|
+
makeMessage({
|
|
1820
|
+
timestamp: 2_000,
|
|
1821
|
+
type: AgentMessageType.THOUGHT,
|
|
1822
|
+
message: longPreamble,
|
|
1823
|
+
details: {
|
|
1824
|
+
display_role: 'tool_preamble',
|
|
1825
|
+
tools: ['learn_web_search'],
|
|
1826
|
+
activity_group_id: 'activity-1',
|
|
1827
|
+
},
|
|
1828
|
+
}),
|
|
1829
|
+
makeMessage({
|
|
1830
|
+
timestamp: 3_000,
|
|
1831
|
+
message: 'Activating the web search tool...',
|
|
1832
|
+
details: {
|
|
1833
|
+
event_class: 'activity',
|
|
1834
|
+
tool: 'learn_web_search',
|
|
1835
|
+
tool_run_id: 'tool-1',
|
|
1836
|
+
tool_status: 'completed',
|
|
1837
|
+
activity_group_id: 'activity-1',
|
|
1838
|
+
},
|
|
1839
|
+
}),
|
|
1840
|
+
],
|
|
1841
|
+
true,
|
|
1842
|
+
);
|
|
1843
|
+
|
|
1844
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
1845
|
+
|
|
1846
|
+
expect(screen.queryByText('Thought')).toBeNull();
|
|
1847
|
+
expect(screen.queryByRole('button', { name: /Thought:/ })).toBeNull();
|
|
1848
|
+
expect(screen.getByText(/I will now activate the web search skill/)).not.toBeNull();
|
|
1849
|
+
|
|
1850
|
+
const showMoreButton = screen.getByRole('button', { name: /Show more/ });
|
|
1851
|
+
const prose = screen.getByTestId('summary-thought-prose');
|
|
1852
|
+
expect(showMoreButton.getAttribute('aria-expanded')).toBe('false');
|
|
1853
|
+
expect(prose.getAttribute('class') ?? '').toContain('[-webkit-line-clamp:6]');
|
|
1854
|
+
expect(Boolean(prose.compareDocumentPosition(showMoreButton) & Node.DOCUMENT_POSITION_FOLLOWING)).toBe(true);
|
|
1855
|
+
fireEvent.click(showMoreButton);
|
|
1856
|
+
|
|
1857
|
+
const showLessButton = screen.getByRole('button', { name: /Show less/ });
|
|
1858
|
+
expect(showLessButton.getAttribute('aria-expanded')).toBe('true');
|
|
1859
|
+
expect(screen.getByText(/This should keep the tool work visible/)).not.toBeNull();
|
|
1860
|
+
});
|
|
1861
|
+
|
|
1862
|
+
it('does not collapse long tool preambles while the summary work row is active', () => {
|
|
1863
|
+
const longPreamble = [
|
|
1864
|
+
'I will now create a plan to retrieve the latest news headlines from France today.',
|
|
1865
|
+
'To do this, I will first activate the web search skill.',
|
|
1866
|
+
'Then I will search for current French news from multiple sources.',
|
|
1867
|
+
'After that I will retrieve and summarize the results.',
|
|
1868
|
+
'I will compare the current reports before answering.',
|
|
1869
|
+
'I will keep this setup visible while the work is still running.',
|
|
1870
|
+
'Finally I will produce a concise answer when the search completes.',
|
|
1871
|
+
].join('\n');
|
|
1872
|
+
|
|
1873
|
+
renderSummary([
|
|
1874
|
+
makeMessage({
|
|
1875
|
+
timestamp: Date.now() - 2_000,
|
|
1876
|
+
type: AgentMessageType.QUESTION,
|
|
1877
|
+
message: 'What are the news headlines in France today?',
|
|
1878
|
+
}),
|
|
1879
|
+
makeMessage({
|
|
1880
|
+
timestamp: Date.now() - 1_500,
|
|
1881
|
+
type: AgentMessageType.THOUGHT,
|
|
1882
|
+
message: longPreamble,
|
|
1883
|
+
details: {
|
|
1884
|
+
display_role: 'tool_preamble',
|
|
1885
|
+
tools: ['learn_web_search'],
|
|
1886
|
+
activity_group_id: 'activity-1',
|
|
1887
|
+
},
|
|
1888
|
+
}),
|
|
1889
|
+
makeMessage({
|
|
1890
|
+
timestamp: Date.now() - 1_000,
|
|
1891
|
+
message: 'Creating a step-by-step plan to search for the latest headlines.',
|
|
1892
|
+
details: {
|
|
1893
|
+
event_class: 'activity',
|
|
1894
|
+
tool: 'update_plan',
|
|
1895
|
+
tool_run_id: 'tool-1',
|
|
1896
|
+
tool_status: 'running',
|
|
1897
|
+
activity_group_id: 'activity-1',
|
|
1898
|
+
},
|
|
1899
|
+
}),
|
|
1900
|
+
]);
|
|
1901
|
+
|
|
1902
|
+
expect(screen.getByRole('button', { name: /Working\s*for/ }).getAttribute('aria-expanded')).toBe('true');
|
|
1903
|
+
expect(screen.queryByRole('button', { name: /Show more/ })).toBeNull();
|
|
1904
|
+
expect(screen.queryByRole('button', { name: /Show less/ })).toBeNull();
|
|
1905
|
+
expect(screen.getByText(/Finally I will produce a concise answer/)).not.toBeNull();
|
|
1906
|
+
|
|
1907
|
+
const prose = screen.getByTestId('summary-thought-prose');
|
|
1908
|
+
expect(prose.getAttribute('class') ?? '').not.toContain('[-webkit-line-clamp:6]');
|
|
725
1909
|
});
|
|
726
1910
|
|
|
727
1911
|
it('renders completed streaming answers as visible summary prose before later tool activity', () => {
|
|
@@ -943,4 +2127,114 @@ describe('AllMessagesMixed summary view', () => {
|
|
|
943
2127
|
expect(screen.getByText('Found 3 relevant docs.')).not.toBeNull();
|
|
944
2128
|
expect(screen.getByText('completed')).not.toBeNull();
|
|
945
2129
|
});
|
|
2130
|
+
|
|
2131
|
+
it('does not render document panel events as duplicate create document tool rows', () => {
|
|
2132
|
+
renderSummary(
|
|
2133
|
+
[
|
|
2134
|
+
makeMessage({
|
|
2135
|
+
timestamp: 1_000,
|
|
2136
|
+
type: AgentMessageType.QUESTION,
|
|
2137
|
+
message: 'Create a Japan news report.',
|
|
2138
|
+
}),
|
|
2139
|
+
makeMessage({
|
|
2140
|
+
timestamp: 2_000,
|
|
2141
|
+
type: AgentMessageType.THOUGHT,
|
|
2142
|
+
message: 'Creating document from artifact:files/japan_news_report.md...',
|
|
2143
|
+
details: {
|
|
2144
|
+
event_class: 'activity',
|
|
2145
|
+
tool: 'create_document',
|
|
2146
|
+
tool_run_id: 'create_document',
|
|
2147
|
+
tool_status: 'running',
|
|
2148
|
+
activity_group_id: 'activity-5',
|
|
2149
|
+
source: 'artifact:files/japan_news_report.md',
|
|
2150
|
+
name: 'Japan News Headlines Today',
|
|
2151
|
+
tool_event: 'progress',
|
|
2152
|
+
},
|
|
2153
|
+
}),
|
|
2154
|
+
makeMessage({
|
|
2155
|
+
timestamp: 2_600,
|
|
2156
|
+
type: AgentMessageType.THOUGHT,
|
|
2157
|
+
message: 'Document [Japan News Headlines Today](store:doc-1) has been successfully created',
|
|
2158
|
+
details: {
|
|
2159
|
+
event_class: 'activity',
|
|
2160
|
+
tool: 'create_document',
|
|
2161
|
+
tool_run_id: 'create_document',
|
|
2162
|
+
tool_status: 'completed',
|
|
2163
|
+
activity_group_id: 'activity-5',
|
|
2164
|
+
tool_event: 'progress',
|
|
2165
|
+
},
|
|
2166
|
+
}),
|
|
2167
|
+
makeMessage({
|
|
2168
|
+
timestamp: 2_650,
|
|
2169
|
+
type: AgentMessageType.UPDATE,
|
|
2170
|
+
message: 'Created document "Japan News Headlines Today"',
|
|
2171
|
+
details: {
|
|
2172
|
+
event_class: 'document_created',
|
|
2173
|
+
document_id: 'doc-1',
|
|
2174
|
+
title: 'Japan News Headlines Today',
|
|
2175
|
+
},
|
|
2176
|
+
}),
|
|
2177
|
+
makeMessage({
|
|
2178
|
+
timestamp: 4_000,
|
|
2179
|
+
type: AgentMessageType.ANSWER,
|
|
2180
|
+
message: 'The report has been created.',
|
|
2181
|
+
}),
|
|
2182
|
+
],
|
|
2183
|
+
true,
|
|
2184
|
+
);
|
|
2185
|
+
|
|
2186
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
2187
|
+
|
|
2188
|
+
expect(screen.getAllByRole('button', { name: /Japan News Headlines Today/ })).toHaveLength(1);
|
|
2189
|
+
expect(screen.queryByText('Created document "Japan News Headlines Today"')).toBeNull();
|
|
2190
|
+
});
|
|
2191
|
+
|
|
2192
|
+
it('groups artifact completion updates into the write artifact tool row', () => {
|
|
2193
|
+
renderSummary(
|
|
2194
|
+
[
|
|
2195
|
+
makeMessage({
|
|
2196
|
+
timestamp: 1_000,
|
|
2197
|
+
type: AgentMessageType.QUESTION,
|
|
2198
|
+
message: 'Write the report to an artifact.',
|
|
2199
|
+
}),
|
|
2200
|
+
makeMessage({
|
|
2201
|
+
timestamp: 2_000,
|
|
2202
|
+
type: AgentMessageType.THOUGHT,
|
|
2203
|
+
message: 'Writing the compiled news report to the temporary workspace artifact...',
|
|
2204
|
+
details: {
|
|
2205
|
+
event_class: 'activity',
|
|
2206
|
+
tool: 'write_artifact',
|
|
2207
|
+
tool_run_id: 'write_artifact',
|
|
2208
|
+
tool_use_id: 'write_artifact',
|
|
2209
|
+
tool_status: 'running',
|
|
2210
|
+
tool_event: 'started',
|
|
2211
|
+
activity_group_id: 'activity-write',
|
|
2212
|
+
message_to_human: 'Writing the compiled news report to the temporary workspace artifact...',
|
|
2213
|
+
},
|
|
2214
|
+
}),
|
|
2215
|
+
makeMessage({
|
|
2216
|
+
timestamp: 3_000,
|
|
2217
|
+
type: AgentMessageType.UPDATE,
|
|
2218
|
+
message: 'Prepared and saved artifact to files/US_News_Report_2026-06-22.md',
|
|
2219
|
+
details: {
|
|
2220
|
+
path: 'files/US_News_Report_2026-06-22.md',
|
|
2221
|
+
size: 4426,
|
|
2222
|
+
},
|
|
2223
|
+
}),
|
|
2224
|
+
],
|
|
2225
|
+
true,
|
|
2226
|
+
);
|
|
2227
|
+
|
|
2228
|
+
fireEvent.click(screen.getByRole('button', { name: /Worked\s*for/ }));
|
|
2229
|
+
|
|
2230
|
+
const writeRow = screen.getByRole('button', {
|
|
2231
|
+
name: /Writing the compiled news report to the temporary workspace artifact/,
|
|
2232
|
+
});
|
|
2233
|
+
expect(writeRow).not.toBeNull();
|
|
2234
|
+
expect(screen.queryByRole('button', { name: /files\/US_News_Report_2026-06-22\.md/ })).toBeNull();
|
|
2235
|
+
|
|
2236
|
+
fireEvent.click(writeRow);
|
|
2237
|
+
|
|
2238
|
+
expect(screen.getByText('Prepared and saved artifact to files/US_News_Report_2026-06-22.md')).not.toBeNull();
|
|
2239
|
+
});
|
|
946
2240
|
});
|