@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
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
normalizeAutoScroll,
|
|
4
|
-
type AutoScrollMode,
|
|
5
|
-
} from "../normalize-auto-scroll";
|
|
6
|
-
|
|
7
|
-
// Strict counterpart of React `normalize-auto-scroll.test.ts`.
|
|
8
|
-
// Keep case order and wording aligned 1:1 with the React suite.
|
|
9
|
-
describe("normalizeAutoScroll", () => {
|
|
10
|
-
it("returns 'pin-to-bottom' for undefined (default)", () => {
|
|
11
|
-
expect(normalizeAutoScroll(undefined)).toBe("pin-to-bottom");
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("maps true -> 'pin-to-bottom'", () => {
|
|
15
|
-
expect(normalizeAutoScroll(true)).toBe("pin-to-bottom");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("maps false -> 'none'", () => {
|
|
19
|
-
expect(normalizeAutoScroll(false)).toBe("none");
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("passes 'pin-to-bottom' through", () => {
|
|
23
|
-
expect(normalizeAutoScroll("pin-to-bottom")).toBe("pin-to-bottom");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("passes 'pin-to-send' through", () => {
|
|
27
|
-
expect(normalizeAutoScroll("pin-to-send")).toBe("pin-to-send");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("passes 'none' through", () => {
|
|
31
|
-
expect(normalizeAutoScroll("none")).toBe("none");
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("falls back to 'pin-to-bottom' for unknown strings", () => {
|
|
35
|
-
expect(normalizeAutoScroll("bogus" as AutoScrollMode)).toBe(
|
|
36
|
-
"pin-to-bottom",
|
|
37
|
-
);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export type AutoScrollMode = "pin-to-bottom" | "pin-to-send" | "none";
|
|
2
|
-
|
|
3
|
-
const VALID: readonly AutoScrollMode[] = [
|
|
4
|
-
"pin-to-bottom",
|
|
5
|
-
"pin-to-send",
|
|
6
|
-
"none",
|
|
7
|
-
];
|
|
8
|
-
|
|
9
|
-
export function normalizeAutoScroll(
|
|
10
|
-
value: AutoScrollMode | boolean | undefined,
|
|
11
|
-
): AutoScrollMode {
|
|
12
|
-
if (value === undefined) return "pin-to-bottom";
|
|
13
|
-
if (value === true) return "pin-to-bottom";
|
|
14
|
-
if (value === false) return "none";
|
|
15
|
-
if ((VALID as readonly string[]).includes(value)) return value;
|
|
16
|
-
return "pin-to-bottom";
|
|
17
|
-
}
|
|
@@ -1,304 +0,0 @@
|
|
|
1
|
-
import type { Message, ToolCall, ToolMessage } from "@ag-ui/core";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* How the chat shows tool calls.
|
|
5
|
-
*
|
|
6
|
-
* - `"grouped"` (default): calls made in a row share one card, collapsed to a
|
|
7
|
-
* summary ("Used 3 tools") that opens to a row per call.
|
|
8
|
-
* - `"line"`: the same grouping as a quiet line of text, like the reasoning
|
|
9
|
-
* message's "Thought for 4 seconds".
|
|
10
|
-
* - `"stacked"`: the latest call on top of a stack of the earlier ones; click
|
|
11
|
-
* to fan the stack out into its cards.
|
|
12
|
-
* - `"turn"`: the agent works in the open (narration, then a row per call),
|
|
13
|
-
* and when the reply is done everything before it folds into "Worked for 9s".
|
|
14
|
-
* - `"separate"`: every call gets its own card, as before grouping existed.
|
|
15
|
-
*
|
|
16
|
-
* Only calls drawn by a renderer that opts into grouping (`group: true`) are
|
|
17
|
-
* grouped; CopilotKit's built-in card from `useDefaultRenderTool()` does. Any
|
|
18
|
-
* other call always shows on its own and splits the group around it.
|
|
19
|
-
*/
|
|
20
|
-
export type CopilotChatToolCallDisplay =
|
|
21
|
-
| "grouped"
|
|
22
|
-
| "line"
|
|
23
|
-
| "stacked"
|
|
24
|
-
| "turn"
|
|
25
|
-
| "separate";
|
|
26
|
-
|
|
27
|
-
/** One tool call and, once it has finished, the message carrying its result. */
|
|
28
|
-
export interface ToolCallEntry {
|
|
29
|
-
toolCall: ToolCall;
|
|
30
|
-
toolMessage?: ToolMessage;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type ToolCallSegment =
|
|
34
|
-
/** Consecutive calls drawn by renderers that opted into grouping. */
|
|
35
|
-
| {
|
|
36
|
-
kind: "group";
|
|
37
|
-
id: string;
|
|
38
|
-
calls: ToolCallEntry[];
|
|
39
|
-
/** Nothing renders after this group yet, so a running agent may add to it. */
|
|
40
|
-
trailing: boolean;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* A call drawn by a renderer that didn't opt into grouping, or with no
|
|
44
|
-
* renderer at all. The latter renders nothing (and warns in development)
|
|
45
|
-
* without breaking a group.
|
|
46
|
-
*/
|
|
47
|
-
| { kind: "call"; id: string; call: ToolCallEntry; rendered: boolean };
|
|
48
|
-
|
|
49
|
-
/** What one assistant message's tool-call area renders. */
|
|
50
|
-
export interface ToolCallLayout {
|
|
51
|
-
segments: ToolCallSegment[];
|
|
52
|
-
/** Changes whenever anything this layout renders changes; for memoization. */
|
|
53
|
-
signature: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Which tool-call renderers are registered. */
|
|
57
|
-
export interface ToolCallRendererNames {
|
|
58
|
-
/** Tool names with a renderer of their own. */
|
|
59
|
-
named: ReadonlySet<string>;
|
|
60
|
-
/** Of those, the ones whose renderer opted into grouping. */
|
|
61
|
-
groupedNames: ReadonlySet<string>;
|
|
62
|
-
/** A wildcard (`"*"`) renderer is registered. */
|
|
63
|
-
wildcard: boolean;
|
|
64
|
-
/** The wildcard renderer opted into grouping (the built-in card does). */
|
|
65
|
-
wildcardGroups: boolean;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function contentLength(content: ToolMessage["content"]): number {
|
|
69
|
-
return typeof content === "string"
|
|
70
|
-
? content.length
|
|
71
|
-
: JSON.stringify(content ?? "").length;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const entrySignature = ({ toolCall, toolMessage }: ToolCallEntry) =>
|
|
75
|
-
[
|
|
76
|
-
toolCall.id,
|
|
77
|
-
toolCall.function.name,
|
|
78
|
-
toolCall.function.arguments.length,
|
|
79
|
-
toolMessage
|
|
80
|
-
? `${contentLength(toolMessage.content)}${toolMessage.error ? "!" : ""}`
|
|
81
|
-
: "-",
|
|
82
|
-
].join(":");
|
|
83
|
-
|
|
84
|
-
function signatureOf(segments: ToolCallSegment[]): string {
|
|
85
|
-
return segments
|
|
86
|
-
.map((segment) =>
|
|
87
|
-
segment.kind === "call"
|
|
88
|
-
? `c(${entrySignature(segment.call)})`
|
|
89
|
-
: `g${segment.trailing ? "*" : ""}(${segment.calls.map(entrySignature).join(",")})`,
|
|
90
|
-
)
|
|
91
|
-
.join("|");
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** Index of tool results by the call they answer. */
|
|
95
|
-
export function getToolResults(messages: Message[]): Map<string, ToolMessage> {
|
|
96
|
-
const results = new Map<string, ToolMessage>();
|
|
97
|
-
for (const message of messages) {
|
|
98
|
-
if (message.role === "tool") results.set(message.toolCallId, message);
|
|
99
|
-
}
|
|
100
|
-
return results;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Lays out the tool calls of every assistant message in `rendered`.
|
|
105
|
-
*
|
|
106
|
-
* Calls drawn by a renderer that opted into grouping join the group that's
|
|
107
|
-
* open; anything else that shows between them closes it: assistant text, a
|
|
108
|
-
* user, reasoning or activity message, or a call drawn by any other renderer. A group belongs to
|
|
109
|
-
* the message where it starts, so later messages whose calls joined it render
|
|
110
|
-
* no tool calls themselves.
|
|
111
|
-
*
|
|
112
|
-
* @param rendered - The messages as the chat renders them, in order.
|
|
113
|
-
* @param all - Every message, for finding tool results (a transform may hide them).
|
|
114
|
-
* @param renderers - The registered renderers.
|
|
115
|
-
*/
|
|
116
|
-
export function getToolCallLayouts(
|
|
117
|
-
rendered: Message[],
|
|
118
|
-
all: Message[],
|
|
119
|
-
renderers: ToolCallRendererNames,
|
|
120
|
-
): Map<string, ToolCallLayout> {
|
|
121
|
-
const results = getToolResults(all);
|
|
122
|
-
const layouts = new Map<string, ToolCallSegment[]>();
|
|
123
|
-
let open: Extract<ToolCallSegment, { kind: "group" }> | undefined;
|
|
124
|
-
|
|
125
|
-
for (const message of rendered) {
|
|
126
|
-
if (message.role === "tool") continue;
|
|
127
|
-
if (message.role !== "assistant") {
|
|
128
|
-
open = undefined;
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (typeof message.content === "string" && message.content.trim()) {
|
|
132
|
-
open = undefined;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const segments: ToolCallSegment[] = [];
|
|
136
|
-
layouts.set(message.id, segments);
|
|
137
|
-
// Streaming can repeat a call: keep its first position, last content.
|
|
138
|
-
const toolCalls = new Map<string, ToolCall>();
|
|
139
|
-
for (const toolCall of message.toolCalls ?? []) {
|
|
140
|
-
toolCalls.set(toolCall.id, toolCall);
|
|
141
|
-
}
|
|
142
|
-
for (const toolCall of toolCalls.values()) {
|
|
143
|
-
const entry = { toolCall, toolMessage: results.get(toolCall.id) };
|
|
144
|
-
|
|
145
|
-
const name = toolCall.function.name;
|
|
146
|
-
const named = renderers.named.has(name);
|
|
147
|
-
const rendered = named || renderers.wildcard;
|
|
148
|
-
const groups = named
|
|
149
|
-
? renderers.groupedNames.has(name)
|
|
150
|
-
: renderers.wildcardGroups;
|
|
151
|
-
|
|
152
|
-
if (!rendered || !groups) {
|
|
153
|
-
if (rendered) open = undefined;
|
|
154
|
-
segments.push({ kind: "call", id: toolCall.id, call: entry, rendered });
|
|
155
|
-
} else if (open) {
|
|
156
|
-
open.calls.push(entry);
|
|
157
|
-
} else {
|
|
158
|
-
open = {
|
|
159
|
-
kind: "group",
|
|
160
|
-
id: toolCall.id,
|
|
161
|
-
calls: [entry],
|
|
162
|
-
trailing: false,
|
|
163
|
-
};
|
|
164
|
-
segments.push(open);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (open) open.trailing = true;
|
|
169
|
-
|
|
170
|
-
const layout = new Map<string, ToolCallLayout>();
|
|
171
|
-
for (const [id, segments] of layouts) {
|
|
172
|
-
layout.set(id, { segments, signature: signatureOf(segments) });
|
|
173
|
-
}
|
|
174
|
-
return layout;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const TOOL_CALL_SLOT_PREFIX = "tool-call-";
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Which renderers draw tool calls, from the registered renderers and the
|
|
181
|
-
* view's tool-call slots. A slot wins over a registered renderer and never
|
|
182
|
-
* groups, since the chat can't tell what it draws: `#tool-call-<name>` takes
|
|
183
|
-
* that tool, and `#tool-call` takes every tool.
|
|
184
|
-
*
|
|
185
|
-
* @param renderers - The registered renderers (`copilotkit.renderToolCalls`).
|
|
186
|
-
* @param slotNames - The names of the slots the view was given.
|
|
187
|
-
*/
|
|
188
|
-
export function getToolCallRendererNames(
|
|
189
|
-
renderers: readonly { name: string; group?: boolean }[],
|
|
190
|
-
slotNames: readonly string[] = [],
|
|
191
|
-
): ToolCallRendererNames {
|
|
192
|
-
const wildcardSlot = slotNames.includes("tool-call");
|
|
193
|
-
const slotTools = slotNames
|
|
194
|
-
.filter((name) => name.startsWith(TOOL_CALL_SLOT_PREFIX))
|
|
195
|
-
.map((name) => name.slice(TOOL_CALL_SLOT_PREFIX.length));
|
|
196
|
-
const named = renderers.filter((renderer) => renderer.name !== "*");
|
|
197
|
-
const wildcards = renderers.filter((renderer) => renderer.name === "*");
|
|
198
|
-
return {
|
|
199
|
-
named: new Set([...named.map((renderer) => renderer.name), ...slotTools]),
|
|
200
|
-
groupedNames: new Set(
|
|
201
|
-
wildcardSlot
|
|
202
|
-
? []
|
|
203
|
-
: named
|
|
204
|
-
.filter(
|
|
205
|
-
(renderer) =>
|
|
206
|
-
renderer.group && !slotTools.includes(renderer.name),
|
|
207
|
-
)
|
|
208
|
-
.map((renderer) => renderer.name),
|
|
209
|
-
),
|
|
210
|
-
wildcard: wildcards.length > 0 || wildcardSlot,
|
|
211
|
-
wildcardGroups:
|
|
212
|
-
!wildcardSlot && wildcards.some((renderer) => renderer.group),
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/** A reply's working phase, for the `"turn"` display. */
|
|
217
|
-
export interface TurnWork {
|
|
218
|
-
/** Stable across the turn's life: the id of the user message it answers. */
|
|
219
|
-
key: string;
|
|
220
|
-
/** The first assistant-side message, where the "Worked for" line goes. */
|
|
221
|
-
firstMessageId: string;
|
|
222
|
-
/** Everything up to and including the last message with a tool call. */
|
|
223
|
-
workMessageIds: ReadonlySet<string>;
|
|
224
|
-
/**
|
|
225
|
-
* The reply's last assistant message, when it has text and is part of the
|
|
226
|
-
* work (it also calls a tool). Its text is the answer, so it stays out.
|
|
227
|
-
*/
|
|
228
|
-
replyTextMessageId?: string;
|
|
229
|
-
calls: ToolCallEntry[];
|
|
230
|
-
/** No user message follows, so the agent may still be working on it. */
|
|
231
|
-
isLatest: boolean;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Finds the working phase of every reply in `rendered`: its messages up to the
|
|
236
|
-
* last one that calls a tool. Text in there was narration; what follows is the
|
|
237
|
-
* reply itself. Replies that called no tools are omitted, except the latest,
|
|
238
|
-
* which may be about to.
|
|
239
|
-
*/
|
|
240
|
-
export function getTurnWork(
|
|
241
|
-
rendered: Message[],
|
|
242
|
-
layouts: ReadonlyMap<string, ToolCallLayout>,
|
|
243
|
-
): Map<string, TurnWork> {
|
|
244
|
-
const turns = new Map<string, TurnWork>();
|
|
245
|
-
let start = 0;
|
|
246
|
-
while (start < rendered.length) {
|
|
247
|
-
let end = start;
|
|
248
|
-
while (end < rendered.length && rendered[end]!.role !== "user") end++;
|
|
249
|
-
const key = start > 0 ? rendered[start - 1]!.id : "start";
|
|
250
|
-
const visible = rendered
|
|
251
|
-
.slice(start, end)
|
|
252
|
-
.filter((message) => message.role !== "tool");
|
|
253
|
-
const isLatest = end === rendered.length;
|
|
254
|
-
|
|
255
|
-
// A message's calls may sit in a group an earlier message owns, so
|
|
256
|
-
// collect every shown call first, then find the last message making one.
|
|
257
|
-
const calls: ToolCallEntry[] = [];
|
|
258
|
-
for (const message of visible) {
|
|
259
|
-
for (const segment of layouts.get(message.id)?.segments ?? []) {
|
|
260
|
-
if (segment.kind === "group") calls.push(...segment.calls);
|
|
261
|
-
else if (segment.rendered) calls.push(segment.call);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
const shown = new Set(calls.map((entry) => entry.toolCall.id));
|
|
265
|
-
let lastWork = -1;
|
|
266
|
-
visible.forEach((message, index) => {
|
|
267
|
-
if (
|
|
268
|
-
message.role === "assistant" &&
|
|
269
|
-
message.toolCalls?.some((call) => shown.has(call.id))
|
|
270
|
-
) {
|
|
271
|
-
lastWork = index;
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
const first = visible[0];
|
|
276
|
-
if (first && (calls.length > 0 || isLatest)) {
|
|
277
|
-
let lastAssistant = -1;
|
|
278
|
-
visible.forEach((message, index) => {
|
|
279
|
-
if (message.role === "assistant") lastAssistant = index;
|
|
280
|
-
});
|
|
281
|
-
const replyText = visible[lastAssistant]?.content;
|
|
282
|
-
const endsWithWork =
|
|
283
|
-
lastAssistant >= 0 &&
|
|
284
|
-
lastAssistant <= lastWork &&
|
|
285
|
-
typeof replyText === "string" &&
|
|
286
|
-
replyText.trim().length > 0;
|
|
287
|
-
|
|
288
|
-
turns.set(key, {
|
|
289
|
-
key,
|
|
290
|
-
firstMessageId: first.id,
|
|
291
|
-
workMessageIds: new Set(
|
|
292
|
-
visible.slice(0, lastWork + 1).map((message) => message.id),
|
|
293
|
-
),
|
|
294
|
-
replyTextMessageId: endsWithWork
|
|
295
|
-
? visible[lastAssistant]!.id
|
|
296
|
-
: undefined,
|
|
297
|
-
calls,
|
|
298
|
-
isLatest,
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
start = end + 1;
|
|
302
|
-
}
|
|
303
|
-
return turns;
|
|
304
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { isMobileViewport } from "../is-mobile-viewport";
|
|
3
|
-
|
|
4
|
-
describe("isMobileViewport", () => {
|
|
5
|
-
const originalMatchMedia = window.matchMedia;
|
|
6
|
-
|
|
7
|
-
afterEach(() => {
|
|
8
|
-
window.matchMedia = originalMatchMedia;
|
|
9
|
-
vi.restoreAllMocks();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("returns false when window.matchMedia is undefined", () => {
|
|
13
|
-
// @ts-expect-error - simulating an environment without matchMedia support.
|
|
14
|
-
delete window.matchMedia;
|
|
15
|
-
|
|
16
|
-
expect(isMobileViewport()).toBe(false);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("returns true when the mobile media query matches", () => {
|
|
20
|
-
window.matchMedia = vi.fn().mockReturnValue({
|
|
21
|
-
matches: true,
|
|
22
|
-
media: "(max-width: 767px)",
|
|
23
|
-
onchange: null,
|
|
24
|
-
addEventListener: vi.fn(),
|
|
25
|
-
removeEventListener: vi.fn(),
|
|
26
|
-
addListener: vi.fn(),
|
|
27
|
-
removeListener: vi.fn(),
|
|
28
|
-
dispatchEvent: vi.fn(),
|
|
29
|
-
} as unknown as MediaQueryList);
|
|
30
|
-
|
|
31
|
-
expect(isMobileViewport()).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("returns false when the mobile media query does not match", () => {
|
|
35
|
-
window.matchMedia = vi.fn().mockReturnValue({
|
|
36
|
-
matches: false,
|
|
37
|
-
media: "(max-width: 767px)",
|
|
38
|
-
onchange: null,
|
|
39
|
-
addEventListener: vi.fn(),
|
|
40
|
-
removeEventListener: vi.fn(),
|
|
41
|
-
addListener: vi.fn(),
|
|
42
|
-
removeListener: vi.fn(),
|
|
43
|
-
dispatchEvent: vi.fn(),
|
|
44
|
-
} as unknown as MediaQueryList);
|
|
45
|
-
|
|
46
|
-
expect(isMobileViewport()).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { CopilotKitCore } from "@copilotkit/core";
|
|
2
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import {
|
|
4
|
-
getMessageFeedback,
|
|
5
|
-
subscribeToMessageFeedback,
|
|
6
|
-
MESSAGE_FEEDBACK_EVENT_NAME,
|
|
7
|
-
setMessageFeedback,
|
|
8
|
-
ɵresetMessageFeedbackCache,
|
|
9
|
-
} from "../message-feedback";
|
|
10
|
-
|
|
11
|
-
const emoji = "👍";
|
|
12
|
-
|
|
13
|
-
/** A Core that records what it emits, with its agent-text choice stubbed. */
|
|
14
|
-
function capturingCore({ agentText = true } = {}) {
|
|
15
|
-
const copilotkit = new CopilotKitCore({});
|
|
16
|
-
vi.spyOn(copilotkit, "ɵlearningCapturesAgentText", "get").mockReturnValue(
|
|
17
|
-
agentText,
|
|
18
|
-
);
|
|
19
|
-
const emit = vi
|
|
20
|
-
.spyOn(copilotkit, "emitTrajectoryEvent")
|
|
21
|
-
.mockImplementation(() => {});
|
|
22
|
-
return { copilotkit, emit };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const reply = { id: "m1", role: "assistant" as const, content: "Approved." };
|
|
26
|
-
|
|
27
|
-
const rate = (
|
|
28
|
-
copilotkit: CopilotKitCore,
|
|
29
|
-
feedback: { rating: "up" | "down"; comment?: string } | null,
|
|
30
|
-
message: { id: string; role: "assistant"; content: string } = reply,
|
|
31
|
-
) =>
|
|
32
|
-
setMessageFeedback({
|
|
33
|
-
copilotkit,
|
|
34
|
-
agentId: "agent",
|
|
35
|
-
threadId: "thread",
|
|
36
|
-
message,
|
|
37
|
-
feedback,
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe("message feedback store", () => {
|
|
41
|
-
beforeEach(() => ɵresetMessageFeedbackCache());
|
|
42
|
-
afterEach(() => vi.restoreAllMocks());
|
|
43
|
-
|
|
44
|
-
it("cuts long text without splitting a character", () => {
|
|
45
|
-
const { copilotkit, emit } = capturingCore();
|
|
46
|
-
|
|
47
|
-
rate(
|
|
48
|
-
copilotkit,
|
|
49
|
-
{ rating: "up", comment: emoji.repeat(1200) },
|
|
50
|
-
{ id: "m1", role: "assistant", content: emoji.repeat(600) },
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const [name, value] = emit.mock.calls[0]!;
|
|
54
|
-
expect(name).toBe(MESSAGE_FEEDBACK_EVENT_NAME);
|
|
55
|
-
expect(value).toMatchObject({
|
|
56
|
-
response: emoji.repeat(500),
|
|
57
|
-
comment: emoji.repeat(1000),
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("keeps the rating and sends each change, a removal as null", () => {
|
|
62
|
-
const { copilotkit, emit } = capturingCore();
|
|
63
|
-
|
|
64
|
-
rate(copilotkit, { rating: "up" });
|
|
65
|
-
expect(getMessageFeedback("agent", "thread", "m1")).toEqual({
|
|
66
|
-
rating: "up",
|
|
67
|
-
});
|
|
68
|
-
rate(copilotkit, null);
|
|
69
|
-
|
|
70
|
-
expect(getMessageFeedback("agent", "thread", "m1")).toBeUndefined();
|
|
71
|
-
expect(emit.mock.calls.map(([, value]) => value)).toEqual([
|
|
72
|
-
expect.objectContaining({ feedbackId: "thread:m1", rating: "up" }),
|
|
73
|
-
expect.objectContaining({ feedbackId: "thread:m1", rating: null }),
|
|
74
|
-
]);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("trims a comment and drops a blank one", () => {
|
|
78
|
-
const { copilotkit } = capturingCore();
|
|
79
|
-
|
|
80
|
-
rate(copilotkit, { rating: "down", comment: " " });
|
|
81
|
-
expect(getMessageFeedback("agent", "thread", "m1")).toEqual({
|
|
82
|
-
rating: "down",
|
|
83
|
-
});
|
|
84
|
-
rate(copilotkit, { rating: "down", comment: " padded " });
|
|
85
|
-
|
|
86
|
-
expect(getMessageFeedback("agent", "thread", "m1")).toEqual({
|
|
87
|
-
rating: "down",
|
|
88
|
-
comment: "padded",
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("tells only the rated Thread's listeners", () => {
|
|
93
|
-
const { copilotkit } = capturingCore();
|
|
94
|
-
const rated = vi.fn();
|
|
95
|
-
const other = vi.fn();
|
|
96
|
-
subscribeToMessageFeedback("agent", "thread", rated);
|
|
97
|
-
subscribeToMessageFeedback("agent", "other", other);
|
|
98
|
-
|
|
99
|
-
rate(copilotkit, { rating: "up" });
|
|
100
|
-
|
|
101
|
-
expect(rated).toHaveBeenCalledTimes(1);
|
|
102
|
-
expect(other).not.toHaveBeenCalled();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("keeps the object of a rating that did not change", () => {
|
|
106
|
-
const { copilotkit } = capturingCore();
|
|
107
|
-
rate(copilotkit, { rating: "up" });
|
|
108
|
-
const before = getMessageFeedback("agent", "thread", "m1");
|
|
109
|
-
|
|
110
|
-
rate(
|
|
111
|
-
copilotkit,
|
|
112
|
-
{ rating: "down" },
|
|
113
|
-
{ id: "m2", role: "assistant", content: "No." },
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
expect(getMessageFeedback("agent", "thread", "m1")).toBe(before);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it("treats message ids like object keys as plain ids", () => {
|
|
120
|
-
const { copilotkit } = capturingCore();
|
|
121
|
-
|
|
122
|
-
rate(
|
|
123
|
-
copilotkit,
|
|
124
|
-
{ rating: "up" },
|
|
125
|
-
{ id: "__proto__", role: "assistant", content: "" },
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
expect(getMessageFeedback("agent", "thread", "__proto__")).toEqual({
|
|
129
|
-
rating: "up",
|
|
130
|
-
});
|
|
131
|
-
expect(
|
|
132
|
-
getMessageFeedback("agent", "thread", "constructor"),
|
|
133
|
-
).toBeUndefined();
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it("leaves out the reply text when capture omits agent text", () => {
|
|
137
|
-
const { copilotkit, emit } = capturingCore({ agentText: false });
|
|
138
|
-
|
|
139
|
-
rate(copilotkit, { rating: "up" });
|
|
140
|
-
|
|
141
|
-
expect(emit.mock.calls[0]![1]).not.toHaveProperty("response");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("names the reply's run when Core knows it", () => {
|
|
145
|
-
const { copilotkit, emit } = capturingCore();
|
|
146
|
-
vi.spyOn(copilotkit, "getRunIdForMessage").mockReturnValue("run-9");
|
|
147
|
-
|
|
148
|
-
rate(copilotkit, { rating: "up" });
|
|
149
|
-
|
|
150
|
-
expect(emit.mock.calls[0]![1]).toMatchObject({ runId: "run-9" });
|
|
151
|
-
});
|
|
152
|
-
});
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
processPartialHtml,
|
|
4
|
-
extractCompleteStyles,
|
|
5
|
-
} from "../processPartialHtml";
|
|
6
|
-
|
|
7
|
-
describe("processPartialHtml", () => {
|
|
8
|
-
it("returns empty string for empty input", () => {
|
|
9
|
-
expect(processPartialHtml("")).toBe("");
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("strips incomplete tag at end", () => {
|
|
13
|
-
expect(processPartialHtml('<div>Hello<span class="fo')).toBe("<div>Hello");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("strips complete <style> blocks", () => {
|
|
17
|
-
const input =
|
|
18
|
-
"<div>Hello</div><style>.foo { color: red; }</style><p>World</p>";
|
|
19
|
-
expect(processPartialHtml(input)).toBe("<div>Hello</div><p>World</p>");
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("strips complete <script> blocks", () => {
|
|
23
|
-
const input = '<div>Hello</div><script>alert("hi")</script><p>World</p>';
|
|
24
|
-
expect(processPartialHtml(input)).toBe("<div>Hello</div><p>World</p>");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("strips incomplete <style> block", () => {
|
|
28
|
-
const input = "<div>Hello</div><style>.foo { color:";
|
|
29
|
-
expect(processPartialHtml(input)).toBe("<div>Hello</div>");
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("strips incomplete <script> block", () => {
|
|
33
|
-
const input = '<div>Hello</div><script>const x = "val';
|
|
34
|
-
expect(processPartialHtml(input)).toBe("<div>Hello</div>");
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("strips incomplete HTML entities", () => {
|
|
38
|
-
expect(processPartialHtml("<p>Hello &")).toBe("<p>Hello ");
|
|
39
|
-
expect(processPartialHtml("<p>Hello {")).toBe("<p>Hello ");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("preserves complete entities", () => {
|
|
43
|
-
expect(processPartialHtml("<p>Hello & World</p>")).toBe(
|
|
44
|
-
"<p>Hello & World</p>",
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("extracts body content from full HTML document", () => {
|
|
49
|
-
const input =
|
|
50
|
-
"<html><head><title>Test</title></head><body><p>Content</p></body></html>";
|
|
51
|
-
expect(processPartialHtml(input)).toBe("<p>Content</p>");
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("handles <body> with attributes", () => {
|
|
55
|
-
const input = '<body class="dark"><p>Content</p></body>';
|
|
56
|
-
expect(processPartialHtml(input)).toBe("<p>Content</p>");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("handles no <body> tag", () => {
|
|
60
|
-
const input = "<div><p>Just content</p></div>";
|
|
61
|
-
expect(processPartialHtml(input)).toBe("<div><p>Just content</p></div>");
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe("extractCompleteStyles", () => {
|
|
66
|
-
it("returns empty string for no styles", () => {
|
|
67
|
-
expect(extractCompleteStyles("<div>Hello</div>")).toBe("");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("extracts a single complete style block", () => {
|
|
71
|
-
const input =
|
|
72
|
-
"<div>Hello</div><style>.foo { color: red; }</style><p>World</p>";
|
|
73
|
-
expect(extractCompleteStyles(input)).toBe(
|
|
74
|
-
"<style>.foo { color: red; }</style>",
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("extracts multiple complete style blocks", () => {
|
|
79
|
-
const input = "<style>a{}</style><div>X</div><style>b{}</style>";
|
|
80
|
-
expect(extractCompleteStyles(input)).toBe(
|
|
81
|
-
"<style>a{}</style><style>b{}</style>",
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
});
|