@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
@@ -530,10 +530,8 @@ describe("useDefaultRenderTool", () => {
530
530
  expect(forwarded.result).toBe("ok");
531
531
  });
532
532
 
533
- // Fix #5: circular-ref parameters must not crash the vue render; log.
534
- it("default renderer survives circular-ref parameters and logs", async () => {
535
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
536
-
533
+ // Fix #5: circular-ref parameters must not crash the vue render.
534
+ it("default renderer survives circular-ref parameters", async () => {
537
535
  const Harness = defineComponent({
538
536
  setup() {
539
537
  useDefaultRenderTool();
@@ -567,14 +565,16 @@ describe("useDefaultRenderTool", () => {
567
565
  }),
568
566
  ).not.toThrow();
569
567
 
568
+ const wrapper = screen.getByTestId("copilot-tool-render");
569
+ expect(wrapper.getAttribute("data-args")).toBe(
570
+ '{"a":1,"self":"[Circular]"}',
571
+ );
572
+
570
573
  const headerButton = screen
571
574
  .getByTestId("copilot-tool-render-name")
572
575
  .closest("button");
573
- if (headerButton) {
574
- await expect(fireEvent.click(headerButton)).resolves.not.toThrow();
575
- }
576
-
577
- expect(warnSpy).toHaveBeenCalled();
578
- warnSpy.mockRestore();
576
+ expect(headerButton).not.toBeNull();
577
+ await fireEvent.click(headerButton!);
578
+ expect(wrapper.textContent).toContain('"self": "[Circular]"');
579
579
  });
580
580
  });
@@ -1,4 +1,12 @@
1
- import { computed, defineComponent, onMounted, ref, watch } from "vue";
1
+ import {
2
+ computed,
3
+ defineComponent,
4
+ h,
5
+ nextTick,
6
+ onMounted,
7
+ ref,
8
+ watch,
9
+ } from "vue";
2
10
  import type { PropType } from "vue";
3
11
  import { screen, fireEvent, waitFor, cleanup } from "@testing-library/vue";
4
12
  import { afterEach, describe, expect, it } from "vitest";
@@ -27,6 +35,11 @@ import {
27
35
  textChunkEvent,
28
36
  testId,
29
37
  } from "../../__tests__/utils/test-helpers";
38
+ import { mountWithProvider } from "../../__tests__/utils/mount";
39
+ import {
40
+ StateCapturingAgent,
41
+ toolCallMessage,
42
+ } from "../../__tests__/utils/agents";
30
43
 
31
44
  afterEach(() => {
32
45
  cleanup();
@@ -874,6 +887,10 @@ describe("useFrontendTool E2E - Dynamic Registration", () => {
874
887
  expect(firstVersion.textContent).toContain("before override");
875
888
  });
876
889
 
890
+ await agent.emit(runFinishedEvent());
891
+ // The tool call starts a follow-up run. A send waits for the run in
892
+ // flight (#5195), so finish the follow-up before the next message.
893
+ await agent.emit(runStartedEvent());
877
894
  await agent.emit(runFinishedEvent());
878
895
 
879
896
  const overrideButton = screen.getByTestId("activate-override");
@@ -912,6 +929,54 @@ describe("useFrontendTool E2E - Dynamic Registration", () => {
912
929
  });
913
930
  });
914
931
 
932
+ describe("Overriding a provider tool", () => {
933
+ it("brings the provider tool back after the overriding component unmounts", async () => {
934
+ const calls: string[] = [];
935
+ const lookupTool = (owner: string): VueFrontendTool => ({
936
+ name: "lookup",
937
+ parameters: z.object({}),
938
+ followUp: false,
939
+ handler: async () => {
940
+ calls.push(owner);
941
+ return owner;
942
+ },
943
+ });
944
+
945
+ const OverridingTool = defineComponent({
946
+ setup() {
947
+ useFrontendTool(lookupTool("component"));
948
+ return () => null;
949
+ },
950
+ });
951
+
952
+ const showOverride = ref(true);
953
+ const agent = new StateCapturingAgent(
954
+ [
955
+ { newMessages: [toolCallMessage("lookup")] },
956
+ { newMessages: [toolCallMessage("lookup")] },
957
+ ],
958
+ "test-agent",
959
+ );
960
+ const { getCore, wrapper } = mountWithProvider(
961
+ () => (showOverride.value ? h(OverridingTool) : h("div")),
962
+ {
963
+ frontendTools: [lookupTool("provider")],
964
+ agents__unsafe_dev_only: { "test-agent": agent },
965
+ },
966
+ );
967
+
968
+ await nextTick();
969
+ await getCore().runAgent({ agent });
970
+
971
+ showOverride.value = false;
972
+ await nextTick();
973
+ await getCore().runAgent({ agent });
974
+
975
+ expect(calls).toEqual(["component", "provider"]);
976
+ wrapper.unmount();
977
+ });
978
+ });
979
+
915
980
  describe("Integration with Chat UI", () => {
916
981
  it("should render tool output correctly in chat interface", async () => {
917
982
  const agent = new MockStepwiseAgent();
@@ -720,7 +720,12 @@ describe("useHumanInTheLoop E2E - HITL Tool Rendering", () => {
720
720
  expect(screen.queryByTestId("hitl-enabled")).toBeNull();
721
721
  });
722
722
 
723
- await submitMessage("Test after disable");
723
+ // The first run still waits for the unanswered HITL prompt, and a send
724
+ // waits for the run in flight (#5195), so this message stays queued.
725
+ // What this test pins is that the unregistered tool no longer renders.
726
+ const input = await screen.findByRole("textbox");
727
+ await fireEvent.update(input, "Test after disable");
728
+ await fireEvent.keyDown(input, { key: "Enter", code: "Enter" });
724
729
 
725
730
  const messageId2 = testId("msg2");
726
731
  const toolCallId2 = testId("tc2");
@@ -4,7 +4,22 @@ import { z } from "zod";
4
4
  import type { AbstractAgent } from "@ag-ui/client";
5
5
  import { useHumanInTheLoop } from "../use-human-in-the-loop";
6
6
  import { mountWithProvider } from "../../__tests__/utils/mount";
7
- import { StateCapturingAgent } from "../../__tests__/utils/agents";
7
+ import {
8
+ SequencedRunAgent,
9
+ StateCapturingAgent,
10
+ toolCallMessage,
11
+ } from "../../__tests__/utils/agents";
12
+
13
+ /** Handler context for one tool call; core always passes the call. */
14
+ function callContext(id: string, name = "tool") {
15
+ return {
16
+ toolCall: {
17
+ id,
18
+ type: "function" as const,
19
+ function: { name, arguments: "{}" },
20
+ },
21
+ };
22
+ }
8
23
 
9
24
  describe("useHumanInTheLoop", () => {
10
25
  beforeEach(() => {
@@ -53,7 +68,7 @@ describe("useHumanInTheLoop", () => {
53
68
 
54
69
  const pending = registeredTool!.handler!(
55
70
  { question: "Proceed?" },
56
- {} as never,
71
+ callContext("tc-approve"),
57
72
  );
58
73
 
59
74
  const executingVNode = renderer!.render({
@@ -107,8 +122,8 @@ describe("useHumanInTheLoop", () => {
107
122
  const renderA = getCore().renderToolCalls.find((rc) => rc.name === "toolA");
108
123
  const renderB = getCore().renderToolCalls.find((rc) => rc.name === "toolB");
109
124
 
110
- const pA = toolA!.handler!({}, {} as never);
111
- const pB = toolB!.handler!({}, {} as never);
125
+ const pA = toolA!.handler!({}, callContext("tc-a"));
126
+ const pB = toolB!.handler!({}, callContext("tc-b"));
112
127
 
113
128
  const respondA = (
114
129
  renderA!.render({
@@ -140,6 +155,72 @@ describe("useHumanInTheLoop", () => {
140
155
  await expect(pB).resolves.toBe("B");
141
156
  });
142
157
 
158
+ it("gives parallel calls of one tool their own respond", async () => {
159
+ const RenderComp = defineComponent({
160
+ props: ["respond"],
161
+ setup() {
162
+ return () => h("div");
163
+ },
164
+ });
165
+ const Child = defineComponent({
166
+ setup() {
167
+ useHumanInTheLoop({
168
+ name: "parallelTool",
169
+ parameters: z.object({}),
170
+ render: RenderComp,
171
+ });
172
+ return () => null;
173
+ },
174
+ });
175
+ const { getCore } = mountWithProvider(() => h(Child));
176
+ const handler = getCore().getTool({ toolName: "parallelTool" })!.handler!;
177
+ const renderer = getCore().renderToolCalls.find(
178
+ (rc) => rc.name === "parallelTool",
179
+ )!;
180
+ const respondFor = (toolCallId: string) =>
181
+ (
182
+ renderer.render({
183
+ name: "parallelTool",
184
+ toolCallId,
185
+ args: {},
186
+ status: "executing",
187
+ result: undefined,
188
+ }) as { props?: { respond?: (result: unknown) => Promise<void> } }
189
+ ).props!.respond!;
190
+
191
+ const first = handler({}, callContext("call-1"));
192
+ const second = handler({}, callContext("call-2"));
193
+ await respondFor("call-2")("second");
194
+ await respondFor("call-1")("first");
195
+
196
+ await expect(first).resolves.toBe("first");
197
+ await expect(second).resolves.toBe("second");
198
+ });
199
+
200
+ it("passes the called tool's name to a catch-all render", () => {
201
+ const RenderComp = defineComponent({
202
+ setup() {
203
+ return () => h("div");
204
+ },
205
+ });
206
+ const Child = defineComponent({
207
+ setup() {
208
+ useHumanInTheLoop({ name: "*", render: RenderComp });
209
+ return () => null;
210
+ },
211
+ });
212
+ const { getCore } = mountWithProvider(() => h(Child));
213
+ const renderer = getCore().renderToolCalls.find((rc) => rc.name === "*")!;
214
+ const vnode = renderer.render({
215
+ name: "deleteFile",
216
+ toolCallId: "tc-any",
217
+ args: {},
218
+ status: "inProgress",
219
+ result: undefined,
220
+ }) as { props?: Record<string, unknown> };
221
+ expect(vnode.props?.name).toBe("deleteFile");
222
+ });
223
+
143
224
  it("only exposes respond during executing status", () => {
144
225
  const RenderComp = defineComponent({
145
226
  props: ["respond"],
@@ -323,9 +404,9 @@ describe("useHumanInTheLoop", () => {
323
404
  const controller = new AbortController();
324
405
  controller.abort();
325
406
 
326
- await expect(handler!({}, { signal: controller.signal })).rejects.toEqual(
327
- new Error("Human-in-the-loop interaction aborted"),
328
- );
407
+ await expect(
408
+ handler!({}, { ...callContext("tc-x"), signal: controller.signal }),
409
+ ).rejects.toEqual(new Error("Human-in-the-loop interaction aborted"));
329
410
  });
330
411
 
331
412
  it("rejects once on abort, clears pending refs, and installs a one-shot listener", async () => {
@@ -344,7 +425,7 @@ describe("useHumanInTheLoop", () => {
344
425
  }),
345
426
  } as unknown as AbortSignal;
346
427
 
347
- const pending = handler!({}, { signal });
428
+ const pending = handler!({}, { ...callContext("tc-aborted"), signal });
348
429
  expect(listeners.size).toBe(1);
349
430
  const onAbort = [...listeners][0];
350
431
  onAbort();
@@ -379,7 +460,13 @@ describe("useHumanInTheLoop", () => {
379
460
  }),
380
461
  } as unknown as AbortSignal;
381
462
 
382
- const pending = handler!({}, { signal }).then((result) => {
463
+ const pending = handler!(
464
+ {},
465
+ {
466
+ ...callContext("tc-respond"),
467
+ signal,
468
+ },
469
+ ).then((result) => {
383
470
  events.push(`resolved:${String(result)}`);
384
471
  return result;
385
472
  });
@@ -511,10 +598,98 @@ describe("useHumanInTheLoop", () => {
511
598
  expect(vnode.props?.agentId).toBeUndefined();
512
599
  });
513
600
 
601
+ it("lets a message queued behind an unanswered prompt send after the prompt unmounts", async () => {
602
+ const prompt = toolCallMessage("unmountApproval");
603
+ const toolCallId = (prompt as { toolCalls: { id: string }[] })
604
+ .toolCalls[0]!.id;
605
+ const agent = new SequencedRunAgent(
606
+ [
607
+ () => ({ result: undefined, newMessages: [prompt] }),
608
+ () => ({
609
+ result: undefined,
610
+ newMessages: [{ id: "reply", role: "assistant", content: "ok" }],
611
+ }),
612
+ ],
613
+ "default",
614
+ );
615
+ const RenderComp = defineComponent({
616
+ setup() {
617
+ return () => h("div");
618
+ },
619
+ });
620
+ const shown = ref(true);
621
+ const Child = defineComponent({
622
+ setup() {
623
+ useHumanInTheLoop({
624
+ name: "unmountApproval",
625
+ parameters: z.object({}),
626
+ render: RenderComp,
627
+ });
628
+ return () => null;
629
+ },
630
+ });
631
+ const { getCore } = mountWithProvider(
632
+ () => (shown.value ? h(Child) : null),
633
+ {
634
+ agents__unsafe_dev_only: {
635
+ default: agent as unknown as AbstractAgent,
636
+ },
637
+ },
638
+ );
639
+ const core = getCore();
640
+ const sendMessage = async (content: string) => {
641
+ agent.addMessage({ id: content, role: "user", content });
642
+ await core.runAgent({ agent: agent as unknown as AbstractAgent });
643
+ };
644
+
645
+ const first = sendMessage("approve this");
646
+ const queued = first.then(() => sendMessage("next question"));
647
+ await vi.waitFor(() =>
648
+ expect(core.ɵhumanInTheLoop.isPending(toolCallId)).toBe(true),
649
+ );
650
+
651
+ shown.value = false;
652
+ await nextTick();
653
+
654
+ await expect(queued).resolves.toBeUndefined();
655
+ expect(agent.messages).toEqual(
656
+ expect.arrayContaining([
657
+ expect.objectContaining({
658
+ role: "tool",
659
+ toolCallId,
660
+ error: "Human-in-the-loop interaction aborted",
661
+ }),
662
+ expect.objectContaining({ id: "reply", content: "ok" }),
663
+ ]),
664
+ );
665
+ });
666
+
514
667
  it("does not settle a pending HITL promise when its renderer unmounts", async () => {
515
- const mounted = mountHitlTool();
516
- const pending = mounted.handler({}, {});
517
- mounted.wrapper.unmount();
668
+ const RenderComp = defineComponent({
669
+ setup() {
670
+ return () => h("div");
671
+ },
672
+ });
673
+ const shown = ref(true);
674
+ const Child = defineComponent({
675
+ setup() {
676
+ useHumanInTheLoop({
677
+ name: "unmountTool",
678
+ parameters: z.object({}),
679
+ render: RenderComp,
680
+ });
681
+ return () => null;
682
+ },
683
+ });
684
+ const { getCore } = mountWithProvider(() =>
685
+ shown.value ? h(Child) : null,
686
+ );
687
+ const pending = getCore().getTool({ toolName: "unmountTool" })!.handler!(
688
+ {},
689
+ callContext("tc-unmount"),
690
+ );
691
+ shown.value = false;
692
+ await nextTick();
518
693
 
519
694
  const outcome = await Promise.race([
520
695
  pending.then(
@@ -347,6 +347,32 @@ describe("useInterrupt", () => {
347
347
  expect(wrapper.get("[data-testid=interrupt-state]").text()).toBe("idle");
348
348
  });
349
349
 
350
+ it("treats a throwing enabled predicate as disabled instead of crashing", async () => {
351
+ vi.spyOn(console, "error").mockImplementation(() => {});
352
+ const wrapper = mountHarness({
353
+ enabled: () => {
354
+ throw new Error("predicate");
355
+ },
356
+ });
357
+ emitInterrupt("hidden");
358
+ await nextTick();
359
+ expect(wrapper.get("[data-testid=interrupt-state]").text()).toBe("idle");
360
+ });
361
+
362
+ it("shows the interrupt with a null result when the handler throws synchronously", async () => {
363
+ vi.spyOn(console, "error").mockImplementation(() => {});
364
+ const wrapper = mountHarness({
365
+ handler: () => {
366
+ throw new Error("handler");
367
+ },
368
+ });
369
+ emitInterrupt("visible");
370
+ await nextTick();
371
+ expect(wrapper.get("[data-testid=interrupt-state]").text()).toBe(
372
+ "no-result:visible",
373
+ );
374
+ });
375
+
350
376
  it("keeps the latest interrupt when multiple interrupts arrive within one run", async () => {
351
377
  const wrapper = mountHarness({ renderInChat: false });
352
378
 
@@ -412,6 +438,77 @@ describe("useInterrupt", () => {
412
438
  handlers.onRunFinalized?.();
413
439
  }
414
440
 
441
+ it("picks up the agent's pending interrupts when it mounts", async () => {
442
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
443
+ (mockAgent as any).pendingInterrupts = [INT];
444
+ const wrapper = mountStandardHarness();
445
+ await nextTick();
446
+ expect(wrapper.find("[data-testid=active]").exists()).toBe(true);
447
+ });
448
+
449
+ it("appends a tool result for a frontend tool-call interrupt before resuming", async () => {
450
+ const addMessage = vi.fn();
451
+ Object.assign(mockAgent, { messages: [], addMessage });
452
+ const TOOL_INT: Interrupt = {
453
+ id: "tool-int",
454
+ reason: "tool_call",
455
+ toolCallId: "call-1",
456
+ };
457
+ const wrapper = mountStandardHarness();
458
+ fireStandardInterrupt([TOOL_INT]);
459
+ await nextTick();
460
+
461
+ await wrapper.get("[data-testid=resolve-btn]").trigger("click");
462
+
463
+ expect(addMessage).toHaveBeenCalledWith(
464
+ expect.objectContaining({
465
+ role: "tool",
466
+ toolCallId: "call-1",
467
+ content: JSON.stringify({ ok: true }),
468
+ }),
469
+ );
470
+ expect(runAgentMock).toHaveBeenCalledWith({
471
+ agent: mockAgent,
472
+ resume: [
473
+ {
474
+ interruptId: "tool-int",
475
+ status: "resolved",
476
+ payload: { ok: true },
477
+ },
478
+ ],
479
+ });
480
+ });
481
+
482
+ it("resumes when the only expired interrupt was cancelled", async () => {
483
+ const EXPIRED: Interrupt = {
484
+ id: "old",
485
+ reason: "confirmation",
486
+ expiresAt: "2000-01-01T00:00:00.000Z",
487
+ };
488
+ let api: ReturnType<typeof useInterrupt> | undefined;
489
+ mount(
490
+ defineComponent({
491
+ setup() {
492
+ api = useInterrupt({ renderInChat: false });
493
+ return () => null;
494
+ },
495
+ }),
496
+ );
497
+ fireStandardInterrupt([EXPIRED, INT]);
498
+ await nextTick();
499
+
500
+ await api!.cancel("old");
501
+ await api!.resolve("yes", INT.id);
502
+
503
+ expect(runAgentMock).toHaveBeenCalledWith({
504
+ agent: mockAgent,
505
+ resume: [
506
+ { interruptId: "old", status: "cancelled" },
507
+ { interruptId: INT.id, status: "resolved", payload: "yes" },
508
+ ],
509
+ });
510
+ });
511
+
415
512
  it("resolveInterrupt resumes with a resolved ResumeEntry", async () => {
416
513
  runAgentMock.mockResolvedValue({ result: undefined, newMessages: [] });
417
514
  const wrapper = mountStandardHarness();
@@ -0,0 +1,106 @@
1
+ import {
2
+ afterEach,
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ expectTypeOf,
7
+ it,
8
+ vi,
9
+ } from "vitest";
10
+ import { defineComponent, h, toRaw } from "vue";
11
+ import { z } from "zod";
12
+ import type { ActivityMessage } from "@ag-ui/core";
13
+ import { useRenderActivityMessage } from "../use-render-activity-message";
14
+ import type {
15
+ VueActivityMessageRenderer,
16
+ VueActivityMessageRendererProps,
17
+ } from "../../types";
18
+ import { renderWithCopilotKit } from "../../__tests__/utils/mount";
19
+
20
+ const ProgressRenderer = defineComponent({
21
+ props: { content: { type: Object, required: true } },
22
+ setup: () => () => null,
23
+ });
24
+
25
+ const progressSchema = z.object({
26
+ label: z.string(),
27
+ percent: z.number().default(0),
28
+ });
29
+
30
+ // A zod schema is a Standard Schema, so it fits the `content` field, and the
31
+ // renderer's content type is the schema's output type.
32
+ const progressRenderer = {
33
+ activityType: "progress",
34
+ content: progressSchema,
35
+ render: ProgressRenderer,
36
+ } satisfies VueActivityMessageRenderer<z.output<typeof progressSchema>>;
37
+
38
+ function activityMessage(content: Record<string, unknown>): ActivityMessage {
39
+ return {
40
+ id: "activity-1",
41
+ role: "activity",
42
+ activityType: "progress",
43
+ content,
44
+ };
45
+ }
46
+
47
+ function renderWithProgressRenderer() {
48
+ let helpers: ReturnType<typeof useRenderActivityMessage> | undefined;
49
+ const Probe = defineComponent({
50
+ setup() {
51
+ helpers = useRenderActivityMessage();
52
+ return () => null;
53
+ },
54
+ });
55
+
56
+ renderWithCopilotKit(() => h(Probe), {
57
+ providerProps: { renderActivityMessages: [progressRenderer] },
58
+ });
59
+
60
+ if (!helpers) throw new Error("useRenderActivityMessage did not run");
61
+ return helpers;
62
+ }
63
+
64
+ describe("useRenderActivityMessage", () => {
65
+ let consoleWarnSpy: ReturnType<typeof vi.spyOn>;
66
+
67
+ beforeEach(() => {
68
+ consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
69
+ });
70
+
71
+ afterEach(() => {
72
+ consoleWarnSpy.mockRestore();
73
+ });
74
+
75
+ it("types a zod content schema's output as the render props content", () => {
76
+ type Props = VueActivityMessageRendererProps<
77
+ z.output<typeof progressSchema>
78
+ >;
79
+ expectTypeOf<Props["content"]>().toEqualTypeOf<{
80
+ label: string;
81
+ percent: number;
82
+ }>();
83
+ });
84
+
85
+ it("passes the zod schema's parsed output to the renderer", () => {
86
+ const { renderActivityMessage } = renderWithProgressRenderer();
87
+
88
+ const result = renderActivityMessage(activityMessage({ label: "Upload" }));
89
+
90
+ // The provider stores renderers in reactive state, so compare the raw value.
91
+ expect(toRaw(result?.renderer)).toBe(ProgressRenderer);
92
+ expect(result?.props.content).toEqual({ label: "Upload", percent: 0 });
93
+ });
94
+
95
+ it("returns null and warns when the content fails the schema", () => {
96
+ const { renderActivityMessage } = renderWithProgressRenderer();
97
+
98
+ const result = renderActivityMessage(activityMessage({ label: 42 }));
99
+
100
+ expect(result).toBeNull();
101
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
102
+ "[CopilotKit] Failed to parse content for activity message 'progress':",
103
+ expect.any(Array),
104
+ );
105
+ });
106
+ });
@@ -93,7 +93,7 @@ describe("useRenderTool", () => {
93
93
  expect(typeof renderer?.render).toBe("function");
94
94
  });
95
95
 
96
- it("registers wildcard renderer and defaults parameters schema to z.any", () => {
96
+ it("registers wildcard renderer and defaults parameters to a schema that accepts any value", () => {
97
97
  const core = createMockCore();
98
98
  mockUseCopilotKit.mockReturnValue({ copilotkit: { value: core } });
99
99
 
@@ -118,11 +118,8 @@ describe("useRenderTool", () => {
118
118
  const renderer = core.renderToolCalls.find((item) => item.name === "*");
119
119
  expect(renderer).toBeDefined();
120
120
  expect(typeof renderer?.render).toBe("function");
121
- const wildcardArgs = renderer?.args as
122
- | { safeParse: (v: unknown) => { success: boolean } }
123
- | undefined;
124
- expect(wildcardArgs).toBeDefined();
125
- expect(wildcardArgs!.safeParse({ arbitrary: true }).success).toBe(true);
121
+ const result = renderer?.args["~standard"].validate({ arbitrary: true });
122
+ expect(result).toEqual({ value: { arbitrary: true } });
126
123
  });
127
124
 
128
125
  it("accepts a Vue component renderer", () => {