@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.
Files changed (335) hide show
  1. package/PARITY.md +3 -3
  2. package/dist/hooks/use-copilot-action.d.ts.map +1 -1
  3. package/dist/hooks/use-frontend-tool.d.ts +1 -1
  4. package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
  5. package/dist/hooks/zod-parameters.d.ts +14 -0
  6. package/dist/hooks/zod-parameters.d.ts.map +1 -0
  7. package/dist/index.cjs +1 -73
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.mjs +365 -16920
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/use-render-activity-message-BAhbpSDh.js +16200 -0
  12. package/dist/use-render-activity-message-BAhbpSDh.js.map +1 -0
  13. package/dist/use-render-activity-message-DJ6q1qHV.cjs +114 -0
  14. package/dist/use-render-activity-message-DJ6q1qHV.cjs.map +1 -0
  15. package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
  16. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
  17. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
  18. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
  19. package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
  20. package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
  21. package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -1
  22. package/dist/v2/components/LicenseWarningBanner.vue.d.ts +2 -2
  23. package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
  24. package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
  25. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -59
  26. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
  27. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +0 -5
  28. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
  29. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
  30. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
  31. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -130
  32. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
  33. package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
  34. package/dist/v2/components/a2ui/utils.d.ts +3 -15
  35. package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
  36. package/dist/v2/components/a2ui.d.ts +9 -8
  37. package/dist/v2/components/a2ui.d.ts.map +1 -1
  38. package/dist/v2/components/chat/CopilotChat.vue.d.ts +2 -2
  39. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  40. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  41. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
  42. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
  43. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
  44. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
  45. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +1 -1
  46. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -1
  47. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +6 -270
  48. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  49. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -1
  50. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
  51. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +1 -1
  52. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  53. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  54. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +1 -1
  55. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
  56. package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
  57. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +1 -1
  58. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
  59. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
  60. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +3 -3
  61. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
  62. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -1
  63. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  64. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +8 -3
  65. package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
  66. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +5 -3
  67. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
  68. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +5 -3
  69. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
  70. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +8 -3
  71. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
  72. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +6 -4
  73. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
  74. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +6 -4
  75. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
  76. package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
  77. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
  78. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
  79. package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
  80. package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
  81. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +3 -3
  82. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
  83. package/dist/v2/components/chat/forwarded-slots.d.ts +12 -0
  84. package/dist/v2/components/chat/forwarded-slots.d.ts.map +1 -0
  85. package/dist/v2/components/chat/index.d.ts +34 -31
  86. package/dist/v2/components/chat/index.d.ts.map +1 -1
  87. package/dist/v2/components/chat/inspector-shortcuts.d.ts +2 -1
  88. package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -1
  89. package/dist/v2/components/chat/message-feedback.d.ts +18 -49
  90. package/dist/v2/components/chat/message-feedback.d.ts.map +1 -1
  91. package/dist/v2/components/chat/tool-call-display-context.d.ts +4 -19
  92. package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
  93. package/dist/v2/components/chat/tool-call-group-parts.d.ts +7 -20
  94. package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
  95. package/dist/v2/components/chat/turn-work.d.ts +0 -2
  96. package/dist/v2/components/chat/turn-work.d.ts.map +1 -1
  97. package/dist/v2/components/chat/types.d.ts +9 -4
  98. package/dist/v2/components/chat/types.d.ts.map +1 -1
  99. package/dist/v2/components/chat/use-chat-labels.d.ts +8 -0
  100. package/dist/v2/components/chat/use-chat-labels.d.ts.map +1 -0
  101. package/dist/v2/components/chat/use-copy-feedback.d.ts +11 -0
  102. package/dist/v2/components/chat/use-copy-feedback.d.ts.map +1 -0
  103. package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
  104. package/dist/v2/components/icons/index.d.ts +968 -1
  105. package/dist/v2/components/icons/index.d.ts.map +1 -1
  106. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
  107. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
  108. package/dist/v2/hooks/use-agent-context.d.ts +2 -3
  109. package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
  110. package/dist/v2/hooks/use-agent.d.ts +4 -1
  111. package/dist/v2/hooks/use-agent.d.ts.map +1 -1
  112. package/dist/v2/hooks/use-attachments.d.ts +7 -0
  113. package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
  114. package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
  115. package/dist/v2/hooks/use-component.d.ts +1 -0
  116. package/dist/v2/hooks/use-component.d.ts.map +1 -1
  117. package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
  118. package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
  119. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
  120. package/dist/v2/hooks/use-frontend-tool.d.ts +5 -0
  121. package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -1
  122. package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
  123. package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
  124. package/dist/v2/hooks/use-interrupt.d.ts +0 -1
  125. package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
  126. package/dist/v2/hooks/use-keyboard-height.d.ts +1 -1
  127. package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -1
  128. package/dist/v2/hooks/use-pin-to-send.d.ts +4 -12
  129. package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -1
  130. package/dist/v2/hooks/use-render-activity-message.d.ts +13 -9
  131. package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
  132. package/dist/v2/hooks/use-render-custom-messages.d.ts +5 -7
  133. package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
  134. package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
  135. package/dist/v2/hooks/use-threads.d.ts +0 -8
  136. package/dist/v2/hooks/use-threads.d.ts.map +1 -1
  137. package/dist/v2/index.cjs +1 -1
  138. package/dist/v2/index.mjs +197 -200
  139. package/dist/v2/index.mjs.map +1 -1
  140. package/dist/v2/lib/processPartialHtml.d.ts +1 -2
  141. package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
  142. package/dist/v2/lib/shallow-stable.d.ts.map +1 -1
  143. package/dist/v2/lib/vue-core.d.ts +12 -12
  144. package/dist/v2/lib/vue-core.d.ts.map +1 -1
  145. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  146. package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -129
  147. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  148. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
  149. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  150. package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
  151. package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
  152. package/dist/v2/providers/markdown-renderer.d.ts +4 -2
  153. package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
  154. package/dist/v2/providers/types.d.ts +3 -46
  155. package/dist/v2/providers/types.d.ts.map +1 -1
  156. package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
  157. package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
  158. package/dist/v2/types/human-in-the-loop.d.ts +8 -29
  159. package/dist/v2/types/human-in-the-loop.d.ts.map +1 -1
  160. package/dist/v2/types/interrupt.d.ts +1 -22
  161. package/dist/v2/types/interrupt.d.ts.map +1 -1
  162. package/dist/v2/types/vue-activity-message-renderer.d.ts +16 -15
  163. package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -1
  164. package/dist/v2/types/vue-custom-message-renderer.d.ts +7 -16
  165. package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -1
  166. package/dist/v2/types/vue-tool-call-renderer.d.ts +16 -35
  167. package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
  168. package/package.json +10 -11
  169. package/src/__tests__/build-entries.test.ts +27 -0
  170. package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
  171. package/src/hooks/use-copilot-action.ts +2 -1
  172. package/src/hooks/use-frontend-tool.ts +3 -6
  173. package/src/hooks/zod-parameters.ts +162 -0
  174. package/src/v2/__tests__/exports.test.ts +10 -0
  175. package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
  176. package/src/v2/__tests__/utils/test-helpers.ts +34 -4
  177. package/src/v2/components/A2UIMessageRenderer.ts +98 -68
  178. package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
  179. package/src/v2/components/CopilotKitInspector.vue +104 -51
  180. package/src/v2/components/InlineFeatureWarning.vue +20 -21
  181. package/src/v2/components/LicenseWarningBanner.vue +27 -135
  182. package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
  183. package/src/v2/components/OpenGenerativeUIRenderer.ts +122 -446
  184. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
  185. package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
  186. package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +60 -0
  187. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +64 -8
  188. package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
  189. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +2 -7
  190. package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -185
  191. package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
  192. package/src/v2/components/a2ui/catalog.ts +3 -3
  193. package/src/v2/components/a2ui/utils.ts +13 -65
  194. package/src/v2/components/a2ui.ts +15 -22
  195. package/src/v2/components/chat/CopilotChat.vue +147 -356
  196. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +19 -43
  197. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +36 -55
  198. package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +14 -6
  199. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
  200. package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +2 -2
  201. package/src/v2/components/chat/CopilotChatInput.vue +108 -436
  202. package/src/v2/components/chat/CopilotChatInspectorButton.vue +45 -108
  203. package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
  204. package/src/v2/components/chat/CopilotChatMessageView.vue +82 -210
  205. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +7 -15
  206. package/src/v2/components/chat/CopilotChatToolCallGroup.vue +63 -71
  207. package/src/v2/components/chat/CopilotChatToolCallItem.vue +8 -6
  208. package/src/v2/components/chat/CopilotChatToolCallsView.vue +31 -32
  209. package/src/v2/components/chat/CopilotChatUserMessage.vue +24 -112
  210. package/src/v2/components/chat/CopilotChatView.vue +33 -28
  211. package/src/v2/components/chat/CopilotChatWorkSummary.vue +26 -36
  212. package/src/v2/components/chat/CopilotModalHeader.vue +11 -23
  213. package/src/v2/components/chat/CopilotPopup.vue +23 -25
  214. package/src/v2/components/chat/CopilotPopupView.vue +10 -39
  215. package/src/v2/components/chat/CopilotPopupViewInternal.vue +35 -131
  216. package/src/v2/components/chat/CopilotSidebar.vue +23 -25
  217. package/src/v2/components/chat/CopilotSidebarView.vue +10 -39
  218. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +38 -59
  219. package/src/v2/components/chat/CopilotThreadsDrawer.vue +37 -102
  220. package/src/v2/components/chat/StreamingMarkdownDefault.vue +15 -28
  221. package/src/v2/components/chat/__tests__/CopilotChat.labels.test.ts +19 -4
  222. package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
  223. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
  224. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +5 -5
  225. package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
  226. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +89 -1
  227. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +247 -403
  228. package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +1 -99
  229. package/src/v2/components/chat/__tests__/CopilotPopup.test.ts +90 -1
  230. package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
  231. package/src/v2/components/chat/__tests__/CopilotSidebar.test.ts +90 -1
  232. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
  233. package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
  234. package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
  235. package/src/v2/components/chat/audioRecorder.ts +4 -7
  236. package/src/v2/components/chat/copilotChatToolCallItemRender.ts +24 -89
  237. package/src/v2/components/chat/forwarded-slots.ts +17 -0
  238. package/src/v2/components/chat/index.ts +0 -1
  239. package/src/v2/components/chat/inspector-shortcuts.ts +10 -16
  240. package/src/v2/components/chat/message-feedback.ts +62 -197
  241. package/src/v2/components/chat/tool-call-display-context.ts +6 -22
  242. package/src/v2/components/chat/tool-call-group-parts.ts +47 -108
  243. package/src/v2/components/chat/turn-work.ts +0 -9
  244. package/src/v2/components/chat/types.ts +12 -4
  245. package/src/v2/components/chat/use-chat-labels.ts +16 -0
  246. package/src/v2/components/chat/use-copy-feedback.ts +21 -0
  247. package/src/v2/components/chat/use-lightbox.ts +15 -33
  248. package/src/v2/components/icons/__tests__/icons.test.ts +72 -68
  249. package/src/v2/components/icons/index.ts +109 -27
  250. package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
  251. package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
  252. package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
  253. package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
  254. package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
  255. package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
  256. package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
  257. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +66 -1
  258. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
  259. package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
  260. package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
  261. package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +106 -0
  262. package/src/v2/hooks/__tests__/use-render-tool.test.ts +3 -6
  263. package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
  264. package/src/v2/hooks/__tests__/zod-regression.test.ts +5 -4
  265. package/src/v2/hooks/use-agent-context.ts +4 -10
  266. package/src/v2/hooks/use-agent.ts +86 -290
  267. package/src/v2/hooks/use-attachments.ts +48 -168
  268. package/src/v2/hooks/use-capabilities.ts +2 -7
  269. package/src/v2/hooks/use-component.ts +7 -4
  270. package/src/v2/hooks/use-configure-suggestions.ts +28 -218
  271. package/src/v2/hooks/use-default-render-tool.ts +34 -94
  272. package/src/v2/hooks/use-frontend-tool.ts +10 -10
  273. package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
  274. package/src/v2/hooks/use-interrupt.ts +29 -308
  275. package/src/v2/hooks/use-keyboard-height.ts +17 -40
  276. package/src/v2/hooks/use-pin-to-send.ts +15 -99
  277. package/src/v2/hooks/use-render-activity-message.ts +31 -55
  278. package/src/v2/hooks/use-render-custom-messages.ts +24 -88
  279. package/src/v2/hooks/use-suggestions.ts +9 -33
  280. package/src/v2/hooks/use-threads.ts +43 -273
  281. package/src/v2/lib/__tests__/shallow-stable.test.ts +54 -0
  282. package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
  283. package/src/v2/lib/processPartialHtml.ts +6 -21
  284. package/src/v2/lib/shallow-stable.ts +2 -16
  285. package/src/v2/lib/vue-core.ts +69 -78
  286. package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
  287. package/src/v2/providers/CopilotKitProvider.types.ts +12 -132
  288. package/src/v2/providers/CopilotKitProvider.vue +237 -510
  289. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
  290. package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +20 -2
  291. package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
  292. package/src/v2/providers/__tests__/CopilotKitProvider.headersAtSendTime.test.ts +3 -3
  293. package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +3 -1
  294. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
  295. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +53 -26
  296. package/src/v2/providers/chat-configuration-store-key.ts +9 -0
  297. package/src/v2/providers/markdown-renderer.ts +8 -2
  298. package/src/v2/providers/types.ts +3 -49
  299. package/src/v2/providers/use-inspector-thread-override.ts +22 -80
  300. package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +28 -33
  301. package/src/v2/types/defineToolCallRenderer.ts +5 -4
  302. package/src/v2/types/human-in-the-loop.ts +8 -32
  303. package/src/v2/types/interrupt.ts +7 -31
  304. package/src/v2/types/vue-activity-message-renderer.ts +24 -15
  305. package/src/v2/types/vue-custom-message-renderer.ts +12 -16
  306. package/src/v2/types/vue-tool-call-renderer.ts +23 -38
  307. package/tsconfig.json +0 -1
  308. package/vite.config.ts +8 -5
  309. package/vitest.config.ts +12 -7
  310. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts +0 -9
  311. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +0 -1
  312. package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
  313. package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
  314. package/dist/v2/components/chat/tool-call-layout.d.ts +0 -115
  315. package/dist/v2/components/chat/tool-call-layout.d.ts.map +0 -1
  316. package/dist/v2/lib/is-mobile-viewport.d.ts +0 -15
  317. package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
  318. package/dist/v2/lib/message-feedback.d.ts +0 -33
  319. package/dist/v2/lib/message-feedback.d.ts.map +0 -1
  320. package/dist/v2/lib/transcription-client.d.ts +0 -19
  321. package/dist/v2/lib/transcription-client.d.ts.map +0 -1
  322. package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
  323. package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
  324. package/src/v2/components/chat/BasicMarkdown.vue +0 -160
  325. package/src/v2/components/chat/__tests__/BasicMarkdown.test.ts +0 -69
  326. package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -39
  327. package/src/v2/components/chat/normalize-auto-scroll.ts +0 -17
  328. package/src/v2/components/chat/tool-call-layout.ts +0 -304
  329. package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +0 -48
  330. package/src/v2/lib/__tests__/message-feedback.test.ts +0 -152
  331. package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
  332. package/src/v2/lib/__tests__/transcription-client.test.ts +0 -67
  333. package/src/v2/lib/is-mobile-viewport.ts +0 -23
  334. package/src/v2/lib/message-feedback.ts +0 -120
  335. package/src/v2/lib/transcription-client.ts +0 -151
@@ -1,11 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { AGUIConnectNotImplementedError, AbstractAgent } from "@ag-ui/client";
3
- import {
4
- createAttachmentContent,
5
- DEFAULT_AGENT_ID,
6
- randomUUID,
7
- TranscriptionErrorCode,
8
- } from "@copilotkit/shared";
3
+ import { DEFAULT_AGENT_ID, randomUUID } from "@copilotkit/shared";
9
4
  import {
10
5
  computed,
11
6
  onBeforeUnmount,
@@ -17,8 +12,16 @@ import {
17
12
  useSlots,
18
13
  watch,
19
14
  } from "vue";
20
- import { CopilotKitCoreErrorCode, ɵisHttpAgent } from "@copilotkit/core";
21
- import type { Suggestion } from "@copilotkit/core";
15
+ import {
16
+ CopilotChatDefaultLabels,
17
+ CopilotKitCoreErrorCode,
18
+ ɵcreateChatSubmitter,
19
+ ɵcreateLastUserMessageTracker,
20
+ ɵisHttpAgent,
21
+ ɵresolveChatNotice,
22
+ ɵThreadSwitchCoordinator,
23
+ } from "@copilotkit/core";
24
+ import type { Suggestion, ɵThreadSelection } from "@copilotkit/core";
22
25
  import CopilotChatConfigurationProvider from "../../providers/CopilotChatConfigurationProvider.vue";
23
26
  import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
24
27
  import { useCopilotKit } from "../../providers/useCopilotKit";
@@ -28,15 +31,10 @@ import { useAgent } from "../../hooks/use-agent";
28
31
  import { useSuggestions } from "../../hooks/use-suggestions";
29
32
  import { useAttachments } from "../../hooks/use-attachments";
30
33
  import { useShallowStableRef } from "../../lib/shallow-stable";
31
- import {
32
- transcribeAudio,
33
- TranscriptionError,
34
- } from "../../lib/transcription-client";
35
34
  import CopilotChatView from "./CopilotChatView.vue";
36
35
  import { LastUserMessageKey } from "./last-user-message-context";
37
36
  import type { LastUserMessageState } from "./last-user-message-context";
38
37
  import type { Message } from "@ag-ui/core";
39
- import type { InputContent } from "@copilotkit/shared";
40
38
  import { useInspectorThreadOverride } from "../../providers/use-inspector-thread-override";
41
39
  import { CopilotKitStyles } from "../../styles/CopilotKitStyles";
42
40
  import type {
@@ -97,27 +95,23 @@ const forwardedChatViewSlotNames = computed(() =>
97
95
  const generatedThreadId = ref(randomUUID());
98
96
  const transcribeMode = ref<"input" | "transcribe" | "processing">("input");
99
97
  const inputValue = ref(props.inputValue ?? "");
100
- const transcriptionError = ref<string | null>(null);
101
- const isTranscribing = ref(false);
102
98
  const isMounted = ref(false);
103
99
  const isUnmounting = ref(false);
104
100
 
105
101
  type ActiveConnectCycle = {
106
102
  core: object;
107
- agent: AbstractAgent;
108
- threadId: string;
109
- inspectorRequestId: string | null;
103
+ selection: ɵThreadSelection;
110
104
  abortController: AbortController;
111
105
  detached: boolean;
112
- clearDiscardedBaseline?: () => void;
113
106
  };
114
107
 
115
108
  const activeConnectCycle = shallowRef<ActiveConnectCycle | null>(null);
116
- let lastConnectCycle: ActiveConnectCycle | null = null;
117
- const detachPromises = new WeakMap<AbstractAgent, Promise<void>>();
118
- // Agent clones can share cursors. Finish every old reset before connecting again.
119
- let pendingTeardown = Promise.resolve();
120
- const baselineThreadIds = new WeakMap<AbstractAgent, string>();
109
+ // Keeps the agent on the thread this chat shows, orders the teardown of the
110
+ // previous thread, and tracks connections a send must wait for.
111
+ const threads = new ɵThreadSwitchCoordinator({
112
+ stopAgent: (params) => copilotkit.value.stopAgent(params),
113
+ subscribe: (subscriber) => copilotkit.value.subscribe(subscriber),
114
+ });
121
115
 
122
116
  const resolvedAgentId = computed(
123
117
  () => props.agentId ?? existingConfig.value?.agentId ?? DEFAULT_AGENT_ID,
@@ -159,6 +153,12 @@ const isConnecting = computed(
159
153
  );
160
154
  const stableLabels = useShallowStableRef(computed(() => props.labels));
161
155
  const resolvedLabels = computed(() => stableLabels.value);
156
+ // The labels this chat shows, the same merge its configuration provider makes.
157
+ const chatLabels = computed(() => ({
158
+ ...CopilotChatDefaultLabels,
159
+ ...existingConfig.value?.labels,
160
+ ...resolvedLabels.value,
161
+ }));
162
162
 
163
163
  // `useAgent` takes no threadId: it pins one only from a surrounding chat
164
164
  // configuration, and this call sits outside the provider rendered in this
@@ -227,27 +227,11 @@ const shouldAllowStop = computed(
227
227
  // Track the latest user message id so descendants (notably `usePinToSend`
228
228
  // inside `CopilotChatView`) can anchor to the most recent user turn.
229
229
  // Mirrors React `CopilotChat.tsx` `lastUserMessageId` + `sendNonce` state.
230
- const lastUserMessageId = computed<string | null>(() => {
231
- for (let i = messages.value.length - 1; i >= 0; i--) {
232
- const message = messages.value[i];
233
- if (message?.role === "user") return message.id;
234
- }
235
- return null;
236
- });
237
- const sendNonce = ref(0);
238
- // Seed with the current value so restoring a thread with existing messages
239
- // does not count as a new send. Only later id transitions bump.
240
- let prevLastUserMessageId: string | null = lastUserMessageId.value;
241
- watch(lastUserMessageId, (next) => {
242
- if (next && next !== prevLastUserMessageId) {
243
- sendNonce.value += 1;
244
- prevLastUserMessageId = next;
245
- }
246
- });
247
- const lastUserMessageState = computed<LastUserMessageState>(() => ({
248
- id: lastUserMessageId.value,
249
- sendNonce: sendNonce.value,
250
- }));
230
+ // Messages the chat starts with (a restored thread) do not count as a send.
231
+ const lastUserMessageTracker = ɵcreateLastUserMessageTracker(messages.value);
232
+ const lastUserMessageState = computed<LastUserMessageState>(() =>
233
+ lastUserMessageTracker.update(messages.value),
234
+ );
251
235
  provide(LastUserMessageKey, lastUserMessageState);
252
236
 
253
237
  watch(
@@ -362,35 +346,23 @@ watch(
362
346
  return;
363
347
  }
364
348
 
365
- const previousCycle = activeConnectCycle.value;
366
- const inspectorTransition =
367
- previousCycle !== null &&
368
- previousCycle.threadId !== threadId &&
369
- previousCycle.inspectorRequestId !== requestId &&
370
- (previousCycle.inspectorRequestId !== null || requestId !== null);
371
- if (inspectorTransition) {
372
- try {
373
- core.stopAgent({ agent: currentAgent });
374
- } catch {
375
- // No live run to stop.
376
- }
377
- }
378
-
379
- // Pin the thread this chat renders onto its agent, before anything issues a
380
- // request. `CopilotKitCore.connectAgent` reads `agent.threadId` synchronously
381
- // to decide whether this is a fresh restore, so a later assignment would let
382
- // /connect address the previous thread. Assigning inside this callback — as
383
- // React does — makes the ordering unconditional instead of depending on
384
- // watcher scheduling. Non-explicit threads skip /connect below, but the first
385
- // runAgent still has to ship the thread the UI is rendering.
386
- baselineThreadIds.set(currentAgent, currentAgent.threadId);
387
- currentAgent.threadId = threadId;
349
+ // Pins the thread on the agent before anything issues a request:
350
+ // `CopilotKitCore.connectAgent` reads `agent.threadId` synchronously. A
351
+ // switch to a fresh, non-explicit thread (a "+ New" reset) empties the
352
+ // agent so the welcome screen shows; moving in or out of an inspector
353
+ // override stops the run.
354
+ const selection = threads.select({
355
+ agent: currentAgent,
356
+ threadId,
357
+ explicit: isExplicit,
358
+ inspectorRequestId: requestId,
359
+ });
388
360
 
389
361
  // When the caller hasn't picked a specific thread, resolvedThreadId is
390
362
  // a UUID minted locally. The backend has never seen it, so /connect
391
363
  // would always 404 — skip the call. A real thread is only created
392
364
  // once the user runs the agent for the first time.
393
- if (!isExplicit) {
365
+ if (!selection.shouldConnect) {
394
366
  return;
395
367
  }
396
368
 
@@ -417,9 +389,7 @@ watch(
417
389
  const hasSameDeps =
418
390
  existingCycle &&
419
391
  existingCycle.core === (core as object) &&
420
- existingCycle.agent === currentAgent &&
421
- existingCycle.threadId === threadId &&
422
- existingCycle.inspectorRequestId === requestId;
392
+ existingCycle.selection === selection;
423
393
 
424
394
  let cycle: ActiveConnectCycle;
425
395
  if (hasSameDeps && existingCycle) {
@@ -428,58 +398,60 @@ watch(
428
398
  const connectAbortController = new AbortController();
429
399
  cycle = {
430
400
  core: core as object,
431
- agent: currentAgent,
432
- threadId,
433
- inspectorRequestId: requestId,
401
+ selection,
434
402
  abortController: connectAbortController,
435
403
  detached: false,
436
404
  };
437
405
  activeConnectCycle.value = cycle;
438
- lastConnectCycle = cycle;
439
-
440
- void pendingTeardown
441
- .then(() => {
442
- if (cycle.detached) return;
443
- if (ɵisHttpAgent(currentAgent))
444
- currentAgent.abortController = connectAbortController;
445
- return core.connectAgent({ agent: currentAgent });
446
- })
447
- .catch((error: unknown) => {
448
- if (cycle.detached) {
449
- cycle.clearDiscardedBaseline?.();
450
- return;
451
- }
452
- if (error instanceof AGUIConnectNotImplementedError) {
453
- return;
454
- }
455
- console.error("CopilotChat: connectAgent failed", error);
456
- if (requestId) {
457
- failInspectorOverride(requestId);
458
- }
459
- })
460
- .finally(() => {
461
- // Whether the connect succeeded or failed, we're no longer in
462
- // the transitional "connecting" state for this thread — release
463
- // the welcome / suggestion gating so the view can settle.
464
- //
465
- // Defer one animation frame so any trailing reactive commits
466
- // from the bootstrap replay (final assistant message content)
467
- // paint before isConnecting flips off. Without this, suggestions
468
- // can briefly render against an incompletely-laid-out message
469
- // tree and visibly snap once the last text chunk lands.
470
- if (cycle.detached) {
471
- cycle.clearDiscardedBaseline?.();
472
- return;
473
- }
474
- const raf =
475
- typeof requestAnimationFrame === "function"
476
- ? requestAnimationFrame
477
- : (cb: () => void) => setTimeout(cb, 16);
478
- raf(() => {
406
+
407
+ // Tracked, so a send waits for the thread to load instead of racing it.
408
+ void threads.trackConnection(selection, () =>
409
+ threads
410
+ .whenTornDown()
411
+ .then(() => {
479
412
  if (cycle.detached) return;
480
- lastConnectedThreadId.value = cycle.threadId;
481
- });
482
- });
413
+ if (ɵisHttpAgent(currentAgent))
414
+ currentAgent.abortController = connectAbortController;
415
+ return core.connectAgent({ agent: currentAgent });
416
+ })
417
+ .catch((error: unknown) => {
418
+ if (cycle.detached) {
419
+ selection.clearDiscardedBaseline();
420
+ return;
421
+ }
422
+ if (error instanceof AGUIConnectNotImplementedError) {
423
+ return;
424
+ }
425
+ if (requestId) {
426
+ failInspectorOverride(requestId);
427
+ }
428
+ // The coordinator logs the failure and blocks sends on it.
429
+ throw error;
430
+ })
431
+ .finally(() => {
432
+ // Whether the connect succeeded or failed, we're no longer in
433
+ // the transitional "connecting" state for this thread — release
434
+ // the welcome / suggestion gating so the view can settle.
435
+ //
436
+ // Defer one animation frame so any trailing reactive commits
437
+ // from the bootstrap replay (final assistant message content)
438
+ // paint before isConnecting flips off. Without this, suggestions
439
+ // can briefly render against an incompletely-laid-out message
440
+ // tree and visibly snap once the last text chunk lands.
441
+ if (cycle.detached) {
442
+ selection.clearDiscardedBaseline();
443
+ return;
444
+ }
445
+ const raf =
446
+ typeof requestAnimationFrame === "function"
447
+ ? requestAnimationFrame
448
+ : (cb: () => void) => setTimeout(cb, 16);
449
+ raf(() => {
450
+ if (cycle.detached) return;
451
+ lastConnectedThreadId.value = selection.threadId;
452
+ });
453
+ }),
454
+ );
483
455
  }
484
456
 
485
457
  onCleanup(() => {
@@ -488,227 +460,94 @@ watch(
488
460
  return;
489
461
  }
490
462
 
463
+ const { selection: cycleSelection } = activeCycle;
491
464
  const shouldDetach =
492
465
  isUnmounting.value ||
493
466
  copilotkit.value !== activeCycle.core ||
494
- agent.value !== activeCycle.agent ||
495
- resolvedThreadId.value !== activeCycle.threadId;
467
+ agent.value !== cycleSelection.agent ||
468
+ resolvedThreadId.value !== cycleSelection.threadId;
496
469
  if (!shouldDetach) {
497
470
  return;
498
471
  }
499
472
 
473
+ cycleSelection.release();
500
474
  activeCycle.detached = true;
501
475
  activeCycle.abortController.abort();
502
- const detach = activeCycle.agent
503
- .detachActiveRun()
504
- .catch((error: unknown) => {
505
- console.error("CopilotChat: detachActiveRun failed", error);
506
- });
507
- detachPromises.set(activeCycle.agent, detach);
508
- pendingTeardown = Promise.all([pendingTeardown, detach]).then(() => {});
509
- void detach.then(() => {
510
- if (detachPromises.get(activeCycle.agent) === detach)
511
- detachPromises.delete(activeCycle.agent);
512
- });
476
+ void threads.detach(cycleSelection.agent);
513
477
  activeConnectCycle.value = null;
514
478
  });
515
479
  },
516
480
  { immediate: true },
517
481
  );
518
482
 
519
- // Clear stale messages when the active thread switches to a fresh,
520
- // non-explicit thread (e.g. a "+ New" reset). Explicit thread switches
521
- // replay their history via the /connect cycle above, and the very first
522
- // resolution (mount) or an agent-store swap that keeps the same thread id
523
- // must never clear — only a real fresh-thread transition does.
524
- let lastFreshSelection:
525
- | { threadId: string; agent: AbstractAgent | null }
526
- | undefined;
527
- watch(
528
- [resolvedThreadId, hasExplicitThreadId, () => agent.value],
529
- ([threadId, isExplicit, currentAgent], _old, onCleanup) => {
530
- const previous = lastFreshSelection;
531
- const selection = { threadId, agent: currentAgent };
532
- lastFreshSelection = selection;
533
- if (!currentAgent) return;
534
- if (isExplicit) return;
535
- if (previous === undefined) return;
536
- if (threadId === previous.threadId) return;
537
- let active = true;
538
- let resetPending = true;
539
- onCleanup(() => {
540
- active = false;
541
- });
542
- const discardedThreadId =
543
- previous.agent === currentAgent
544
- ? previous.threadId
545
- : baselineThreadIds.get(currentAgent);
546
- const clearCursor = () => {
547
- if (!discardedThreadId) return;
548
- if (
549
- "clearReplayCursor" in currentAgent &&
550
- typeof currentAgent.clearReplayCursor === "function"
551
- )
552
- currentAgent.clearReplayCursor(discardedThreadId);
553
- if (
554
- "clearReconnectCursor" in currentAgent &&
555
- typeof currentAgent.clearReconnectCursor === "function"
556
- )
557
- currentAgent.clearReconnectCursor(discardedThreadId);
558
- };
559
- const clearDiscardedBaseline = () => {
560
- if (
561
- !active ||
562
- !resetPending ||
563
- isUnmounting.value ||
564
- lastFreshSelection !== selection ||
565
- agent.value !== currentAgent
566
- )
567
- return;
568
- currentAgent.setMessages([]);
569
- currentAgent.setState({});
570
- currentAgent.pendingInterrupts = [];
571
- clearCursor();
572
- };
573
- if (
574
- lastConnectCycle?.agent === currentAgent &&
575
- lastConnectCycle.threadId === discardedThreadId
576
- )
577
- lastConnectCycle.clearDiscardedBaseline = clearDiscardedBaseline;
578
- const detach =
579
- detachPromises.get(currentAgent) ?? currentAgent.detachActiveRun();
580
- detachPromises.set(currentAgent, detach);
581
- const finishReset = () => {
582
- if (!resetPending) return;
583
- // The cursor belongs to the discarded view, even after a fast reopen.
584
- clearCursor();
585
- clearDiscardedBaseline();
586
- resetPending = false;
587
- };
588
- clearDiscardedBaseline();
589
- pendingTeardown = Promise.all([pendingTeardown, detach])
590
- .then(finishReset)
591
- .catch((error: unknown) => {
592
- console.error("CopilotChat: detachActiveRun failed", error);
593
- })
594
- .finally(() => {
595
- if (detachPromises.get(currentAgent) === detach)
596
- detachPromises.delete(currentAgent);
597
- });
483
+ // The send side — queueing behind the run in flight and the thread's
484
+ // connection, the upload guard, stop, and transcription — lives in core.
485
+ const submitter = ɵcreateChatSubmitter({
486
+ core: {
487
+ get runtimeUrl() {
488
+ return copilotkit.value.runtimeUrl;
489
+ },
490
+ get runtimeTransport() {
491
+ return copilotkit.value.runtimeTransport;
492
+ },
493
+ get credentials() {
494
+ return copilotkit.value.credentials;
495
+ },
496
+ resolveHeaders: () => copilotkit.value.resolveHeaders(),
497
+ runAgent: (params) => copilotkit.value.runAgent(params),
498
+ stopAgent: (params) => copilotkit.value.stopAgent(params),
598
499
  },
599
- { immediate: true },
600
- );
500
+ getAgent: () => agent.value ?? undefined,
501
+ input: {
502
+ get: () => inputValue.value,
503
+ set: (value) => {
504
+ inputValue.value = value;
505
+ },
506
+ },
507
+ attachments: {
508
+ isUploading: () =>
509
+ attachments.value.some((attachment) => attachment.status === "uploading"),
510
+ consumeReady: consumeAttachments,
511
+ },
512
+ threads,
513
+ });
514
+ const submitterState = shallowRef(submitter.getSnapshot());
515
+ const unsubscribeSubmitter = submitter.subscribe(() => {
516
+ submitterState.value = submitter.getSnapshot();
517
+ });
518
+ const isTranscribing = computed(() => submitterState.value.isTranscribing);
519
+ const transcriptionError = computed(() => {
520
+ const { notice } = submitterState.value;
521
+ return notice ? ɵresolveChatNotice(notice, chatLabels.value) : null;
522
+ });
601
523
 
602
524
  onBeforeUnmount(() => {
603
525
  isUnmounting.value = true;
526
+ unsubscribeSubmitter();
527
+ submitter.dispose();
528
+ threads.dispose();
604
529
  });
605
530
 
606
531
  onMounted(() => {
607
532
  isMounted.value = true;
608
533
  });
609
534
 
610
- watch(transcriptionError, (next, _old, onCleanup) => {
611
- if (!next) {
612
- return;
613
- }
614
- const timer = setTimeout(() => {
615
- transcriptionError.value = null;
616
- }, 5000);
617
- onCleanup(() => clearTimeout(timer));
618
- });
619
-
620
- async function runCurrentAgent() {
621
- const currentAgent = agent.value;
622
- if (!currentAgent) {
623
- return;
624
- }
625
-
626
- try {
627
- const activeCycle = activeConnectCycle.value;
628
- if (
629
- activeCycle &&
630
- activeCycle.agent === currentAgent &&
631
- activeCycle.threadId === resolvedThreadId.value
632
- ) {
633
- activeCycle.detached = true;
634
- activeCycle.abortController.abort();
635
- activeConnectCycle.value = null;
636
- await activeCycle.agent.detachActiveRun?.();
637
- }
638
- await copilotkit.value.runAgent({ agent: currentAgent });
639
- } catch (error) {
640
- console.error("CopilotChat: runAgent failed", error);
641
- }
642
- }
643
-
644
535
  async function handleSubmitMessage(value: string) {
645
- const hasUploading = attachments.value.some(
536
+ // A send blocked by an upload shows its notice but is not reported.
537
+ const isBlockedByUpload = attachments.value.some(
646
538
  (attachment) => attachment.status === "uploading",
647
539
  );
648
- if (hasUploading) {
649
- console.error("[CopilotKit] Cannot send while attachments are uploading");
650
- return;
651
- }
652
-
653
- emit("submit-message", value);
654
-
655
- if (!agent.value) {
656
- console.error("[CopilotKit] Cannot send message: no agent available");
657
- return;
658
- }
659
-
660
- const readyAttachments = consumeAttachments();
661
- if (readyAttachments.length > 0) {
662
- const contentParts: InputContent[] = [];
663
- if (value.trim()) {
664
- contentParts.push({ type: "text", text: value });
665
- }
666
- for (const attachment of readyAttachments) {
667
- contentParts.push(createAttachmentContent(attachment));
668
- }
669
- agent.value.addMessage({
670
- id: randomUUID(),
671
- role: "user",
672
- content: contentParts,
673
- });
674
- } else {
675
- agent.value.addMessage({
676
- id: randomUUID(),
677
- role: "user",
678
- content: value,
679
- });
680
- }
681
-
682
- inputValue.value = "";
683
- await runCurrentAgent();
540
+ if (!isBlockedByUpload) emit("submit-message", value);
541
+ await submitter.submit(value);
684
542
  }
685
543
 
686
544
  async function handleSelectSuggestion(suggestion: Suggestion, index: number) {
687
545
  emit("select-suggestion", suggestion, index);
688
- agent.value?.addMessage({
689
- id: randomUUID(),
690
- role: "user",
691
- content: suggestion.message,
692
- });
693
- await runCurrentAgent();
546
+ await submitter.selectSuggestion(suggestion);
694
547
  }
695
548
 
696
549
  function stopCurrentRun() {
697
- const currentAgent = agent.value;
698
- if (!currentAgent) {
699
- return;
700
- }
701
-
702
- try {
703
- copilotkit.value.stopAgent({ agent: currentAgent });
704
- } catch (error) {
705
- console.error("CopilotChat: stopAgent failed", error);
706
- try {
707
- currentAgent.abortRun();
708
- } catch (abortError) {
709
- console.error("CopilotChat: abortRun fallback failed", abortError);
710
- }
711
- }
550
+ submitter.stop();
712
551
  }
713
552
 
714
553
  function handleStop() {
@@ -737,7 +576,7 @@ function handleStartTranscribe() {
737
576
  if (!showTranscription.value) {
738
577
  return;
739
578
  }
740
- transcriptionError.value = null;
579
+ submitter.showNotice(null);
741
580
  transcribeMode.value = "transcribe";
742
581
  emit("start-transcribe");
743
582
  }
@@ -746,7 +585,7 @@ function handleCancelTranscribe() {
746
585
  if (!showTranscription.value) {
747
586
  return;
748
587
  }
749
- transcriptionError.value = null;
588
+ submitter.showNotice(null);
750
589
  transcribeMode.value = "input";
751
590
  emit("cancel-transcribe");
752
591
  }
@@ -768,55 +607,7 @@ async function handleFinishTranscribeWithAudio(audioBlob: Blob) {
768
607
  return;
769
608
  }
770
609
 
771
- isTranscribing.value = true;
772
- try {
773
- transcriptionError.value = null;
774
- const result = await transcribeAudio(copilotkit.value, audioBlob);
775
- const trimmedPrevious = inputValue.value.trim();
776
- inputValue.value = trimmedPrevious
777
- ? `${trimmedPrevious} ${result.text}`
778
- : result.text;
779
- } catch (error) {
780
- console.error("CopilotChat: Transcription failed", error);
781
- if (error instanceof TranscriptionError) {
782
- const { code, retryable, message } = error.info;
783
- switch (code) {
784
- case TranscriptionErrorCode.RATE_LIMITED:
785
- transcriptionError.value = "Too many requests. Please wait a moment.";
786
- break;
787
- case TranscriptionErrorCode.AUTH_FAILED:
788
- transcriptionError.value =
789
- "Authentication error. Please check your configuration.";
790
- break;
791
- case TranscriptionErrorCode.AUDIO_TOO_LONG:
792
- transcriptionError.value =
793
- "Recording is too long. Please try a shorter recording.";
794
- break;
795
- case TranscriptionErrorCode.AUDIO_TOO_SHORT:
796
- transcriptionError.value =
797
- "Recording is too short. Please try again.";
798
- break;
799
- case TranscriptionErrorCode.INVALID_AUDIO_FORMAT:
800
- transcriptionError.value = "Audio format not supported.";
801
- break;
802
- case TranscriptionErrorCode.SERVICE_NOT_CONFIGURED:
803
- transcriptionError.value = "Transcription service is not available.";
804
- break;
805
- case TranscriptionErrorCode.NETWORK_ERROR:
806
- transcriptionError.value =
807
- "Network error. Please check your connection.";
808
- break;
809
- default:
810
- transcriptionError.value = retryable
811
- ? "Transcription failed. Please try again."
812
- : message;
813
- }
814
- } else {
815
- transcriptionError.value = "Transcription failed. Please try again.";
816
- }
817
- } finally {
818
- isTranscribing.value = false;
819
- }
610
+ await submitter.transcribe(audioBlob);
820
611
  }
821
612
 
822
613
  const chatViewSlotProps = computed<CopilotChatViewOverrideSlotProps>(() => ({