@copilotkit/vue 2.0.0-rc.3 → 2.0.0-rc.30
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/CONTRIBUTOR_GUIDE.md +1 -1
- package/PARITY.md +3 -3
- package/dist/hooks/use-copilot-action.d.ts.map +1 -1
- package/dist/hooks/use-frontend-tool.d.ts +1 -1
- package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
- package/dist/hooks/zod-parameters.d.ts +14 -0
- package/dist/hooks/zod-parameters.d.ts.map +1 -0
- package/dist/index.cjs +1 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +365 -16920
- package/dist/index.mjs.map +1 -1
- package/dist/use-render-activity-message-BZJ33B_r.cjs +113 -0
- package/dist/use-render-activity-message-BZJ33B_r.cjs.map +1 -0
- package/dist/use-render-activity-message-DrR407LQ.js +15901 -0
- package/dist/use-render-activity-message-DrR407LQ.js.map +1 -0
- package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
- package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
- package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
- package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
- package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
- package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
- package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -1
- package/dist/v2/components/LicenseWarningBanner.vue.d.ts +2 -2
- package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
- package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -59
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +3 -11
- package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -130
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
- package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
- package/dist/v2/components/a2ui/utils.d.ts +3 -15
- package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
- package/dist/v2/components/a2ui.d.ts +9 -8
- package/dist/v2/components/a2ui.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChat.vue.d.ts +2 -2
- package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
- package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +7 -286
- package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts +3 -3
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopup.vue.d.ts +8 -3
- package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +5 -3
- package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +5 -3
- package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +8 -3
- package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +6 -4
- package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +6 -4
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
- package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
- package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +4 -4
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
- package/dist/v2/components/chat/forwarded-slots.d.ts +12 -0
- package/dist/v2/components/chat/forwarded-slots.d.ts.map +1 -0
- package/dist/v2/components/chat/index.d.ts +34 -31
- package/dist/v2/components/chat/index.d.ts.map +1 -1
- package/dist/v2/components/chat/inspector-shortcuts.d.ts +2 -1
- package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -1
- package/dist/v2/components/chat/message-feedback.d.ts +38 -49
- package/dist/v2/components/chat/message-feedback.d.ts.map +1 -1
- package/dist/v2/components/chat/tool-call-display-context.d.ts +4 -19
- package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
- package/dist/v2/components/chat/tool-call-group-parts.d.ts +7 -20
- package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
- package/dist/v2/components/chat/turn-work.d.ts +0 -2
- package/dist/v2/components/chat/turn-work.d.ts.map +1 -1
- package/dist/v2/components/chat/types.d.ts +9 -4
- package/dist/v2/components/chat/types.d.ts.map +1 -1
- package/dist/v2/components/chat/use-chat-labels.d.ts +8 -0
- package/dist/v2/components/chat/use-chat-labels.d.ts.map +1 -0
- package/dist/v2/components/chat/use-copy-feedback.d.ts +11 -0
- package/dist/v2/components/chat/use-copy-feedback.d.ts.map +1 -0
- package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
- package/dist/v2/components/icons/index.d.ts +968 -1
- package/dist/v2/components/icons/index.d.ts.map +1 -1
- package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
- package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
- package/dist/v2/hooks/use-agent-context.d.ts +2 -3
- package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
- package/dist/v2/hooks/use-agent.d.ts +4 -1
- package/dist/v2/hooks/use-agent.d.ts.map +1 -1
- package/dist/v2/hooks/use-attachments.d.ts +7 -0
- package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
- package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
- package/dist/v2/hooks/use-component.d.ts +1 -0
- package/dist/v2/hooks/use-component.d.ts.map +1 -1
- package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
- package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-default-render-tool.d.ts +2 -7
- package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
- package/dist/v2/hooks/use-frontend-tool.d.ts +5 -0
- package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -1
- package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
- package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
- package/dist/v2/hooks/use-interrupt.d.ts +0 -1
- package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
- package/dist/v2/hooks/use-keyboard-height.d.ts +1 -1
- package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -1
- package/dist/v2/hooks/use-pin-to-send.d.ts +4 -12
- package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-activity-message.d.ts +13 -9
- package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-custom-messages.d.ts +5 -7
- package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-tool.d.ts +1 -1
- package/dist/v2/hooks/use-render-tool.d.ts.map +1 -1
- package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-threads.d.ts +6 -23
- package/dist/v2/hooks/use-threads.d.ts.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.mjs +197 -200
- package/dist/v2/index.mjs.map +1 -1
- package/dist/v2/lib/processPartialHtml.d.ts +1 -2
- package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
- package/dist/v2/lib/shallow-stable.d.ts.map +1 -1
- package/dist/v2/lib/vue-core.d.ts +33 -19
- package/dist/v2/lib/vue-core.d.ts.map +1 -1
- package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -129
- package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
- package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
- package/dist/v2/providers/markdown-renderer.d.ts +4 -2
- package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
- package/dist/v2/providers/types.d.ts +3 -46
- package/dist/v2/providers/types.d.ts.map +1 -1
- package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
- package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
- package/dist/v2/types/defineToolCallRenderer.d.ts +1 -1
- package/dist/v2/types/defineToolCallRenderer.d.ts.map +1 -1
- package/dist/v2/types/human-in-the-loop.d.ts +8 -29
- package/dist/v2/types/human-in-the-loop.d.ts.map +1 -1
- package/dist/v2/types/interrupt.d.ts +1 -22
- package/dist/v2/types/interrupt.d.ts.map +1 -1
- package/dist/v2/types/vue-activity-message-renderer.d.ts +16 -15
- package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -1
- package/dist/v2/types/vue-custom-message-renderer.d.ts +7 -16
- package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -1
- package/dist/v2/types/vue-tool-call-renderer.d.ts +16 -35
- package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
- package/package.json +12 -13
- package/src/__tests__/build-entries.test.ts +29 -0
- package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
- package/src/hooks/use-copilot-action.ts +2 -1
- package/src/hooks/use-frontend-tool.ts +3 -6
- package/src/hooks/zod-parameters.ts +162 -0
- package/src/v2/__tests__/exports.test.ts +10 -0
- package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
- package/src/v2/__tests__/utils/test-helpers.ts +34 -4
- package/src/v2/components/A2UIMessageRenderer.ts +98 -68
- package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
- package/src/v2/components/CopilotKitInspector.vue +104 -51
- package/src/v2/components/InlineFeatureWarning.vue +20 -21
- package/src/v2/components/LicenseWarningBanner.vue +27 -135
- package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
- package/src/v2/components/OpenGenerativeUIRenderer.ts +122 -446
- package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
- package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
- package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +60 -0
- package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +64 -8
- package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
- package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +6 -26
- package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -185
- package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
- package/src/v2/components/a2ui/catalog.ts +3 -3
- package/src/v2/components/a2ui/utils.ts +13 -65
- package/src/v2/components/a2ui.ts +15 -22
- package/src/v2/components/chat/CopilotChat.vue +121 -498
- package/src/v2/components/chat/CopilotChatAssistantMessage.vue +47 -184
- package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +36 -55
- package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +14 -6
- package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
- package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +12 -77
- package/src/v2/components/chat/CopilotChatInput.vue +139 -654
- package/src/v2/components/chat/CopilotChatInspectorButton.vue +45 -108
- package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
- package/src/v2/components/chat/CopilotChatMessageView.vue +96 -274
- package/src/v2/components/chat/CopilotChatReasoningMessage.vue +27 -62
- package/src/v2/components/chat/CopilotChatToolCallGroup.vue +63 -71
- package/src/v2/components/chat/CopilotChatToolCallItem.vue +8 -6
- package/src/v2/components/chat/CopilotChatToolCallsView.vue +31 -32
- package/src/v2/components/chat/CopilotChatUserMessage.vue +24 -112
- package/src/v2/components/chat/CopilotChatView.vue +123 -161
- package/src/v2/components/chat/CopilotChatWorkSummary.vue +26 -36
- package/src/v2/components/chat/CopilotModalHeader.vue +11 -23
- package/src/v2/components/chat/CopilotPopup.vue +23 -25
- package/src/v2/components/chat/CopilotPopupView.vue +10 -39
- package/src/v2/components/chat/CopilotPopupViewInternal.vue +49 -185
- package/src/v2/components/chat/CopilotSidebar.vue +23 -25
- package/src/v2/components/chat/CopilotSidebarView.vue +10 -39
- package/src/v2/components/chat/CopilotSidebarViewInternal.vue +56 -100
- package/src/v2/components/chat/CopilotThreadsDrawer.vue +43 -105
- package/src/v2/components/chat/StreamingMarkdownDefault.vue +15 -28
- package/src/v2/components/chat/__tests__/CopilotChat.labels.test.ts +19 -4
- package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
- package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +5 -5
- package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +132 -1
- package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +247 -403
- package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +1 -99
- package/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.ts +43 -1
- package/src/v2/components/chat/__tests__/CopilotPopup.test.ts +90 -1
- package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
- package/src/v2/components/chat/__tests__/CopilotSidebar.test.ts +90 -1
- package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
- package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
- package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
- package/src/v2/components/chat/audioRecorder.ts +4 -7
- package/src/v2/components/chat/copilotChatToolCallItemRender.ts +25 -90
- package/src/v2/components/chat/forwarded-slots.ts +17 -0
- package/src/v2/components/chat/index.ts +0 -1
- package/src/v2/components/chat/inspector-shortcuts.ts +10 -16
- package/src/v2/components/chat/message-feedback.ts +92 -195
- package/src/v2/components/chat/tool-call-display-context.ts +6 -22
- package/src/v2/components/chat/tool-call-group-parts.ts +47 -108
- package/src/v2/components/chat/turn-work.ts +0 -9
- package/src/v2/components/chat/types.ts +12 -4
- package/src/v2/components/chat/use-chat-labels.ts +16 -0
- package/src/v2/components/chat/use-copy-feedback.ts +21 -0
- package/src/v2/components/chat/use-lightbox.ts +15 -33
- package/src/v2/components/icons/__tests__/icons.test.ts +72 -68
- package/src/v2/components/icons/index.ts +109 -27
- package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
- package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
- package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
- package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
- package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
- package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
- package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
- package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +66 -1
- package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
- package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
- package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
- package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +106 -0
- package/src/v2/hooks/__tests__/use-render-tool.test.ts +3 -6
- package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
- package/src/v2/hooks/__tests__/zod-regression.test.ts +5 -4
- package/src/v2/hooks/use-agent-context.ts +4 -10
- package/src/v2/hooks/use-agent.ts +86 -290
- package/src/v2/hooks/use-attachments.ts +48 -168
- package/src/v2/hooks/use-capabilities.ts +2 -7
- package/src/v2/hooks/use-component.ts +7 -4
- package/src/v2/hooks/use-configure-suggestions.ts +29 -220
- package/src/v2/hooks/use-default-render-tool.ts +31 -152
- package/src/v2/hooks/use-frontend-tool.ts +15 -25
- package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
- package/src/v2/hooks/use-interrupt.ts +29 -308
- package/src/v2/hooks/use-keyboard-height.ts +17 -40
- package/src/v2/hooks/use-pin-to-send.ts +15 -99
- package/src/v2/hooks/use-render-activity-message.ts +35 -57
- package/src/v2/hooks/use-render-custom-messages.ts +24 -88
- package/src/v2/hooks/use-render-tool.ts +2 -4
- package/src/v2/hooks/use-suggestions.ts +17 -36
- package/src/v2/hooks/use-threads.ts +49 -288
- package/src/v2/lib/__tests__/shallow-stable.test.ts +54 -0
- package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
- package/src/v2/lib/processPartialHtml.ts +6 -21
- package/src/v2/lib/shallow-stable.ts +2 -16
- package/src/v2/lib/vue-core.ts +90 -85
- package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
- package/src/v2/providers/CopilotKitProvider.types.ts +12 -132
- package/src/v2/providers/CopilotKitProvider.vue +291 -641
- package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
- package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +38 -2
- package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.headersAtSendTime.test.ts +3 -3
- package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +3 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +88 -28
- package/src/v2/providers/chat-configuration-store-key.ts +9 -0
- package/src/v2/providers/markdown-renderer.ts +8 -2
- package/src/v2/providers/types.ts +3 -49
- package/src/v2/providers/use-inspector-thread-override.ts +22 -80
- package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +28 -33
- package/src/v2/types/defineToolCallRenderer.ts +7 -6
- package/src/v2/types/human-in-the-loop.ts +8 -32
- package/src/v2/types/interrupt.ts +7 -31
- package/src/v2/types/vue-activity-message-renderer.ts +24 -15
- package/src/v2/types/vue-custom-message-renderer.ts +12 -16
- package/src/v2/types/vue-tool-call-renderer.ts +23 -38
- package/tsconfig.json +0 -1
- package/vite.config.ts +8 -5
- package/vitest.config.ts +12 -7
- package/dist/v2/components/chat/BasicMarkdown.vue.d.ts +0 -9
- package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +0 -1
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
- package/dist/v2/components/chat/tool-call-layout.d.ts +0 -115
- package/dist/v2/components/chat/tool-call-layout.d.ts.map +0 -1
- package/dist/v2/lib/is-mobile-viewport.d.ts +0 -15
- package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
- package/dist/v2/lib/message-feedback.d.ts +0 -33
- package/dist/v2/lib/message-feedback.d.ts.map +0 -1
- package/dist/v2/lib/transcription-client.d.ts +0 -19
- package/dist/v2/lib/transcription-client.d.ts.map +0 -1
- package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
- package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
- package/src/v2/components/chat/BasicMarkdown.vue +0 -160
- package/src/v2/components/chat/__tests__/BasicMarkdown.test.ts +0 -69
- package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -39
- package/src/v2/components/chat/normalize-auto-scroll.ts +0 -17
- package/src/v2/components/chat/tool-call-layout.ts +0 -304
- package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +0 -48
- package/src/v2/lib/__tests__/message-feedback.test.ts +0 -152
- package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
- package/src/v2/lib/__tests__/transcription-client.test.ts +0 -67
- package/src/v2/lib/is-mobile-viewport.ts +0 -23
- package/src/v2/lib/message-feedback.ts +0 -120
- package/src/v2/lib/transcription-client.ts +0 -151
|
@@ -31,10 +31,10 @@ describe("useAgent error state", () => {
|
|
|
31
31
|
|
|
32
32
|
const TestComponent = defineComponent({
|
|
33
33
|
setup() {
|
|
34
|
-
const { agent } = useAgent({ agentId: "nonexistent" });
|
|
35
|
-
return { agent };
|
|
34
|
+
const { agent, isReady } = useAgent({ agentId: "nonexistent" });
|
|
35
|
+
return { agent, isReady };
|
|
36
36
|
},
|
|
37
|
-
template: `<div data-testid="agent-id">{{ agent.agentId }}</div>`,
|
|
37
|
+
template: `<div data-testid="agent-id">{{ agent.agentId }}</div><div data-testid="ready">{{ isReady }}</div>`,
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
const Host = defineComponent({
|
|
@@ -59,6 +59,8 @@ describe("useAgent error state", () => {
|
|
|
59
59
|
// Should render without crashing — agent is provisional
|
|
60
60
|
const el = await screen.findByTestId("agent-id");
|
|
61
61
|
expect(el.textContent).toBe("nonexistent");
|
|
62
|
+
// A provisional stand-in is not the real agent.
|
|
63
|
+
expect(screen.getByTestId("ready").textContent).toBe("false");
|
|
62
64
|
expect(capturedErrors).toEqual([]);
|
|
63
65
|
});
|
|
64
66
|
});
|
|
@@ -6,7 +6,23 @@ import type { AbstractAgent } from "@ag-ui/client";
|
|
|
6
6
|
import { useCopilotKit } from "../../providers/useCopilotKit";
|
|
7
7
|
import { MockStepwiseAgent } from "../../__tests__/utils/test-helpers";
|
|
8
8
|
import { useAgent } from "../use-agent";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
CopilotKitCoreRuntimeConnectionStatus,
|
|
11
|
+
ProxiedCopilotRuntimeAgent,
|
|
12
|
+
} from "@copilotkit/core";
|
|
13
|
+
|
|
14
|
+
/** Core's `ɵruntimeInfo` snapshot, built from a fake core's runtime fields. */
|
|
15
|
+
function runtimeInfoOf(core: {
|
|
16
|
+
runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus;
|
|
17
|
+
threadEndpoints?: unknown;
|
|
18
|
+
intelligence?: unknown;
|
|
19
|
+
}) {
|
|
20
|
+
return {
|
|
21
|
+
status: core.runtimeConnectionStatus,
|
|
22
|
+
threadEndpoints: core.threadEndpoints,
|
|
23
|
+
intelligence: core.intelligence,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
10
26
|
|
|
11
27
|
// Mock the CopilotKitProvider to control copilotkit state directly
|
|
12
28
|
vi.mock("../../providers/useCopilotKit", () => ({
|
|
@@ -26,6 +42,7 @@ describe("useAgent stability during runtime connection", () => {
|
|
|
26
42
|
type MockCopilotkit = {
|
|
27
43
|
getAgent: ReturnType<typeof vi.fn>;
|
|
28
44
|
runtimeUrl: string | undefined;
|
|
45
|
+
readonly ɵruntimeInfo: unknown;
|
|
29
46
|
runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus;
|
|
30
47
|
runtimeTransport: string;
|
|
31
48
|
headers: Record<string, string>;
|
|
@@ -45,6 +62,9 @@ describe("useAgent stability during runtime connection", () => {
|
|
|
45
62
|
copilotkitRef = ref({
|
|
46
63
|
getAgent: vi.fn(() => undefined),
|
|
47
64
|
runtimeUrl: "http://localhost:3000/api/copilotkit",
|
|
65
|
+
get ɵruntimeInfo() {
|
|
66
|
+
return runtimeInfoOf(this);
|
|
67
|
+
},
|
|
48
68
|
runtimeConnectionStatus:
|
|
49
69
|
CopilotKitCoreRuntimeConnectionStatus.Disconnected,
|
|
50
70
|
runtimeTransport: "rest",
|
|
@@ -198,7 +218,6 @@ describe("useAgent stability during runtime connection", () => {
|
|
|
198
218
|
// Phase 1: Disconnected — provisional created
|
|
199
219
|
const { rerender } = render(AgentTracker, { props: { tick: 0 } });
|
|
200
220
|
await nextTick();
|
|
201
|
-
const provisionalThreadId = agentInstances[0]!.threadId;
|
|
202
221
|
|
|
203
222
|
// Phase 2: Connecting
|
|
204
223
|
mockCopilotkit.runtimeConnectionStatus =
|
|
@@ -232,8 +251,10 @@ describe("useAgent stability during runtime connection", () => {
|
|
|
232
251
|
// CopilotChat's connect guard ensures connect fires only once (when Connected),
|
|
233
252
|
// so the agent reference change doesn't cause a duplicate connect.
|
|
234
253
|
expect(agentInstances.length).toBe(2);
|
|
235
|
-
// First instance was the provisional
|
|
236
|
-
|
|
254
|
+
// First instance was the provisional. The hand-off then syncs it with
|
|
255
|
+
// the registered agent, so its threadId follows the registered one.
|
|
256
|
+
expect(agentInstances[0]).toBeInstanceOf(ProxiedCopilotRuntimeAgent);
|
|
257
|
+
expect(agentInstances[0]!.threadId).toBe(registeredAgent.threadId);
|
|
237
258
|
// Second instance is the registered agent
|
|
238
259
|
expect(agentInstances[1]).toBe(registeredAgent);
|
|
239
260
|
});
|
|
@@ -541,6 +541,8 @@ describe("useAgent throttleMs", () => {
|
|
|
541
541
|
it("single notification within window does not trigger a trailing re-render", async () => {
|
|
542
542
|
const renderCount = { current: 0 };
|
|
543
543
|
mountHookComponent({ agent, throttleMs: 100, renderCount });
|
|
544
|
+
// The provider connects on mount, and the status change re-renders once.
|
|
545
|
+
await flushVue();
|
|
544
546
|
const afterMount = renderCount.current;
|
|
545
547
|
agent.setMessages([userMsg("1", "a")]);
|
|
546
548
|
agent.notifyMessagesChanged();
|
|
@@ -692,8 +694,10 @@ describe("useAgent defaultThrottleMs from provider", () => {
|
|
|
692
694
|
agent,
|
|
693
695
|
defaultThrottleMs: value,
|
|
694
696
|
});
|
|
697
|
+
// Core validates the value (the provider no longer logs its own copy).
|
|
695
698
|
expect(errorSpy).toHaveBeenCalledWith(
|
|
696
|
-
expect.stringContaining("
|
|
699
|
+
expect.stringContaining("CopilotKitCore.setDefaultThrottleMs"),
|
|
700
|
+
expect.any(Error),
|
|
697
701
|
);
|
|
698
702
|
agent.setMessages([userMsg("1", "a")]);
|
|
699
703
|
agent.notifyMessagesChanged();
|
|
@@ -21,13 +21,15 @@ describe("useAgent", () => {
|
|
|
21
21
|
|
|
22
22
|
const Child = defineComponent({
|
|
23
23
|
setup() {
|
|
24
|
-
const { agent } = useAgent({ agentId: "test-agent" });
|
|
25
|
-
return () =>
|
|
24
|
+
const { agent, isReady } = useAgent({ agentId: "test-agent" });
|
|
25
|
+
return () => [
|
|
26
26
|
h(
|
|
27
27
|
"span",
|
|
28
28
|
{ "data-testid": "agent-id" },
|
|
29
29
|
agent.value?.agentId ?? "none",
|
|
30
|
-
)
|
|
30
|
+
),
|
|
31
|
+
h("span", { "data-testid": "ready" }, String(isReady.value)),
|
|
32
|
+
];
|
|
31
33
|
},
|
|
32
34
|
});
|
|
33
35
|
|
|
@@ -38,6 +40,7 @@ describe("useAgent", () => {
|
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
expect(wrapper.find("[data-testid=agent-id]").text()).toBe("test-agent");
|
|
43
|
+
expect(wrapper.find("[data-testid=ready]").text()).toBe("true");
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
it("uses agentId from chat configuration when no agentId prop is provided", () => {
|
|
@@ -106,6 +106,27 @@ describe("useComponent", () => {
|
|
|
106
106
|
expect(forwardedDeps).toBe(deps);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
+
it("forwards followUp, as React and Angular do", () => {
|
|
110
|
+
const Harness = defineComponent({
|
|
111
|
+
setup() {
|
|
112
|
+
useComponent({
|
|
113
|
+
name: "showWeatherCard",
|
|
114
|
+
render: defineComponent({ template: `<div />` }),
|
|
115
|
+
followUp: false,
|
|
116
|
+
});
|
|
117
|
+
return {};
|
|
118
|
+
},
|
|
119
|
+
template: `<div />`,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
render(Harness);
|
|
123
|
+
|
|
124
|
+
const [toolConfig] = mockUseFrontendTool.mock.calls[0] as [
|
|
125
|
+
{ followUp?: boolean },
|
|
126
|
+
];
|
|
127
|
+
expect(toolConfig.followUp).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
|
|
109
130
|
it("creates a render function that passes args into the component", () => {
|
|
110
131
|
const DemoComponent = defineComponent({
|
|
111
132
|
props: {
|
|
@@ -12,7 +12,10 @@ import type { Observable } from "rxjs";
|
|
|
12
12
|
import { useConfigureSuggestions } from "../use-configure-suggestions";
|
|
13
13
|
import { useSuggestions } from "../use-suggestions";
|
|
14
14
|
import { useCopilotKit } from "../../providers/useCopilotKit";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
mountWithProvider,
|
|
17
|
+
renderWithCopilotKit,
|
|
18
|
+
} from "../../__tests__/utils/mount";
|
|
16
19
|
import {
|
|
17
20
|
StateCapturingAgent,
|
|
18
21
|
SuggestionsProviderAgent,
|
|
@@ -396,4 +399,30 @@ describe("useConfigureSuggestions", () => {
|
|
|
396
399
|
|
|
397
400
|
expect(wrapper.find("[data-testid=json]").text()).toContain("Deferred");
|
|
398
401
|
});
|
|
402
|
+
|
|
403
|
+
it("loads a global static config for the chat's agent before any agent registers", async () => {
|
|
404
|
+
const Harness = defineComponent({
|
|
405
|
+
setup() {
|
|
406
|
+
useConfigureSuggestions({
|
|
407
|
+
suggestions: [{ title: "Welcome", message: "Say hi" }],
|
|
408
|
+
available: "always",
|
|
409
|
+
});
|
|
410
|
+
const { suggestions } = useSuggestions({ agentId: "support" });
|
|
411
|
+
return () =>
|
|
412
|
+
h(
|
|
413
|
+
"span",
|
|
414
|
+
{ "data-testid": "titles" },
|
|
415
|
+
suggestions.value.map((suggestion) => suggestion.title).join(","),
|
|
416
|
+
);
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const { wrapper } = renderWithCopilotKit(() => h(Harness), {
|
|
421
|
+
agentId: "support",
|
|
422
|
+
agents: {},
|
|
423
|
+
});
|
|
424
|
+
await nextTick();
|
|
425
|
+
|
|
426
|
+
expect(wrapper.find("[data-testid=titles]").text()).toBe("Welcome");
|
|
427
|
+
});
|
|
399
428
|
});
|
|
@@ -530,10 +530,8 @@ describe("useDefaultRenderTool", () => {
|
|
|
530
530
|
expect(forwarded.result).toBe("ok");
|
|
531
531
|
});
|
|
532
532
|
|
|
533
|
-
// Fix #5: circular-ref parameters must not crash the vue render
|
|
534
|
-
it("default renderer survives circular-ref parameters
|
|
535
|
-
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
536
|
-
|
|
533
|
+
// Fix #5: circular-ref parameters must not crash the vue render.
|
|
534
|
+
it("default renderer survives circular-ref parameters", async () => {
|
|
537
535
|
const Harness = defineComponent({
|
|
538
536
|
setup() {
|
|
539
537
|
useDefaultRenderTool();
|
|
@@ -567,14 +565,16 @@ describe("useDefaultRenderTool", () => {
|
|
|
567
565
|
}),
|
|
568
566
|
).not.toThrow();
|
|
569
567
|
|
|
568
|
+
const wrapper = screen.getByTestId("copilot-tool-render");
|
|
569
|
+
expect(wrapper.getAttribute("data-args")).toBe(
|
|
570
|
+
'{"a":1,"self":"[Circular]"}',
|
|
571
|
+
);
|
|
572
|
+
|
|
570
573
|
const headerButton = screen
|
|
571
574
|
.getByTestId("copilot-tool-render-name")
|
|
572
575
|
.closest("button");
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
expect(warnSpy).toHaveBeenCalled();
|
|
578
|
-
warnSpy.mockRestore();
|
|
576
|
+
expect(headerButton).not.toBeNull();
|
|
577
|
+
await fireEvent.click(headerButton!);
|
|
578
|
+
expect(wrapper.textContent).toContain('"self": "[Circular]"');
|
|
579
579
|
});
|
|
580
580
|
});
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
defineComponent,
|
|
4
|
+
h,
|
|
5
|
+
nextTick,
|
|
6
|
+
onMounted,
|
|
7
|
+
ref,
|
|
8
|
+
watch,
|
|
9
|
+
} from "vue";
|
|
2
10
|
import type { PropType } from "vue";
|
|
3
11
|
import { screen, fireEvent, waitFor, cleanup } from "@testing-library/vue";
|
|
4
12
|
import { afterEach, describe, expect, it } from "vitest";
|
|
@@ -27,6 +35,11 @@ import {
|
|
|
27
35
|
textChunkEvent,
|
|
28
36
|
testId,
|
|
29
37
|
} from "../../__tests__/utils/test-helpers";
|
|
38
|
+
import { mountWithProvider } from "../../__tests__/utils/mount";
|
|
39
|
+
import {
|
|
40
|
+
StateCapturingAgent,
|
|
41
|
+
toolCallMessage,
|
|
42
|
+
} from "../../__tests__/utils/agents";
|
|
30
43
|
|
|
31
44
|
afterEach(() => {
|
|
32
45
|
cleanup();
|
|
@@ -874,6 +887,10 @@ describe("useFrontendTool E2E - Dynamic Registration", () => {
|
|
|
874
887
|
expect(firstVersion.textContent).toContain("before override");
|
|
875
888
|
});
|
|
876
889
|
|
|
890
|
+
await agent.emit(runFinishedEvent());
|
|
891
|
+
// The tool call starts a follow-up run. A send waits for the run in
|
|
892
|
+
// flight (#5195), so finish the follow-up before the next message.
|
|
893
|
+
await agent.emit(runStartedEvent());
|
|
877
894
|
await agent.emit(runFinishedEvent());
|
|
878
895
|
|
|
879
896
|
const overrideButton = screen.getByTestId("activate-override");
|
|
@@ -912,6 +929,54 @@ describe("useFrontendTool E2E - Dynamic Registration", () => {
|
|
|
912
929
|
});
|
|
913
930
|
});
|
|
914
931
|
|
|
932
|
+
describe("Overriding a provider tool", () => {
|
|
933
|
+
it("brings the provider tool back after the overriding component unmounts", async () => {
|
|
934
|
+
const calls: string[] = [];
|
|
935
|
+
const lookupTool = (owner: string): VueFrontendTool => ({
|
|
936
|
+
name: "lookup",
|
|
937
|
+
parameters: z.object({}),
|
|
938
|
+
followUp: false,
|
|
939
|
+
handler: async () => {
|
|
940
|
+
calls.push(owner);
|
|
941
|
+
return owner;
|
|
942
|
+
},
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
const OverridingTool = defineComponent({
|
|
946
|
+
setup() {
|
|
947
|
+
useFrontendTool(lookupTool("component"));
|
|
948
|
+
return () => null;
|
|
949
|
+
},
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
const showOverride = ref(true);
|
|
953
|
+
const agent = new StateCapturingAgent(
|
|
954
|
+
[
|
|
955
|
+
{ newMessages: [toolCallMessage("lookup")] },
|
|
956
|
+
{ newMessages: [toolCallMessage("lookup")] },
|
|
957
|
+
],
|
|
958
|
+
"test-agent",
|
|
959
|
+
);
|
|
960
|
+
const { getCore, wrapper } = mountWithProvider(
|
|
961
|
+
() => (showOverride.value ? h(OverridingTool) : h("div")),
|
|
962
|
+
{
|
|
963
|
+
frontendTools: [lookupTool("provider")],
|
|
964
|
+
agents__unsafe_dev_only: { "test-agent": agent },
|
|
965
|
+
},
|
|
966
|
+
);
|
|
967
|
+
|
|
968
|
+
await nextTick();
|
|
969
|
+
await getCore().runAgent({ agent });
|
|
970
|
+
|
|
971
|
+
showOverride.value = false;
|
|
972
|
+
await nextTick();
|
|
973
|
+
await getCore().runAgent({ agent });
|
|
974
|
+
|
|
975
|
+
expect(calls).toEqual(["component", "provider"]);
|
|
976
|
+
wrapper.unmount();
|
|
977
|
+
});
|
|
978
|
+
});
|
|
979
|
+
|
|
915
980
|
describe("Integration with Chat UI", () => {
|
|
916
981
|
it("should render tool output correctly in chat interface", async () => {
|
|
917
982
|
const agent = new MockStepwiseAgent();
|
|
@@ -720,7 +720,12 @@ describe("useHumanInTheLoop E2E - HITL Tool Rendering", () => {
|
|
|
720
720
|
expect(screen.queryByTestId("hitl-enabled")).toBeNull();
|
|
721
721
|
});
|
|
722
722
|
|
|
723
|
-
|
|
723
|
+
// The first run still waits for the unanswered HITL prompt, and a send
|
|
724
|
+
// waits for the run in flight (#5195), so this message stays queued.
|
|
725
|
+
// What this test pins is that the unregistered tool no longer renders.
|
|
726
|
+
const input = await screen.findByRole("textbox");
|
|
727
|
+
await fireEvent.update(input, "Test after disable");
|
|
728
|
+
await fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
|
|
724
729
|
|
|
725
730
|
const messageId2 = testId("msg2");
|
|
726
731
|
const toolCallId2 = testId("tc2");
|
|
@@ -4,7 +4,22 @@ import { z } from "zod";
|
|
|
4
4
|
import type { AbstractAgent } from "@ag-ui/client";
|
|
5
5
|
import { useHumanInTheLoop } from "../use-human-in-the-loop";
|
|
6
6
|
import { mountWithProvider } from "../../__tests__/utils/mount";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
SequencedRunAgent,
|
|
9
|
+
StateCapturingAgent,
|
|
10
|
+
toolCallMessage,
|
|
11
|
+
} from "../../__tests__/utils/agents";
|
|
12
|
+
|
|
13
|
+
/** Handler context for one tool call; core always passes the call. */
|
|
14
|
+
function callContext(id: string, name = "tool") {
|
|
15
|
+
return {
|
|
16
|
+
toolCall: {
|
|
17
|
+
id,
|
|
18
|
+
type: "function" as const,
|
|
19
|
+
function: { name, arguments: "{}" },
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
8
23
|
|
|
9
24
|
describe("useHumanInTheLoop", () => {
|
|
10
25
|
beforeEach(() => {
|
|
@@ -53,7 +68,7 @@ describe("useHumanInTheLoop", () => {
|
|
|
53
68
|
|
|
54
69
|
const pending = registeredTool!.handler!(
|
|
55
70
|
{ question: "Proceed?" },
|
|
56
|
-
|
|
71
|
+
callContext("tc-approve"),
|
|
57
72
|
);
|
|
58
73
|
|
|
59
74
|
const executingVNode = renderer!.render({
|
|
@@ -107,8 +122,8 @@ describe("useHumanInTheLoop", () => {
|
|
|
107
122
|
const renderA = getCore().renderToolCalls.find((rc) => rc.name === "toolA");
|
|
108
123
|
const renderB = getCore().renderToolCalls.find((rc) => rc.name === "toolB");
|
|
109
124
|
|
|
110
|
-
const pA = toolA!.handler!({},
|
|
111
|
-
const pB = toolB!.handler!({},
|
|
125
|
+
const pA = toolA!.handler!({}, callContext("tc-a"));
|
|
126
|
+
const pB = toolB!.handler!({}, callContext("tc-b"));
|
|
112
127
|
|
|
113
128
|
const respondA = (
|
|
114
129
|
renderA!.render({
|
|
@@ -140,6 +155,72 @@ describe("useHumanInTheLoop", () => {
|
|
|
140
155
|
await expect(pB).resolves.toBe("B");
|
|
141
156
|
});
|
|
142
157
|
|
|
158
|
+
it("gives parallel calls of one tool their own respond", async () => {
|
|
159
|
+
const RenderComp = defineComponent({
|
|
160
|
+
props: ["respond"],
|
|
161
|
+
setup() {
|
|
162
|
+
return () => h("div");
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
const Child = defineComponent({
|
|
166
|
+
setup() {
|
|
167
|
+
useHumanInTheLoop({
|
|
168
|
+
name: "parallelTool",
|
|
169
|
+
parameters: z.object({}),
|
|
170
|
+
render: RenderComp,
|
|
171
|
+
});
|
|
172
|
+
return () => null;
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
const { getCore } = mountWithProvider(() => h(Child));
|
|
176
|
+
const handler = getCore().getTool({ toolName: "parallelTool" })!.handler!;
|
|
177
|
+
const renderer = getCore().renderToolCalls.find(
|
|
178
|
+
(rc) => rc.name === "parallelTool",
|
|
179
|
+
)!;
|
|
180
|
+
const respondFor = (toolCallId: string) =>
|
|
181
|
+
(
|
|
182
|
+
renderer.render({
|
|
183
|
+
name: "parallelTool",
|
|
184
|
+
toolCallId,
|
|
185
|
+
args: {},
|
|
186
|
+
status: "executing",
|
|
187
|
+
result: undefined,
|
|
188
|
+
}) as { props?: { respond?: (result: unknown) => Promise<void> } }
|
|
189
|
+
).props!.respond!;
|
|
190
|
+
|
|
191
|
+
const first = handler({}, callContext("call-1"));
|
|
192
|
+
const second = handler({}, callContext("call-2"));
|
|
193
|
+
await respondFor("call-2")("second");
|
|
194
|
+
await respondFor("call-1")("first");
|
|
195
|
+
|
|
196
|
+
await expect(first).resolves.toBe("first");
|
|
197
|
+
await expect(second).resolves.toBe("second");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("passes the called tool's name to a catch-all render", () => {
|
|
201
|
+
const RenderComp = defineComponent({
|
|
202
|
+
setup() {
|
|
203
|
+
return () => h("div");
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
const Child = defineComponent({
|
|
207
|
+
setup() {
|
|
208
|
+
useHumanInTheLoop({ name: "*", render: RenderComp });
|
|
209
|
+
return () => null;
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
const { getCore } = mountWithProvider(() => h(Child));
|
|
213
|
+
const renderer = getCore().renderToolCalls.find((rc) => rc.name === "*")!;
|
|
214
|
+
const vnode = renderer.render({
|
|
215
|
+
name: "deleteFile",
|
|
216
|
+
toolCallId: "tc-any",
|
|
217
|
+
args: {},
|
|
218
|
+
status: "inProgress",
|
|
219
|
+
result: undefined,
|
|
220
|
+
}) as { props?: Record<string, unknown> };
|
|
221
|
+
expect(vnode.props?.name).toBe("deleteFile");
|
|
222
|
+
});
|
|
223
|
+
|
|
143
224
|
it("only exposes respond during executing status", () => {
|
|
144
225
|
const RenderComp = defineComponent({
|
|
145
226
|
props: ["respond"],
|
|
@@ -323,9 +404,9 @@ describe("useHumanInTheLoop", () => {
|
|
|
323
404
|
const controller = new AbortController();
|
|
324
405
|
controller.abort();
|
|
325
406
|
|
|
326
|
-
await expect(
|
|
327
|
-
|
|
328
|
-
);
|
|
407
|
+
await expect(
|
|
408
|
+
handler!({}, { ...callContext("tc-x"), signal: controller.signal }),
|
|
409
|
+
).rejects.toEqual(new Error("Human-in-the-loop interaction aborted"));
|
|
329
410
|
});
|
|
330
411
|
|
|
331
412
|
it("rejects once on abort, clears pending refs, and installs a one-shot listener", async () => {
|
|
@@ -344,7 +425,7 @@ describe("useHumanInTheLoop", () => {
|
|
|
344
425
|
}),
|
|
345
426
|
} as unknown as AbortSignal;
|
|
346
427
|
|
|
347
|
-
const pending = handler!({}, { signal });
|
|
428
|
+
const pending = handler!({}, { ...callContext("tc-aborted"), signal });
|
|
348
429
|
expect(listeners.size).toBe(1);
|
|
349
430
|
const onAbort = [...listeners][0];
|
|
350
431
|
onAbort();
|
|
@@ -379,7 +460,13 @@ describe("useHumanInTheLoop", () => {
|
|
|
379
460
|
}),
|
|
380
461
|
} as unknown as AbortSignal;
|
|
381
462
|
|
|
382
|
-
const pending = handler!(
|
|
463
|
+
const pending = handler!(
|
|
464
|
+
{},
|
|
465
|
+
{
|
|
466
|
+
...callContext("tc-respond"),
|
|
467
|
+
signal,
|
|
468
|
+
},
|
|
469
|
+
).then((result) => {
|
|
383
470
|
events.push(`resolved:${String(result)}`);
|
|
384
471
|
return result;
|
|
385
472
|
});
|
|
@@ -511,10 +598,98 @@ describe("useHumanInTheLoop", () => {
|
|
|
511
598
|
expect(vnode.props?.agentId).toBeUndefined();
|
|
512
599
|
});
|
|
513
600
|
|
|
601
|
+
it("lets a message queued behind an unanswered prompt send after the prompt unmounts", async () => {
|
|
602
|
+
const prompt = toolCallMessage("unmountApproval");
|
|
603
|
+
const toolCallId = (prompt as { toolCalls: { id: string }[] })
|
|
604
|
+
.toolCalls[0]!.id;
|
|
605
|
+
const agent = new SequencedRunAgent(
|
|
606
|
+
[
|
|
607
|
+
() => ({ result: undefined, newMessages: [prompt] }),
|
|
608
|
+
() => ({
|
|
609
|
+
result: undefined,
|
|
610
|
+
newMessages: [{ id: "reply", role: "assistant", content: "ok" }],
|
|
611
|
+
}),
|
|
612
|
+
],
|
|
613
|
+
"default",
|
|
614
|
+
);
|
|
615
|
+
const RenderComp = defineComponent({
|
|
616
|
+
setup() {
|
|
617
|
+
return () => h("div");
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
const shown = ref(true);
|
|
621
|
+
const Child = defineComponent({
|
|
622
|
+
setup() {
|
|
623
|
+
useHumanInTheLoop({
|
|
624
|
+
name: "unmountApproval",
|
|
625
|
+
parameters: z.object({}),
|
|
626
|
+
render: RenderComp,
|
|
627
|
+
});
|
|
628
|
+
return () => null;
|
|
629
|
+
},
|
|
630
|
+
});
|
|
631
|
+
const { getCore } = mountWithProvider(
|
|
632
|
+
() => (shown.value ? h(Child) : null),
|
|
633
|
+
{
|
|
634
|
+
agents__unsafe_dev_only: {
|
|
635
|
+
default: agent as unknown as AbstractAgent,
|
|
636
|
+
},
|
|
637
|
+
},
|
|
638
|
+
);
|
|
639
|
+
const core = getCore();
|
|
640
|
+
const sendMessage = async (content: string) => {
|
|
641
|
+
agent.addMessage({ id: content, role: "user", content });
|
|
642
|
+
await core.runAgent({ agent: agent as unknown as AbstractAgent });
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
const first = sendMessage("approve this");
|
|
646
|
+
const queued = first.then(() => sendMessage("next question"));
|
|
647
|
+
await vi.waitFor(() =>
|
|
648
|
+
expect(core.ɵhumanInTheLoop.isPending(toolCallId)).toBe(true),
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
shown.value = false;
|
|
652
|
+
await nextTick();
|
|
653
|
+
|
|
654
|
+
await expect(queued).resolves.toBeUndefined();
|
|
655
|
+
expect(agent.messages).toEqual(
|
|
656
|
+
expect.arrayContaining([
|
|
657
|
+
expect.objectContaining({
|
|
658
|
+
role: "tool",
|
|
659
|
+
toolCallId,
|
|
660
|
+
error: "Human-in-the-loop interaction aborted",
|
|
661
|
+
}),
|
|
662
|
+
expect.objectContaining({ id: "reply", content: "ok" }),
|
|
663
|
+
]),
|
|
664
|
+
);
|
|
665
|
+
});
|
|
666
|
+
|
|
514
667
|
it("does not settle a pending HITL promise when its renderer unmounts", async () => {
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
668
|
+
const RenderComp = defineComponent({
|
|
669
|
+
setup() {
|
|
670
|
+
return () => h("div");
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
const shown = ref(true);
|
|
674
|
+
const Child = defineComponent({
|
|
675
|
+
setup() {
|
|
676
|
+
useHumanInTheLoop({
|
|
677
|
+
name: "unmountTool",
|
|
678
|
+
parameters: z.object({}),
|
|
679
|
+
render: RenderComp,
|
|
680
|
+
});
|
|
681
|
+
return () => null;
|
|
682
|
+
},
|
|
683
|
+
});
|
|
684
|
+
const { getCore } = mountWithProvider(() =>
|
|
685
|
+
shown.value ? h(Child) : null,
|
|
686
|
+
);
|
|
687
|
+
const pending = getCore().getTool({ toolName: "unmountTool" })!.handler!(
|
|
688
|
+
{},
|
|
689
|
+
callContext("tc-unmount"),
|
|
690
|
+
);
|
|
691
|
+
shown.value = false;
|
|
692
|
+
await nextTick();
|
|
518
693
|
|
|
519
694
|
const outcome = await Promise.race([
|
|
520
695
|
pending.then(
|