@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
|
@@ -5,11 +5,19 @@ import {
|
|
|
5
5
|
onBeforeUnmount,
|
|
6
6
|
onMounted,
|
|
7
7
|
ref,
|
|
8
|
+
shallowRef,
|
|
8
9
|
useAttrs,
|
|
9
10
|
watch,
|
|
10
11
|
} from "vue";
|
|
11
|
-
import {
|
|
12
|
-
|
|
12
|
+
import {
|
|
13
|
+
ɵComposerController,
|
|
14
|
+
ɵcomposerButtonState,
|
|
15
|
+
ɵcreateComposerAutosize,
|
|
16
|
+
ɵflattenToolsMenuForDisplay,
|
|
17
|
+
ɵnormalizeToolsMenu,
|
|
18
|
+
ɵshowsComposerDisclaimer,
|
|
19
|
+
ɵsyncRecorderToMode,
|
|
20
|
+
} from "@copilotkit/core";
|
|
13
21
|
import {
|
|
14
22
|
IconArrowUp,
|
|
15
23
|
IconCheck,
|
|
@@ -29,20 +37,11 @@ import type {
|
|
|
29
37
|
import { useCopilotId } from "../ui/use-id";
|
|
30
38
|
import type { CopilotChatAudioRecorderRef } from "./audioRecorder";
|
|
31
39
|
import type { CopilotChatInputMode, ToolsMenuItem } from "./types";
|
|
40
|
+
import { useChatLabels } from "./use-chat-labels";
|
|
32
41
|
|
|
33
42
|
defineOptions({ inheritAttrs: false });
|
|
34
43
|
|
|
35
44
|
type MenuEntry = ToolsMenuItem | "-";
|
|
36
|
-
type MenuDisplayEntry =
|
|
37
|
-
| { type: "separator"; key: string }
|
|
38
|
-
| { type: "label"; key: string; label: string; depth: number }
|
|
39
|
-
| {
|
|
40
|
-
type: "item";
|
|
41
|
-
key: string;
|
|
42
|
-
label: string;
|
|
43
|
-
depth: number;
|
|
44
|
-
action: () => void;
|
|
45
|
-
};
|
|
46
45
|
|
|
47
46
|
const props = withDefaults(
|
|
48
47
|
defineProps<{
|
|
@@ -107,7 +106,6 @@ const emit = defineEmits<{
|
|
|
107
106
|
}>();
|
|
108
107
|
|
|
109
108
|
const attrs = useAttrs();
|
|
110
|
-
const config = useCopilotChatConfiguration();
|
|
111
109
|
const shellRef = ref<HTMLElement | null>(null);
|
|
112
110
|
const textareaRef = ref<HTMLTextAreaElement | null>(null);
|
|
113
111
|
const gridRef = ref<HTMLElement | null>(null);
|
|
@@ -115,12 +113,31 @@ const addButtonContainerRef = ref<HTMLElement | null>(null);
|
|
|
115
113
|
const actionsContainerRef = ref<HTMLElement | null>(null);
|
|
116
114
|
const slashMenuRef = ref<HTMLElement | null>(null);
|
|
117
115
|
const audioRecorderRef = ref<CopilotChatAudioRecorderRef | null>(null);
|
|
118
|
-
const localValue = ref(props.modelValue ?? "");
|
|
119
116
|
const isComposing = ref(false);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
117
|
+
// The text, controlled or not, and the slash-command menu: see core's
|
|
118
|
+
// ɵComposerController.
|
|
119
|
+
const composer = new ɵComposerController<ToolsMenuItem>({
|
|
120
|
+
initialValue: props.modelValue ?? "",
|
|
121
|
+
onChange: (value) => emit("update:modelValue", value),
|
|
122
|
+
});
|
|
123
|
+
const composerState = shallowRef(composer.getSnapshot());
|
|
124
|
+
composer.subscribe(() => {
|
|
125
|
+
composerState.value = composer.getSnapshot();
|
|
126
|
+
});
|
|
127
|
+
// Sizes the text box and picks the compact or expanded layout.
|
|
128
|
+
const autosize = ɵcreateComposerAutosize({
|
|
129
|
+
getElements: () => ({
|
|
130
|
+
textarea: textareaRef.value,
|
|
131
|
+
grid: gridRef.value,
|
|
132
|
+
start: addButtonContainerRef.value,
|
|
133
|
+
actions: actionsContainerRef.value,
|
|
134
|
+
}),
|
|
135
|
+
maxRows: props.maxRows,
|
|
136
|
+
});
|
|
137
|
+
const layout = shallowRef(autosize.getSnapshot());
|
|
138
|
+
autosize.subscribe(() => {
|
|
139
|
+
layout.value = autosize.getSnapshot();
|
|
140
|
+
});
|
|
124
141
|
const addMenuOpen = ref(false);
|
|
125
142
|
// Where focus goes as the add menu opens: its first or last item for the
|
|
126
143
|
// keyboard, the menu itself for a pointer, as Radix's DropdownMenu does.
|
|
@@ -128,38 +145,27 @@ const addMenuInitialFocus = ref<"first" | "last" | "content">("content");
|
|
|
128
145
|
const addMenuAnchor = ref<HTMLElement | null>(null);
|
|
129
146
|
const addMenuId = useCopilotId("cpk-add-menu");
|
|
130
147
|
const addMenuTriggerId = `${addMenuId}-trigger`;
|
|
131
|
-
const measurements = ref({
|
|
132
|
-
singleLineHeight: 0,
|
|
133
|
-
maxHeight: 0,
|
|
134
|
-
paddingLeft: 0,
|
|
135
|
-
paddingRight: 0,
|
|
136
|
-
});
|
|
137
|
-
const resizeEvaluationRafRef = ref<number | null>(null);
|
|
138
|
-
const ignoreResizeRef = ref(false);
|
|
139
|
-
const measurementCanvasRef = ref<HTMLCanvasElement | null>(null);
|
|
140
|
-
const containerCacheRef = ref<{
|
|
141
|
-
compactWidth: number;
|
|
142
|
-
} | null>(null);
|
|
143
|
-
const didWarnMissingFontRef = ref(false);
|
|
144
|
-
const didWarnMissingCanvasContextRef = ref(false);
|
|
145
|
-
let resizeObserver: ResizeObserver | null = null;
|
|
146
148
|
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
|
|
149
|
+
const inputValue = computed(() => composerState.value.value);
|
|
150
|
+
const filteredCommands = computed(() => composerState.value.slashCommands);
|
|
151
|
+
const slashHighlightIndex = computed(
|
|
152
|
+
() => composerState.value.slashHighlightIndex,
|
|
150
153
|
);
|
|
151
|
-
const
|
|
154
|
+
const slashMenuVisible = computed(
|
|
155
|
+
() => composerState.value.slashQuery !== null,
|
|
156
|
+
);
|
|
157
|
+
const labels = useChatLabels();
|
|
152
158
|
const resolvedPlaceholder = computed(
|
|
153
159
|
() => props.placeholder ?? labels.value.chatInputPlaceholder,
|
|
154
160
|
);
|
|
155
161
|
const isExpanded = computed(
|
|
156
162
|
() => props.mode === "input" && layout.value === "expanded",
|
|
157
163
|
);
|
|
158
|
-
const
|
|
159
|
-
(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
164
|
+
const shouldShowDisclaimer = computed(() =>
|
|
165
|
+
ɵshowsComposerDisclaimer({
|
|
166
|
+
showDisclaimer: props.showDisclaimer,
|
|
167
|
+
positioning: props.positioning,
|
|
168
|
+
}),
|
|
163
169
|
);
|
|
164
170
|
const hasSubmitAction = computed(
|
|
165
171
|
() => typeof props.onSubmitMessage === "function",
|
|
@@ -177,16 +183,20 @@ const hasFinishTranscribeAction = computed(
|
|
|
177
183
|
typeof props.onFinishTranscribe === "function" ||
|
|
178
184
|
typeof props.onFinishTranscribeWithAudio === "function",
|
|
179
185
|
);
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
186
|
+
const composerInput = computed(() => ({
|
|
187
|
+
mode: props.mode,
|
|
188
|
+
isRunning: props.isRunning,
|
|
189
|
+
value: inputValue.value,
|
|
190
|
+
canSubmit: hasSubmitAction.value,
|
|
191
|
+
canStop: hasStopAction.value,
|
|
192
|
+
disabled: props.disabled,
|
|
193
|
+
}));
|
|
194
|
+
const composerButton = computed(() =>
|
|
195
|
+
ɵcomposerButtonState(composerInput.value),
|
|
189
196
|
);
|
|
197
|
+
const isProcessing = computed(() => composerButton.value.isProcessing);
|
|
198
|
+
const sendDisabled = computed(() => composerButton.value.disabled);
|
|
199
|
+
const showsStop = computed(() => composerButton.value.action === "stop");
|
|
190
200
|
|
|
191
201
|
const containerClass = computed(() => [
|
|
192
202
|
"cpk-chat-input",
|
|
@@ -200,288 +210,98 @@ const rootAttrs = computed(() => {
|
|
|
200
210
|
return rest;
|
|
201
211
|
});
|
|
202
212
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (!hasAddFileAction.value) {
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
return {
|
|
214
|
-
label: labels.value.chatInputToolbarAddButtonLabel,
|
|
215
|
-
action: () => emit("add-file"),
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function normalizeMenuItems() {
|
|
220
|
-
const items: MenuEntry[] = [];
|
|
221
|
-
const addItem = createDefaultAddItem();
|
|
222
|
-
if (addItem) {
|
|
223
|
-
items.push(addItem);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (props.toolsMenu.length > 0) {
|
|
227
|
-
if (items.length > 0) {
|
|
228
|
-
items.push("-");
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
for (const menuEntry of props.toolsMenu) {
|
|
232
|
-
if (menuEntry === "-") {
|
|
233
|
-
if (items.length === 0 || items[items.length - 1] === "-") {
|
|
234
|
-
continue;
|
|
213
|
+
const menuItems = computed(() =>
|
|
214
|
+
ɵnormalizeToolsMenu<ToolsMenuItem>(
|
|
215
|
+
props.toolsMenu,
|
|
216
|
+
hasAddFileAction.value
|
|
217
|
+
? {
|
|
218
|
+
label: labels.value.chatInputToolbarAddButtonLabel,
|
|
219
|
+
action: () => emit("add-file"),
|
|
235
220
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
items.push(menuEntry);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
while (items.length > 0 && items[items.length - 1] === "-") {
|
|
245
|
-
items.pop();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return items;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const menuItems = computed(() => normalizeMenuItems());
|
|
221
|
+
: undefined,
|
|
222
|
+
),
|
|
223
|
+
);
|
|
252
224
|
const hasMenuItems = computed(() => menuItems.value.length > 0);
|
|
225
|
+
const menuDisplayItems = computed(() =>
|
|
226
|
+
ɵflattenToolsMenuForDisplay(menuItems.value),
|
|
227
|
+
);
|
|
253
228
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const walk = (entryList: MenuEntry[]) => {
|
|
259
|
-
for (const entry of entryList) {
|
|
260
|
-
if (entry === "-") {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (isMenuGroup(entry) && entry.items.length > 0) {
|
|
265
|
-
walk(entry.items);
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (!entry.action || seen.has(entry.label)) {
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
seen.add(entry.label);
|
|
274
|
-
commands.push(entry);
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
walk(items);
|
|
279
|
-
return commands;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const commandItems = computed(() => flattenMenuForCommands(menuItems.value));
|
|
283
|
-
|
|
284
|
-
function flattenMenuDisplay(items: MenuEntry[], depth = 0, prefix = "root") {
|
|
285
|
-
const entries: MenuDisplayEntry[] = [];
|
|
286
|
-
for (const [index, item] of items.entries()) {
|
|
287
|
-
const key = `${prefix}-${index}`;
|
|
288
|
-
if (item === "-") {
|
|
289
|
-
entries.push({ type: "separator", key: `sep-${key}` });
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
if (isMenuGroup(item) && item.items.length > 0) {
|
|
293
|
-
entries.push({
|
|
294
|
-
type: "label",
|
|
295
|
-
key: `label-${key}`,
|
|
296
|
-
label: item.label,
|
|
297
|
-
depth,
|
|
298
|
-
});
|
|
299
|
-
entries.push(...flattenMenuDisplay(item.items, depth + 1, key));
|
|
300
|
-
continue;
|
|
301
|
-
}
|
|
302
|
-
if (item.action) {
|
|
303
|
-
entries.push({
|
|
304
|
-
type: "item",
|
|
305
|
-
key: `item-${key}`,
|
|
306
|
-
label: item.label,
|
|
307
|
-
depth,
|
|
308
|
-
action: item.action,
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return entries;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const menuDisplayItems = computed(() => flattenMenuDisplay(menuItems.value));
|
|
316
|
-
|
|
317
|
-
const filteredCommands = computed(() => {
|
|
318
|
-
if (commandQuery.value === null || commandItems.value.length === 0) {
|
|
319
|
-
return [] as ToolsMenuItem[];
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const normalized = commandQuery.value.trim().toLowerCase();
|
|
323
|
-
if (normalized.length === 0) {
|
|
324
|
-
return commandItems.value;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const startsWith: ToolsMenuItem[] = [];
|
|
328
|
-
const contains: ToolsMenuItem[] = [];
|
|
329
|
-
|
|
330
|
-
for (const command of commandItems.value) {
|
|
331
|
-
const label = command.label.toLowerCase();
|
|
332
|
-
if (label.startsWith(normalized)) {
|
|
333
|
-
startsWith.push(command);
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
if (label.includes(normalized)) {
|
|
337
|
-
contains.push(command);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return [...startsWith, ...contains];
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
const slashMenuVisible = computed(
|
|
345
|
-
() => commandQuery.value !== null && commandItems.value.length > 0,
|
|
229
|
+
watch(
|
|
230
|
+
[() => props.modelValue, () => props.mode, menuItems],
|
|
231
|
+
([value, mode, menu]) => composer.setInputs({ value, mode, menu }),
|
|
232
|
+
{ immediate: true },
|
|
346
233
|
);
|
|
347
234
|
|
|
348
235
|
function updateInputValue(nextValue: string) {
|
|
349
|
-
|
|
350
|
-
localValue.value = nextValue;
|
|
351
|
-
}
|
|
352
|
-
emit("update:modelValue", nextValue);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function clearInputValue() {
|
|
356
|
-
updateInputValue("");
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
function updateSlashState(value: string) {
|
|
360
|
-
if (commandItems.value.length === 0) {
|
|
361
|
-
commandQuery.value = null;
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (value.startsWith("/")) {
|
|
366
|
-
const firstLine = value.split(/\r?\n/, 1)[0] ?? "";
|
|
367
|
-
commandQuery.value = firstLine.slice(1);
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
commandQuery.value = null;
|
|
236
|
+
composer.setValue(nextValue);
|
|
372
237
|
}
|
|
373
238
|
|
|
374
|
-
function
|
|
375
|
-
clearInputValue();
|
|
376
|
-
command.action?.();
|
|
377
|
-
commandQuery.value = null;
|
|
378
|
-
slashHighlightIndex.value = 0;
|
|
239
|
+
function focusTextareaSoon() {
|
|
379
240
|
requestAnimationFrame(() => {
|
|
380
241
|
textareaRef.value?.focus();
|
|
381
242
|
});
|
|
382
243
|
}
|
|
383
244
|
|
|
245
|
+
function runCommand(command: ToolsMenuItem) {
|
|
246
|
+
composer.runCommand(command);
|
|
247
|
+
focusTextareaSoon();
|
|
248
|
+
}
|
|
249
|
+
|
|
384
250
|
function submit() {
|
|
385
251
|
if (props.mode !== "input" || props.disabled || !hasSubmitAction.value) {
|
|
386
252
|
return;
|
|
387
253
|
}
|
|
388
254
|
// In controlled mode, parent-updated modelValue can lag one tick behind
|
|
389
255
|
// the actual textarea value during intense runtime/connect churn.
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
emit("submit-message", trimmed);
|
|
397
|
-
|
|
398
|
-
if (props.clearOnSubmit) {
|
|
399
|
-
clearInputValue();
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
textareaRef.value?.focus();
|
|
256
|
+
const sent = composer.submit((text) => emit("submit-message", text), {
|
|
257
|
+
value: textareaRef.value?.value ?? inputValue.value,
|
|
258
|
+
clear: props.clearOnSubmit,
|
|
259
|
+
});
|
|
260
|
+
if (sent) textareaRef.value?.focus();
|
|
403
261
|
}
|
|
404
262
|
|
|
405
263
|
function handleInput(event: Event) {
|
|
406
|
-
|
|
407
|
-
updateInputValue(nextValue);
|
|
408
|
-
updateSlashState(nextValue);
|
|
264
|
+
updateInputValue((event.target as HTMLTextAreaElement).value);
|
|
409
265
|
}
|
|
410
266
|
|
|
267
|
+
// The button stops a run whatever the input holds. Enter differs: see
|
|
268
|
+
// handleKeydown.
|
|
411
269
|
function handleSendButtonClick() {
|
|
412
|
-
if (
|
|
413
|
-
|
|
414
|
-
emit("stop");
|
|
415
|
-
}
|
|
270
|
+
if (showsStop.value) {
|
|
271
|
+
emit("stop");
|
|
416
272
|
return;
|
|
417
273
|
}
|
|
418
|
-
|
|
274
|
+
if (!isProcessing.value) {
|
|
275
|
+
submit();
|
|
276
|
+
}
|
|
419
277
|
}
|
|
420
278
|
|
|
421
279
|
function handleKeydown(event: KeyboardEvent) {
|
|
422
|
-
if (props.disabled) {
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if (isComposing.value || event.isComposing || event.keyCode === 229) {
|
|
280
|
+
if (props.disabled || props.mode !== "input") {
|
|
427
281
|
return;
|
|
428
282
|
}
|
|
429
283
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
slashHighlightIndex.value =
|
|
449
|
-
slashHighlightIndex.value <= 0
|
|
450
|
-
? filteredCommands.value.length - 1
|
|
451
|
-
: slashHighlightIndex.value - 1;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (event.key === "Enter") {
|
|
458
|
-
const selected =
|
|
459
|
-
slashHighlightIndex.value >= 0
|
|
460
|
-
? filteredCommands.value[slashHighlightIndex.value]
|
|
461
|
-
: undefined;
|
|
462
|
-
if (selected) {
|
|
463
|
-
event.preventDefault();
|
|
464
|
-
runCommand(selected);
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (event.key === "Escape") {
|
|
470
|
-
event.preventDefault();
|
|
471
|
-
commandQuery.value = null;
|
|
472
|
-
return;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
if (event.key === "Enter" && !event.shiftKey && props.mode === "input") {
|
|
477
|
-
event.preventDefault();
|
|
478
|
-
if (isProcessing.value) {
|
|
479
|
-
if (hasStopAction.value) {
|
|
480
|
-
emit("stop");
|
|
481
|
-
}
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
284
|
+
// Enter with text sends, also while a run is going. Enter in an empty input
|
|
285
|
+
// stops the run. Read the textarea: a controlled modelValue can lag a tick.
|
|
286
|
+
const { preventDefault, action } = composer.keyDown(
|
|
287
|
+
{
|
|
288
|
+
key: event.key,
|
|
289
|
+
shiftKey: event.shiftKey,
|
|
290
|
+
isComposing: isComposing.value || event.isComposing,
|
|
291
|
+
keyCode: event.keyCode,
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
...composerInput.value,
|
|
295
|
+
value: textareaRef.value?.value ?? inputValue.value,
|
|
296
|
+
},
|
|
297
|
+
);
|
|
298
|
+
if (preventDefault) event.preventDefault();
|
|
299
|
+
if (action === "command") {
|
|
300
|
+
focusTextareaSoon();
|
|
301
|
+
} else if (action === "send") {
|
|
484
302
|
submit();
|
|
303
|
+
} else if (action === "stop") {
|
|
304
|
+
emit("stop");
|
|
485
305
|
}
|
|
486
306
|
}
|
|
487
307
|
|
|
@@ -593,346 +413,39 @@ function handleContainerClick(event: MouseEvent) {
|
|
|
593
413
|
textareaRef.value?.focus();
|
|
594
414
|
}
|
|
595
415
|
|
|
596
|
-
function ensureMeasurements() {
|
|
597
|
-
const textarea = textareaRef.value;
|
|
598
|
-
if (!textarea || isComposing.value) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
const previousValue = textarea.value;
|
|
603
|
-
const previousHeight = textarea.style.height;
|
|
604
|
-
textarea.style.height = "auto";
|
|
605
|
-
|
|
606
|
-
const computedStyle = window.getComputedStyle(textarea);
|
|
607
|
-
const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
|
|
608
|
-
const paddingRight = parseFloat(computedStyle.paddingRight) || 0;
|
|
609
|
-
const paddingTop = parseFloat(computedStyle.paddingTop) || 0;
|
|
610
|
-
const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;
|
|
611
|
-
|
|
612
|
-
textarea.value = "";
|
|
613
|
-
const singleLineHeight = textarea.scrollHeight;
|
|
614
|
-
textarea.value = previousValue;
|
|
615
|
-
|
|
616
|
-
const contentHeight = singleLineHeight - paddingTop - paddingBottom;
|
|
617
|
-
const maxHeight = contentHeight * props.maxRows + paddingTop + paddingBottom;
|
|
618
|
-
|
|
619
|
-
measurements.value = {
|
|
620
|
-
singleLineHeight,
|
|
621
|
-
maxHeight,
|
|
622
|
-
paddingLeft,
|
|
623
|
-
paddingRight,
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
textarea.style.height = previousHeight;
|
|
627
|
-
textarea.style.maxHeight = `${maxHeight}px`;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
function adjustTextareaHeight() {
|
|
631
|
-
const textarea = textareaRef.value;
|
|
632
|
-
if (!textarea) {
|
|
633
|
-
return 0;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
if (measurements.value.singleLineHeight === 0) {
|
|
637
|
-
ensureMeasurements();
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
const { maxHeight } = measurements.value;
|
|
641
|
-
if (maxHeight) {
|
|
642
|
-
textarea.style.maxHeight = `${maxHeight}px`;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
textarea.style.height = "auto";
|
|
646
|
-
const scrollHeight = textarea.scrollHeight;
|
|
647
|
-
textarea.style.height = `${maxHeight ? Math.min(scrollHeight, maxHeight) : scrollHeight}px`;
|
|
648
|
-
return scrollHeight;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
function updateLayout(nextLayout: "compact" | "expanded") {
|
|
652
|
-
if (layout.value === nextLayout) {
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
ignoreResizeRef.value = true;
|
|
656
|
-
layout.value = nextLayout;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
function resolveTextareaFont(textarea: HTMLTextAreaElement): string | null {
|
|
660
|
-
const textareaStyles = window.getComputedStyle(textarea);
|
|
661
|
-
if (textareaStyles.font?.trim()) {
|
|
662
|
-
return textareaStyles.font;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
if (textareaStyles.fontSize && textareaStyles.fontFamily) {
|
|
666
|
-
const fallbackFont =
|
|
667
|
-
`${textareaStyles.fontStyle} ${textareaStyles.fontVariant} ` +
|
|
668
|
-
`${textareaStyles.fontWeight} ${textareaStyles.fontSize}/${textareaStyles.lineHeight} ` +
|
|
669
|
-
`${textareaStyles.fontFamily}`;
|
|
670
|
-
if (fallbackFont.trim()) {
|
|
671
|
-
return fallbackFont;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
if (process.env.NODE_ENV !== "production" && !didWarnMissingFontRef.value) {
|
|
676
|
-
didWarnMissingFontRef.value = true;
|
|
677
|
-
console.warn(
|
|
678
|
-
"[CopilotChatInput] Could not resolve textarea font for layout measurement. " +
|
|
679
|
-
"Text-width-based expansion will be skipped until the next container resize.",
|
|
680
|
-
);
|
|
681
|
-
}
|
|
682
|
-
return null;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
function updateContainerCache() {
|
|
686
|
-
const grid = gridRef.value;
|
|
687
|
-
const addContainer = addButtonContainerRef.value;
|
|
688
|
-
const actionsContainer = actionsContainerRef.value;
|
|
689
|
-
if (!grid || !addContainer || !actionsContainer) {
|
|
690
|
-
containerCacheRef.value = null;
|
|
691
|
-
return null;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
const gridStyles = window.getComputedStyle(grid);
|
|
695
|
-
const paddingLeft = parseFloat(gridStyles.paddingLeft) || 0;
|
|
696
|
-
const paddingRight = parseFloat(gridStyles.paddingRight) || 0;
|
|
697
|
-
const columnGap = parseFloat(gridStyles.columnGap) || 0;
|
|
698
|
-
const gridAvailableWidth = grid.clientWidth - paddingLeft - paddingRight;
|
|
699
|
-
if (gridAvailableWidth <= 0) {
|
|
700
|
-
containerCacheRef.value = null;
|
|
701
|
-
return null;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
const addWidth = addContainer.getBoundingClientRect().width;
|
|
705
|
-
const actionsWidth = actionsContainer.getBoundingClientRect().width;
|
|
706
|
-
const compactWidth = Math.max(
|
|
707
|
-
gridAvailableWidth - addWidth - actionsWidth - columnGap * 2,
|
|
708
|
-
0,
|
|
709
|
-
);
|
|
710
|
-
if (compactWidth <= 0) {
|
|
711
|
-
containerCacheRef.value = null;
|
|
712
|
-
return null;
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
const cache = { compactWidth };
|
|
716
|
-
containerCacheRef.value = cache;
|
|
717
|
-
return cache;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
function evaluateLayout() {
|
|
721
|
-
if (props.mode !== "input") {
|
|
722
|
-
updateLayout("compact");
|
|
723
|
-
return;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
if (
|
|
727
|
-
typeof window.matchMedia === "function" &&
|
|
728
|
-
window.matchMedia("(max-width: 767px)").matches
|
|
729
|
-
) {
|
|
730
|
-
ensureMeasurements();
|
|
731
|
-
adjustTextareaHeight();
|
|
732
|
-
updateLayout("expanded");
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
const textarea = textareaRef.value;
|
|
737
|
-
if (
|
|
738
|
-
!textarea ||
|
|
739
|
-
!gridRef.value ||
|
|
740
|
-
!addButtonContainerRef.value ||
|
|
741
|
-
!actionsContainerRef.value
|
|
742
|
-
) {
|
|
743
|
-
return;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
if (measurements.value.singleLineHeight === 0) {
|
|
747
|
-
ensureMeasurements();
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
const scrollHeight = adjustTextareaHeight();
|
|
751
|
-
const baseline = measurements.value.singleLineHeight;
|
|
752
|
-
const hasExplicitBreak = inputValue.value.includes("\n");
|
|
753
|
-
const renderedMultiline = baseline > 0 ? scrollHeight > baseline + 1 : false;
|
|
754
|
-
let shouldExpand = hasExplicitBreak || renderedMultiline;
|
|
755
|
-
|
|
756
|
-
if (!shouldExpand) {
|
|
757
|
-
const cache = containerCacheRef.value ?? updateContainerCache();
|
|
758
|
-
if (cache && cache.compactWidth > 0) {
|
|
759
|
-
const compactInnerWidth = Math.max(
|
|
760
|
-
cache.compactWidth -
|
|
761
|
-
measurements.value.paddingLeft -
|
|
762
|
-
measurements.value.paddingRight,
|
|
763
|
-
0,
|
|
764
|
-
);
|
|
765
|
-
|
|
766
|
-
if (compactInnerWidth > 0) {
|
|
767
|
-
const canvas =
|
|
768
|
-
measurementCanvasRef.value ?? document.createElement("canvas");
|
|
769
|
-
if (!measurementCanvasRef.value) {
|
|
770
|
-
measurementCanvasRef.value = canvas;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
const context = canvas.getContext("2d");
|
|
774
|
-
if (context) {
|
|
775
|
-
const resolvedFont = resolveTextareaFont(textarea);
|
|
776
|
-
if (resolvedFont) {
|
|
777
|
-
context.font = resolvedFont;
|
|
778
|
-
const lines =
|
|
779
|
-
inputValue.value.length > 0 ? inputValue.value.split("\n") : [""];
|
|
780
|
-
let longestLine = 0;
|
|
781
|
-
for (const line of lines) {
|
|
782
|
-
const width = context.measureText(line || " ").width;
|
|
783
|
-
if (width > longestLine) {
|
|
784
|
-
longestLine = width;
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
if (longestLine > compactInnerWidth) {
|
|
788
|
-
shouldExpand = true;
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
} else if (
|
|
792
|
-
process.env.NODE_ENV !== "production" &&
|
|
793
|
-
!didWarnMissingCanvasContextRef.value
|
|
794
|
-
) {
|
|
795
|
-
didWarnMissingCanvasContextRef.value = true;
|
|
796
|
-
console.warn(
|
|
797
|
-
"[CopilotChatInput] canvas.getContext('2d') returned null. " +
|
|
798
|
-
"Text-width-based expansion will be skipped.",
|
|
799
|
-
);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
updateLayout(shouldExpand ? "expanded" : "compact");
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
function scheduleLayoutEvaluation(invalidateCache: boolean) {
|
|
809
|
-
if (ignoreResizeRef.value) {
|
|
810
|
-
ignoreResizeRef.value = false;
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
if (invalidateCache) {
|
|
815
|
-
containerCacheRef.value = null;
|
|
816
|
-
didWarnMissingFontRef.value = false;
|
|
817
|
-
didWarnMissingCanvasContextRef.value = false;
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
if (resizeEvaluationRafRef.value !== null) {
|
|
821
|
-
cancelAnimationFrame(resizeEvaluationRafRef.value);
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
resizeEvaluationRafRef.value = requestAnimationFrame(() => {
|
|
825
|
-
resizeEvaluationRafRef.value = null;
|
|
826
|
-
evaluateLayout();
|
|
827
|
-
});
|
|
828
|
-
}
|
|
829
|
-
|
|
830
416
|
watch(
|
|
831
|
-
() => props.
|
|
832
|
-
(
|
|
833
|
-
|
|
834
|
-
localValue.value = next ?? "";
|
|
835
|
-
}
|
|
417
|
+
[inputValue, () => props.mode],
|
|
418
|
+
([value, mode]) => {
|
|
419
|
+
autosize.evaluate(value, mode);
|
|
836
420
|
},
|
|
421
|
+
{ flush: "post" },
|
|
837
422
|
);
|
|
838
423
|
|
|
839
|
-
watch(inputValue, (value) => {
|
|
840
|
-
updateSlashState(value);
|
|
841
|
-
evaluateLayout();
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
watch(commandItems, () => {
|
|
845
|
-
if (commandItems.value.length === 0) {
|
|
846
|
-
commandQuery.value = null;
|
|
847
|
-
}
|
|
848
|
-
});
|
|
849
|
-
|
|
850
424
|
watch(
|
|
851
|
-
|
|
852
|
-
(
|
|
853
|
-
|
|
854
|
-
query !== null &&
|
|
855
|
-
query !== previousCommandQuery.value &&
|
|
856
|
-
filteredCount > 0
|
|
857
|
-
) {
|
|
858
|
-
slashHighlightIndex.value = 0;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
previousCommandQuery.value = query;
|
|
425
|
+
() => props.maxRows,
|
|
426
|
+
(maxRows) => {
|
|
427
|
+
autosize.setMaxRows(maxRows);
|
|
862
428
|
},
|
|
863
|
-
{ immediate: true },
|
|
864
|
-
);
|
|
865
|
-
|
|
866
|
-
watch(
|
|
867
|
-
[commandQuery, filteredCommands],
|
|
868
|
-
() => {
|
|
869
|
-
if (commandQuery.value === null) {
|
|
870
|
-
slashHighlightIndex.value = 0;
|
|
871
|
-
return;
|
|
872
|
-
}
|
|
873
|
-
if (filteredCommands.value.length === 0) {
|
|
874
|
-
slashHighlightIndex.value = -1;
|
|
875
|
-
return;
|
|
876
|
-
}
|
|
877
|
-
if (
|
|
878
|
-
slashHighlightIndex.value < 0 ||
|
|
879
|
-
slashHighlightIndex.value >= filteredCommands.value.length
|
|
880
|
-
) {
|
|
881
|
-
slashHighlightIndex.value = 0;
|
|
882
|
-
}
|
|
883
|
-
},
|
|
884
|
-
{ immediate: true },
|
|
885
429
|
);
|
|
886
430
|
|
|
887
431
|
watch(
|
|
888
432
|
() => props.mode,
|
|
889
|
-
|
|
433
|
+
(mode) => {
|
|
890
434
|
if (mode !== "input") {
|
|
891
|
-
layout.value = "compact";
|
|
892
|
-
commandQuery.value = null;
|
|
893
435
|
closeAddMenu();
|
|
894
436
|
}
|
|
895
|
-
|
|
896
|
-
const recorder = audioRecorderRef.value;
|
|
897
|
-
if (!recorder) {
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
if (mode === "transcribe") {
|
|
902
|
-
try {
|
|
903
|
-
await recorder.start();
|
|
904
|
-
} catch (error) {
|
|
905
|
-
console.error(error);
|
|
906
|
-
}
|
|
907
|
-
return;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
if (recorder.state === "recording") {
|
|
911
|
-
try {
|
|
912
|
-
await recorder.stop();
|
|
913
|
-
} catch {
|
|
914
|
-
// ignore transition stop failures
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
437
|
},
|
|
918
|
-
{ immediate: true },
|
|
919
438
|
);
|
|
920
439
|
|
|
440
|
+
// Recording follows the mode: it starts in transcribe mode and stops when the
|
|
441
|
+
// mode changes. The recorder renders only in transcribe mode, so also sync
|
|
442
|
+
// when it appears.
|
|
921
443
|
watch(
|
|
922
|
-
audioRecorderRef,
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
return;
|
|
926
|
-
}
|
|
927
|
-
if (recorder.state === "idle") {
|
|
928
|
-
try {
|
|
929
|
-
await recorder.start();
|
|
930
|
-
} catch (error) {
|
|
931
|
-
console.error(error);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
444
|
+
[audioRecorderRef, () => props.mode],
|
|
445
|
+
([recorder, mode]) => {
|
|
446
|
+
void ɵsyncRecorderToMode(recorder, mode);
|
|
934
447
|
},
|
|
935
|
-
{ immediate: true },
|
|
448
|
+
{ immediate: true, flush: "post" },
|
|
936
449
|
);
|
|
937
450
|
|
|
938
451
|
watch(slashHighlightIndex, async (index) => {
|
|
@@ -960,39 +473,11 @@ onMounted(() => {
|
|
|
960
473
|
textareaRef.value?.focus();
|
|
961
474
|
}
|
|
962
475
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
966
|
-
const containerTargets = new Set<HTMLElement>();
|
|
967
|
-
if (gridRef.value) containerTargets.add(gridRef.value);
|
|
968
|
-
if (addButtonContainerRef.value)
|
|
969
|
-
containerTargets.add(addButtonContainerRef.value);
|
|
970
|
-
if (actionsContainerRef.value)
|
|
971
|
-
containerTargets.add(actionsContainerRef.value);
|
|
972
|
-
|
|
973
|
-
resizeObserver = new ResizeObserver((entries) => {
|
|
974
|
-
const shouldInvalidate = entries.some((entry) =>
|
|
975
|
-
containerTargets.has(entry.target as HTMLElement),
|
|
976
|
-
);
|
|
977
|
-
scheduleLayoutEvaluation(shouldInvalidate);
|
|
978
|
-
});
|
|
979
|
-
|
|
980
|
-
if (gridRef.value) resizeObserver.observe(gridRef.value);
|
|
981
|
-
if (addButtonContainerRef.value)
|
|
982
|
-
resizeObserver.observe(addButtonContainerRef.value);
|
|
983
|
-
if (actionsContainerRef.value)
|
|
984
|
-
resizeObserver.observe(actionsContainerRef.value);
|
|
985
|
-
if (textareaRef.value) resizeObserver.observe(textareaRef.value);
|
|
986
|
-
}
|
|
476
|
+
autosize.evaluate(inputValue.value, props.mode);
|
|
987
477
|
});
|
|
988
478
|
|
|
989
479
|
onBeforeUnmount(() => {
|
|
990
|
-
|
|
991
|
-
resizeObserver = null;
|
|
992
|
-
if (resizeEvaluationRafRef.value !== null) {
|
|
993
|
-
cancelAnimationFrame(resizeEvaluationRafRef.value);
|
|
994
|
-
resizeEvaluationRafRef.value = null;
|
|
995
|
-
}
|
|
480
|
+
autosize.dispose();
|
|
996
481
|
});
|
|
997
482
|
</script>
|
|
998
483
|
|
|
@@ -1174,7 +659,7 @@ onBeforeUnmount(() => {
|
|
|
1174
659
|
index === slashHighlightIndex ? 'true' : undefined
|
|
1175
660
|
"
|
|
1176
661
|
class="cpk-chat-input-slash-menu-item"
|
|
1177
|
-
@mouseenter="
|
|
662
|
+
@mouseenter="composer.highlight(index)"
|
|
1178
663
|
@mousedown.prevent="runCommand(command)"
|
|
1179
664
|
>
|
|
1180
665
|
{{ command.label }}
|
|
@@ -1295,7 +780,7 @@ onBeforeUnmount(() => {
|
|
|
1295
780
|
type="button"
|
|
1296
781
|
data-testid="copilot-chat-input-send"
|
|
1297
782
|
:aria-label="
|
|
1298
|
-
|
|
783
|
+
showsStop
|
|
1299
784
|
? labels.chatInputToolbarStopButtonLabel
|
|
1300
785
|
: labels.chatInputToolbarSendButtonLabel
|
|
1301
786
|
"
|
|
@@ -1304,7 +789,7 @@ onBeforeUnmount(() => {
|
|
|
1304
789
|
@click="handleSendButtonClick"
|
|
1305
790
|
>
|
|
1306
791
|
<IconSquare
|
|
1307
|
-
v-if="
|
|
792
|
+
v-if="showsStop"
|
|
1308
793
|
class="cpk-chat-input-stop-icon"
|
|
1309
794
|
/>
|
|
1310
795
|
<IconArrowUp v-else class="cpk-chat-input-send-icon" />
|