@copilotkit/vue 2.0.0-rc.2 → 2.0.0-rc.21
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/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-BAhbpSDh.js +16200 -0
- package/dist/use-render-activity-message-BAhbpSDh.js.map +1 -0
- package/dist/use-render-activity-message-DJ6q1qHV.cjs +114 -0
- package/dist/use-render-activity-message-DJ6q1qHV.cjs.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 +0 -5
- 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 +6 -270
- 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 +3 -3
- 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 +18 -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.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-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-threads.d.ts +0 -8
- 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 +12 -12
- 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/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 +10 -11
- package/src/__tests__/build-entries.test.ts +27 -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 +2 -7
- 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 +147 -356
- package/src/v2/components/chat/CopilotChatAssistantMessage.vue +19 -43
- 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 +2 -2
- package/src/v2/components/chat/CopilotChatInput.vue +108 -436
- 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 +82 -210
- package/src/v2/components/chat/CopilotChatReasoningMessage.vue +7 -15
- 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 +33 -28
- 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 +35 -131
- 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 +38 -59
- package/src/v2/components/chat/CopilotThreadsDrawer.vue +37 -102
- 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 +89 -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__/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 +24 -89
- 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 +62 -197
- 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 +28 -218
- package/src/v2/hooks/use-default-render-tool.ts +34 -94
- package/src/v2/hooks/use-frontend-tool.ts +10 -10
- 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 +31 -55
- package/src/v2/hooks/use-render-custom-messages.ts +24 -88
- package/src/v2/hooks/use-suggestions.ts +9 -33
- package/src/v2/hooks/use-threads.ts +43 -273
- 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 +69 -78
- package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
- package/src/v2/providers/CopilotKitProvider.types.ts +12 -132
- package/src/v2/providers/CopilotKitProvider.vue +237 -510
- package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
- package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +20 -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 +53 -26
- 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 +5 -4
- 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,7 +1,7 @@
|
|
|
1
1
|
import { computed, onScopeDispose, shallowRef, watch } from "vue";
|
|
2
2
|
import type { ComputedRef, Ref } from "vue";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import type { Interrupt } from "@ag-ui/client";
|
|
4
|
+
import { ɵInterruptController } from "@copilotkit/core";
|
|
5
5
|
import { useCopilotKit } from "../providers/useCopilotKit";
|
|
6
6
|
import { useAgent } from "./use-agent";
|
|
7
7
|
import type {
|
|
@@ -19,21 +19,6 @@ export type {
|
|
|
19
19
|
Interrupt,
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const INTERRUPT_EVENT_NAME = "on_interrupt";
|
|
23
|
-
|
|
24
|
-
/** Internal accumulator response shape consumed by buildResumeArray. */
|
|
25
|
-
type ResumeResponse =
|
|
26
|
-
| { status: "resolved"; payload?: unknown }
|
|
27
|
-
| { status: "cancelled" };
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Normalized pending interrupt. `legacy` carries the custom-event payload;
|
|
31
|
-
* `standard` carries the AG-UI `outcome:"interrupt"` interrupts array.
|
|
32
|
-
*/
|
|
33
|
-
type PendingInterrupt =
|
|
34
|
-
| { kind: "legacy"; event: InterruptEvent }
|
|
35
|
-
| { kind: "standard"; interrupts: Interrupt[] };
|
|
36
|
-
|
|
37
22
|
type InterruptHandlerFn<TValue, TResult> = (
|
|
38
23
|
props: InterruptHandlerProps<TValue>,
|
|
39
24
|
) => TResult | PromiseLike<TResult>;
|
|
@@ -75,38 +60,6 @@ export interface UseInterruptResult<TValue = unknown, TResult = never> {
|
|
|
75
60
|
> | null>;
|
|
76
61
|
}
|
|
77
62
|
|
|
78
|
-
export function isPromiseLike<TValue>(
|
|
79
|
-
value: TValue | PromiseLike<TValue>,
|
|
80
|
-
): value is PromiseLike<TValue> {
|
|
81
|
-
return (
|
|
82
|
-
(typeof value === "object" || typeof value === "function") &&
|
|
83
|
-
value !== null &&
|
|
84
|
-
typeof Reflect.get(value, "then") === "function"
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function normalizeAsyncResult<TValue>(
|
|
89
|
-
value: PromiseLike<TValue>,
|
|
90
|
-
): Promise<TValue> {
|
|
91
|
-
if (value instanceof Promise) {
|
|
92
|
-
return value;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return new Promise<TValue>((resolve, reject) => {
|
|
96
|
-
try {
|
|
97
|
-
value.then(resolve, reject);
|
|
98
|
-
} catch (error) {
|
|
99
|
-
reject(error);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** Derive the legacy-compatible `event` for any pending interrupt. */
|
|
105
|
-
function toLegacyEvent(pending: PendingInterrupt): InterruptEvent {
|
|
106
|
-
if (pending.kind === "legacy") return pending.event;
|
|
107
|
-
return { name: INTERRUPT_EVENT_NAME, value: pending.interrupts[0] };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
63
|
/**
|
|
111
64
|
* Vue composable for handling agent interrupts with optional filtering,
|
|
112
65
|
* preprocessing, and resume behavior.
|
|
@@ -131,262 +84,33 @@ export function useInterrupt<TValue = unknown, TResult = never>(
|
|
|
131
84
|
): UseInterruptResult<TValue, TResult> {
|
|
132
85
|
const { copilotkit } = useCopilotKit();
|
|
133
86
|
const { agent } = useAgent({ agentId: config.agentId });
|
|
134
|
-
const pending = shallowRef<PendingInterrupt | null>(null);
|
|
135
|
-
const result = shallowRef<InterruptResult<TValue, TResult>>(null);
|
|
136
|
-
|
|
137
|
-
// Accumulated per-interrupt responses for the current standard interrupt set.
|
|
138
|
-
const responses: Record<string, ResumeResponse> = {};
|
|
139
|
-
|
|
140
|
-
watch(
|
|
141
|
-
agent,
|
|
142
|
-
(resolvedAgent, _previousAgent, onCleanup) => {
|
|
143
|
-
if (!resolvedAgent) {
|
|
144
|
-
pending.value = null;
|
|
145
|
-
result.value = null;
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
87
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
value: event.value as TValue,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
onRunFinishedEvent: (params) => {
|
|
162
|
-
if (params.outcome === "interrupt") {
|
|
163
|
-
localStandard = params.interrupts;
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
onRunStartedEvent: () => {
|
|
167
|
-
localLegacy = null;
|
|
168
|
-
localStandard = null;
|
|
169
|
-
// Reset accumulated responses for the new run.
|
|
170
|
-
for (const k of Object.keys(responses)) {
|
|
171
|
-
delete responses[k];
|
|
172
|
-
}
|
|
173
|
-
pending.value = null;
|
|
174
|
-
},
|
|
175
|
-
onRunFinalized: () => {
|
|
176
|
-
// Standard wins if both somehow appear for one run.
|
|
177
|
-
if (localStandard && localStandard.length > 0) {
|
|
178
|
-
pending.value = { kind: "standard", interrupts: localStandard };
|
|
179
|
-
} else if (localLegacy) {
|
|
180
|
-
pending.value = { kind: "legacy", event: localLegacy };
|
|
181
|
-
}
|
|
182
|
-
localLegacy = null;
|
|
183
|
-
localStandard = null;
|
|
184
|
-
},
|
|
185
|
-
onRunFailed: () => {
|
|
186
|
-
localLegacy = null;
|
|
187
|
-
localStandard = null;
|
|
188
|
-
for (const k of Object.keys(responses)) {
|
|
189
|
-
delete responses[k];
|
|
190
|
-
}
|
|
191
|
-
pending.value = null;
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
onCleanup(() => subscription.unsubscribe());
|
|
88
|
+
const controller = new ɵInterruptController<
|
|
89
|
+
TValue,
|
|
90
|
+
InterruptResult<TValue, TResult>
|
|
91
|
+
>(
|
|
92
|
+
{ runAgent: (params) => copilotkit.value.runAgent(params) },
|
|
93
|
+
{
|
|
94
|
+
enabled: (event) => config.enabled?.(event) ?? true,
|
|
95
|
+
handler: (props) => (config.handler ? config.handler(props) : null),
|
|
196
96
|
},
|
|
197
|
-
{ immediate: true },
|
|
198
97
|
);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
): Promise<RunAgentResult | void> => {
|
|
204
|
-
const allAddressed = interrupts.every((i) => responses[i.id]);
|
|
205
|
-
if (!allAddressed) return;
|
|
206
|
-
|
|
207
|
-
const expired = interrupts.find((i) => isInterruptExpired(i));
|
|
208
|
-
if (expired) {
|
|
209
|
-
console.error(
|
|
210
|
-
`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`,
|
|
211
|
-
);
|
|
212
|
-
for (const k of Object.keys(responses)) {
|
|
213
|
-
delete responses[k];
|
|
214
|
-
}
|
|
215
|
-
pending.value = null;
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const resume = buildResumeArray(interrupts, responses);
|
|
220
|
-
for (const k of Object.keys(responses)) {
|
|
221
|
-
delete responses[k];
|
|
222
|
-
}
|
|
223
|
-
const resolvedAgent = agent.value;
|
|
224
|
-
if (!resolvedAgent) return;
|
|
225
|
-
try {
|
|
226
|
-
return await copilotkit.value.runAgent({ agent: resolvedAgent, resume });
|
|
227
|
-
} catch (err) {
|
|
228
|
-
console.error(
|
|
229
|
-
"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing",
|
|
230
|
-
err,
|
|
231
|
-
);
|
|
232
|
-
pending.value = null;
|
|
233
|
-
throw err;
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const resolve: InterruptResolveFn = async (payload?, interruptId?) => {
|
|
238
|
-
const current = pending.value;
|
|
239
|
-
if (!current) return;
|
|
240
|
-
|
|
241
|
-
const resolvedAgent = agent.value;
|
|
242
|
-
if (!resolvedAgent) return;
|
|
243
|
-
|
|
244
|
-
if (current.kind === "legacy") {
|
|
245
|
-
const interruptEventValue = current.event.value;
|
|
246
|
-
try {
|
|
247
|
-
return await copilotkit.value.runAgent({
|
|
248
|
-
agent: resolvedAgent,
|
|
249
|
-
forwardedProps: {
|
|
250
|
-
command: {
|
|
251
|
-
resume: payload,
|
|
252
|
-
interruptEvent: interruptEventValue,
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
} catch (err) {
|
|
257
|
-
console.error(
|
|
258
|
-
"[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing",
|
|
259
|
-
err,
|
|
260
|
-
);
|
|
261
|
-
pending.value = null;
|
|
262
|
-
throw err;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (current.interrupts.length > 1 && interruptId === undefined) {
|
|
267
|
-
console.warn(
|
|
268
|
-
`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
const id = interruptId ?? current.interrupts[0]?.id;
|
|
272
|
-
if (!id) return;
|
|
273
|
-
responses[id] = { status: "resolved", payload };
|
|
274
|
-
return submitStandardIfComplete(current.interrupts);
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const cancel: InterruptCancelFn = async (interruptId?) => {
|
|
278
|
-
const current = pending.value;
|
|
279
|
-
if (!current) return;
|
|
280
|
-
|
|
281
|
-
if (current.kind === "legacy") {
|
|
282
|
-
// Legacy interrupts have no cancel semantics; dismiss without resuming.
|
|
283
|
-
console.warn(
|
|
284
|
-
"[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.",
|
|
285
|
-
);
|
|
286
|
-
pending.value = null;
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (current.interrupts.length > 1 && interruptId === undefined) {
|
|
291
|
-
console.warn(
|
|
292
|
-
`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
const id = interruptId ?? current.interrupts[0]?.id;
|
|
296
|
-
if (!id) return;
|
|
297
|
-
responses[id] = { status: "cancelled" };
|
|
298
|
-
return submitStandardIfComplete(current.interrupts);
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
// Keep resolveInterrupt and cancelInterrupt as aliases for back-compat.
|
|
302
|
-
const resolveInterrupt: InterruptResolveFn = resolve;
|
|
303
|
-
const cancelInterrupt: InterruptCancelFn = cancel;
|
|
98
|
+
const snapshot = shallowRef(controller.getSnapshot());
|
|
99
|
+
controller.subscribe(() => {
|
|
100
|
+
snapshot.value = controller.getSnapshot();
|
|
101
|
+
});
|
|
304
102
|
|
|
305
103
|
watch(
|
|
306
|
-
|
|
307
|
-
(
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
const legacyEvent = toLegacyEvent(
|
|
313
|
-
currentPending,
|
|
314
|
-
) as InterruptEvent<TValue>;
|
|
315
|
-
if (config.enabled && !config.enabled(legacyEvent)) {
|
|
316
|
-
result.value = null;
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
const handler = config.handler;
|
|
320
|
-
if (!handler) {
|
|
321
|
-
result.value = null;
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
let cancelled = false;
|
|
326
|
-
const maybePromise = handler({
|
|
327
|
-
event: legacyEvent,
|
|
328
|
-
interrupt:
|
|
329
|
-
currentPending.kind === "standard"
|
|
330
|
-
? (currentPending.interrupts[0] ?? null)
|
|
331
|
-
: null,
|
|
332
|
-
interrupts:
|
|
333
|
-
currentPending.kind === "standard" ? currentPending.interrupts : [],
|
|
334
|
-
resolve,
|
|
335
|
-
cancel,
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
if (isPromiseLike(maybePromise)) {
|
|
339
|
-
normalizeAsyncResult(maybePromise)
|
|
340
|
-
.then((resolved) => {
|
|
341
|
-
if (!cancelled) {
|
|
342
|
-
result.value = resolved;
|
|
343
|
-
}
|
|
344
|
-
})
|
|
345
|
-
.catch((err) => {
|
|
346
|
-
if (!cancelled) {
|
|
347
|
-
console.error("[CopilotKit] useInterrupt handler failed:", err);
|
|
348
|
-
result.value = null;
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
} else {
|
|
352
|
-
result.value = maybePromise;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
onCleanup(() => {
|
|
356
|
-
cancelled = true;
|
|
357
|
-
});
|
|
104
|
+
agent,
|
|
105
|
+
(resolvedAgent) => {
|
|
106
|
+
if (resolvedAgent) controller.connect(resolvedAgent);
|
|
107
|
+
else controller.disconnect();
|
|
358
108
|
},
|
|
359
109
|
{ immediate: true },
|
|
360
110
|
);
|
|
361
111
|
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
if (!pending.value) return null;
|
|
365
|
-
return toLegacyEvent(pending.value) as InterruptEvent<TValue>;
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
const slotProps = computed<InterruptRenderProps<
|
|
369
|
-
TValue,
|
|
370
|
-
InterruptResult<TValue, TResult>
|
|
371
|
-
> | null>(() => {
|
|
372
|
-
const currentPending = pending.value;
|
|
373
|
-
if (!currentPending) return null;
|
|
374
|
-
const legacyEvent = toLegacyEvent(currentPending) as InterruptEvent<TValue>;
|
|
375
|
-
if (config.enabled && !config.enabled(legacyEvent)) return null;
|
|
376
|
-
|
|
377
|
-
return {
|
|
378
|
-
event: legacyEvent,
|
|
379
|
-
interrupt:
|
|
380
|
-
currentPending.kind === "standard"
|
|
381
|
-
? (currentPending.interrupts[0] ?? null)
|
|
382
|
-
: null,
|
|
383
|
-
interrupts:
|
|
384
|
-
currentPending.kind === "standard" ? currentPending.interrupts : [],
|
|
385
|
-
result: result.value,
|
|
386
|
-
resolve,
|
|
387
|
-
cancel,
|
|
388
|
-
};
|
|
389
|
-
});
|
|
112
|
+
const { resolve, cancel } = controller;
|
|
113
|
+
const slotProps = computed(() => snapshot.value.renderProps);
|
|
390
114
|
|
|
391
115
|
watch(
|
|
392
116
|
[() => copilotkit.value, slotProps, () => config.renderInChat !== false],
|
|
@@ -395,10 +119,7 @@ export function useInterrupt<TValue = unknown, TResult = never>(
|
|
|
395
119
|
return;
|
|
396
120
|
}
|
|
397
121
|
|
|
398
|
-
core.setInterruptState(
|
|
399
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
400
|
-
nextSlotProps as InterruptRenderProps<any, any> | null,
|
|
401
|
-
);
|
|
122
|
+
core.setInterruptState(nextSlotProps);
|
|
402
123
|
const publishedState = nextSlotProps;
|
|
403
124
|
|
|
404
125
|
onCleanup(() => {
|
|
@@ -420,17 +141,17 @@ export function useInterrupt<TValue = unknown, TResult = never>(
|
|
|
420
141
|
}
|
|
421
142
|
});
|
|
422
143
|
|
|
144
|
+
onScopeDispose(() => controller.dispose());
|
|
145
|
+
|
|
423
146
|
return {
|
|
424
|
-
interrupt:
|
|
425
|
-
result:
|
|
147
|
+
interrupt: computed(() => slotProps.value?.event ?? null),
|
|
148
|
+
result: computed(() => snapshot.value.result),
|
|
426
149
|
hasInterrupt: computed(() => slotProps.value !== null),
|
|
427
150
|
resolve,
|
|
428
|
-
|
|
151
|
+
// Aliases kept for back-compat.
|
|
152
|
+
resolveInterrupt: resolve,
|
|
429
153
|
cancel,
|
|
430
|
-
cancelInterrupt,
|
|
431
|
-
slotProps
|
|
432
|
-
TValue,
|
|
433
|
-
InterruptResult<TValue, TResult>
|
|
434
|
-
> | null>,
|
|
154
|
+
cancelInterrupt: cancel,
|
|
155
|
+
slotProps,
|
|
435
156
|
};
|
|
436
157
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { onBeforeUnmount, onMounted, readonly, ref
|
|
1
|
+
import { onBeforeUnmount, onMounted, readonly, ref } from "vue";
|
|
2
|
+
import type { Ref } from "vue";
|
|
3
|
+
import { ɵinitialKeyboardState, ɵwatchKeyboardState } from "@copilotkit/core";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Vue-idiomatic result of {@link useKeyboardHeight}. Fields mirror the React
|
|
@@ -32,50 +34,25 @@ export interface KeyboardState {
|
|
|
32
34
|
* ```
|
|
33
35
|
*/
|
|
34
36
|
export function useKeyboardHeight(): KeyboardState {
|
|
35
|
-
const
|
|
36
|
-
const isKeyboardOpen = ref(
|
|
37
|
-
const keyboardHeight = ref(
|
|
38
|
-
const availableHeight = ref(
|
|
39
|
-
const viewportHeight = ref(
|
|
40
|
-
|
|
41
|
-
const updateKeyboardState = () => {
|
|
42
|
-
if (typeof window === "undefined") return;
|
|
43
|
-
const visualViewport = window.visualViewport;
|
|
44
|
-
if (!visualViewport) return;
|
|
45
|
-
|
|
46
|
-
const layoutHeight = window.innerHeight;
|
|
47
|
-
const visualHeight = visualViewport.height;
|
|
48
|
-
|
|
49
|
-
// Keyboard height = layout viewport minus visual viewport, clamped to 0.
|
|
50
|
-
const nextKeyboardHeight = Math.max(0, layoutHeight - visualHeight);
|
|
51
|
-
// Only treat the keyboard as open past the 150px threshold, matching
|
|
52
|
-
// the React implementation's mobile heuristic.
|
|
53
|
-
const nextIsOpen = nextKeyboardHeight > 150;
|
|
54
|
-
|
|
55
|
-
keyboardHeight.value = nextKeyboardHeight;
|
|
56
|
-
isKeyboardOpen.value = nextIsOpen;
|
|
57
|
-
availableHeight.value = visualHeight;
|
|
58
|
-
viewportHeight.value = layoutHeight;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
let visualViewport: VisualViewport | null = null;
|
|
37
|
+
const initial = ɵinitialKeyboardState();
|
|
38
|
+
const isKeyboardOpen = ref(initial.isKeyboardOpen);
|
|
39
|
+
const keyboardHeight = ref(initial.keyboardHeight);
|
|
40
|
+
const availableHeight = ref(initial.availableHeight);
|
|
41
|
+
const viewportHeight = ref(initial.viewportHeight);
|
|
42
|
+
let stopWatching: (() => void) | undefined;
|
|
62
43
|
|
|
63
44
|
onMounted(() => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
visualViewport.addEventListener("resize", updateKeyboardState);
|
|
71
|
-
visualViewport.addEventListener("scroll", updateKeyboardState);
|
|
45
|
+
stopWatching = ɵwatchKeyboardState((state) => {
|
|
46
|
+
keyboardHeight.value = state.keyboardHeight;
|
|
47
|
+
isKeyboardOpen.value = state.isKeyboardOpen;
|
|
48
|
+
availableHeight.value = state.availableHeight;
|
|
49
|
+
viewportHeight.value = state.viewportHeight;
|
|
50
|
+
});
|
|
72
51
|
});
|
|
73
52
|
|
|
74
53
|
onBeforeUnmount(() => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
visualViewport.removeEventListener("scroll", updateKeyboardState);
|
|
78
|
-
visualViewport = null;
|
|
54
|
+
stopWatching?.();
|
|
55
|
+
stopWatching = undefined;
|
|
79
56
|
});
|
|
80
57
|
|
|
81
58
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { inject, watch } from "vue";
|
|
2
2
|
import type { Ref } from "vue";
|
|
3
|
+
import { ɵpinMessageToTop } from "@copilotkit/core";
|
|
3
4
|
import {
|
|
4
5
|
LastUserMessageKey,
|
|
5
6
|
createDefaultLastUserMessageRef,
|
|
@@ -19,18 +20,10 @@ export interface UsePinToSendOptions {
|
|
|
19
20
|
* pinned near the top of the viewport while the assistant streams a
|
|
20
21
|
* response beneath it.
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* `viewportHeight - bubbleHeight - topOffset` and scrolls so the bubble
|
|
27
|
-
* sits `topOffset` from the viewport top (padding above the bubble is
|
|
28
|
-
* pushed off-screen).
|
|
29
|
-
* - Installs a `ResizeObserver` on `contentRef` that adjusts the spacer in
|
|
30
|
-
* both directions as content below the anchored message changes, keeping
|
|
31
|
-
* the bubble pinned.
|
|
32
|
-
* - Cancels the scheduled `requestAnimationFrame` and disconnects the
|
|
33
|
-
* `ResizeObserver` on subsequent re-runs and on scope dispose.
|
|
23
|
+
* Reads the latest user message via `LastUserMessageKey` and, on each
|
|
24
|
+
* `sendNonce` increment, runs core's `ɵpinMessageToTop`, which sizes the
|
|
25
|
+
* spacer, scrolls, and follows the reply's growth. The previous pin stops on
|
|
26
|
+
* the next run and on scope dispose.
|
|
34
27
|
*/
|
|
35
28
|
export function usePinToSend({
|
|
36
29
|
scrollRef,
|
|
@@ -45,17 +38,6 @@ export function usePinToSend({
|
|
|
45
38
|
);
|
|
46
39
|
|
|
47
40
|
let lastNonce = -1;
|
|
48
|
-
let raf: number | null = null;
|
|
49
|
-
let ro: ResizeObserver | null = null;
|
|
50
|
-
|
|
51
|
-
function teardown() {
|
|
52
|
-
if (raf !== null && typeof cancelAnimationFrame === "function") {
|
|
53
|
-
cancelAnimationFrame(raf);
|
|
54
|
-
}
|
|
55
|
-
raf = null;
|
|
56
|
-
ro?.disconnect();
|
|
57
|
-
ro = null;
|
|
58
|
-
}
|
|
59
41
|
|
|
60
42
|
watch(
|
|
61
43
|
[
|
|
@@ -67,90 +49,24 @@ export function usePinToSend({
|
|
|
67
49
|
() => topOffset,
|
|
68
50
|
],
|
|
69
51
|
([id, sendNonce, scrollEl, contentEl, spacerEl], _old, onCleanup) => {
|
|
70
|
-
// Always tear down the previous run's RAF / ResizeObserver before
|
|
71
|
-
// evaluating any of the early-exit guards below. Mirrors React
|
|
72
|
-
// `useEffect` cleanup semantics: the prior run's cleanup runs before
|
|
73
|
-
// the next callback executes regardless of why the deps changed.
|
|
74
|
-
// Without this, a reactive `autoScroll` mode change (e.g. switching
|
|
75
|
-
// away from `"pin-to-send"`) or a `ref` swap that doesn't bump
|
|
76
|
-
// `sendNonce` would leak the stale content-element observer because
|
|
77
|
-
// the nonce guard skips the body. Registering via `onCleanup` also
|
|
78
|
-
// covers watcher stop on scope dispose, so an explicit
|
|
79
|
-
// `onScopeDispose(teardown)` is no longer required.
|
|
80
|
-
onCleanup(teardown);
|
|
81
|
-
|
|
82
52
|
if (sendNonce === lastNonce) return;
|
|
83
53
|
lastNonce = sendNonce;
|
|
84
54
|
|
|
85
55
|
if (!id) return;
|
|
86
56
|
if (!scrollEl || !contentEl || !spacerEl) return;
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
58
|
+
// Registered through `onCleanup`, so the previous pin stops before the
|
|
59
|
+
// next run and when the watcher stops on scope dispose.
|
|
60
|
+
onCleanup(
|
|
61
|
+
ɵpinMessageToTop({
|
|
62
|
+
scrollEl,
|
|
63
|
+
contentEl,
|
|
64
|
+
spacerEl,
|
|
65
|
+
messageId: id,
|
|
66
|
+
topOffset,
|
|
67
|
+
}),
|
|
94
68
|
);
|
|
95
|
-
if (!targetEl) return;
|
|
96
|
-
|
|
97
|
-
// The target message's element has a top padding (e.g. `pt-10`) that
|
|
98
|
-
// creates breathing room above the visible bubble. When we "anchor at
|
|
99
|
-
// the top", we mean anchor the *bubble*, not the element's padded box.
|
|
100
|
-
// So we scroll past the padding (it goes above the viewport, hiding
|
|
101
|
-
// whatever was above the element too — including the previous message's
|
|
102
|
-
// trailing copy button).
|
|
103
|
-
const viewportHeight = scrollEl.clientHeight;
|
|
104
|
-
const userMessageHeight = targetEl.getBoundingClientRect().height;
|
|
105
|
-
const paddingTop = parseFloat(getComputedStyle(targetEl).paddingTop) || 0;
|
|
106
|
-
const bubbleHeight = Math.max(0, userMessageHeight - paddingTop);
|
|
107
|
-
const spacerHeight = Math.max(
|
|
108
|
-
0,
|
|
109
|
-
viewportHeight - bubbleHeight - topOffset,
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
spacerEl.style.height = `${spacerHeight}px`;
|
|
113
|
-
|
|
114
|
-
if (typeof requestAnimationFrame === "function") {
|
|
115
|
-
raf = requestAnimationFrame(() => {
|
|
116
|
-
// Scroll so the BUBBLE is `topOffset` from the viewport top — the
|
|
117
|
-
// padding above the bubble ends up scrolled off-screen.
|
|
118
|
-
const targetTop =
|
|
119
|
-
computeOffsetTop(targetEl, scrollEl) + paddingTop - topOffset;
|
|
120
|
-
scrollEl.scrollTo({
|
|
121
|
-
top: Math.max(0, targetTop),
|
|
122
|
-
behavior: "smooth",
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// As content below the anchored user message changes, adjust the spacer
|
|
128
|
-
// by the same amount so total scrollable space below the bubble stays
|
|
129
|
-
// constant and the bubble stays pinned.
|
|
130
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
131
|
-
ro = new ResizeObserver(() => {
|
|
132
|
-
if (!contentEl || !spacerEl || !scrollEl) return;
|
|
133
|
-
const contentHeight = contentEl.getBoundingClientRect().height;
|
|
134
|
-
const targetOffsetWithinContent = computeOffsetTop(
|
|
135
|
-
targetEl,
|
|
136
|
-
contentEl,
|
|
137
|
-
);
|
|
138
|
-
const consumedBelow =
|
|
139
|
-
contentHeight - targetOffsetWithinContent - userMessageHeight;
|
|
140
|
-
const remaining = Math.max(0, spacerHeight - consumedBelow);
|
|
141
|
-
spacerEl.style.height = `${remaining}px`;
|
|
142
|
-
});
|
|
143
|
-
ro.observe(contentEl);
|
|
144
|
-
}
|
|
145
69
|
},
|
|
146
70
|
{ immediate: true, flush: "post" },
|
|
147
71
|
);
|
|
148
72
|
}
|
|
149
|
-
|
|
150
|
-
// Compute the offset of el relative to stopAt, accounting for stopAt's current scrollTop.
|
|
151
|
-
// Uses getBoundingClientRect so it works regardless of CSS positioning (including position:static).
|
|
152
|
-
function computeOffsetTop(el: HTMLElement, stopAt: HTMLElement): number {
|
|
153
|
-
const elRect = el.getBoundingClientRect();
|
|
154
|
-
const stopRect = stopAt.getBoundingClientRect();
|
|
155
|
-
return elRect.top - stopRect.top + stopAt.scrollTop;
|
|
156
|
-
}
|