@copilotkit/vue 1.57.1

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 (437) hide show
  1. package/AGENTS.md +50 -0
  2. package/CHANGELOG.md +13 -0
  3. package/PARITY.md +434 -0
  4. package/README.md +396 -0
  5. package/dist/components/copilot-provider/CopilotKit.vue.d.ts +20 -0
  6. package/dist/components/copilot-provider/CopilotKit.vue.d.ts.map +1 -0
  7. package/dist/components/copilot-provider/index.d.ts +3 -0
  8. package/dist/components/copilot-provider/index.d.ts.map +1 -0
  9. package/dist/components/copilot-provider/types.d.ts +22 -0
  10. package/dist/components/copilot-provider/types.d.ts.map +1 -0
  11. package/dist/hooks/index.d.ts +7 -0
  12. package/dist/hooks/index.d.ts.map +1 -0
  13. package/dist/hooks/use-copilot-action.d.ts +27 -0
  14. package/dist/hooks/use-copilot-action.d.ts.map +1 -0
  15. package/dist/hooks/use-copilot-readable.d.ts +20 -0
  16. package/dist/hooks/use-copilot-readable.d.ts.map +1 -0
  17. package/dist/hooks/use-frontend-tool.d.ts +21 -0
  18. package/dist/hooks/use-frontend-tool.d.ts.map +1 -0
  19. package/dist/index.cjs +2 -0
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.d.cts +10 -0
  22. package/dist/index.d.mts +10 -0
  23. package/dist/index.d.ts +10 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.mjs +252 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/styles.css +2 -0
  28. package/dist/use-render-activity-message-BRL1Rpl-.cjs +85 -0
  29. package/dist/use-render-activity-message-BRL1Rpl-.cjs.map +1 -0
  30. package/dist/use-render-activity-message-CqtxiFSs.js +8927 -0
  31. package/dist/use-render-activity-message-CqtxiFSs.js.map +1 -0
  32. package/dist/v2/components/A2UIMessageRenderer.d.ts +9 -0
  33. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -0
  34. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +16 -0
  35. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -0
  36. package/dist/v2/components/CopilotKitInspector.vue.d.ts +7 -0
  37. package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -0
  38. package/dist/v2/components/InlineFeatureWarning.vue.d.ts +6 -0
  39. package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -0
  40. package/dist/v2/components/LicenseWarningBanner.vue.d.ts +18 -0
  41. package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -0
  42. package/dist/v2/components/MCPAppsActivityRenderer.d.ts +88 -0
  43. package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -0
  44. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +154 -0
  45. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -0
  46. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +19 -0
  47. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -0
  48. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +16 -0
  49. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -0
  50. package/dist/v2/components/a2ui/VueSurface.d.ts +62 -0
  51. package/dist/v2/components/a2ui/VueSurface.d.ts.map +1 -0
  52. package/dist/v2/components/a2ui/adapter.d.ts +38 -0
  53. package/dist/v2/components/a2ui/adapter.d.ts.map +1 -0
  54. package/dist/v2/components/a2ui/catalog.d.ts +29 -0
  55. package/dist/v2/components/a2ui/catalog.d.ts.map +1 -0
  56. package/dist/v2/components/a2ui/index.d.ts +5 -0
  57. package/dist/v2/components/a2ui/index.d.ts.map +1 -0
  58. package/dist/v2/components/a2ui/utils.d.ts +18 -0
  59. package/dist/v2/components/a2ui/utils.d.ts.map +1 -0
  60. package/dist/v2/components/a2ui.d.ts +12 -0
  61. package/dist/v2/components/a2ui.d.ts.map +1 -0
  62. package/dist/v2/components/chat/CopilotChat.vue.d.ts +50 -0
  63. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -0
  64. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts +164 -0
  65. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -0
  66. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts +12 -0
  67. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -0
  68. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts +7 -0
  69. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -0
  70. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +12 -0
  71. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -0
  72. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +290 -0
  73. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -0
  74. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +72 -0
  75. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -0
  76. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts +65 -0
  77. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -0
  78. package/dist/v2/components/chat/CopilotChatSuggestionPill.vue.d.ts +27 -0
  79. package/dist/v2/components/chat/CopilotChatSuggestionPill.vue.d.ts.map +1 -0
  80. package/dist/v2/components/chat/CopilotChatSuggestionView.vue.d.ts +26 -0
  81. package/dist/v2/components/chat/CopilotChatSuggestionView.vue.d.ts.map +1 -0
  82. package/dist/v2/components/chat/CopilotChatToggleButton.vue.d.ts +17 -0
  83. package/dist/v2/components/chat/CopilotChatToggleButton.vue.d.ts.map +1 -0
  84. package/dist/v2/components/chat/CopilotChatToggleButtonCloseIcon.d.ts +5 -0
  85. package/dist/v2/components/chat/CopilotChatToggleButtonCloseIcon.d.ts.map +1 -0
  86. package/dist/v2/components/chat/CopilotChatToggleButtonOpenIcon.d.ts +5 -0
  87. package/dist/v2/components/chat/CopilotChatToggleButtonOpenIcon.d.ts.map +1 -0
  88. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +21 -0
  89. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -0
  90. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts +34 -0
  91. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -0
  92. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +106 -0
  93. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -0
  94. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts +15 -0
  95. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -0
  96. package/dist/v2/components/chat/CopilotModalHeaderCloseButton.d.ts +5 -0
  97. package/dist/v2/components/chat/CopilotModalHeaderCloseButton.d.ts.map +1 -0
  98. package/dist/v2/components/chat/CopilotModalHeaderTitle.d.ts +5 -0
  99. package/dist/v2/components/chat/CopilotModalHeaderTitle.d.ts.map +1 -0
  100. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +50 -0
  101. package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -0
  102. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +55 -0
  103. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -0
  104. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +55 -0
  105. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -0
  106. package/dist/v2/components/chat/CopilotPopupWelcomeScreen.vue.d.ts +28 -0
  107. package/dist/v2/components/chat/CopilotPopupWelcomeScreen.vue.d.ts.map +1 -0
  108. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +48 -0
  109. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -0
  110. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +62 -0
  111. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -0
  112. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +53 -0
  113. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -0
  114. package/dist/v2/components/chat/CopilotSidebarWelcomeScreen.vue.d.ts +28 -0
  115. package/dist/v2/components/chat/CopilotSidebarWelcomeScreen.vue.d.ts.map +1 -0
  116. package/dist/v2/components/chat/audioRecorder.d.ts +11 -0
  117. package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -0
  118. package/dist/v2/components/chat/index.d.ts +682 -0
  119. package/dist/v2/components/chat/index.d.ts.map +1 -0
  120. package/dist/v2/components/chat/last-user-message-context.d.ts +29 -0
  121. package/dist/v2/components/chat/last-user-message-context.d.ts.map +1 -0
  122. package/dist/v2/components/chat/normalize-auto-scroll.d.ts +3 -0
  123. package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +1 -0
  124. package/dist/v2/components/chat/types.d.ts +380 -0
  125. package/dist/v2/components/chat/types.d.ts.map +1 -0
  126. package/dist/v2/components/icons/index.d.ts +2 -0
  127. package/dist/v2/components/icons/index.d.ts.map +1 -0
  128. package/dist/v2/components/index.d.ts +8 -0
  129. package/dist/v2/components/index.d.ts.map +1 -0
  130. package/dist/v2/hooks/index.d.ts +24 -0
  131. package/dist/v2/hooks/index.d.ts.map +1 -0
  132. package/dist/v2/hooks/use-agent-context.d.ts +24 -0
  133. package/dist/v2/hooks/use-agent-context.d.ts.map +1 -0
  134. package/dist/v2/hooks/use-agent.d.ts +53 -0
  135. package/dist/v2/hooks/use-agent.d.ts.map +1 -0
  136. package/dist/v2/hooks/use-attachments.d.ts +21 -0
  137. package/dist/v2/hooks/use-attachments.d.ts.map +1 -0
  138. package/dist/v2/hooks/use-capabilities.d.ts +16 -0
  139. package/dist/v2/hooks/use-capabilities.d.ts.map +1 -0
  140. package/dist/v2/hooks/use-component.d.ts +13 -0
  141. package/dist/v2/hooks/use-component.d.ts.map +1 -0
  142. package/dist/v2/hooks/use-configure-suggestions.d.ts +24 -0
  143. package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -0
  144. package/dist/v2/hooks/use-default-render-tool.d.ts +14 -0
  145. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -0
  146. package/dist/v2/hooks/use-frontend-tool.d.ts +19 -0
  147. package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -0
  148. package/dist/v2/hooks/use-human-in-the-loop.d.ts +19 -0
  149. package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -0
  150. package/dist/v2/hooks/use-interrupt.d.ts +36 -0
  151. package/dist/v2/hooks/use-interrupt.d.ts.map +1 -0
  152. package/dist/v2/hooks/use-katex-styles.d.ts +22 -0
  153. package/dist/v2/hooks/use-katex-styles.d.ts.map +1 -0
  154. package/dist/v2/hooks/use-keyboard-height.d.ts +33 -0
  155. package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -0
  156. package/dist/v2/hooks/use-pin-to-send.d.ts +28 -0
  157. package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -0
  158. package/dist/v2/hooks/use-render-activity-message.d.ts +21 -0
  159. package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -0
  160. package/dist/v2/hooks/use-render-custom-messages.d.ts +27 -0
  161. package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -0
  162. package/dist/v2/hooks/use-render-tool.d.ts +36 -0
  163. package/dist/v2/hooks/use-render-tool.d.ts.map +1 -0
  164. package/dist/v2/hooks/use-suggestions.d.ts +26 -0
  165. package/dist/v2/hooks/use-suggestions.d.ts.map +1 -0
  166. package/dist/v2/hooks/use-threads.d.ts +42 -0
  167. package/dist/v2/hooks/use-threads.d.ts.map +1 -0
  168. package/dist/v2/index.cjs +2 -0
  169. package/dist/v2/index.cjs.map +1 -0
  170. package/dist/v2/index.d.cts +9 -0
  171. package/dist/v2/index.d.mts +9 -0
  172. package/dist/v2/index.d.ts +9 -0
  173. package/dist/v2/index.d.ts.map +1 -0
  174. package/dist/v2/index.mjs +75 -0
  175. package/dist/v2/index.mjs.map +1 -0
  176. package/dist/v2/lib/processPartialHtml.d.ts +3 -0
  177. package/dist/v2/lib/processPartialHtml.d.ts.map +1 -0
  178. package/dist/v2/lib/shallow-stable.d.ts +7 -0
  179. package/dist/v2/lib/shallow-stable.d.ts.map +1 -0
  180. package/dist/v2/lib/transcription-client.d.ts +19 -0
  181. package/dist/v2/lib/transcription-client.d.ts.map +1 -0
  182. package/dist/v2/lib/vue-core.d.ts +47 -0
  183. package/dist/v2/lib/vue-core.d.ts.map +1 -0
  184. package/dist/v2/providers/CopilotChatConfigurationProvider.types.d.ts +15 -0
  185. package/dist/v2/providers/CopilotChatConfigurationProvider.types.d.ts.map +1 -0
  186. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts +17 -0
  187. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -0
  188. package/dist/v2/providers/CopilotKitProvider.types.d.ts +61 -0
  189. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -0
  190. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +37 -0
  191. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -0
  192. package/dist/v2/providers/SandboxFunctionsContext.d.ts +4 -0
  193. package/dist/v2/providers/SandboxFunctionsContext.d.ts.map +1 -0
  194. package/dist/v2/providers/index.d.ts +13 -0
  195. package/dist/v2/providers/index.d.ts.map +1 -0
  196. package/dist/v2/providers/keys.d.ts +17 -0
  197. package/dist/v2/providers/keys.d.ts.map +1 -0
  198. package/dist/v2/providers/license-context.d.ts +7 -0
  199. package/dist/v2/providers/license-context.d.ts.map +1 -0
  200. package/dist/v2/providers/types.d.ts +38 -0
  201. package/dist/v2/providers/types.d.ts.map +1 -0
  202. package/dist/v2/providers/useCopilotChatConfiguration.d.ts +4 -0
  203. package/dist/v2/providers/useCopilotChatConfiguration.d.ts.map +1 -0
  204. package/dist/v2/providers/useCopilotKit.d.ts +2 -0
  205. package/dist/v2/providers/useCopilotKit.d.ts.map +1 -0
  206. package/dist/v2/providers/useLicenseContext.d.ts +14 -0
  207. package/dist/v2/providers/useLicenseContext.d.ts.map +1 -0
  208. package/dist/v2/types/a2ui.d.ts +5 -0
  209. package/dist/v2/types/a2ui.d.ts.map +1 -0
  210. package/dist/v2/types/defineToolCallRenderer.d.ts +15 -0
  211. package/dist/v2/types/defineToolCallRenderer.d.ts.map +1 -0
  212. package/dist/v2/types/frontend-tool.d.ts +6 -0
  213. package/dist/v2/types/frontend-tool.d.ts.map +1 -0
  214. package/dist/v2/types/human-in-the-loop.d.ts +29 -0
  215. package/dist/v2/types/human-in-the-loop.d.ts.map +1 -0
  216. package/dist/v2/types/index.d.ts +10 -0
  217. package/dist/v2/types/index.d.ts.map +1 -0
  218. package/dist/v2/types/interrupt.d.ts +14 -0
  219. package/dist/v2/types/interrupt.d.ts.map +1 -0
  220. package/dist/v2/types/sandbox-function.d.ts +8 -0
  221. package/dist/v2/types/sandbox-function.d.ts.map +1 -0
  222. package/dist/v2/types/vue-activity-message-renderer.d.ts +18 -0
  223. package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -0
  224. package/dist/v2/types/vue-custom-message-renderer.d.ts +19 -0
  225. package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -0
  226. package/dist/v2/types/vue-tool-call-renderer.d.ts +37 -0
  227. package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -0
  228. package/env.d.ts +7 -0
  229. package/eslint.config.mjs +42 -0
  230. package/package.json +130 -0
  231. package/scripts/scope-preflight.mjs +100 -0
  232. package/src/components/copilot-provider/CopilotKit.vue +18 -0
  233. package/src/components/copilot-provider/index.ts +2 -0
  234. package/src/components/copilot-provider/types.ts +24 -0
  235. package/src/hooks/index.ts +9 -0
  236. package/src/hooks/use-copilot-action.ts +168 -0
  237. package/src/hooks/use-copilot-readable.ts +75 -0
  238. package/src/hooks/use-frontend-tool.ts +76 -0
  239. package/src/index.ts +12 -0
  240. package/src/styles/globals.css +314 -0
  241. package/src/v2/__tests__/exports.test.ts +35 -0
  242. package/src/v2/__tests__/mocks/web-inspector.ts +5 -0
  243. package/src/v2/__tests__/setup.ts +141 -0
  244. package/src/v2/__tests__/utils/agents.ts +391 -0
  245. package/src/v2/__tests__/utils/mount.ts +83 -0
  246. package/src/v2/__tests__/utils/test-helpers.ts +712 -0
  247. package/src/v2/components/A2UIMessageRenderer.ts +125 -0
  248. package/src/v2/components/A2UISurfaceActivityRenderer.vue +186 -0
  249. package/src/v2/components/CopilotKitInspector.vue +42 -0
  250. package/src/v2/components/InlineFeatureWarning.vue +35 -0
  251. package/src/v2/components/LicenseWarningBanner.vue +196 -0
  252. package/src/v2/components/MCPAppsActivityRenderer.ts +778 -0
  253. package/src/v2/components/OpenGenerativeUIRenderer.ts +550 -0
  254. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +271 -0
  255. package/src/v2/components/__tests__/CopilotKitInspector.test.ts +57 -0
  256. package/src/v2/components/__tests__/MCPAppsActivityRenderer.e2e.test.ts +851 -0
  257. package/src/v2/components/__tests__/MCPAppsActivityRenderer.test.ts +237 -0
  258. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +516 -0
  259. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +295 -0
  260. package/src/v2/components/a2ui/A2UICatalogContext.ts +190 -0
  261. package/src/v2/components/a2ui/VueSurface.ts +144 -0
  262. package/src/v2/components/a2ui/adapter.ts +156 -0
  263. package/src/v2/components/a2ui/catalog.ts +858 -0
  264. package/src/v2/components/a2ui/index.ts +7 -0
  265. package/src/v2/components/a2ui/utils.ts +67 -0
  266. package/src/v2/components/a2ui.ts +30 -0
  267. package/src/v2/components/chat/CopilotChat.vue +777 -0
  268. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +891 -0
  269. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +411 -0
  270. package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +87 -0
  271. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +269 -0
  272. package/src/v2/components/chat/CopilotChatInput.vue +1271 -0
  273. package/src/v2/components/chat/CopilotChatMessageView.vue +476 -0
  274. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +247 -0
  275. package/src/v2/components/chat/CopilotChatSuggestionPill.vue +56 -0
  276. package/src/v2/components/chat/CopilotChatSuggestionView.vue +93 -0
  277. package/src/v2/components/chat/CopilotChatToggleButton.vue +145 -0
  278. package/src/v2/components/chat/CopilotChatToggleButtonCloseIcon.ts +17 -0
  279. package/src/v2/components/chat/CopilotChatToggleButtonOpenIcon.ts +18 -0
  280. package/src/v2/components/chat/CopilotChatToolCallsView.vue +161 -0
  281. package/src/v2/components/chat/CopilotChatUserMessage.vue +322 -0
  282. package/src/v2/components/chat/CopilotChatView.vue +740 -0
  283. package/src/v2/components/chat/CopilotModalHeader.vue +73 -0
  284. package/src/v2/components/chat/CopilotModalHeaderCloseButton.ts +38 -0
  285. package/src/v2/components/chat/CopilotModalHeaderTitle.ts +22 -0
  286. package/src/v2/components/chat/CopilotPopup.vue +182 -0
  287. package/src/v2/components/chat/CopilotPopupView.vue +168 -0
  288. package/src/v2/components/chat/CopilotPopupViewInternal.vue +453 -0
  289. package/src/v2/components/chat/CopilotPopupWelcomeScreen.vue +140 -0
  290. package/src/v2/components/chat/CopilotSidebar.vue +178 -0
  291. package/src/v2/components/chat/CopilotSidebarView.vue +172 -0
  292. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +366 -0
  293. package/src/v2/components/chat/CopilotSidebarWelcomeScreen.vue +142 -0
  294. package/src/v2/components/chat/__tests__/CopilotChat.attachments.test.ts +237 -0
  295. package/src/v2/components/chat/__tests__/CopilotChat.e2e.test.ts +1240 -0
  296. package/src/v2/components/chat/__tests__/CopilotChat.licenseWarning.test.ts +138 -0
  297. package/src/v2/components/chat/__tests__/CopilotChat.onError.test.ts +85 -0
  298. package/src/v2/components/chat/__tests__/CopilotChat.slots.e2e.test.ts +141 -0
  299. package/src/v2/components/chat/__tests__/CopilotChat.test.ts +652 -0
  300. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +683 -0
  301. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.slots.e2e.test.ts +768 -0
  302. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.ts +1108 -0
  303. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.thumbs.test.ts +87 -0
  304. package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +277 -0
  305. package/src/v2/components/chat/__tests__/CopilotChatAttachmentRenderer.test.ts +124 -0
  306. package/src/v2/components/chat/__tests__/CopilotChatCopyButton.clipboard.test.ts +230 -0
  307. package/src/v2/components/chat/__tests__/CopilotChatInput.bottomAnchored.test.ts +83 -0
  308. package/src/v2/components/chat/__tests__/CopilotChatInput.slots.e2e.test.ts +1139 -0
  309. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +1051 -0
  310. package/src/v2/components/chat/__tests__/CopilotChatMessageView.slots.e2e.test.ts +141 -0
  311. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +494 -0
  312. package/src/v2/components/chat/__tests__/CopilotChatPropsRerender.e2e.test.ts +181 -0
  313. package/src/v2/components/chat/__tests__/CopilotChatReasoningMessage.test.ts +73 -0
  314. package/src/v2/components/chat/__tests__/CopilotChatSuggestionPill.test.ts +73 -0
  315. package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.slots.e2e.test.ts +674 -0
  316. package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.test.ts +91 -0
  317. package/src/v2/components/chat/__tests__/CopilotChatToggleButton.test.ts +93 -0
  318. package/src/v2/components/chat/__tests__/CopilotChatToolCallsView.test.ts +382 -0
  319. package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.ts +1019 -0
  320. package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.ts +516 -0
  321. package/src/v2/components/chat/__tests__/CopilotChatUserMessage.slots.e2e.test.ts +701 -0
  322. package/src/v2/components/chat/__tests__/CopilotChatUserMessage.test.ts +337 -0
  323. package/src/v2/components/chat/__tests__/CopilotChatView.connectingGate.test.ts +135 -0
  324. package/src/v2/components/chat/__tests__/CopilotChatView.inputOverlay.test.ts +278 -0
  325. package/src/v2/components/chat/__tests__/CopilotChatView.onClick.e2e.test.ts +1082 -0
  326. package/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.ts +166 -0
  327. package/src/v2/components/chat/__tests__/CopilotChatView.slots.e2e.test.ts +1145 -0
  328. package/src/v2/components/chat/__tests__/CopilotChatView.test.ts +374 -0
  329. package/src/v2/components/chat/__tests__/CopilotModalHeader.slots.e2e.test.ts +636 -0
  330. package/src/v2/components/chat/__tests__/CopilotModalHeader.test.ts +112 -0
  331. package/src/v2/components/chat/__tests__/CopilotPopup.test.ts +58 -0
  332. package/src/v2/components/chat/__tests__/CopilotPopupView.slots.e2e.test.ts +725 -0
  333. package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +112 -0
  334. package/src/v2/components/chat/__tests__/CopilotSidebar.test.ts +58 -0
  335. package/src/v2/components/chat/__tests__/CopilotSidebarView.slots.e2e.test.ts +603 -0
  336. package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +214 -0
  337. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.ts +394 -0
  338. package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.ts +82 -0
  339. package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +39 -0
  340. package/src/v2/components/chat/audioRecorder.ts +15 -0
  341. package/src/v2/components/chat/index.ts +52 -0
  342. package/src/v2/components/chat/last-user-message-context.ts +39 -0
  343. package/src/v2/components/chat/normalize-auto-scroll.ts +17 -0
  344. package/src/v2/components/chat/types.ts +481 -0
  345. package/src/v2/components/icons/__tests__/icons.test.ts +86 -0
  346. package/src/v2/components/icons/index.ts +22 -0
  347. package/src/v2/components/index.ts +7 -0
  348. package/src/v2/hooks/__tests__/standard-schema-types.test.ts +149 -0
  349. package/src/v2/hooks/__tests__/standard-schema.test.ts +315 -0
  350. package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.ts +144 -0
  351. package/src/v2/hooks/__tests__/use-agent-context.test.ts +271 -0
  352. package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +64 -0
  353. package/src/v2/hooks/__tests__/use-agent-stability.test.ts +268 -0
  354. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.ts +433 -0
  355. package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +747 -0
  356. package/src/v2/hooks/__tests__/use-agent.e2e.test.ts +187 -0
  357. package/src/v2/hooks/__tests__/use-agent.test.ts +126 -0
  358. package/src/v2/hooks/__tests__/use-attachments.test.ts +181 -0
  359. package/src/v2/hooks/__tests__/use-component.test.ts +145 -0
  360. package/src/v2/hooks/__tests__/use-configure-suggestions.e2e.test.ts +527 -0
  361. package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +399 -0
  362. package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +214 -0
  363. package/src/v2/hooks/__tests__/use-frontend-tool-available.test.ts +220 -0
  364. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +2320 -0
  365. package/src/v2/hooks/__tests__/use-frontend-tool.test.ts +648 -0
  366. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +1379 -0
  367. package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +282 -0
  368. package/src/v2/hooks/__tests__/use-interrupt.test.ts +345 -0
  369. package/src/v2/hooks/__tests__/use-katex-styles.test.ts +69 -0
  370. package/src/v2/hooks/__tests__/use-keyboard-height.test.ts +199 -0
  371. package/src/v2/hooks/__tests__/use-pin-to-send.test.ts +363 -0
  372. package/src/v2/hooks/__tests__/use-render-tool.test.ts +329 -0
  373. package/src/v2/hooks/__tests__/use-suggestions.e2e.test.ts +397 -0
  374. package/src/v2/hooks/__tests__/use-suggestions.test.ts +198 -0
  375. package/src/v2/hooks/__tests__/use-threads.test.ts +1041 -0
  376. package/src/v2/hooks/__tests__/zod-regression.test.ts +339 -0
  377. package/src/v2/hooks/index.ts +29 -0
  378. package/src/v2/hooks/use-agent-context.ts +55 -0
  379. package/src/v2/hooks/use-agent.ts +345 -0
  380. package/src/v2/hooks/use-attachments.ts +261 -0
  381. package/src/v2/hooks/use-capabilities.ts +30 -0
  382. package/src/v2/hooks/use-component.ts +46 -0
  383. package/src/v2/hooks/use-configure-suggestions.ts +252 -0
  384. package/src/v2/hooks/use-default-render-tool.ts +130 -0
  385. package/src/v2/hooks/use-frontend-tool.ts +68 -0
  386. package/src/v2/hooks/use-human-in-the-loop.ts +90 -0
  387. package/src/v2/hooks/use-interrupt.ts +257 -0
  388. package/src/v2/hooks/use-katex-styles.ts +44 -0
  389. package/src/v2/hooks/use-keyboard-height.ts +87 -0
  390. package/src/v2/hooks/use-pin-to-send.ts +160 -0
  391. package/src/v2/hooks/use-render-activity-message.ts +92 -0
  392. package/src/v2/hooks/use-render-custom-messages.ts +129 -0
  393. package/src/v2/hooks/use-render-tool.ts +128 -0
  394. package/src/v2/hooks/use-suggestions.ts +98 -0
  395. package/src/v2/hooks/use-threads.ts +208 -0
  396. package/src/v2/index.ts +11 -0
  397. package/src/v2/lib/__tests__/processPartialHtml.test.ts +84 -0
  398. package/src/v2/lib/__tests__/transcription-client.test.ts +65 -0
  399. package/src/v2/lib/processPartialHtml.ts +21 -0
  400. package/src/v2/lib/shallow-stable.ts +54 -0
  401. package/src/v2/lib/transcription-client.ts +151 -0
  402. package/src/v2/lib/vue-core.ts +161 -0
  403. package/src/v2/providers/CopilotChatConfigurationProvider.types.ts +15 -0
  404. package/src/v2/providers/CopilotChatConfigurationProvider.vue +95 -0
  405. package/src/v2/providers/CopilotKitProvider.types.ts +66 -0
  406. package/src/v2/providers/CopilotKitProvider.vue +653 -0
  407. package/src/v2/providers/SandboxFunctionsContext.ts +11 -0
  408. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +309 -0
  409. package/src/v2/providers/__tests__/CopilotKitProvider.debug.test.ts +295 -0
  410. package/src/v2/providers/__tests__/CopilotKitProvider.license.test.ts +110 -0
  411. package/src/v2/providers/__tests__/CopilotKitProvider.onError.test.ts +67 -0
  412. package/src/v2/providers/__tests__/CopilotKitProvider.renderCustomMessages.e2e.test.ts +901 -0
  413. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +141 -0
  414. package/src/v2/providers/__tests__/CopilotKitProvider.stability.test.ts +871 -0
  415. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +603 -0
  416. package/src/v2/providers/__tests__/CopilotKitProvider.wildcard.test.ts +104 -0
  417. package/src/v2/providers/index.ts +21 -0
  418. package/src/v2/providers/keys.ts +25 -0
  419. package/src/v2/providers/license-context.ts +16 -0
  420. package/src/v2/providers/types.ts +40 -0
  421. package/src/v2/providers/useCopilotChatConfiguration.ts +11 -0
  422. package/src/v2/providers/useCopilotKit.ts +11 -0
  423. package/src/v2/providers/useLicenseContext.ts +21 -0
  424. package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +157 -0
  425. package/src/v2/types/a2ui.ts +5 -0
  426. package/src/v2/types/defineToolCallRenderer.ts +32 -0
  427. package/src/v2/types/frontend-tool.ts +8 -0
  428. package/src/v2/types/human-in-the-loop.ts +38 -0
  429. package/src/v2/types/index.ts +9 -0
  430. package/src/v2/types/interrupt.ts +15 -0
  431. package/src/v2/types/sandbox-function.ts +8 -0
  432. package/src/v2/types/vue-activity-message-renderer.ts +22 -0
  433. package/src/v2/types/vue-custom-message-renderer.ts +24 -0
  434. package/src/v2/types/vue-tool-call-renderer.ts +44 -0
  435. package/tsconfig.json +27 -0
  436. package/vite.config.ts +49 -0
  437. package/vitest.config.ts +23 -0
@@ -0,0 +1,257 @@
1
+ import { computed, onScopeDispose, shallowRef, watch } from "vue";
2
+ import type { ComputedRef, Ref } from "vue";
3
+ import { useCopilotKit } from "../providers/useCopilotKit";
4
+ import { useAgent } from "./use-agent";
5
+ import type {
6
+ InterruptEvent,
7
+ InterruptHandlerProps,
8
+ InterruptRenderProps,
9
+ } from "../types/interrupt";
10
+
11
+ export type { InterruptEvent, InterruptHandlerProps, InterruptRenderProps };
12
+
13
+ const INTERRUPT_EVENT_NAME = "on_interrupt";
14
+
15
+ type InterruptHandlerFn<TValue, TResult> = (
16
+ props: InterruptHandlerProps<TValue>,
17
+ ) => TResult | PromiseLike<TResult>;
18
+
19
+ type InterruptResultFromHandler<THandler> = THandler extends (
20
+ ...args: never[]
21
+ ) => infer TResult
22
+ ? TResult extends PromiseLike<infer TResolved>
23
+ ? TResolved | null
24
+ : TResult | null
25
+ : null;
26
+
27
+ type InterruptResult<TValue, TResult> = InterruptResultFromHandler<
28
+ InterruptHandlerFn<TValue, TResult>
29
+ >;
30
+
31
+ export interface UseInterruptConfig<TValue = unknown, TResult = never> {
32
+ handler?: InterruptHandlerFn<TValue, TResult>;
33
+ enabled?: (event: InterruptEvent<TValue>) => boolean;
34
+ agentId?: string;
35
+ renderInChat?: boolean;
36
+ }
37
+
38
+ export interface UseInterruptResult<TValue = unknown, TResult = never> {
39
+ interrupt: Ref<InterruptEvent<TValue> | null>;
40
+ result: Ref<InterruptResult<TValue, TResult>>;
41
+ hasInterrupt: ComputedRef<boolean>;
42
+ resolveInterrupt: (response: unknown) => void;
43
+ slotProps: ComputedRef<InterruptRenderProps<
44
+ TValue,
45
+ InterruptResult<TValue, TResult>
46
+ > | null>;
47
+ }
48
+
49
+ export function isPromiseLike<TValue>(
50
+ value: TValue | PromiseLike<TValue>,
51
+ ): value is PromiseLike<TValue> {
52
+ return (
53
+ (typeof value === "object" || typeof value === "function") &&
54
+ value !== null &&
55
+ typeof Reflect.get(value, "then") === "function"
56
+ );
57
+ }
58
+
59
+ function normalizeAsyncResult<TValue>(
60
+ value: PromiseLike<TValue>,
61
+ ): Promise<TValue> {
62
+ if (value instanceof Promise) {
63
+ return value;
64
+ }
65
+
66
+ return new Promise<TValue>((resolve, reject) => {
67
+ try {
68
+ value.then(resolve, reject);
69
+ } catch (error) {
70
+ reject(error);
71
+ }
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Vue composable for handling `on_interrupt` custom events from an agent.
77
+ *
78
+ * It tracks the latest pending interrupt, optionally derives UI data via
79
+ * `handler`, and can publish slot state into `CopilotChat` so consumers render
80
+ * interrupts through the `#interrupt` slot instead of render functions/TSX.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const { interrupt, hasInterrupt, resolveInterrupt } = useInterrupt({
85
+ * handler: ({ event }) => ({ label: String(event.value) }),
86
+ * });
87
+ * ```
88
+ */
89
+ export function useInterrupt<TValue = unknown, TResult = never>(
90
+ config: UseInterruptConfig<TValue, TResult> = {},
91
+ ): UseInterruptResult<TValue, TResult> {
92
+ const { copilotkit } = useCopilotKit();
93
+ const { agent } = useAgent({ agentId: config.agentId });
94
+ const interrupt = shallowRef<InterruptEvent<TValue> | null>(null);
95
+ const result = shallowRef<InterruptResult<TValue, TResult>>(null);
96
+
97
+ watch(
98
+ agent,
99
+ (resolvedAgent, _previousAgent, onCleanup) => {
100
+ if (!resolvedAgent) {
101
+ interrupt.value = null;
102
+ result.value = null;
103
+ return;
104
+ }
105
+
106
+ let localInterrupt: InterruptEvent<TValue> | null = null;
107
+ const subscription = resolvedAgent.subscribe({
108
+ onCustomEvent: ({ event }) => {
109
+ if (event.name === INTERRUPT_EVENT_NAME) {
110
+ localInterrupt = {
111
+ name: event.name,
112
+ value: event.value as TValue,
113
+ };
114
+ }
115
+ },
116
+ onRunStartedEvent: () => {
117
+ localInterrupt = null;
118
+ interrupt.value = null;
119
+ },
120
+ onRunFinalized: () => {
121
+ if (localInterrupt) {
122
+ interrupt.value = localInterrupt;
123
+ localInterrupt = null;
124
+ }
125
+ },
126
+ onRunFailed: () => {
127
+ localInterrupt = null;
128
+ },
129
+ });
130
+
131
+ onCleanup(() => subscription.unsubscribe());
132
+ },
133
+ { immediate: true },
134
+ );
135
+
136
+ const resolveInterrupt = (response: unknown) => {
137
+ const resolvedAgent = agent.value;
138
+ if (!resolvedAgent) return;
139
+
140
+ const interruptEventValue = interrupt.value?.value;
141
+ interrupt.value = null;
142
+ void copilotkit.value.runAgent({
143
+ agent: resolvedAgent,
144
+ forwardedProps: {
145
+ command: {
146
+ resume: response,
147
+ interruptEvent: interruptEventValue,
148
+ },
149
+ },
150
+ }).catch((error) => {
151
+ console.error("[CopilotKit] useInterrupt: failed to resume agent:", error);
152
+ });
153
+ };
154
+
155
+ watch(
156
+ interrupt,
157
+ (pendingEvent, _previous, onCleanup) => {
158
+ if (!pendingEvent) {
159
+ result.value = null;
160
+ return;
161
+ }
162
+ if (config.enabled && !config.enabled(pendingEvent)) {
163
+ result.value = null;
164
+ return;
165
+ }
166
+ const handler = config.handler;
167
+ if (!handler) {
168
+ result.value = null;
169
+ return;
170
+ }
171
+
172
+ let cancelled = false;
173
+ const maybePromise = handler({
174
+ event: pendingEvent,
175
+ resolve: resolveInterrupt,
176
+ });
177
+
178
+ if (isPromiseLike(maybePromise)) {
179
+ normalizeAsyncResult(maybePromise)
180
+ .then((resolved) => {
181
+ if (!cancelled) {
182
+ result.value = resolved;
183
+ }
184
+ })
185
+ .catch((err) => {
186
+ if (!cancelled) {
187
+ console.error("[CopilotKit] useInterrupt handler failed:", err);
188
+ result.value = null;
189
+ }
190
+ });
191
+ } else {
192
+ result.value = maybePromise;
193
+ }
194
+
195
+ onCleanup(() => {
196
+ cancelled = true;
197
+ });
198
+ },
199
+ { immediate: true },
200
+ );
201
+
202
+ const slotProps = computed<InterruptRenderProps<
203
+ TValue,
204
+ InterruptResult<TValue, TResult>
205
+ > | null>(() => {
206
+ if (!interrupt.value) return null;
207
+ if (config.enabled && !config.enabled(interrupt.value)) return null;
208
+
209
+ return {
210
+ event: interrupt.value,
211
+ result: result.value,
212
+ resolve: resolveInterrupt,
213
+ };
214
+ });
215
+
216
+ watch(
217
+ [() => copilotkit.value, slotProps, () => config.renderInChat !== false],
218
+ ([core, nextSlotProps, shouldRenderInChat], _previous, onCleanup) => {
219
+ if (!shouldRenderInChat) {
220
+ return;
221
+ }
222
+
223
+ core.setInterruptState(
224
+ nextSlotProps as InterruptRenderProps<any, any> | null,
225
+ );
226
+ const publishedState = nextSlotProps;
227
+
228
+ onCleanup(() => {
229
+ if (core.interruptState === publishedState) {
230
+ core.setInterruptState(null);
231
+ }
232
+ });
233
+ },
234
+ { immediate: true },
235
+ );
236
+
237
+ onScopeDispose(() => {
238
+ const core = copilotkit.value;
239
+ if (
240
+ config.renderInChat !== false &&
241
+ core.interruptState === slotProps.value
242
+ ) {
243
+ core.setInterruptState(null);
244
+ }
245
+ });
246
+
247
+ return {
248
+ interrupt: interrupt as Ref<InterruptEvent<TValue> | null>,
249
+ result: result as Ref<InterruptResult<TValue, TResult>>,
250
+ hasInterrupt: computed(() => slotProps.value !== null),
251
+ resolveInterrupt,
252
+ slotProps: slotProps as ComputedRef<InterruptRenderProps<
253
+ TValue,
254
+ InterruptResult<TValue, TResult>
255
+ > | null>,
256
+ };
257
+ }
@@ -0,0 +1,44 @@
1
+ import { onMounted } from "vue";
2
+
3
+ // Module-level singleton flag so the stylesheet is only injected once per
4
+ // module graph (matches the React singleton injection intent).
5
+ let injected = false;
6
+
7
+ /**
8
+ * Dynamically loads KaTeX CSS at runtime to avoid Next.js-style
9
+ * "Global CSS cannot be imported from within node_modules" build errors and
10
+ * to keep the CSS out of the static import graph.
11
+ *
12
+ * Uses a module-level singleton flag so the stylesheet is only loaded once,
13
+ * regardless of how many components call this composable.
14
+ *
15
+ * Mirrors the React `useKatexStyles` hook: returns `void`, never throws, and
16
+ * logs a warning with equivalent intent if the dynamic import fails.
17
+ *
18
+ * @example
19
+ * ```vue
20
+ * <script setup lang="ts">
21
+ * import { useKatexStyles } from "@copilotkit/vue";
22
+ *
23
+ * useKatexStyles();
24
+ * </script>
25
+ * ```
26
+ */
27
+ export function useKatexStyles(): void {
28
+ onMounted(() => {
29
+ if (injected || typeof document === "undefined") return;
30
+ injected = true;
31
+
32
+ // Dynamic import defers CSS loading to runtime, bypassing build-time
33
+ // static analysis that rejects global CSS from node_modules.
34
+ // The `@vite-ignore` + indirect specifier keeps TypeScript from trying
35
+ // to resolve a type declaration for the CSS module while still letting
36
+ // the bundler handle the actual side-effect import at runtime.
37
+ const katexStylesSpecifier = "katex/dist/katex.min.css";
38
+ void import(/* @vite-ignore */ katexStylesSpecifier).catch(() => {
39
+ console.warn(
40
+ "[CopilotKit] Failed to load katex styles — math content may render without formatting",
41
+ );
42
+ });
43
+ });
44
+ }
@@ -0,0 +1,87 @@
1
+ import { onBeforeUnmount, onMounted, readonly, ref, type Ref } from "vue";
2
+
3
+ /**
4
+ * Vue-idiomatic result of {@link useKeyboardHeight}. Fields mirror the React
5
+ * `KeyboardState` shape (`isKeyboardOpen`, `keyboardHeight`, `availableHeight`,
6
+ * `viewportHeight`) and are exposed as readonly refs so consumers can bind them
7
+ * reactively inside templates or computed values.
8
+ */
9
+ export interface KeyboardState {
10
+ isKeyboardOpen: Readonly<Ref<boolean>>;
11
+ keyboardHeight: Readonly<Ref<number>>;
12
+ availableHeight: Readonly<Ref<number>>;
13
+ viewportHeight: Readonly<Ref<number>>;
14
+ }
15
+
16
+ /**
17
+ * Composable to detect mobile keyboard appearance and calculate available
18
+ * viewport height. Uses the Visual Viewport API to track keyboard state on
19
+ * mobile devices.
20
+ *
21
+ * Mirrors the React `useKeyboardHeight` hook: returns `keyboardHeight` as the
22
+ * difference between `window.innerHeight` and `visualViewport.height`, clamped
23
+ * to `0`, and reports the keyboard as open when the diff exceeds `150` px.
24
+ *
25
+ * @example
26
+ * ```vue
27
+ * <script setup lang="ts">
28
+ * import { useKeyboardHeight } from "@copilotkit/vue";
29
+ *
30
+ * const { isKeyboardOpen, keyboardHeight } = useKeyboardHeight();
31
+ * </script>
32
+ * ```
33
+ */
34
+ export function useKeyboardHeight(): KeyboardState {
35
+ const initialHeight = typeof window !== "undefined" ? window.innerHeight : 0;
36
+ const isKeyboardOpen = ref(false);
37
+ const keyboardHeight = ref(0);
38
+ const availableHeight = ref(initialHeight);
39
+ const viewportHeight = ref(initialHeight);
40
+
41
+ const updateKeyboardState = () => {
42
+ if (typeof window === "undefined") return;
43
+ const visualViewport = window.visualViewport;
44
+ if (!visualViewport) return;
45
+
46
+ const layoutHeight = window.innerHeight;
47
+ const visualHeight = visualViewport.height;
48
+
49
+ // Keyboard height = layout viewport minus visual viewport, clamped to 0.
50
+ const nextKeyboardHeight = Math.max(0, layoutHeight - visualHeight);
51
+ // Only treat the keyboard as open past the 150px threshold, matching
52
+ // the React implementation's mobile heuristic.
53
+ const nextIsOpen = nextKeyboardHeight > 150;
54
+
55
+ keyboardHeight.value = nextKeyboardHeight;
56
+ isKeyboardOpen.value = nextIsOpen;
57
+ availableHeight.value = visualHeight;
58
+ viewportHeight.value = layoutHeight;
59
+ };
60
+
61
+ let visualViewport: VisualViewport | null = null;
62
+
63
+ onMounted(() => {
64
+ if (typeof window === "undefined") return;
65
+ visualViewport = window.visualViewport ?? null;
66
+ if (!visualViewport) return;
67
+
68
+ updateKeyboardState();
69
+
70
+ visualViewport.addEventListener("resize", updateKeyboardState);
71
+ visualViewport.addEventListener("scroll", updateKeyboardState);
72
+ });
73
+
74
+ onBeforeUnmount(() => {
75
+ if (!visualViewport) return;
76
+ visualViewport.removeEventListener("resize", updateKeyboardState);
77
+ visualViewport.removeEventListener("scroll", updateKeyboardState);
78
+ visualViewport = null;
79
+ });
80
+
81
+ return {
82
+ isKeyboardOpen: readonly(isKeyboardOpen),
83
+ keyboardHeight: readonly(keyboardHeight),
84
+ availableHeight: readonly(availableHeight),
85
+ viewportHeight: readonly(viewportHeight),
86
+ };
87
+ }
@@ -0,0 +1,160 @@
1
+ import { inject, watch, type Ref } from "vue";
2
+ import {
3
+ LastUserMessageKey,
4
+ createDefaultLastUserMessageRef,
5
+ } from "../components/chat/last-user-message-context";
6
+
7
+ export interface UsePinToSendOptions {
8
+ scrollRef: Ref<HTMLElement | null>;
9
+ contentRef: Ref<HTMLElement | null>;
10
+ spacerRef: Ref<HTMLElement | null>;
11
+ topOffset?: number;
12
+ }
13
+
14
+ /**
15
+ * Vue counterpart of React's `usePinToSend` (`packages/react-core/src/v2/hooks/use-pin-to-send.ts`).
16
+ *
17
+ * Anchors the chat scroll container so the most recent user message stays
18
+ * pinned near the top of the viewport while the assistant streams a
19
+ * response beneath it.
20
+ *
21
+ * Implementation parity with React:
22
+ * - Reads the latest user message via the `LastUserMessageContext`
23
+ * equivalent (`LastUserMessageKey` + `Ref<LastUserMessageState>`).
24
+ * - On each `sendNonce` increment, sizes the spacer to
25
+ * `viewportHeight - bubbleHeight - topOffset` and scrolls so the bubble
26
+ * sits `topOffset` from the viewport top (padding above the bubble is
27
+ * pushed off-screen).
28
+ * - Installs a shrink-only `ResizeObserver` on `contentRef` that collapses
29
+ * the spacer as the assistant response grows; never grows it back.
30
+ * - Cancels the scheduled `requestAnimationFrame` and disconnects the
31
+ * `ResizeObserver` on subsequent re-runs and on scope dispose.
32
+ */
33
+ export function usePinToSend({
34
+ scrollRef,
35
+ contentRef,
36
+ spacerRef,
37
+ topOffset = 16,
38
+ }: UsePinToSendOptions): void {
39
+ const lastUserMessage = inject(
40
+ LastUserMessageKey,
41
+ createDefaultLastUserMessageRef(),
42
+ true,
43
+ );
44
+
45
+ let lastNonce = -1;
46
+ let currentSpacerHeight = 0;
47
+ let raf: number | null = null;
48
+ let ro: ResizeObserver | null = null;
49
+
50
+ function teardown() {
51
+ if (raf !== null && typeof cancelAnimationFrame === "function") {
52
+ cancelAnimationFrame(raf);
53
+ }
54
+ raf = null;
55
+ ro?.disconnect();
56
+ ro = null;
57
+ }
58
+
59
+ watch(
60
+ [
61
+ () => lastUserMessage.value.id,
62
+ () => lastUserMessage.value.sendNonce,
63
+ scrollRef,
64
+ contentRef,
65
+ spacerRef,
66
+ () => topOffset,
67
+ ],
68
+ ([id, sendNonce, scrollEl, contentEl, spacerEl], _old, onCleanup) => {
69
+ // Always tear down the previous run's RAF / ResizeObserver before
70
+ // evaluating any of the early-exit guards below. Mirrors React
71
+ // `useEffect` cleanup semantics: the prior run's cleanup runs before
72
+ // the next callback executes regardless of why the deps changed.
73
+ // Without this, a reactive `autoScroll` mode change (e.g. switching
74
+ // away from `"pin-to-send"`) or a `ref` swap that doesn't bump
75
+ // `sendNonce` would leak the stale content-element observer because
76
+ // the nonce guard skips the body. Registering via `onCleanup` also
77
+ // covers watcher stop on scope dispose, so an explicit
78
+ // `onScopeDispose(teardown)` is no longer required.
79
+ onCleanup(teardown);
80
+
81
+ if (sendNonce === lastNonce) return;
82
+ lastNonce = sendNonce;
83
+
84
+ if (!id) return;
85
+ if (!scrollEl || !contentEl || !spacerEl) return;
86
+
87
+ const escaped =
88
+ typeof CSS !== "undefined" && typeof CSS.escape === "function"
89
+ ? CSS.escape(id)
90
+ : id.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
91
+ const targetEl = contentEl.querySelector<HTMLElement>(
92
+ `[data-message-id="${escaped}"]`,
93
+ );
94
+ if (!targetEl) return;
95
+
96
+ // The target message's element has a top padding (e.g. `pt-10`) that
97
+ // creates breathing room above the visible bubble. When we "anchor at
98
+ // the top", we mean anchor the *bubble*, not the element's padded box.
99
+ // So we scroll past the padding (it goes above the viewport, hiding
100
+ // whatever was above the element too — including the previous message's
101
+ // trailing copy button).
102
+ const viewportHeight = scrollEl.clientHeight;
103
+ const userMessageHeight = targetEl.getBoundingClientRect().height;
104
+ const paddingTop = parseFloat(getComputedStyle(targetEl).paddingTop) || 0;
105
+ const bubbleHeight = Math.max(0, userMessageHeight - paddingTop);
106
+ const spacerHeight = Math.max(
107
+ 0,
108
+ viewportHeight - bubbleHeight - topOffset,
109
+ );
110
+
111
+ spacerEl.style.height = `${spacerHeight}px`;
112
+ currentSpacerHeight = spacerHeight;
113
+
114
+ if (typeof requestAnimationFrame === "function") {
115
+ raf = requestAnimationFrame(() => {
116
+ // Scroll so the BUBBLE is `topOffset` from the viewport top — the
117
+ // padding above the bubble ends up scrolled off-screen.
118
+ const targetTop =
119
+ computeOffsetTop(targetEl, scrollEl) + paddingTop - topOffset;
120
+ scrollEl.scrollTo({
121
+ top: Math.max(0, targetTop),
122
+ behavior: "smooth",
123
+ });
124
+ });
125
+ }
126
+
127
+ // Shrink-only ResizeObserver: as the assistant response grows below the
128
+ // anchored user message, collapse the spacer by the same amount so total
129
+ // scrollable space below the bubble stays constant (and the bubble stays
130
+ // pinned). Never grow the spacer after initial sizing.
131
+ if (typeof ResizeObserver !== "undefined") {
132
+ ro = new ResizeObserver(() => {
133
+ if (!contentEl || !spacerEl || !scrollEl) return;
134
+ const contentHeight = contentEl.getBoundingClientRect().height;
135
+ const targetOffsetWithinContent = computeOffsetTop(
136
+ targetEl,
137
+ contentEl,
138
+ );
139
+ const consumedBelow =
140
+ contentHeight - targetOffsetWithinContent - userMessageHeight;
141
+ const remaining = Math.max(0, spacerHeight - consumedBelow);
142
+ if (remaining < currentSpacerHeight) {
143
+ spacerEl.style.height = `${remaining}px`;
144
+ currentSpacerHeight = remaining;
145
+ }
146
+ });
147
+ ro.observe(contentEl);
148
+ }
149
+ },
150
+ { immediate: true, flush: "post" },
151
+ );
152
+ }
153
+
154
+ // Compute the offset of el relative to stopAt, accounting for stopAt's current scrollTop.
155
+ // Uses getBoundingClientRect so it works regardless of CSS positioning (including position:static).
156
+ function computeOffsetTop(el: HTMLElement, stopAt: HTMLElement): number {
157
+ const elRect = el.getBoundingClientRect();
158
+ const stopRect = stopAt.getBoundingClientRect();
159
+ return elRect.top - stopRect.top + stopAt.scrollTop;
160
+ }
@@ -0,0 +1,92 @@
1
+ import { computed } from "vue";
2
+ import type { Component } from "vue";
3
+ import type { ActivityMessage } from "@ag-ui/core";
4
+ import type { AbstractAgent } from "@ag-ui/client";
5
+ import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
6
+ import { useCopilotKit } from "../providers/useCopilotKit";
7
+ import { useCopilotChatConfiguration } from "../providers/useCopilotChatConfiguration";
8
+ import type {
9
+ VueActivityMessageRenderer,
10
+ VueActivityMessageRendererProps,
11
+ } from "../types";
12
+
13
+ interface ActivityRendererResult {
14
+ renderer: Component<VueActivityMessageRendererProps<unknown>>;
15
+ props: VueActivityMessageRendererProps<unknown>;
16
+ }
17
+
18
+ /**
19
+ * Returns helpers for rendering activity messages.
20
+ *
21
+ * Matches the React `useRenderActivityMessage` API: `findRenderer` locates a
22
+ * registered renderer by activity type (preferring agent-scoped over global,
23
+ * with `"*"` as a wildcard fallback), and `renderActivityMessage` resolves the
24
+ * renderer and validates the content schema.
25
+ */
26
+ export function useRenderActivityMessage() {
27
+ const { copilotkit } = useCopilotKit();
28
+ const config = useCopilotChatConfiguration();
29
+ const agentId = computed(
30
+ () => config.value?.agentId ?? DEFAULT_AGENT_ID,
31
+ );
32
+
33
+ const renderers = computed(() => [...copilotkit.value.renderActivityMessages]);
34
+
35
+ function findRenderer(
36
+ activityType: string,
37
+ ): VueActivityMessageRenderer<unknown> | null {
38
+ const list = renderers.value;
39
+ if (!list.length) {
40
+ return null;
41
+ }
42
+
43
+ const matches = list.filter(
44
+ (renderer) => renderer.activityType === activityType,
45
+ );
46
+
47
+ return (
48
+ matches.find((candidate) => candidate.agentId === agentId.value) ??
49
+ matches.find((candidate) => candidate.agentId === undefined) ??
50
+ list.find((candidate) => candidate.activityType === "*") ??
51
+ null
52
+ );
53
+ }
54
+
55
+ function renderActivityMessage(
56
+ message: ActivityMessage,
57
+ ): ActivityRendererResult | null {
58
+ const renderer = findRenderer(message.activityType);
59
+
60
+ if (!renderer) {
61
+ return null;
62
+ }
63
+
64
+ const parseResult = renderer.content.safeParse(message.content);
65
+
66
+ if (!parseResult.success) {
67
+ console.warn(
68
+ `Failed to parse content for activity message ` +
69
+ `'${message.activityType}':`,
70
+ parseResult.error,
71
+ );
72
+ return null;
73
+ }
74
+
75
+ const agent: AbstractAgent | undefined =
76
+ copilotkit.value.getAgent(agentId.value);
77
+
78
+ return {
79
+ renderer: renderer.render as Component<
80
+ VueActivityMessageRendererProps<unknown>
81
+ >,
82
+ props: {
83
+ activityType: message.activityType,
84
+ content: parseResult.data,
85
+ message,
86
+ agent,
87
+ },
88
+ };
89
+ }
90
+
91
+ return { renderActivityMessage, findRenderer };
92
+ }