@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.
Files changed (343) hide show
  1. package/CONTRIBUTOR_GUIDE.md +1 -1
  2. package/PARITY.md +3 -3
  3. package/dist/hooks/use-copilot-action.d.ts.map +1 -1
  4. package/dist/hooks/use-frontend-tool.d.ts +1 -1
  5. package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
  6. package/dist/hooks/zod-parameters.d.ts +14 -0
  7. package/dist/hooks/zod-parameters.d.ts.map +1 -0
  8. package/dist/index.cjs +1 -73
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.mjs +365 -16920
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/use-render-activity-message-BZJ33B_r.cjs +113 -0
  13. package/dist/use-render-activity-message-BZJ33B_r.cjs.map +1 -0
  14. package/dist/use-render-activity-message-DrR407LQ.js +15901 -0
  15. package/dist/use-render-activity-message-DrR407LQ.js.map +1 -0
  16. package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
  17. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
  18. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
  19. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
  20. package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
  21. package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
  22. package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -1
  23. package/dist/v2/components/LicenseWarningBanner.vue.d.ts +2 -2
  24. package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
  25. package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
  26. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -59
  27. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
  28. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +3 -11
  29. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
  30. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
  31. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
  32. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -130
  33. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
  34. package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
  35. package/dist/v2/components/a2ui/utils.d.ts +3 -15
  36. package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
  37. package/dist/v2/components/a2ui.d.ts +9 -8
  38. package/dist/v2/components/a2ui.d.ts.map +1 -1
  39. package/dist/v2/components/chat/CopilotChat.vue.d.ts +2 -2
  40. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  41. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  42. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
  43. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
  44. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
  45. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
  46. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +1 -1
  47. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -1
  48. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +7 -286
  49. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  50. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -1
  51. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
  52. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +1 -1
  53. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  54. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  55. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +1 -1
  56. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
  57. package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
  58. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +1 -1
  59. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
  60. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
  61. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +3 -3
  62. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
  63. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -1
  64. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  65. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +8 -3
  66. package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
  67. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +5 -3
  68. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
  69. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +5 -3
  70. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
  71. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +8 -3
  72. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
  73. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +6 -4
  74. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
  75. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +6 -4
  76. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
  77. package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
  78. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
  79. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
  80. package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
  81. package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
  82. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +4 -4
  83. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
  84. package/dist/v2/components/chat/forwarded-slots.d.ts +12 -0
  85. package/dist/v2/components/chat/forwarded-slots.d.ts.map +1 -0
  86. package/dist/v2/components/chat/index.d.ts +34 -31
  87. package/dist/v2/components/chat/index.d.ts.map +1 -1
  88. package/dist/v2/components/chat/inspector-shortcuts.d.ts +2 -1
  89. package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -1
  90. package/dist/v2/components/chat/message-feedback.d.ts +38 -49
  91. package/dist/v2/components/chat/message-feedback.d.ts.map +1 -1
  92. package/dist/v2/components/chat/tool-call-display-context.d.ts +4 -19
  93. package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
  94. package/dist/v2/components/chat/tool-call-group-parts.d.ts +7 -20
  95. package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
  96. package/dist/v2/components/chat/turn-work.d.ts +0 -2
  97. package/dist/v2/components/chat/turn-work.d.ts.map +1 -1
  98. package/dist/v2/components/chat/types.d.ts +9 -4
  99. package/dist/v2/components/chat/types.d.ts.map +1 -1
  100. package/dist/v2/components/chat/use-chat-labels.d.ts +8 -0
  101. package/dist/v2/components/chat/use-chat-labels.d.ts.map +1 -0
  102. package/dist/v2/components/chat/use-copy-feedback.d.ts +11 -0
  103. package/dist/v2/components/chat/use-copy-feedback.d.ts.map +1 -0
  104. package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
  105. package/dist/v2/components/icons/index.d.ts +968 -1
  106. package/dist/v2/components/icons/index.d.ts.map +1 -1
  107. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
  108. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
  109. package/dist/v2/hooks/use-agent-context.d.ts +2 -3
  110. package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
  111. package/dist/v2/hooks/use-agent.d.ts +4 -1
  112. package/dist/v2/hooks/use-agent.d.ts.map +1 -1
  113. package/dist/v2/hooks/use-attachments.d.ts +7 -0
  114. package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
  115. package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
  116. package/dist/v2/hooks/use-component.d.ts +1 -0
  117. package/dist/v2/hooks/use-component.d.ts.map +1 -1
  118. package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
  119. package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
  120. package/dist/v2/hooks/use-default-render-tool.d.ts +2 -7
  121. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
  122. package/dist/v2/hooks/use-frontend-tool.d.ts +5 -0
  123. package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -1
  124. package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
  125. package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
  126. package/dist/v2/hooks/use-interrupt.d.ts +0 -1
  127. package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
  128. package/dist/v2/hooks/use-keyboard-height.d.ts +1 -1
  129. package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -1
  130. package/dist/v2/hooks/use-pin-to-send.d.ts +4 -12
  131. package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -1
  132. package/dist/v2/hooks/use-render-activity-message.d.ts +13 -9
  133. package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
  134. package/dist/v2/hooks/use-render-custom-messages.d.ts +5 -7
  135. package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
  136. package/dist/v2/hooks/use-render-tool.d.ts +1 -1
  137. package/dist/v2/hooks/use-render-tool.d.ts.map +1 -1
  138. package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
  139. package/dist/v2/hooks/use-threads.d.ts +6 -23
  140. package/dist/v2/hooks/use-threads.d.ts.map +1 -1
  141. package/dist/v2/index.cjs +1 -1
  142. package/dist/v2/index.mjs +197 -200
  143. package/dist/v2/index.mjs.map +1 -1
  144. package/dist/v2/lib/processPartialHtml.d.ts +1 -2
  145. package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
  146. package/dist/v2/lib/shallow-stable.d.ts.map +1 -1
  147. package/dist/v2/lib/vue-core.d.ts +33 -19
  148. package/dist/v2/lib/vue-core.d.ts.map +1 -1
  149. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  150. package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -129
  151. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  152. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
  153. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  154. package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
  155. package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
  156. package/dist/v2/providers/markdown-renderer.d.ts +4 -2
  157. package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
  158. package/dist/v2/providers/types.d.ts +3 -46
  159. package/dist/v2/providers/types.d.ts.map +1 -1
  160. package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
  161. package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
  162. package/dist/v2/types/defineToolCallRenderer.d.ts +1 -1
  163. package/dist/v2/types/defineToolCallRenderer.d.ts.map +1 -1
  164. package/dist/v2/types/human-in-the-loop.d.ts +8 -29
  165. package/dist/v2/types/human-in-the-loop.d.ts.map +1 -1
  166. package/dist/v2/types/interrupt.d.ts +1 -22
  167. package/dist/v2/types/interrupt.d.ts.map +1 -1
  168. package/dist/v2/types/vue-activity-message-renderer.d.ts +16 -15
  169. package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -1
  170. package/dist/v2/types/vue-custom-message-renderer.d.ts +7 -16
  171. package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -1
  172. package/dist/v2/types/vue-tool-call-renderer.d.ts +16 -35
  173. package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
  174. package/package.json +12 -13
  175. package/src/__tests__/build-entries.test.ts +29 -0
  176. package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
  177. package/src/hooks/use-copilot-action.ts +2 -1
  178. package/src/hooks/use-frontend-tool.ts +3 -6
  179. package/src/hooks/zod-parameters.ts +162 -0
  180. package/src/v2/__tests__/exports.test.ts +10 -0
  181. package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
  182. package/src/v2/__tests__/utils/test-helpers.ts +34 -4
  183. package/src/v2/components/A2UIMessageRenderer.ts +98 -68
  184. package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
  185. package/src/v2/components/CopilotKitInspector.vue +104 -51
  186. package/src/v2/components/InlineFeatureWarning.vue +20 -21
  187. package/src/v2/components/LicenseWarningBanner.vue +27 -135
  188. package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
  189. package/src/v2/components/OpenGenerativeUIRenderer.ts +122 -446
  190. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
  191. package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
  192. package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +60 -0
  193. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +64 -8
  194. package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
  195. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +6 -26
  196. package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -185
  197. package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
  198. package/src/v2/components/a2ui/catalog.ts +3 -3
  199. package/src/v2/components/a2ui/utils.ts +13 -65
  200. package/src/v2/components/a2ui.ts +15 -22
  201. package/src/v2/components/chat/CopilotChat.vue +121 -498
  202. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +47 -184
  203. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +36 -55
  204. package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +14 -6
  205. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
  206. package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +12 -77
  207. package/src/v2/components/chat/CopilotChatInput.vue +139 -654
  208. package/src/v2/components/chat/CopilotChatInspectorButton.vue +45 -108
  209. package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
  210. package/src/v2/components/chat/CopilotChatMessageView.vue +96 -274
  211. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +27 -62
  212. package/src/v2/components/chat/CopilotChatToolCallGroup.vue +63 -71
  213. package/src/v2/components/chat/CopilotChatToolCallItem.vue +8 -6
  214. package/src/v2/components/chat/CopilotChatToolCallsView.vue +31 -32
  215. package/src/v2/components/chat/CopilotChatUserMessage.vue +24 -112
  216. package/src/v2/components/chat/CopilotChatView.vue +123 -161
  217. package/src/v2/components/chat/CopilotChatWorkSummary.vue +26 -36
  218. package/src/v2/components/chat/CopilotModalHeader.vue +11 -23
  219. package/src/v2/components/chat/CopilotPopup.vue +23 -25
  220. package/src/v2/components/chat/CopilotPopupView.vue +10 -39
  221. package/src/v2/components/chat/CopilotPopupViewInternal.vue +49 -185
  222. package/src/v2/components/chat/CopilotSidebar.vue +23 -25
  223. package/src/v2/components/chat/CopilotSidebarView.vue +10 -39
  224. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +56 -100
  225. package/src/v2/components/chat/CopilotThreadsDrawer.vue +43 -105
  226. package/src/v2/components/chat/StreamingMarkdownDefault.vue +15 -28
  227. package/src/v2/components/chat/__tests__/CopilotChat.labels.test.ts +19 -4
  228. package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
  229. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
  230. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +5 -5
  231. package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
  232. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +132 -1
  233. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +247 -403
  234. package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +1 -99
  235. package/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.ts +43 -1
  236. package/src/v2/components/chat/__tests__/CopilotPopup.test.ts +90 -1
  237. package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
  238. package/src/v2/components/chat/__tests__/CopilotSidebar.test.ts +90 -1
  239. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
  240. package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
  241. package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
  242. package/src/v2/components/chat/audioRecorder.ts +4 -7
  243. package/src/v2/components/chat/copilotChatToolCallItemRender.ts +25 -90
  244. package/src/v2/components/chat/forwarded-slots.ts +17 -0
  245. package/src/v2/components/chat/index.ts +0 -1
  246. package/src/v2/components/chat/inspector-shortcuts.ts +10 -16
  247. package/src/v2/components/chat/message-feedback.ts +92 -195
  248. package/src/v2/components/chat/tool-call-display-context.ts +6 -22
  249. package/src/v2/components/chat/tool-call-group-parts.ts +47 -108
  250. package/src/v2/components/chat/turn-work.ts +0 -9
  251. package/src/v2/components/chat/types.ts +12 -4
  252. package/src/v2/components/chat/use-chat-labels.ts +16 -0
  253. package/src/v2/components/chat/use-copy-feedback.ts +21 -0
  254. package/src/v2/components/chat/use-lightbox.ts +15 -33
  255. package/src/v2/components/icons/__tests__/icons.test.ts +72 -68
  256. package/src/v2/components/icons/index.ts +109 -27
  257. package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
  258. package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
  259. package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
  260. package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
  261. package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
  262. package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
  263. package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
  264. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +66 -1
  265. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
  266. package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
  267. package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
  268. package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +106 -0
  269. package/src/v2/hooks/__tests__/use-render-tool.test.ts +3 -6
  270. package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
  271. package/src/v2/hooks/__tests__/zod-regression.test.ts +5 -4
  272. package/src/v2/hooks/use-agent-context.ts +4 -10
  273. package/src/v2/hooks/use-agent.ts +86 -290
  274. package/src/v2/hooks/use-attachments.ts +48 -168
  275. package/src/v2/hooks/use-capabilities.ts +2 -7
  276. package/src/v2/hooks/use-component.ts +7 -4
  277. package/src/v2/hooks/use-configure-suggestions.ts +29 -220
  278. package/src/v2/hooks/use-default-render-tool.ts +31 -152
  279. package/src/v2/hooks/use-frontend-tool.ts +15 -25
  280. package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
  281. package/src/v2/hooks/use-interrupt.ts +29 -308
  282. package/src/v2/hooks/use-keyboard-height.ts +17 -40
  283. package/src/v2/hooks/use-pin-to-send.ts +15 -99
  284. package/src/v2/hooks/use-render-activity-message.ts +35 -57
  285. package/src/v2/hooks/use-render-custom-messages.ts +24 -88
  286. package/src/v2/hooks/use-render-tool.ts +2 -4
  287. package/src/v2/hooks/use-suggestions.ts +17 -36
  288. package/src/v2/hooks/use-threads.ts +49 -288
  289. package/src/v2/lib/__tests__/shallow-stable.test.ts +54 -0
  290. package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
  291. package/src/v2/lib/processPartialHtml.ts +6 -21
  292. package/src/v2/lib/shallow-stable.ts +2 -16
  293. package/src/v2/lib/vue-core.ts +90 -85
  294. package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
  295. package/src/v2/providers/CopilotKitProvider.types.ts +12 -132
  296. package/src/v2/providers/CopilotKitProvider.vue +291 -641
  297. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
  298. package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +38 -2
  299. package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
  300. package/src/v2/providers/__tests__/CopilotKitProvider.headersAtSendTime.test.ts +3 -3
  301. package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +3 -1
  302. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
  303. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +88 -28
  304. package/src/v2/providers/chat-configuration-store-key.ts +9 -0
  305. package/src/v2/providers/markdown-renderer.ts +8 -2
  306. package/src/v2/providers/types.ts +3 -49
  307. package/src/v2/providers/use-inspector-thread-override.ts +22 -80
  308. package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +28 -33
  309. package/src/v2/types/defineToolCallRenderer.ts +7 -6
  310. package/src/v2/types/human-in-the-loop.ts +8 -32
  311. package/src/v2/types/interrupt.ts +7 -31
  312. package/src/v2/types/vue-activity-message-renderer.ts +24 -15
  313. package/src/v2/types/vue-custom-message-renderer.ts +12 -16
  314. package/src/v2/types/vue-tool-call-renderer.ts +23 -38
  315. package/tsconfig.json +0 -1
  316. package/vite.config.ts +8 -5
  317. package/vitest.config.ts +12 -7
  318. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts +0 -9
  319. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +0 -1
  320. package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
  321. package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
  322. package/dist/v2/components/chat/tool-call-layout.d.ts +0 -115
  323. package/dist/v2/components/chat/tool-call-layout.d.ts.map +0 -1
  324. package/dist/v2/lib/is-mobile-viewport.d.ts +0 -15
  325. package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
  326. package/dist/v2/lib/message-feedback.d.ts +0 -33
  327. package/dist/v2/lib/message-feedback.d.ts.map +0 -1
  328. package/dist/v2/lib/transcription-client.d.ts +0 -19
  329. package/dist/v2/lib/transcription-client.d.ts.map +0 -1
  330. package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
  331. package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
  332. package/src/v2/components/chat/BasicMarkdown.vue +0 -160
  333. package/src/v2/components/chat/__tests__/BasicMarkdown.test.ts +0 -69
  334. package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -39
  335. package/src/v2/components/chat/normalize-auto-scroll.ts +0 -17
  336. package/src/v2/components/chat/tool-call-layout.ts +0 -304
  337. package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +0 -48
  338. package/src/v2/lib/__tests__/message-feedback.test.ts +0 -152
  339. package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
  340. package/src/v2/lib/__tests__/transcription-client.test.ts +0 -67
  341. package/src/v2/lib/is-mobile-viewport.ts +0 -23
  342. package/src/v2/lib/message-feedback.ts +0 -120
  343. package/src/v2/lib/transcription-client.ts +0 -151
@@ -1,18 +1,16 @@
1
1
  <script setup lang="ts">
2
- import {
3
- computed,
4
- nextTick,
5
- onBeforeUnmount,
6
- onMounted,
7
- ref,
8
- useSlots,
9
- watch,
10
- } from "vue";
2
+ import { computed, ref, useSlots, watch } from "vue";
11
3
  import type { Message } from "@ag-ui/core";
12
- import type { Suggestion } from "@copilotkit/core";
4
+ import {
5
+ ɵcreateStickToBottom,
6
+ ɵgetChatViewState,
7
+ ɵisContentScrolledToBottom,
8
+ ɵnormalizeAutoScroll,
9
+ ɵwatchElementHeight,
10
+ } from "@copilotkit/core";
11
+ import type { Suggestion, ɵStickToBottom } from "@copilotkit/core";
13
12
  import type { Attachment } from "@copilotkit/shared";
14
- import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
15
- import { CopilotChatDefaultLabels } from "../../providers/types";
13
+ import { useChatLabels } from "./use-chat-labels";
16
14
  import { useKeyboardHeight } from "../../hooks/use-keyboard-height";
17
15
  import { usePinToSend } from "../../hooks/use-pin-to-send";
18
16
  import { IconChevronDown, IconUpload } from "../icons";
@@ -20,7 +18,6 @@ import CopilotChatInput from "./CopilotChatInput.vue";
20
18
  import CopilotChatAttachmentQueue from "./CopilotChatAttachmentQueue.vue";
21
19
  import CopilotChatMessageView from "./CopilotChatMessageView.vue";
22
20
  import CopilotChatSuggestionView from "./CopilotChatSuggestionView.vue";
23
- import { normalizeAutoScroll } from "./normalize-auto-scroll";
24
21
  import type {
25
22
  CopilotChatInputMode,
26
23
  CopilotChatInterruptSlotProps,
@@ -31,7 +28,6 @@ import type {
31
28
  // Vertical gap between the scroll-to-bottom button and the input container.
32
29
  // Mirrors React `CopilotChatView` `SCROLL_BUTTON_OFFSET`.
33
30
  const SCROLL_BUTTON_OFFSET = 16;
34
- const SCROLL_BOTTOM_THRESHOLD = 12;
35
31
 
36
32
  const props = withDefaults(defineProps<CopilotChatViewProps>(), {
37
33
  messageFeedback: true,
@@ -127,8 +123,7 @@ const emit = defineEmits<{
127
123
  "finish-transcribe": [];
128
124
  }>();
129
125
 
130
- const config = useCopilotChatConfiguration();
131
- const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
126
+ const labels = useChatLabels();
132
127
  const componentSlots = useSlots();
133
128
 
134
129
  const scrollContainerRef = ref<HTMLElement | null>(null);
@@ -137,13 +132,16 @@ const spacerRef = ref<HTMLElement | null>(null);
137
132
  const inputContainerRef = ref<HTMLElement | null>(null);
138
133
  const inputContainerHeight = ref(0);
139
134
  const isAtBottom = ref(true);
135
+ // The end of the messages is in view. Without following ("pin-to-send" and
136
+ // "none"), this, not the scroll height, decides the scroll-to-bottom button.
137
+ const isContentAtBottom = ref(true);
140
138
  const isControlledInput = computed(() => props.inputValue !== undefined);
141
139
  const localInputValue = ref(props.inputValue ?? "");
142
140
 
143
141
  // Normalize the `autoScroll` prop into the canonical mode triplet
144
142
  // (`pin-to-bottom` | `pin-to-send` | `none`). Boolean back-compat is
145
- // preserved by `normalizeAutoScroll` (parity with React).
146
- const autoScrollMode = computed(() => normalizeAutoScroll(props.autoScroll));
143
+ // preserved by `ɵnormalizeAutoScroll` (parity with React).
144
+ const autoScrollMode = computed(() => ɵnormalizeAutoScroll(props.autoScroll));
147
145
  const isPinToBottomMode = computed(
148
146
  () => autoScrollMode.value === "pin-to-bottom",
149
147
  );
@@ -169,13 +167,23 @@ const effectiveKeyboardHeight = computed(() =>
169
167
  const resolvedInputValue = computed(() =>
170
168
  isControlledInput.value ? (props.inputValue ?? "") : localInputValue.value,
171
169
  );
172
- const hasSuggestions = computed(
173
- () =>
174
- !props.isConnecting &&
175
- !props.isRunning &&
176
- Array.isArray(props.suggestions) &&
177
- props.suggestions.length > 0,
170
+ // Suggestions, the welcome screen and the bottom padding follow core's rules:
171
+ // no suggestions while connecting or running, no generic welcome for a
172
+ // connecting or caller-picked thread.
173
+ const viewState = computed(() =>
174
+ ɵgetChatViewState({
175
+ messageCount: props.messages.length,
176
+ suggestionCount: Array.isArray(props.suggestions)
177
+ ? props.suggestions.length
178
+ : 0,
179
+ isRunning: props.isRunning,
180
+ isConnecting: props.isConnecting,
181
+ hasExplicitThreadId: props.hasExplicitThreadId,
182
+ welcomeScreenEnabled: props.welcomeScreen !== false,
183
+ inputContainerHeight: inputContainerHeight.value,
184
+ }),
178
185
  );
186
+ const hasSuggestions = computed(() => viewState.value.hasSuggestions);
179
187
  const hasAttachments = computed(
180
188
  () => Array.isArray(props.attachments) && props.attachments.length > 0,
181
189
  );
@@ -193,142 +201,119 @@ const forwardedMessageViewSlotNames = computed(() =>
193
201
  ),
194
202
  );
195
203
  const shouldShowWelcomeScreen = computed(
196
- () =>
197
- props.messages.length === 0 &&
198
- props.welcomeScreen !== false &&
199
- !props.isConnecting &&
200
- !props.hasExplicitThreadId,
204
+ () => viewState.value.showWelcomeScreen,
201
205
  );
202
- // Mirrors React: `paddingBottom = inputContainerHeight + (hasSuggestions ? 4 : 32)`.
203
- // React intentionally does NOT add bonus padding for attachments — the
204
- // attachment queue lives inside the input overlay, so its height is already
205
- // captured by the overlay's measured `inputContainerHeight`.
206
+ // No bonus padding for attachments: the attachment queue lives inside the
207
+ // input overlay, so its height is already in `inputContainerHeight`.
206
208
  const messagePaddingBottom = computed(
207
- () => `${inputContainerHeight.value + (hasSuggestions.value ? 4 : 32)}px`,
209
+ () => `${viewState.value.paddingBottom}px`,
208
210
  );
209
211
  const showScrollToBottomButton = computed(
210
- () => !shouldShowWelcomeScreen.value && !isAtBottom.value,
212
+ () =>
213
+ !shouldShowWelcomeScreen.value &&
214
+ !(isPinToBottomMode.value ? isAtBottom.value : isContentAtBottom.value),
211
215
  );
212
216
 
213
- let inputResizeObserver: ResizeObserver | null = null;
214
- let contentResizeObserver: ResizeObserver | null = null;
215
-
216
- function attachInputOverlayObserver() {
217
- if (typeof ResizeObserver === "undefined") return;
218
-
219
- inputResizeObserver?.disconnect();
220
- inputResizeObserver = null;
221
-
222
- const el = inputContainerRef.value;
223
- if (!el) return;
224
-
225
- inputResizeObserver = new ResizeObserver((entries) => {
226
- const wasAtBottom = isAtBottom.value;
227
- const measured = entries[0]?.contentRect?.height;
228
- if (typeof measured === "number") {
229
- inputContainerHeight.value = measured;
230
- } else {
231
- syncInputContainerHeight();
232
- }
233
- updateIsAtBottom();
234
- if (isPinToBottomMode.value && wasAtBottom) {
235
- scrollToBottom("auto");
217
+ // Core keeps the list at the bottom while content arrives in `pin-to-bottom`
218
+ // mode, and tracks the position for the scroll-to-bottom button in every
219
+ // mode. It attaches when the scroll container mounts, also after the welcome
220
+ // screen gives way to the chat.
221
+ let stickToBottom: ɵStickToBottom | null = null;
222
+ watch(
223
+ [scrollContainerRef, scrollContentRef],
224
+ ([scrollElement, contentElement], _old, onCleanup) => {
225
+ if (!scrollElement) {
226
+ isAtBottom.value = true;
227
+ return;
236
228
  }
237
- });
238
- inputResizeObserver.observe(el);
239
- }
240
-
241
- function attachScrollContentObserver() {
242
- if (typeof ResizeObserver === "undefined") return;
243
-
244
- contentResizeObserver?.disconnect();
245
- contentResizeObserver = null;
246
-
247
- const el = scrollContentRef.value;
248
- if (!el) return;
229
+ const controller = ɵcreateStickToBottom({
230
+ scrollElement,
231
+ contentElement: contentElement ?? scrollElement,
232
+ follow: isPinToBottomMode.value,
233
+ onChange: (value) => {
234
+ isAtBottom.value = value;
235
+ },
236
+ });
237
+ stickToBottom = controller;
238
+ isAtBottom.value = controller.isAtBottom;
239
+ onCleanup(() => {
240
+ controller.dispose();
241
+ if (stickToBottom === controller) stickToBottom = null;
242
+ });
243
+ },
244
+ { flush: "post" },
245
+ );
249
246
 
250
- contentResizeObserver = new ResizeObserver(() => {
251
- const wasAtBottom = isAtBottom.value;
252
- updateIsAtBottom();
253
- if (isPinToBottomMode.value && wasAtBottom) {
254
- scrollToBottom("auto");
255
- }
256
- });
257
- contentResizeObserver.observe(el);
247
+ watch(isPinToBottomMode, (follow) => stickToBottom?.setFollow(follow));
248
+
249
+ // Without following, the button shows while messages sit below the viewport.
250
+ // That is the end of the messages, not the scroll height: in "pin-to-send"
251
+ // mode an empty spacer under them lets a sent message reach the top, and
252
+ // scrolling into it would only clear the screen (parity with React).
253
+ function checkContentAtBottom() {
254
+ const scrollElement = scrollContainerRef.value;
255
+ const contentElement = scrollContentRef.value;
256
+ isContentAtBottom.value =
257
+ !scrollElement ||
258
+ !contentElement ||
259
+ ɵisContentScrolledToBottom(scrollElement, contentElement);
258
260
  }
259
261
 
260
- // When the welcome screen disappears and the main chat view (with the input
261
- // overlay) appears, the template-ref elements become non-null. Re-attach
262
- // observers that were skipped during the initial mount.
263
- watch(shouldShowWelcomeScreen, async (show) => {
264
- if (show) return;
265
- await nextTick();
266
- syncInputContainerHeight();
267
- attachInputOverlayObserver();
268
- attachScrollContentObserver();
269
- });
270
-
271
262
  watch(
272
- () => props.inputValue,
273
- (next) => {
274
- if (isControlledInput.value) {
275
- localInputValue.value = next ?? "";
276
- }
263
+ [scrollContainerRef, scrollContentRef],
264
+ ([scrollElement, contentElement], _old, onCleanup) => {
265
+ checkContentAtBottom();
266
+ if (!scrollElement) return;
267
+ scrollElement.addEventListener("scroll", checkContentAtBottom);
268
+ // A reply that streams past the bottom needs the button before anyone
269
+ // scrolls, so check again when the viewport or the messages resize.
270
+ const resizeObserver =
271
+ typeof ResizeObserver === "undefined"
272
+ ? null
273
+ : new ResizeObserver(checkContentAtBottom);
274
+ resizeObserver?.observe(scrollElement);
275
+ if (contentElement) resizeObserver?.observe(contentElement);
276
+ onCleanup(() => {
277
+ scrollElement.removeEventListener("scroll", checkContentAtBottom);
278
+ resizeObserver?.disconnect();
279
+ });
277
280
  },
281
+ { flush: "post" },
278
282
  );
279
283
 
284
+ // The input overlay's height becomes the bottom padding of the messages.
280
285
  watch(
281
- [() => props.messages, () => props.suggestions, () => props.isRunning],
282
- async () => {
283
- const wasAtBottom = isAtBottom.value;
284
- await nextTick();
285
- if (!isPinToBottomMode.value || !wasAtBottom) {
286
+ inputContainerRef,
287
+ (element, _old, onCleanup) => {
288
+ if (!element) {
289
+ inputContainerHeight.value = 0;
286
290
  return;
287
291
  }
288
- scrollToBottom("auto");
289
- if (typeof requestAnimationFrame === "function") {
290
- requestAnimationFrame(() => {
291
- scrollToBottom("auto");
292
- });
293
- }
292
+ onCleanup(
293
+ ɵwatchElementHeight(element, ({ height }) => {
294
+ inputContainerHeight.value = height;
295
+ }),
296
+ );
294
297
  },
295
- { deep: true },
298
+ { flush: "post" },
296
299
  );
297
300
 
298
- function updateIsAtBottom() {
299
- const element = scrollContainerRef.value;
300
- if (!element) {
301
- isAtBottom.value = true;
302
- return;
303
- }
304
-
305
- const distance =
306
- element.scrollHeight - element.scrollTop - element.clientHeight;
307
- isAtBottom.value = distance <= SCROLL_BOTTOM_THRESHOLD;
308
- }
309
-
310
- function syncInputContainerHeight() {
311
- const element = inputContainerRef.value;
312
- inputContainerHeight.value = element?.offsetHeight ?? 0;
313
- }
301
+ watch(
302
+ () => props.inputValue,
303
+ (next) => {
304
+ if (isControlledInput.value) {
305
+ localInputValue.value = next ?? "";
306
+ }
307
+ },
308
+ );
314
309
 
315
310
  function scrollToBottom(behavior: ScrollBehavior = "smooth") {
316
- const element = scrollContainerRef.value;
317
- if (!element) return;
318
-
319
- if (typeof element.scrollTo === "function") {
320
- element.scrollTo({
321
- top: element.scrollHeight,
322
- behavior,
323
- });
324
- } else {
325
- element.scrollTop = element.scrollHeight;
326
- }
327
- updateIsAtBottom();
311
+ stickToBottom?.scrollToBottom(behavior);
328
312
  }
329
313
 
330
314
  function handleScroll() {
331
- updateIsAtBottom();
315
+ stickToBottom?.update();
316
+ checkContentAtBottom();
332
317
  }
333
318
 
334
319
  function handleInputValueChange(value: string) {
@@ -413,30 +398,6 @@ const inputEventProps = computed(() => {
413
398
  const canStop = computed(() => !!props.onStop);
414
399
  const canAddFile = computed(() => !!props.onAddFile);
415
400
  const canTranscribe = computed(() => !!props.onStartTranscribe);
416
-
417
- onMounted(async () => {
418
- await nextTick();
419
- syncInputContainerHeight();
420
- updateIsAtBottom();
421
- if (isPinToBottomMode.value) {
422
- scrollToBottom("auto");
423
- if (typeof requestAnimationFrame === "function") {
424
- requestAnimationFrame(() => {
425
- scrollToBottom("auto");
426
- });
427
- }
428
- }
429
-
430
- attachInputOverlayObserver();
431
- attachScrollContentObserver();
432
- });
433
-
434
- onBeforeUnmount(() => {
435
- inputResizeObserver?.disconnect();
436
- contentResizeObserver?.disconnect();
437
- inputResizeObserver = null;
438
- contentResizeObserver = null;
439
- });
440
401
  </script>
441
402
 
442
403
  <template>
@@ -457,7 +418,9 @@ onBeforeUnmount(() => {
457
418
  >
458
419
  <div class="cpk-chat-view-drop-overlay-content">
459
420
  <IconUpload class="cpk-chat-view-drop-overlay-icon" />
460
- <span class="cpk-chat-view-drop-overlay-label">Drop files here</span>
421
+ <span class="cpk-chat-view-drop-overlay-label">{{
422
+ labels.chatDropFilesLabel
423
+ }}</span>
461
424
  </div>
462
425
  </div>
463
426
  <slot
@@ -578,7 +541,6 @@ onBeforeUnmount(() => {
578
541
  ref="scrollContainerRef"
579
542
  data-testid="copilot-chat-view-scroll"
580
543
  class="cpk-chat-view-scroll-area cpk-chat-view-scroll-viewport"
581
- @scroll="handleScroll"
582
544
  >
583
545
  <div class="cpk-chat-view-scroll-content">
584
546
  <div
@@ -5,10 +5,10 @@
5
5
  * for 9s · 7 tools" and toggles the work it folded away.
6
6
  */
7
7
  import { computed, ref, watch } from "vue";
8
+ import { ɵgetWorkSummaryText } from "@copilotkit/core";
8
9
  import { IconChevronRight } from "../icons";
9
10
  import type { CopilotChatWorkSummarySlotProps } from "./types";
10
- import { pluralize } from "./tool-call-group-parts";
11
- import { formatDuration } from "./turn-work";
11
+ import { useChatLabels } from "./use-chat-labels";
12
12
 
13
13
  // `onClick` falls through to the button.
14
14
  const props = defineProps<Omit<CopilotChatWorkSummarySlotProps, "onClick">>();
@@ -28,19 +28,16 @@ watch(
28
28
  { immediate: true },
29
29
  );
30
30
 
31
- const failed = computed(
32
- () => props.calls.filter((call) => call.toolMessage?.error).length,
33
- );
34
- const liveMs = computed(() =>
35
- props.elapsedMs !== undefined && props.workingSince !== undefined
36
- ? props.elapsedMs + Math.max(0, now.value - props.workingSince)
37
- : undefined,
38
- );
39
- // A finished reply worked for at least a second.
40
- const duration = computed(() =>
41
- props.elapsedMs !== undefined
42
- ? formatDuration(Math.max(1000, props.elapsedMs))
43
- : undefined,
31
+ const labels = useChatLabels();
32
+ const text = computed(() =>
33
+ ɵgetWorkSummaryText({
34
+ isWorking: props.isWorking,
35
+ calls: props.calls,
36
+ elapsedMs: props.elapsedMs,
37
+ workingSince: props.workingSince,
38
+ now: now.value,
39
+ labels: labels.value,
40
+ }),
44
41
  );
45
42
  </script>
46
43
 
@@ -53,27 +50,20 @@ const duration = computed(() =>
53
50
  :aria-expanded="isOpen ? 'true' : 'false'"
54
51
  class="cpk-work-summary"
55
52
  >
56
- <template v-if="isWorking">
57
- <span class="cpk-work-summary-label cpk-shimmer">Working</span>
58
- <span
59
- v-if="liveMs !== undefined"
60
- class="cpk-work-summary-detail cpk-work-summary-timer"
61
- >{{ formatDuration(liveMs) }}</span
62
- >
63
- </template>
64
- <template v-else>
65
- <span class="cpk-work-summary-label">{{
66
- duration
67
- ? `Worked for ${duration}`
68
- : `Used ${pluralize(calls.length, "tool")}`
69
- }}</span>
70
- <span v-if="duration" class="cpk-work-summary-detail">{{
71
- pluralize(calls.length, "tool")
72
- }}</span>
73
- <span v-if="failed > 0" class="cpk-work-summary-failed"
74
- >{{ failed }} failed</span
75
- >
76
- </template>
53
+ <span :class="['cpk-work-summary-label', isWorking && 'cpk-shimmer']">{{
54
+ text.label
55
+ }}</span>
56
+ <span
57
+ v-if="text.detail !== null"
58
+ :class="[
59
+ 'cpk-work-summary-detail',
60
+ isWorking && 'cpk-work-summary-timer',
61
+ ]"
62
+ >{{ text.detail }}</span
63
+ >
64
+ <span v-if="text.failed !== null" class="cpk-work-summary-failed">{{
65
+ text.failed
66
+ }}</span>
77
67
  <IconChevronRight
78
68
  aria-hidden="true"
79
69
  :class="[
@@ -2,7 +2,7 @@
2
2
  import { computed, onBeforeUnmount, onMounted, ref, useAttrs } from "vue";
3
3
  import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
4
4
  import { CopilotChatDefaultLabels } from "../../providers/types";
5
- import { MOBILE_MAX_WIDTH_QUERY } from "../../lib/is-mobile-viewport";
5
+ import { ɵwatchMobileViewport } from "@copilotkit/core";
6
6
  import CopilotModalHeaderCloseButton from "./CopilotModalHeaderCloseButton";
7
7
  import CopilotModalHeaderTitle from "./CopilotModalHeaderTitle";
8
8
  import { IconPanelLeftOpen } from "../icons";
@@ -45,34 +45,22 @@ function handleClose() {
45
45
  config.value?.setModalOpen?.(false);
46
46
  }
47
47
 
48
- // Tracks whether the viewport is in the mobile range (MOBILE_MAX_WIDTH_QUERY) — the same
49
- // breakpoint the drawer + chat coordination use. SSR-safe: starts `false`
50
- // (desktop) so the server render and first client render agree, then syncs
51
- // on mount and on viewport changes.
48
+ // Tracks whether the viewport is in the mobile range — the same breakpoint
49
+ // the drawer + chat coordination use. SSR-safe: starts `false` (desktop) so
50
+ // the server render and first client render agree, then syncs on mount and
51
+ // on viewport changes.
52
52
  const isMobile = ref(false);
53
- let mobileMediaQuery: MediaQueryList | null = null;
54
-
55
- function syncIsMobile() {
56
- if (mobileMediaQuery) {
57
- isMobile.value = mobileMediaQuery.matches;
58
- }
59
- }
53
+ let stopWatchingMobile: (() => void) | undefined;
60
54
 
61
55
  onMounted(() => {
62
- if (
63
- typeof window === "undefined" ||
64
- typeof window.matchMedia !== "function"
65
- ) {
66
- return;
67
- }
68
- mobileMediaQuery = window.matchMedia(MOBILE_MAX_WIDTH_QUERY);
69
- mobileMediaQuery.addEventListener("change", syncIsMobile);
70
- syncIsMobile();
56
+ stopWatchingMobile = ɵwatchMobileViewport((mobile) => {
57
+ isMobile.value = mobile;
58
+ });
71
59
  });
72
60
 
73
61
  onBeforeUnmount(() => {
74
- mobileMediaQuery?.removeEventListener("change", syncIsMobile);
75
- mobileMediaQuery = null;
62
+ stopWatchingMobile?.();
63
+ stopWatchingMobile = undefined;
76
64
  });
77
65
 
78
66
  // The thread-list launcher renders ONLY when a <CopilotThreadsDrawer> wrapper
@@ -4,9 +4,14 @@ import CopilotChat from "./CopilotChat.vue";
4
4
  import CopilotPopupView from "./CopilotPopupView.vue";
5
5
  import CopilotPopupWelcomeScreen from "./CopilotPopupWelcomeScreen.vue";
6
6
  import InlineFeatureWarning from "../InlineFeatureWarning.vue";
7
+ import { forwardedSlotNames } from "./forwarded-slots";
7
8
  import { useLicenseContext } from "../../providers/useLicenseContext";
8
9
  import type {
10
+ CopilotChatFeatherSlotProps,
11
+ CopilotChatInterruptSlotProps,
9
12
  CopilotChatMessageViewSlotProps,
13
+ CopilotChatScrollToBottomButtonSlotProps,
14
+ CopilotChatScrollViewSlotProps,
10
15
  CopilotChatViewOverrideSlotProps,
11
16
  CopilotChatWelcomeScreenSlotProps,
12
17
  CopilotPopupProps,
@@ -53,14 +58,28 @@ defineSlots<{
53
58
  "toggle-button"?: (props: CopilotPopupViewToggleButtonSlotProps) => unknown;
54
59
  "chat-view"?: (props: CopilotChatViewOverrideSlotProps) => unknown;
55
60
  "message-view"?: (props: CopilotChatMessageViewSlotProps) => unknown;
61
+ "scroll-view"?: (props: CopilotChatScrollViewSlotProps) => unknown;
62
+ feather?: (props: CopilotChatFeatherSlotProps) => unknown;
63
+ "scroll-to-bottom-button"?: (
64
+ props: CopilotChatScrollToBottomButtonSlotProps,
65
+ ) => unknown;
66
+ interrupt?: (props: CopilotChatInterruptSlotProps) => unknown;
56
67
  input?: (props: CopilotSidebarWelcomeScreenInputSlotProps) => unknown;
57
68
  "suggestion-view"?: (
58
69
  props: CopilotSidebarWelcomeScreenSuggestionViewSlotProps,
59
70
  ) => unknown;
60
71
  "welcome-screen"?: (props: CopilotChatWelcomeScreenSlotProps) => unknown;
61
72
  "welcome-message"?: () => unknown;
73
+ // Any other slot goes to the chat view, as on CopilotChat.
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ [key: string]: ((props: any) => unknown) | undefined;
62
76
  }>();
63
77
 
78
+ // Slots this component renders itself and does not pass to the view. It passes
79
+ // every other slot to the view. It also renders `input` and `suggestion-view`
80
+ // in its welcome screen, so those two go to both places.
81
+ const OWN_SLOTS = ["chat-view", "welcome-screen", "welcome-message"] as const;
82
+
64
83
  defineEmits<{
65
84
  "submit-message": [value: string];
66
85
  stop: [];
@@ -125,15 +144,12 @@ watch(
125
144
  :on-finish-transcribe-with-audio="slotProps.onFinishTranscribeWithAudio"
126
145
  v-bind="popupViewEventBindings(slotProps)"
127
146
  >
128
- <template v-if="$slots.header" #header="headerProps">
129
- <slot name="header" v-bind="headerProps" />
130
- </template>
131
-
132
147
  <template
133
- v-if="$slots['toggle-button']"
134
- #toggle-button="toggleButtonProps"
148
+ v-for="slotName in forwardedSlotNames($slots, OWN_SLOTS)"
149
+ :key="slotName"
150
+ #[slotName]="forwardedProps"
135
151
  >
136
- <slot name="toggle-button" v-bind="toggleButtonProps" />
152
+ <slot :name="slotName" v-bind="forwardedProps" />
137
153
  </template>
138
154
 
139
155
  <template #welcome-screen="welcomeScreenProps">
@@ -159,24 +175,6 @@ watch(
159
175
  </template>
160
176
  </CopilotPopupWelcomeScreen>
161
177
  </template>
162
-
163
- <template
164
- v-if="$slots['message-view']"
165
- #message-view="messageViewProps"
166
- >
167
- <slot name="message-view" v-bind="messageViewProps" />
168
- </template>
169
-
170
- <template v-if="$slots.input" #input="inputProps">
171
- <slot name="input" v-bind="inputProps" />
172
- </template>
173
-
174
- <template
175
- v-if="$slots['suggestion-view']"
176
- #suggestion-view="suggestionViewProps"
177
- >
178
- <slot name="suggestion-view" v-bind="suggestionViewProps" />
179
- </template>
180
178
  </CopilotPopupView>
181
179
  </template>
182
180
  </CopilotChat>