@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,101 +1,44 @@
1
- import { computed, defineComponent, h, onBeforeUnmount, ref, watch } from "vue";
1
+ import {
2
+ defineComponent,
3
+ h,
4
+ onBeforeUnmount,
5
+ onMounted,
6
+ ref,
7
+ shallowRef,
8
+ watch,
9
+ } from "vue";
2
10
  import type { PropType } from "vue";
3
- import { z } from "zod";
4
- import { ToolCallStatus } from "@copilotkit/core";
5
11
  import {
6
- processPartialHtml,
7
- extractCompleteStyles,
8
- } from "../lib/processPartialHtml";
12
+ OPEN_GENERATIVE_UI_ACTIVITY_TYPE,
13
+ ToolCallStatus,
14
+ ɵGENERATE_SANDBOXED_UI_ARGS_SCHEMA,
15
+ ɵOPEN_GENERATIVE_UI_CONTENT_SCHEMA,
16
+ ɵOpenGenerativeUIController,
17
+ ɵPlaceholderCycler,
18
+ } from "@copilotkit/core";
19
+ import type {
20
+ GenerateSandboxedUiArgs,
21
+ OpenGenerativeUIContent,
22
+ } from "@copilotkit/core";
9
23
  import { useSandboxFunctions } from "../providers/SandboxFunctionsContext";
10
24
 
11
- export const OpenGenerativeUIActivityType = "open-generative-ui";
12
-
13
- export const OpenGenerativeUIContentSchema = z.object({
14
- initialHeight: z.number().optional(),
15
- generating: z.boolean().optional(),
16
- css: z.string().optional(),
17
- cssComplete: z.boolean().optional(),
18
- html: z.array(z.string()).optional(),
19
- htmlComplete: z.boolean().optional(),
20
- jsFunctions: z.string().optional(),
21
- jsFunctionsComplete: z.boolean().optional(),
22
- jsExpressions: z.array(z.string()).optional(),
23
- jsExpressionsComplete: z.boolean().optional(),
24
- });
25
-
26
- export type OpenGenerativeUIContent = z.infer<
27
- typeof OpenGenerativeUIContentSchema
28
- >;
29
-
30
- export const GenerateSandboxedUiArgsSchema = z.object({
31
- initialHeight: z.number().optional(),
32
- placeholderMessages: z.array(z.string()).optional(),
33
- css: z.string().optional(),
34
- html: z.string().optional(),
35
- jsFunctions: z.string().optional(),
36
- jsExpressions: z.array(z.string()).optional(),
37
- });
38
-
39
- export type GenerateSandboxedUiArgs = z.infer<
40
- typeof GenerateSandboxedUiArgsSchema
41
- >;
42
-
43
- function shouldFlushImmediately(
44
- previous: OpenGenerativeUIContent | null,
45
- next: OpenGenerativeUIContent,
46
- ): boolean {
47
- if (next.cssComplete && (!previous || !previous.cssComplete)) return true;
48
- if (next.htmlComplete) return true;
49
- if (next.generating === false) return true;
50
- if (next.jsFunctions && (!previous || !previous.jsFunctions)) return true;
51
- if (
52
- (next.jsExpressions?.length ?? 0) > (previous?.jsExpressions?.length ?? 0)
53
- )
54
- return true;
55
- if (next.html?.length && (!previous || !previous.html?.length)) return true;
56
- return false;
57
- }
58
-
59
- function ensureHead(html: string): string {
60
- if (/<head[\s>]/i.test(html)) return html;
61
- return `<head></head>${html}`;
62
- }
25
+ export type { GenerateSandboxedUiArgs, OpenGenerativeUIContent };
63
26
 
64
- function injectCssIntoHtml(html: string, css: string): string {
65
- const headCloseIdx = html.indexOf("</head>");
66
- if (headCloseIdx !== -1) {
67
- return (
68
- html.slice(0, headCloseIdx) +
69
- `<style>${css}</style>` +
70
- html.slice(headCloseIdx)
71
- );
72
- }
73
- return `<head><style>${css}</style></head>${html}`;
74
- }
75
-
76
- type SandboxInstance = {
77
- iframe: HTMLIFrameElement;
78
- promise: Promise<unknown>;
79
- run: (code: string | Function) => Promise<unknown>;
80
- destroy: () => void;
81
- };
27
+ export const OpenGenerativeUIActivityType = OPEN_GENERATIVE_UI_ACTIVITY_TYPE;
82
28
 
83
- type WebsandboxModule = {
84
- create: (
85
- localApi: Record<string, unknown>,
86
- options: {
87
- frameContainer: HTMLElement;
88
- frameContent: string;
89
- allowAdditionalAttributes: string;
90
- },
91
- ) => SandboxInstance;
92
- };
29
+ /** Validates Open Generative UI activity content (shared with React and Angular). */
30
+ export const OpenGenerativeUIContentSchema = ɵOPEN_GENERATIVE_UI_CONTENT_SCHEMA;
93
31
 
94
- async function loadWebsandbox(): Promise<WebsandboxModule> {
95
- const mod = (await import("@jetbrains/websandbox")) as any;
96
- return (mod.default?.default ?? mod.default) as WebsandboxModule;
97
- }
32
+ /**
33
+ * Schema for the generateSandboxedUi tool call arguments (shared with React
34
+ * and Angular). It also describes the arguments to the model as JSON Schema.
35
+ */
36
+ export const GenerateSandboxedUiArgsSchema = ɵGENERATE_SANDBOXED_UI_ARGS_SCHEMA;
98
37
 
38
+ /**
39
+ * Renders Open Generative UI content. The core controller throttles the
40
+ * content and runs the websandbox iframes inside the container div.
41
+ */
99
42
  export const OpenGenerativeUIRenderer = defineComponent({
100
43
  name: "OpenGenerativeUIRenderer",
101
44
  props: {
@@ -107,307 +50,32 @@ export const OpenGenerativeUIRenderer = defineComponent({
107
50
  setup(props) {
108
51
  const sandboxFunctions = useSandboxFunctions();
109
52
  const containerRef = ref<HTMLElement | null>(null);
110
- const throttledContent = ref<OpenGenerativeUIContent>(props.content);
111
- const latestContent = ref<OpenGenerativeUIContent>(props.content);
112
- const throttleTimer = ref<number | null>(null);
113
- const sandboxRef = ref<SandboxInstance | null>(null);
114
- const previewSandboxRef = ref<SandboxInstance | null>(null);
115
- const sandboxReady = ref(false);
116
- const previewReady = ref(false);
117
- const executedExpressionIndex = ref(0);
118
- const jsFunctionsInjected = ref(false);
119
- const pendingQueue = ref<string[]>([]);
120
-
121
- const localApi = computed(() => {
122
- const api: Record<string, unknown> = {};
123
- for (const fn of sandboxFunctions.value) {
124
- api[fn.name] = fn.handler;
125
- }
126
- return api;
53
+ const controller = new ɵOpenGenerativeUIController();
54
+ controller.setContent(props.content);
55
+ const state = shallowRef(controller.getState());
56
+ const unsubscribe = controller.subscribe(() => {
57
+ state.value = controller.getState();
127
58
  });
128
59
 
129
60
  watch(
130
61
  () => props.content,
131
- (next) => {
132
- latestContent.value = next;
133
- if (shouldFlushImmediately(throttledContent.value, next)) {
134
- if (throttleTimer.value !== null) {
135
- window.clearTimeout(throttleTimer.value);
136
- throttleTimer.value = null;
137
- }
138
- throttledContent.value = next;
139
- return;
140
- }
141
- if (throttleTimer.value === null) {
142
- throttleTimer.value = window.setTimeout(() => {
143
- throttledContent.value = latestContent.value;
144
- throttleTimer.value = null;
145
- }, 1000);
146
- }
147
- },
148
- { immediate: true },
62
+ (content) => controller.setContent(content),
149
63
  );
150
-
151
- onBeforeUnmount(() => {
152
- if (throttleTimer.value !== null) {
153
- window.clearTimeout(throttleTimer.value);
154
- }
155
- });
156
-
157
- const partialHtml = computed(() => {
158
- if (throttledContent.value.htmlComplete) return undefined;
159
- if (!throttledContent.value.html?.length) return undefined;
160
- return throttledContent.value.html.join("");
161
- });
162
- const previewBody = computed(() =>
163
- partialHtml.value ? processPartialHtml(partialHtml.value) : undefined,
164
- );
165
- const previewStyles = computed(() =>
166
- partialHtml.value ? extractCompleteStyles(partialHtml.value) : "",
167
- );
168
- const fullHtml = computed(() =>
169
- throttledContent.value.htmlComplete && throttledContent.value.html?.length
170
- ? throttledContent.value.html.join("")
171
- : undefined,
172
- );
173
- const css = computed(() =>
174
- throttledContent.value.cssComplete
175
- ? throttledContent.value.css
176
- : undefined,
177
- );
178
- const hasPreview = computed(
179
- () =>
180
- !!throttledContent.value.cssComplete &&
181
- !!previewBody.value &&
182
- previewBody.value.trim().length > 0,
183
- );
184
- const hasVisibleSandbox = computed(
185
- () => !!fullHtml.value || hasPreview.value,
186
- );
187
- const resolvedHeight = computed(
188
- () => `${throttledContent.value.initialHeight ?? 200}px`,
189
- );
190
-
191
- const destroyPreview = () => {
192
- if (previewSandboxRef.value) {
193
- previewSandboxRef.value.destroy();
194
- previewSandboxRef.value = null;
195
- }
196
- previewReady.value = false;
197
- };
198
-
199
- const destroyFinal = () => {
200
- if (sandboxRef.value) {
201
- sandboxRef.value.destroy();
202
- sandboxRef.value = null;
203
- }
204
- sandboxReady.value = false;
205
- pendingQueue.value = [];
206
- executedExpressionIndex.value = 0;
207
- jsFunctionsInjected.value = false;
208
- };
209
-
210
64
  watch(
211
- [
212
- hasPreview,
213
- fullHtml,
214
- css,
215
- previewBody,
216
- previewStyles,
217
- () => containerRef.value,
218
- ],
219
- async ([previewVisible, htmlComplete], _previous, onCleanup) => {
220
- if (!previewVisible || htmlComplete || !containerRef.value) return;
221
- if (previewSandboxRef.value) return;
222
-
223
- let cancelled = false;
224
- try {
225
- const Websandbox = await loadWebsandbox();
226
- if (cancelled || !containerRef.value) return;
227
-
228
- const sandbox = Websandbox.create(
229
- {},
230
- {
231
- frameContainer: containerRef.value,
232
- frameContent: "<head></head><body></body>",
233
- allowAdditionalAttributes: "",
234
- },
235
- );
236
- previewSandboxRef.value = sandbox;
237
- sandbox.iframe.setAttribute(
238
- "data-testid",
239
- "open-generative-ui-preview-sandbox",
240
- );
241
- sandbox.iframe.style.width = "100%";
242
- sandbox.iframe.style.height = "100%";
243
- sandbox.iframe.style.border = "none";
244
- sandbox.iframe.style.backgroundColor = "transparent";
245
-
246
- sandbox.promise.then(() => {
247
- if (cancelled || !previewSandboxRef.value) return;
248
- previewReady.value = true;
249
- void sandbox.run(
250
- "var s=document.createElement('style');s.textContent='html, body { overflow: hidden !important; }';document.head.appendChild(s);",
251
- );
252
- });
253
- } catch (error) {
254
- console.error(
255
- "[OpenGenerativeUI] Failed to load sandbox module:",
256
- error,
257
- );
258
- }
259
-
260
- onCleanup(() => {
261
- cancelled = true;
262
- });
263
- },
264
- { immediate: true },
265
- );
266
-
267
- watch(
268
- [previewBody, previewStyles, css, previewReady],
269
- ([body, styles, cssText, ready]) => {
270
- if (!previewSandboxRef.value || !ready) return;
271
- const headParts: string[] = [];
272
- if (cssText) headParts.push(`<style>${cssText}</style>`);
273
- if (styles) headParts.push(styles);
274
- if (headParts.length) {
275
- void previewSandboxRef.value.run(
276
- `document.head.innerHTML = ${JSON.stringify(headParts.join(""))}`,
277
- );
278
- }
279
- if (body) {
280
- void previewSandboxRef.value.run(
281
- `document.body.innerHTML = ${JSON.stringify(body)}`,
282
- );
283
- }
284
- },
285
- { immediate: true },
286
- );
287
-
288
- watch(
289
- [fullHtml, css, localApi, () => containerRef.value],
290
- async ([html, cssText, api], _previous, onCleanup) => {
291
- destroyFinal();
292
- if (!html || !containerRef.value) return;
293
- destroyPreview();
294
-
295
- let cancelled = false;
296
- try {
297
- const Websandbox = await loadWebsandbox();
298
- if (cancelled || !containerRef.value) return;
299
- const htmlWithHead = ensureHead(html);
300
- const htmlWithCss = cssText
301
- ? injectCssIntoHtml(htmlWithHead, cssText)
302
- : htmlWithHead;
303
- const sandbox = Websandbox.create(api, {
304
- frameContainer: containerRef.value,
305
- frameContent: htmlWithCss,
306
- allowAdditionalAttributes: "",
307
- });
308
- sandboxRef.value = sandbox;
309
- sandbox.iframe.setAttribute(
310
- "data-testid",
311
- "open-generative-ui-final-sandbox",
312
- );
313
- sandbox.iframe.style.width = "100%";
314
- sandbox.iframe.style.height = "100%";
315
- sandbox.iframe.style.border = "none";
316
- sandbox.iframe.style.backgroundColor = "transparent";
317
-
318
- sandbox.promise.then(() => {
319
- if (cancelled || !sandboxRef.value) return;
320
- sandboxReady.value = true;
321
- void sandbox.run(
322
- "var s=document.createElement('style');s.textContent='html, body { overflow: hidden !important; }';document.head.appendChild(s);",
323
- );
324
- const functionsCode = throttledContent.value.jsFunctions;
325
- if (functionsCode && !jsFunctionsInjected.value) {
326
- jsFunctionsInjected.value = true;
327
- pendingQueue.value.unshift(functionsCode);
328
- }
329
- const expressions = throttledContent.value.jsExpressions;
330
- if (expressions?.length) {
331
- const startIndex = executedExpressionIndex.value;
332
- if (startIndex < expressions.length) {
333
- pendingQueue.value.push(...expressions.slice(startIndex));
334
- executedExpressionIndex.value = expressions.length;
335
- }
336
- }
337
- const queue = [...pendingQueue.value];
338
- pendingQueue.value = [];
339
- for (const code of queue) {
340
- void sandbox.run(code);
341
- }
342
- });
343
- } catch (error) {
344
- console.error(
345
- "[OpenGenerativeUI] Failed to load sandbox module:",
346
- error,
347
- );
348
- }
349
-
350
- onCleanup(() => {
351
- cancelled = true;
352
- });
353
- },
354
- { immediate: true },
355
- );
356
-
357
- watch(
358
- () => throttledContent.value.jsFunctions,
359
- (functionsCode) => {
360
- if (!functionsCode || jsFunctionsInjected.value) return;
361
- jsFunctionsInjected.value = true;
362
- if (sandboxReady.value && sandboxRef.value) {
363
- void sandboxRef.value.run(functionsCode);
364
- } else {
365
- pendingQueue.value.push(functionsCode);
366
- }
367
- },
368
- );
369
-
370
- watch(
371
- () => throttledContent.value.jsExpressions,
372
- (expressions) => {
373
- if (!expressions?.length) return;
374
- const startIndex = executedExpressionIndex.value;
375
- if (startIndex >= expressions.length) return;
376
- const newExpressions = expressions.slice(startIndex);
377
- executedExpressionIndex.value = expressions.length;
378
- if (sandboxReady.value && sandboxRef.value) {
379
- for (const expression of newExpressions) {
380
- void sandboxRef.value.run(expression);
381
- }
382
- } else {
383
- pendingQueue.value.push(...newExpressions);
384
- }
385
- },
386
- { deep: true },
387
- );
388
-
389
- const isGenerating = computed(
390
- () => throttledContent.value.generating !== false,
391
- );
392
- watch(
393
- [hasPreview, fullHtml],
394
- ([previewVisible, html]) => {
395
- if (html) destroyPreview();
396
- if (!previewVisible) destroyPreview();
397
- },
65
+ sandboxFunctions,
66
+ (functions) => controller.setSandboxFunctions(functions),
398
67
  { immediate: true },
399
68
  );
400
-
69
+ onMounted(() => controller.setHost(containerRef.value));
401
70
  onBeforeUnmount(() => {
402
- if (throttleTimer.value !== null) {
403
- window.clearTimeout(throttleTimer.value);
404
- }
405
- destroyPreview();
406
- destroyFinal();
71
+ unsubscribe();
72
+ controller.destroy();
407
73
  });
408
74
 
409
- return () =>
410
- h(
75
+ return () => {
76
+ const { phase, height, showSpinner, showOverlay } = state.value;
77
+ const hasVisibleSandbox = phase !== "placeholder";
78
+ return h(
411
79
  "div",
412
80
  {
413
81
  ref: containerRef,
@@ -415,64 +83,72 @@ export const OpenGenerativeUIRenderer = defineComponent({
415
83
  style: {
416
84
  position: "relative",
417
85
  width: "100%",
418
- height: resolvedHeight.value,
86
+ height: `${height}px`,
419
87
  borderRadius: "8px",
420
- backgroundColor: hasVisibleSandbox.value
421
- ? "transparent"
422
- : "#f5f5f5",
423
- border: hasVisibleSandbox.value ? "none" : "1px solid #e0e0e0",
88
+ backgroundColor: hasVisibleSandbox ? "transparent" : "#f5f5f5",
89
+ border: hasVisibleSandbox ? "none" : "1px solid #e0e0e0",
424
90
  overflow: "hidden",
425
- display: hasVisibleSandbox.value ? "block" : "flex",
426
- alignItems: hasVisibleSandbox.value ? undefined : "center",
427
- justifyContent: hasVisibleSandbox.value ? undefined : "center",
91
+ display: hasVisibleSandbox ? "block" : "flex",
92
+ alignItems: hasVisibleSandbox ? undefined : "center",
93
+ justifyContent: hasVisibleSandbox ? undefined : "center",
428
94
  },
429
95
  },
430
96
  [
431
- !hasVisibleSandbox.value
432
- ? h("div", { "data-testid": "open-generative-ui-placeholder" }, [
433
- h(
434
- "svg",
435
- {
436
- width: "48",
437
- height: "48",
438
- viewBox: "0 0 24 24",
439
- fill: "none",
440
- style: { animation: "ck-spin 1s linear infinite" },
97
+ showOverlay
98
+ ? h(
99
+ "div",
100
+ {
101
+ "data-testid": "open-generative-ui-progress-overlay",
102
+ style: {
103
+ position: "absolute",
104
+ inset: 0,
105
+ zIndex: 10,
106
+ pointerEvents: "all",
107
+ backgroundColor: "rgba(255, 255, 255, 0.5)",
108
+ display: "flex",
109
+ alignItems: "center",
110
+ justifyContent: "center",
441
111
  },
442
- [
443
- h("circle", {
444
- cx: "12",
445
- cy: "12",
446
- r: "10",
447
- stroke: "#e0e0e0",
448
- "stroke-width": "3",
449
- }),
450
- h("path", {
451
- d: "M12 2a10 10 0 0 1 10 10",
452
- stroke: "#999",
453
- "stroke-width": "3",
454
- "stroke-linecap": "round",
455
- }),
456
- ],
457
- ),
458
- h(
459
- "style",
460
- "@keyframes ck-spin { to { transform: rotate(360deg) } }",
461
- ),
462
- ])
463
- : null,
464
- isGenerating.value
465
- ? h("div", {
466
- "data-testid": "open-generative-ui-progress-overlay",
467
- style: {
468
- position: "absolute",
469
- inset: 0,
470
- backgroundColor: "rgba(255,255,255,0.45)",
471
112
  },
472
- })
113
+ showSpinner
114
+ ? [
115
+ h(
116
+ "svg",
117
+ {
118
+ "data-testid": "open-generative-ui-spinner",
119
+ width: "48",
120
+ height: "48",
121
+ viewBox: "0 0 24 24",
122
+ fill: "none",
123
+ style: { animation: "ck-spin 1s linear infinite" },
124
+ },
125
+ [
126
+ h("circle", {
127
+ cx: "12",
128
+ cy: "12",
129
+ r: "10",
130
+ stroke: "#e0e0e0",
131
+ "stroke-width": "3",
132
+ }),
133
+ h("path", {
134
+ d: "M12 2a10 10 0 0 1 10 10",
135
+ stroke: "#999",
136
+ "stroke-width": "3",
137
+ "stroke-linecap": "round",
138
+ }),
139
+ ],
140
+ ),
141
+ h(
142
+ "style",
143
+ "@keyframes ck-spin { to { transform: rotate(360deg) } }",
144
+ ),
145
+ ]
146
+ : [],
147
+ )
473
148
  : null,
474
149
  ],
475
150
  );
151
+ };
476
152
  },
477
153
  });
478
154
 
@@ -508,35 +184,35 @@ export const OpenGenerativeUIToolRenderer = defineComponent({
508
184
  result: { type: String as PropType<string | undefined>, required: false },
509
185
  },
510
186
  setup(props) {
511
- const visibleMessageIndex = ref(0);
512
-
187
+ const cycler = new ɵPlaceholderCycler();
188
+ const message = shallowRef(cycler.getSnapshot().message);
189
+ const unsubscribe = cycler.subscribe(() => {
190
+ message.value = cycler.getSnapshot().message;
191
+ });
513
192
  watch(
514
- () => props.args.placeholderMessages,
515
- (messages, _, onCleanup) => {
516
- if (!messages?.length || props.status === ToolCallStatus.Complete)
517
- return;
518
- visibleMessageIndex.value = Math.max(messages.length - 1, 0);
519
- const timer = window.setInterval(() => {
520
- visibleMessageIndex.value =
521
- (visibleMessageIndex.value + 1) % Math.max(messages.length, 1);
522
- }, 5000);
523
- onCleanup(() => window.clearInterval(timer));
524
- },
193
+ () =>
194
+ [
195
+ props.args.placeholderMessages,
196
+ props.status === ToolCallStatus.Complete,
197
+ ] as const,
198
+ ([messages, complete]) => cycler.update(messages, complete),
525
199
  { immediate: true },
526
200
  );
201
+ onBeforeUnmount(() => {
202
+ unsubscribe();
203
+ cycler.dispose();
204
+ });
527
205
 
528
206
  return () => {
529
- if (props.status === ToolCallStatus.Complete) return null;
530
- const messages = props.args.placeholderMessages;
531
- if (!messages?.length) return null;
532
- const currentMessage = messages[visibleMessageIndex.value] ?? messages[0];
207
+ // Nothing once complete — the activity renderer handles the UI.
208
+ if (message.value === undefined) return null;
533
209
  return h(
534
210
  "div",
535
211
  {
536
212
  style: { padding: "8px 12px", color: "#999", fontSize: "14px" },
537
213
  "data-testid": "open-generative-ui-tool-placeholder",
538
214
  },
539
- currentMessage,
215
+ message.value,
540
216
  );
541
217
  };
542
218
  },