@copilotkit/vue 2.0.0-rc.3 → 2.0.0-rc.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/CONTRIBUTOR_GUIDE.md +1 -1
  2. package/PARITY.md +3 -3
  3. package/dist/hooks/use-copilot-action.d.ts.map +1 -1
  4. package/dist/hooks/use-frontend-tool.d.ts +1 -1
  5. package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
  6. package/dist/hooks/zod-parameters.d.ts +14 -0
  7. package/dist/hooks/zod-parameters.d.ts.map +1 -0
  8. package/dist/index.cjs +1 -73
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.mjs +365 -16920
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/use-render-activity-message-BMTHA_P2.js +15901 -0
  13. package/dist/use-render-activity-message-BMTHA_P2.js.map +1 -0
  14. package/dist/use-render-activity-message-CH3beu7z.cjs +113 -0
  15. package/dist/use-render-activity-message-CH3beu7z.cjs.map +1 -0
  16. package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
  17. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
  18. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
  19. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
  20. package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
  21. package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
  22. package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -1
  23. package/dist/v2/components/LicenseWarningBanner.vue.d.ts +2 -2
  24. package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
  25. package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
  26. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -59
  27. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
  28. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +3 -11
  29. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
  30. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
  31. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
  32. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -130
  33. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
  34. package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
  35. package/dist/v2/components/a2ui/utils.d.ts +3 -15
  36. package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
  37. package/dist/v2/components/a2ui.d.ts +9 -8
  38. package/dist/v2/components/a2ui.d.ts.map +1 -1
  39. package/dist/v2/components/chat/CopilotChat.vue.d.ts +2 -2
  40. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  41. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  42. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
  43. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
  44. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
  45. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
  46. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +1 -1
  47. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -1
  48. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +7 -286
  49. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  50. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -1
  51. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
  52. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +1 -1
  53. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  54. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  55. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +1 -1
  56. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
  57. package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
  58. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +1 -1
  59. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
  60. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
  61. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +3 -3
  62. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
  63. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -1
  64. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  65. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +8 -3
  66. package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
  67. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +5 -3
  68. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
  69. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +5 -3
  70. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
  71. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +8 -3
  72. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
  73. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +6 -4
  74. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
  75. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +6 -4
  76. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
  77. package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
  78. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
  79. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
  80. package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
  81. package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
  82. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +4 -4
  83. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
  84. package/dist/v2/components/chat/forwarded-slots.d.ts +12 -0
  85. package/dist/v2/components/chat/forwarded-slots.d.ts.map +1 -0
  86. package/dist/v2/components/chat/index.d.ts +34 -31
  87. package/dist/v2/components/chat/index.d.ts.map +1 -1
  88. package/dist/v2/components/chat/inspector-shortcuts.d.ts +2 -1
  89. package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -1
  90. package/dist/v2/components/chat/message-feedback.d.ts +38 -49
  91. package/dist/v2/components/chat/message-feedback.d.ts.map +1 -1
  92. package/dist/v2/components/chat/tool-call-display-context.d.ts +4 -19
  93. package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
  94. package/dist/v2/components/chat/tool-call-group-parts.d.ts +7 -20
  95. package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
  96. package/dist/v2/components/chat/turn-work.d.ts +0 -2
  97. package/dist/v2/components/chat/turn-work.d.ts.map +1 -1
  98. package/dist/v2/components/chat/types.d.ts +9 -4
  99. package/dist/v2/components/chat/types.d.ts.map +1 -1
  100. package/dist/v2/components/chat/use-chat-labels.d.ts +8 -0
  101. package/dist/v2/components/chat/use-chat-labels.d.ts.map +1 -0
  102. package/dist/v2/components/chat/use-copy-feedback.d.ts +11 -0
  103. package/dist/v2/components/chat/use-copy-feedback.d.ts.map +1 -0
  104. package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
  105. package/dist/v2/components/icons/index.d.ts +968 -1
  106. package/dist/v2/components/icons/index.d.ts.map +1 -1
  107. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
  108. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
  109. package/dist/v2/hooks/use-agent-context.d.ts +2 -3
  110. package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
  111. package/dist/v2/hooks/use-agent.d.ts +4 -1
  112. package/dist/v2/hooks/use-agent.d.ts.map +1 -1
  113. package/dist/v2/hooks/use-attachments.d.ts +7 -0
  114. package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
  115. package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
  116. package/dist/v2/hooks/use-component.d.ts +1 -0
  117. package/dist/v2/hooks/use-component.d.ts.map +1 -1
  118. package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
  119. package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
  120. package/dist/v2/hooks/use-default-render-tool.d.ts +2 -7
  121. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
  122. package/dist/v2/hooks/use-frontend-tool.d.ts +5 -0
  123. package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -1
  124. package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
  125. package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
  126. package/dist/v2/hooks/use-interrupt.d.ts +0 -1
  127. package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
  128. package/dist/v2/hooks/use-keyboard-height.d.ts +1 -1
  129. package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -1
  130. package/dist/v2/hooks/use-pin-to-send.d.ts +4 -12
  131. package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -1
  132. package/dist/v2/hooks/use-render-activity-message.d.ts +13 -9
  133. package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
  134. package/dist/v2/hooks/use-render-custom-messages.d.ts +5 -7
  135. package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
  136. package/dist/v2/hooks/use-render-tool.d.ts +1 -1
  137. package/dist/v2/hooks/use-render-tool.d.ts.map +1 -1
  138. package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
  139. package/dist/v2/hooks/use-threads.d.ts +6 -23
  140. package/dist/v2/hooks/use-threads.d.ts.map +1 -1
  141. package/dist/v2/index.cjs +1 -1
  142. package/dist/v2/index.mjs +197 -200
  143. package/dist/v2/index.mjs.map +1 -1
  144. package/dist/v2/lib/processPartialHtml.d.ts +1 -2
  145. package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
  146. package/dist/v2/lib/shallow-stable.d.ts.map +1 -1
  147. package/dist/v2/lib/vue-core.d.ts +33 -19
  148. package/dist/v2/lib/vue-core.d.ts.map +1 -1
  149. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  150. package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -129
  151. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  152. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
  153. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  154. package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
  155. package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
  156. package/dist/v2/providers/markdown-renderer.d.ts +4 -2
  157. package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
  158. package/dist/v2/providers/types.d.ts +3 -46
  159. package/dist/v2/providers/types.d.ts.map +1 -1
  160. package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
  161. package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
  162. package/dist/v2/types/defineToolCallRenderer.d.ts +1 -1
  163. package/dist/v2/types/defineToolCallRenderer.d.ts.map +1 -1
  164. package/dist/v2/types/human-in-the-loop.d.ts +8 -29
  165. package/dist/v2/types/human-in-the-loop.d.ts.map +1 -1
  166. package/dist/v2/types/interrupt.d.ts +1 -22
  167. package/dist/v2/types/interrupt.d.ts.map +1 -1
  168. package/dist/v2/types/vue-activity-message-renderer.d.ts +16 -15
  169. package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -1
  170. package/dist/v2/types/vue-custom-message-renderer.d.ts +7 -16
  171. package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -1
  172. package/dist/v2/types/vue-tool-call-renderer.d.ts +16 -35
  173. package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
  174. package/package.json +12 -13
  175. package/src/__tests__/build-entries.test.ts +29 -0
  176. package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
  177. package/src/hooks/use-copilot-action.ts +2 -1
  178. package/src/hooks/use-frontend-tool.ts +3 -6
  179. package/src/hooks/zod-parameters.ts +162 -0
  180. package/src/v2/__tests__/exports.test.ts +10 -0
  181. package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
  182. package/src/v2/__tests__/utils/test-helpers.ts +34 -4
  183. package/src/v2/components/A2UIMessageRenderer.ts +98 -68
  184. package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
  185. package/src/v2/components/CopilotKitInspector.vue +104 -51
  186. package/src/v2/components/InlineFeatureWarning.vue +20 -21
  187. package/src/v2/components/LicenseWarningBanner.vue +27 -135
  188. package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
  189. package/src/v2/components/OpenGenerativeUIRenderer.ts +122 -446
  190. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
  191. package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
  192. package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +60 -0
  193. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +64 -8
  194. package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
  195. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +6 -26
  196. package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -185
  197. package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
  198. package/src/v2/components/a2ui/catalog.ts +3 -3
  199. package/src/v2/components/a2ui/utils.ts +13 -65
  200. package/src/v2/components/a2ui.ts +15 -22
  201. package/src/v2/components/chat/CopilotChat.vue +121 -498
  202. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +47 -184
  203. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +36 -55
  204. package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +14 -6
  205. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
  206. package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +12 -77
  207. package/src/v2/components/chat/CopilotChatInput.vue +139 -654
  208. package/src/v2/components/chat/CopilotChatInspectorButton.vue +45 -108
  209. package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
  210. package/src/v2/components/chat/CopilotChatMessageView.vue +96 -274
  211. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +27 -62
  212. package/src/v2/components/chat/CopilotChatToolCallGroup.vue +63 -71
  213. package/src/v2/components/chat/CopilotChatToolCallItem.vue +8 -6
  214. package/src/v2/components/chat/CopilotChatToolCallsView.vue +31 -32
  215. package/src/v2/components/chat/CopilotChatUserMessage.vue +24 -112
  216. package/src/v2/components/chat/CopilotChatView.vue +123 -161
  217. package/src/v2/components/chat/CopilotChatWorkSummary.vue +26 -36
  218. package/src/v2/components/chat/CopilotModalHeader.vue +11 -23
  219. package/src/v2/components/chat/CopilotPopup.vue +23 -25
  220. package/src/v2/components/chat/CopilotPopupView.vue +10 -39
  221. package/src/v2/components/chat/CopilotPopupViewInternal.vue +49 -185
  222. package/src/v2/components/chat/CopilotSidebar.vue +23 -25
  223. package/src/v2/components/chat/CopilotSidebarView.vue +10 -39
  224. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +56 -100
  225. package/src/v2/components/chat/CopilotThreadsDrawer.vue +43 -105
  226. package/src/v2/components/chat/StreamingMarkdownDefault.vue +15 -28
  227. package/src/v2/components/chat/__tests__/CopilotChat.labels.test.ts +19 -4
  228. package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
  229. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
  230. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +5 -5
  231. package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
  232. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +132 -1
  233. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +247 -403
  234. package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +1 -99
  235. package/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.ts +43 -1
  236. package/src/v2/components/chat/__tests__/CopilotPopup.test.ts +90 -1
  237. package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
  238. package/src/v2/components/chat/__tests__/CopilotSidebar.test.ts +90 -1
  239. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
  240. package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
  241. package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
  242. package/src/v2/components/chat/audioRecorder.ts +4 -7
  243. package/src/v2/components/chat/copilotChatToolCallItemRender.ts +25 -90
  244. package/src/v2/components/chat/forwarded-slots.ts +17 -0
  245. package/src/v2/components/chat/index.ts +0 -1
  246. package/src/v2/components/chat/inspector-shortcuts.ts +10 -16
  247. package/src/v2/components/chat/message-feedback.ts +92 -195
  248. package/src/v2/components/chat/tool-call-display-context.ts +6 -22
  249. package/src/v2/components/chat/tool-call-group-parts.ts +47 -108
  250. package/src/v2/components/chat/turn-work.ts +0 -9
  251. package/src/v2/components/chat/types.ts +12 -4
  252. package/src/v2/components/chat/use-chat-labels.ts +16 -0
  253. package/src/v2/components/chat/use-copy-feedback.ts +21 -0
  254. package/src/v2/components/chat/use-lightbox.ts +15 -33
  255. package/src/v2/components/icons/__tests__/icons.test.ts +72 -68
  256. package/src/v2/components/icons/index.ts +109 -27
  257. package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
  258. package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
  259. package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
  260. package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
  261. package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
  262. package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
  263. package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
  264. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +66 -1
  265. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
  266. package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
  267. package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
  268. package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +106 -0
  269. package/src/v2/hooks/__tests__/use-render-tool.test.ts +3 -6
  270. package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
  271. package/src/v2/hooks/__tests__/zod-regression.test.ts +5 -4
  272. package/src/v2/hooks/use-agent-context.ts +4 -10
  273. package/src/v2/hooks/use-agent.ts +86 -290
  274. package/src/v2/hooks/use-attachments.ts +48 -168
  275. package/src/v2/hooks/use-capabilities.ts +2 -7
  276. package/src/v2/hooks/use-component.ts +7 -4
  277. package/src/v2/hooks/use-configure-suggestions.ts +29 -220
  278. package/src/v2/hooks/use-default-render-tool.ts +31 -152
  279. package/src/v2/hooks/use-frontend-tool.ts +15 -25
  280. package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
  281. package/src/v2/hooks/use-interrupt.ts +29 -308
  282. package/src/v2/hooks/use-keyboard-height.ts +17 -40
  283. package/src/v2/hooks/use-pin-to-send.ts +15 -99
  284. package/src/v2/hooks/use-render-activity-message.ts +35 -57
  285. package/src/v2/hooks/use-render-custom-messages.ts +24 -88
  286. package/src/v2/hooks/use-render-tool.ts +2 -4
  287. package/src/v2/hooks/use-suggestions.ts +17 -36
  288. package/src/v2/hooks/use-threads.ts +49 -288
  289. package/src/v2/lib/__tests__/shallow-stable.test.ts +54 -0
  290. package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
  291. package/src/v2/lib/processPartialHtml.ts +6 -21
  292. package/src/v2/lib/shallow-stable.ts +2 -16
  293. package/src/v2/lib/vue-core.ts +90 -85
  294. package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
  295. package/src/v2/providers/CopilotKitProvider.types.ts +12 -132
  296. package/src/v2/providers/CopilotKitProvider.vue +291 -641
  297. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
  298. package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +38 -2
  299. package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
  300. package/src/v2/providers/__tests__/CopilotKitProvider.headersAtSendTime.test.ts +3 -3
  301. package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +3 -1
  302. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
  303. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +88 -28
  304. package/src/v2/providers/chat-configuration-store-key.ts +9 -0
  305. package/src/v2/providers/markdown-renderer.ts +8 -2
  306. package/src/v2/providers/types.ts +3 -49
  307. package/src/v2/providers/use-inspector-thread-override.ts +22 -80
  308. package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +28 -33
  309. package/src/v2/types/defineToolCallRenderer.ts +7 -6
  310. package/src/v2/types/human-in-the-loop.ts +8 -32
  311. package/src/v2/types/interrupt.ts +7 -31
  312. package/src/v2/types/vue-activity-message-renderer.ts +24 -15
  313. package/src/v2/types/vue-custom-message-renderer.ts +12 -16
  314. package/src/v2/types/vue-tool-call-renderer.ts +23 -38
  315. package/tsconfig.json +0 -1
  316. package/vite.config.ts +8 -5
  317. package/vitest.config.ts +12 -7
  318. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts +0 -9
  319. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +0 -1
  320. package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
  321. package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
  322. package/dist/v2/components/chat/tool-call-layout.d.ts +0 -115
  323. package/dist/v2/components/chat/tool-call-layout.d.ts.map +0 -1
  324. package/dist/v2/lib/is-mobile-viewport.d.ts +0 -15
  325. package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
  326. package/dist/v2/lib/message-feedback.d.ts +0 -33
  327. package/dist/v2/lib/message-feedback.d.ts.map +0 -1
  328. package/dist/v2/lib/transcription-client.d.ts +0 -19
  329. package/dist/v2/lib/transcription-client.d.ts.map +0 -1
  330. package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
  331. package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
  332. package/src/v2/components/chat/BasicMarkdown.vue +0 -160
  333. package/src/v2/components/chat/__tests__/BasicMarkdown.test.ts +0 -69
  334. package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -39
  335. package/src/v2/components/chat/normalize-auto-scroll.ts +0 -17
  336. package/src/v2/components/chat/tool-call-layout.ts +0 -304
  337. package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +0 -48
  338. package/src/v2/lib/__tests__/message-feedback.test.ts +0 -152
  339. package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
  340. package/src/v2/lib/__tests__/transcription-client.test.ts +0 -67
  341. package/src/v2/lib/is-mobile-viewport.ts +0 -23
  342. package/src/v2/lib/message-feedback.ts +0 -120
  343. package/src/v2/lib/transcription-client.ts +0 -151
@@ -1,5 +1,15 @@
1
1
  <script setup lang="ts">
2
- import { computed, h, onMounted, provide, ref, useSlots, watch } from "vue";
2
+ import {
3
+ computed,
4
+ h,
5
+ onBeforeUnmount,
6
+ onMounted,
7
+ provide,
8
+ ref,
9
+ shallowRef,
10
+ useSlots,
11
+ watch,
12
+ } from "vue";
3
13
  import type { Component, FunctionalComponent, VNode, VNodeChild } from "vue";
4
14
  import type {
5
15
  ActivityMessage,
@@ -10,11 +20,25 @@ import type {
10
20
  UserMessage,
11
21
  } from "@ag-ui/core";
12
22
  import {
13
- DEFAULT_AGENT_ID,
14
23
  commitRowKeyStore,
15
24
  createRowKeyStore,
16
25
  resolveRowRenderKeysById,
17
26
  } from "@copilotkit/shared";
27
+ import {
28
+ ɵdeduplicateMessages,
29
+ ɵcreateMessageViewModel,
30
+ ɵduplicateMessagesWarning,
31
+ ɵgetCustomMessageRenderProps,
32
+ ɵgetToolCallRendererNames,
33
+ ɵresolveActivityRenderer,
34
+ ɵresolveAgentId,
35
+ ɵresolveCustomMessageRenderers,
36
+ } from "@copilotkit/core";
37
+ import type {
38
+ CopilotChatToolCallDisplay,
39
+ ToolCallEntry,
40
+ ɵToolCallDisplayContextValue,
41
+ } from "@copilotkit/core";
18
42
  import type {
19
43
  InterruptRenderProps,
20
44
  VueCustomMessageRendererProps,
@@ -33,18 +57,6 @@ import {
33
57
  } from "./message-feedback";
34
58
  import type { MessageFeedbackScope } from "./message-feedback";
35
59
  import { ToolCallDisplayContextKey } from "./tool-call-display-context";
36
- import type { ToolCallDisplayContextValue } from "./tool-call-display-context";
37
- import {
38
- getToolCallLayouts,
39
- getToolCallRendererNames,
40
- getTurnWork,
41
- } from "./tool-call-layout";
42
- import type {
43
- CopilotChatToolCallDisplay,
44
- ToolCallEntry,
45
- ToolCallLayout,
46
- TurnWork,
47
- } from "./tool-call-layout";
48
60
  import type { CopilotChatWorkSummarySlotProps } from "./types";
49
61
 
50
62
  interface MessageMetaProps {
@@ -145,8 +157,8 @@ const stateTick = ref(0);
145
157
  const interruptState = ref<InterruptSlotProps | null>(null);
146
158
  const componentSlots = useSlots() as Record<string, (props?: any) => unknown>;
147
159
  const forwardedSlotNames = computed(() => Object.keys(componentSlots));
148
- const resolvedAgentId = computed(
149
- () => config.value?.agentId ?? DEFAULT_AGENT_ID,
160
+ const resolvedAgentId = computed(() =>
161
+ ɵresolveAgentId({ chatAgentId: config.value?.agentId }),
150
162
  );
151
163
  const resolvedThreadAgent = computed(() => {
152
164
  // Read the registry so this recomputes when agents are added or replaced.
@@ -203,49 +215,37 @@ watch(
203
215
  { immediate: true },
204
216
  );
205
217
 
206
- function deduplicateMessages(messages: Message[]): Message[] {
207
- const byId = new Map<string, Message>();
208
- for (const message of messages) {
209
- const existing = byId.get(message.id);
210
- if (
211
- existing &&
212
- message.role === "assistant" &&
213
- existing.role === "assistant"
214
- ) {
215
- const content = message.content || existing.content;
216
- const toolCalls = message.toolCalls ?? existing.toolCalls;
217
- byId.set(message.id, {
218
- ...existing,
219
- ...message,
220
- content,
221
- toolCalls,
222
- } as AssistantMessage);
223
- } else {
224
- byId.set(message.id, message);
225
- }
226
- }
227
- return [...byId.values()];
228
- }
229
-
230
218
  const deduplicatedMessages = computed(() =>
231
- deduplicateMessages(props.messages),
219
+ ɵdeduplicateMessages(props.messages),
232
220
  );
233
221
 
234
222
  // Groups of calls can span messages (an agent often sends each call as its
235
223
  // own message), so they're laid out here for the whole list and handed to
236
224
  // each message's tool calls view through provide/inject.
237
- const toolCallLayouts = computed<ReadonlyMap<string, ToolCallLayout>>(() =>
238
- props.toolCallDisplay === "separate"
239
- ? new Map()
240
- : getToolCallLayouts(
241
- deduplicatedMessages.value,
242
- props.messages,
243
- getToolCallRendererNames(
244
- copilotkit.value.renderToolCalls,
245
- forwardedSlotNames.value,
246
- ),
247
- ),
225
+ const rendererNames = computed(() =>
226
+ ɵgetToolCallRendererNames(copilotkit.value.renderToolCalls, {
227
+ slotNames: forwardedSlotNames.value,
228
+ }),
248
229
  );
230
+ // The list's tool-call layout and turn state live in core. A user's open or
231
+ // close of a reply's work is the only change it reports by itself.
232
+ const viewModel = ɵcreateMessageViewModel();
233
+ const toggledTurns = shallowRef(viewModel.getSnapshot());
234
+ const unsubscribeViewModel = viewModel.subscribe(() => {
235
+ toggledTurns.value = viewModel.getSnapshot();
236
+ });
237
+ onBeforeUnmount(unsubscribeViewModel);
238
+ const viewState = computed(() => {
239
+ void toggledTurns.value;
240
+ return viewModel.update({
241
+ display: props.toolCallDisplay,
242
+ messages: props.messages,
243
+ rendered: deduplicatedMessages.value,
244
+ isRunning: props.isRunning,
245
+ rendererNames: rendererNames.value,
246
+ now: Date.now(),
247
+ });
248
+ });
249
249
  const learningFeedbackEnabled = useLearningFeedbackEnabled(copilotkit);
250
250
  provide(
251
251
  MessageFeedbackScopeKey,
@@ -263,98 +263,18 @@ provide(
263
263
  ),
264
264
  );
265
265
 
266
- const turnWork = computed(() =>
267
- props.toolCallDisplay === "turn"
268
- ? getTurnWork(deduplicatedMessages.value, toolCallLayouts.value)
269
- : undefined,
270
- );
271
- const turnByFirstMessage = computed(() => {
272
- const byFirst = new Map<string, TurnWork>();
273
- for (const turn of turnWork.value?.values() ?? []) {
274
- byFirst.set(turn.firstMessageId, turn);
275
- }
276
- return byFirst;
277
- });
278
-
279
- const lastRenderedMessage = computed(
280
- () => deduplicatedMessages.value[deduplicatedMessages.value.length - 1],
281
- );
266
+ const turnByFirstMessage = computed(() => viewState.value.turnByFirstMessage);
282
267
  // The latest reply is keyed by the user message it answers (see getTurnWork).
283
- const latestTurnKey = computed(() => {
284
- const rendered = deduplicatedMessages.value;
285
- for (let i = rendered.length - 1; i >= 0; i--) {
286
- if (rendered[i]!.role === "user") return rendered[i]!.id;
287
- }
288
- return "start";
289
- });
290
- const isWorkingOn = (turnKey: string) =>
291
- props.isRunning && turnKey === latestTurnKey.value;
292
-
293
- // Work shows while the agent is on it and folds once the reply is done,
294
- // unless the user has opened or closed it themselves.
295
- const toggledTurns = ref<ReadonlyMap<string, boolean>>(new Map());
296
- const isWorkOpen = (turnKey: string) =>
297
- toggledTurns.value.get(turnKey) ?? isWorkingOn(turnKey);
298
-
299
- // How long the agent worked, for "Worked for 9s": the sum of its runs on the
300
- // reply, so waiting between them (say, for an approval) doesn't count. Only
301
- // known for replies this client watched start from the user's message; a
302
- // restored thread shows the tool count instead.
303
- const workTimes = new Map<
304
- string,
305
- { elapsedMs: number; workingSince?: number }
306
- >();
307
- const workTimesVersion = ref(0);
308
- watch(
309
- [
310
- () => props.toolCallDisplay,
311
- () => props.isRunning,
312
- latestTurnKey,
313
- () => lastRenderedMessage.value?.role,
314
- ],
315
- ([display, isRunning, turnKey, lastRole]) => {
316
- if (display !== "turn") return;
317
- const now = Date.now();
318
- if (isRunning) {
319
- const times = workTimes.get(turnKey);
320
- if (times) times.workingSince ??= now;
321
- else if (lastRole === "user")
322
- workTimes.set(turnKey, { elapsedMs: 0, workingSince: now });
323
- } else {
324
- for (const times of workTimes.values()) {
325
- if (times.workingSince === undefined) continue;
326
- times.elapsedMs += now - times.workingSince;
327
- times.workingSince = undefined;
328
- }
329
- }
330
- workTimesVersion.value++;
331
- },
332
- { immediate: true },
333
- );
334
-
335
- // Whether each working-phase message's work shows. Text that ends the reply
336
- // stays out even when its message also calls a tool: it's the answer.
337
- const workOpenState = computed(() => {
338
- const open = new Map<string, boolean>();
339
- const textOpen = new Map<string, boolean>();
340
- for (const turn of turnWork.value?.values() ?? []) {
341
- const turnOpen = isWorkOpen(turn.key);
342
- for (const id of turn.workMessageIds) {
343
- open.set(id, turnOpen);
344
- if (id !== turn.replyTextMessageId) textOpen.set(id, turnOpen);
345
- }
346
- }
347
- return { workOpen: open, workTextOpen: textOpen };
348
- });
268
+ const latestTurnKey = computed(() => viewState.value.latestTurnKey);
349
269
 
350
270
  provide(
351
271
  ToolCallDisplayContextKey,
352
- computed<ToolCallDisplayContextValue>(() => ({
272
+ computed<ɵToolCallDisplayContextValue>(() => ({
353
273
  display: props.toolCallDisplay,
354
274
  isRunning: props.isRunning,
355
- layouts: toolCallLayouts.value,
356
- workOpen: workOpenState.value.workOpen,
357
- workTextOpen: workOpenState.value.workTextOpen,
275
+ layouts: viewState.value.layouts,
276
+ workOpen: viewState.value.workOpen,
277
+ workTextOpen: viewState.value.workTextOpen,
358
278
  })),
359
279
  );
360
280
 
@@ -363,10 +283,10 @@ const WorkSummaryRow: FunctionalComponent<{
363
283
  turnKey: string;
364
284
  calls: ToolCallEntry[];
365
285
  }> = ({ turnKey, calls }) => {
366
- void workTimesVersion.value;
367
- const isWorking = isWorkingOn(turnKey);
368
- const isOpen = isWorkOpen(turnKey);
369
- const times = workTimes.get(turnKey);
286
+ void viewState.value;
287
+ const isWorking = viewModel.isTurnWorking(turnKey);
288
+ const isOpen = viewModel.isTurnOpen(turnKey);
289
+ const times = viewModel.getWorkTime(turnKey);
370
290
  const summaryProps: CopilotChatWorkSummarySlotProps = {
371
291
  isWorking,
372
292
  isOpen,
@@ -374,7 +294,7 @@ const WorkSummaryRow: FunctionalComponent<{
374
294
  elapsedMs: times?.elapsedMs,
375
295
  workingSince: times?.workingSince,
376
296
  onClick: () => {
377
- toggledTurns.value = new Map(toggledTurns.value).set(turnKey, !isOpen);
297
+ viewModel.toggleTurn(turnKey);
378
298
  },
379
299
  };
380
300
  const slot = componentSlots["work-summary"];
@@ -411,103 +331,33 @@ watch(
411
331
  (messages) => commitRowKeyStore(rowKeyStore, messages),
412
332
  { flush: "post" },
413
333
  );
414
- const lastMessage = computed(() => props.messages[props.messages.length - 1]);
415
- // In the "turn" display the "Working" line at the top of the reply is the
416
- // progress indicator; before the reply's first message it sits where the
417
- // cursor would.
418
- const showCursor = computed(
419
- () =>
420
- props.isRunning &&
421
- lastMessage.value?.role !== "reasoning" &&
422
- props.toolCallDisplay !== "turn",
423
- );
424
- const pendingWorkSummary = computed(
425
- () =>
426
- props.toolCallDisplay === "turn" &&
427
- props.isRunning &&
428
- lastRenderedMessage.value?.role === "user",
429
- );
334
+ const showCursor = computed(() => viewState.value.showCursor);
335
+ const pendingWorkSummary = computed(() => viewState.value.pendingWorkSummary);
430
336
 
431
337
  watch(
432
338
  [() => props.messages.length, () => deduplicatedMessages.value.length],
433
339
  ([messageCount, deduplicatedCount]) => {
434
- if (
435
- process.env.NODE_ENV === "development" &&
436
- deduplicatedCount < messageCount
437
- ) {
438
- console.warn(
439
- `CopilotChatMessageView: Deduplicated ${messageCount - deduplicatedCount} message(s) with duplicate IDs.`,
440
- );
441
- }
340
+ if (process.env.NODE_ENV !== "development") return;
341
+ const warning = ɵduplicateMessagesWarning(messageCount, deduplicatedCount);
342
+ if (warning) console.warn(warning);
442
343
  },
443
344
  { immediate: true },
444
345
  );
445
346
 
446
- function getMeta(
447
- message: Message,
448
- ): Omit<MessageMetaProps, "position" | "message"> {
449
- stateTick.value += 0;
450
- const agentId = resolvedAgentId.value;
451
- const threadId = config.value?.threadId ?? "";
452
- const core = copilotkit.value;
453
-
454
- const resolvedRunId =
455
- core.getRunIdForMessage(agentId, threadId, message.id) ??
456
- core.getRunIdsForThread(agentId, threadId).slice(-1)[0];
457
- const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
458
-
459
- const agent = resolvedThreadAgent.value ?? core.getAgent(agentId);
460
-
461
- const messageIdsInRun =
462
- resolvedRunId && agent
463
- ? agent.messages
464
- .filter(
465
- (msg) =>
466
- core.getRunIdForMessage(agentId, threadId, msg.id) ===
467
- resolvedRunId,
468
- )
469
- .map((msg) => msg.id)
470
- : [message.id];
471
-
472
- const rawMessageIndex = agent
473
- ? agent.messages.findIndex((msg) => msg.id === message.id)
474
- : -1;
475
- const messageIndex = rawMessageIndex >= 0 ? rawMessageIndex : 0;
476
- const messageIndexInRun = resolvedRunId
477
- ? Math.max(messageIdsInRun.indexOf(message.id), 0)
478
- : 0;
479
- const numberOfMessagesInRun = resolvedRunId ? messageIdsInRun.length : 1;
480
-
481
- // `getStateByRun` deep-clones the whole run state, so resolve it only when
482
- // a consumer reads `stateSnapshot`, and at most once per meta object.
483
- let stateSnapshot: unknown;
484
- let stateSnapshotResolved = false;
485
-
486
- return {
487
- runId,
488
- messageIndex,
489
- messageIndexInRun,
490
- numberOfMessagesInRun,
491
- agentId,
492
- get stateSnapshot() {
493
- if (!stateSnapshotResolved) {
494
- stateSnapshotResolved = true;
495
- stateSnapshot = resolvedRunId
496
- ? core.getStateByRun(agentId, threadId, resolvedRunId)
497
- : undefined;
498
- }
499
- return stateSnapshot;
500
- },
501
- };
502
- }
503
-
504
- // `Object.assign` onto the meta object keeps the lazy `stateSnapshot` getter.
505
- // A spread would call it.
347
+ // Core builds the props with a lazy `stateSnapshot` getter, so slots that
348
+ // never read it do not clone the run state.
506
349
  function getMessageSlotProps(
507
350
  message: Message,
508
351
  position: MessageMetaProps["position"],
509
352
  ): MessageMetaProps {
510
- return Object.assign(getMeta(message), { message, position });
353
+ stateTick.value += 0;
354
+ return ɵgetCustomMessageRenderProps(copilotkit.value, {
355
+ agentId: resolvedAgentId.value,
356
+ threadId: config.value?.threadId ?? "",
357
+ agent: resolvedThreadAgent.value,
358
+ message,
359
+ position,
360
+ });
511
361
  }
512
362
 
513
363
  // Calls a `#message-before` / `#message-after` slot with the meta object
@@ -534,21 +384,12 @@ function resolveCustomMessageRenderer(
534
384
  return null;
535
385
  }
536
386
 
537
- const agentId = resolvedAgentId.value;
538
- const renderers = [...copilotkit.value.renderCustomMessages]
539
- .filter(
540
- (renderer) =>
541
- renderer.agentId === undefined || renderer.agentId === agentId,
542
- )
543
- .sort((a, b) => {
544
- const aHasAgent = a.agentId !== undefined;
545
- const bHasAgent = b.agentId !== undefined;
546
- if (aHasAgent === bHasAgent) return 0;
547
- return aHasAgent ? -1 : 1;
548
- });
549
-
550
- const selected = renderers[0];
551
- if (!selected?.render) {
387
+ // Try each renderer in order and use the first that has something to draw.
388
+ const selected = ɵresolveCustomMessageRenderers(
389
+ copilotkit.value.renderCustomMessages,
390
+ resolvedAgentId.value,
391
+ ).find((renderer) => renderer.render);
392
+ if (!selected) {
552
393
  return null;
553
394
  }
554
395
 
@@ -563,45 +404,26 @@ function resolveActivityRenderer(
563
404
  ): { renderer: Component; props: ActivitySlotProps } | null {
564
405
  stateTick.value += 0;
565
406
 
566
- const agentId = resolvedAgentId.value;
567
- const renderer = [...copilotkit.value.renderActivityMessages]
568
- .filter(
569
- (entry) =>
570
- entry.activityType === message.activityType &&
571
- (entry.agentId === undefined || entry.agentId === agentId),
572
- )
573
- .sort((a, b) => {
574
- const aScoped = a.agentId !== undefined;
575
- const bScoped = b.agentId !== undefined;
576
- if (aScoped === bScoped) return 0;
577
- return aScoped ? -1 : 1;
578
- })[0];
579
-
580
- if (!renderer) return null;
581
- const parsed = renderer.content.safeParse(message.content);
582
- if (!parsed.success) return null;
407
+ const match = ɵresolveActivityRenderer(
408
+ copilotkit.value.renderActivityMessages,
409
+ {
410
+ activityType: message.activityType,
411
+ agentId: resolvedAgentId.value,
412
+ content: message.content,
413
+ },
414
+ );
415
+ if (!match) return null;
583
416
 
584
417
  return {
585
- renderer: renderer.render as Component,
418
+ renderer: match.renderer.render as Component,
586
419
  props: {
587
420
  activityType: message.activityType,
588
- content: parsed.data,
421
+ content: match.content,
589
422
  message,
590
423
  agent: resolvedThreadAgent.value,
591
424
  },
592
425
  };
593
426
  }
594
-
595
- function resolveToolMessage(
596
- message: Message,
597
- toolCallId: string,
598
- ): ToolMessage | undefined {
599
- return props.messages.find(
600
- (candidate) =>
601
- candidate.role === "tool" &&
602
- (candidate as ToolMessage).toolCallId === toolCallId,
603
- ) as ToolMessage | undefined;
604
- }
605
427
  </script>
606
428
 
607
429
  <template>
@@ -675,7 +497,7 @@ function resolveToolMessage(
675
497
  v-else-if="message.role === 'reasoning'"
676
498
  :open="
677
499
  toolCallDisplay === 'turn'
678
- ? (workOpenState.workOpen.get(message.id) ?? true)
500
+ ? (viewState.workOpen.get(message.id) ?? true)
679
501
  : undefined
680
502
  "
681
503
  >
@@ -1,10 +1,13 @@
1
1
  <script setup lang="ts">
2
- import { computed, onBeforeUnmount, ref, watch } from "vue";
2
+ import { computed, onBeforeUnmount, shallowRef, watch } from "vue";
3
3
  import type { Message, ReasoningMessage } from "@ag-ui/core";
4
4
  import { IconChevronRight } from "../icons";
5
5
  import StreamingMarkdownDefault from "./StreamingMarkdownDefault.vue";
6
- import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
7
- import { CopilotChatDefaultLabels } from "../../providers/types";
6
+ import {
7
+ ɵgetReasoningHeaderLabel,
8
+ ɵReasoningDisclosure,
9
+ } from "@copilotkit/core";
10
+ import { useChatLabels } from "./use-chat-labels";
8
11
 
9
12
  const props = withDefaults(
10
13
  defineProps<{
@@ -69,15 +72,6 @@ defineSlots<{
69
72
  }) => unknown;
70
73
  }>();
71
74
 
72
- function formatDuration(seconds: number): string {
73
- if (seconds < 1) return "a few seconds";
74
- if (seconds < 60) return `${Math.round(seconds)} seconds`;
75
- const mins = Math.floor(seconds / 60);
76
- const secs = Math.round(seconds % 60);
77
- if (secs === 0) return `${mins} minute${mins > 1 ? "s" : ""}`;
78
- return `${mins}m ${secs}s`;
79
- }
80
-
81
75
  const normalizedContent = computed(() =>
82
76
  typeof props.message.content === "string" ? props.message.content : "",
83
77
  );
@@ -87,65 +81,36 @@ const isLatest = computed(
87
81
  );
88
82
  const isStreaming = computed(() => !!(props.isRunning && isLatest.value));
89
83
 
90
- const elapsed = ref(0);
91
- const isOpen = ref(isStreaming.value);
92
- const userToggledDuringStreaming = ref(false);
93
- let startTimeMs: number | null = null;
94
- let elapsedInterval: ReturnType<typeof setInterval> | null = null;
95
-
96
- function clearElapsedInterval() {
97
- if (elapsedInterval) {
98
- clearInterval(elapsedInterval);
99
- elapsedInterval = null;
100
- }
101
- }
102
-
103
- function updateElapsedNow() {
104
- if (startTimeMs !== null) {
105
- elapsed.value = (Date.now() - startTimeMs) / 1000;
106
- }
107
- }
108
-
109
- watch(
110
- isStreaming,
111
- (nextIsStreaming) => {
112
- if (nextIsStreaming) {
113
- if (startTimeMs === null) {
114
- startTimeMs = Date.now();
115
- }
116
- clearElapsedInterval();
117
- elapsedInterval = setInterval(updateElapsedNow, 1000);
118
- userToggledDuringStreaming.value = false;
119
- isOpen.value = true;
120
- return;
121
- }
122
-
123
- clearElapsedInterval();
124
- updateElapsedNow();
125
- if (!userToggledDuringStreaming.value) {
126
- isOpen.value = false;
127
- }
128
- },
129
- { immediate: true },
130
- );
131
-
84
+ // Open while streaming, auto-collapse when it ends unless the user toggled,
85
+ // and the elapsed time: see core's ɵReasoningDisclosure.
86
+ const disclosure = new ɵReasoningDisclosure({ isStreaming: isStreaming.value });
87
+ const disclosureState = shallowRef(disclosure.getSnapshot());
88
+ const unsubscribe = disclosure.subscribe(() => {
89
+ disclosureState.value = disclosure.getSnapshot();
90
+ });
91
+ watch(isStreaming, (next) => disclosure.setStreaming(next), {
92
+ immediate: true,
93
+ });
132
94
  onBeforeUnmount(() => {
133
- clearElapsedInterval();
95
+ unsubscribe();
96
+ disclosure.dispose();
134
97
  });
135
98
 
136
- const config = useCopilotChatConfiguration();
99
+ const elapsed = computed(() => disclosureState.value.elapsedSeconds);
100
+ const isOpen = computed(() => disclosureState.value.isOpen);
101
+
102
+ const labels = useChatLabels();
137
103
  /** `labels.reasoningMessageThinkingLabel` while streaming, then "Thought for …". */
138
104
  const label = computed(() =>
139
- isStreaming.value
140
- ? (config.value?.labels ?? CopilotChatDefaultLabels)
141
- .reasoningMessageThinkingLabel
142
- : `Thought for ${formatDuration(elapsed.value)}`,
105
+ ɵgetReasoningHeaderLabel(
106
+ { isStreaming: isStreaming.value, elapsedSeconds: elapsed.value },
107
+ labels.value,
108
+ ),
143
109
  );
144
110
 
145
111
  function toggleOpen() {
146
112
  if (!hasContent.value) return;
147
- userToggledDuringStreaming.value = true;
148
- isOpen.value = !isOpen.value;
113
+ disclosure.toggle();
149
114
  }
150
115
  </script>
151
116