@copilotkit/vue 2.0.0-rc.1 → 2.0.0-rc.10

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 (317) hide show
  1. package/PARITY.md +13 -12
  2. package/README.md +1 -2
  3. package/dist/components/copilot-provider/CopilotKit.vue.d.ts +3 -1
  4. package/dist/components/copilot-provider/CopilotKit.vue.d.ts.map +1 -1
  5. package/dist/hooks/use-copilot-action.d.ts.map +1 -1
  6. package/dist/hooks/use-frontend-tool.d.ts +1 -1
  7. package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
  8. package/dist/hooks/zod-parameters.d.ts +14 -0
  9. package/dist/hooks/zod-parameters.d.ts.map +1 -0
  10. package/dist/index.cjs +1 -76
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.mjs +384 -14275
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/use-render-activity-message-CTR_ziWV.js +18097 -0
  15. package/dist/use-render-activity-message-CTR_ziWV.js.map +1 -0
  16. package/dist/use-render-activity-message-Dky9_GRG.cjs +92 -0
  17. package/dist/use-render-activity-message-Dky9_GRG.cjs.map +1 -0
  18. package/dist/v2/components/A2UIMessageRenderer.d.ts +7 -0
  19. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
  20. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
  21. package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
  22. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -45
  23. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
  24. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +11 -2
  25. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
  26. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +1 -1
  27. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
  28. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +144 -0
  29. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -0
  30. package/dist/v2/components/a2ui.d.ts +3 -7
  31. package/dist/v2/components/a2ui.d.ts.map +1 -1
  32. package/dist/v2/components/chat/CopilotChat.vue.d.ts +1 -0
  33. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  34. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts +3 -1
  35. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  36. package/dist/v2/components/chat/CopilotChatAssistantToolbarButton.vue.d.ts +16 -0
  37. package/dist/v2/components/chat/CopilotChatAssistantToolbarButton.vue.d.ts.map +1 -0
  38. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
  39. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
  40. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
  41. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +22 -0
  42. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -0
  43. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +21 -232
  44. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  45. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts +12 -0
  46. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -0
  47. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts +22 -0
  48. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -0
  49. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +20 -0
  50. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  51. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  52. package/dist/v2/components/chat/CopilotChatSuggestionPill.vue.d.ts.map +1 -1
  53. package/dist/v2/components/chat/CopilotChatSuggestionView.vue.d.ts.map +1 -1
  54. package/dist/v2/components/chat/CopilotChatToggleButton.vue.d.ts.map +1 -1
  55. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +32 -0
  56. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -0
  57. package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
  58. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +11 -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 +1 -0
  62. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
  63. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts +5 -0
  64. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -0
  65. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  66. package/dist/v2/components/chat/CopilotModalHeaderCloseButton.d.ts.map +1 -1
  67. package/dist/v2/components/chat/CopilotModalHeaderTitle.d.ts.map +1 -1
  68. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +1 -0
  69. package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
  70. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +1 -0
  71. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
  72. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +1 -0
  73. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
  74. package/dist/v2/components/chat/CopilotPopupWelcomeScreen.vue.d.ts.map +1 -1
  75. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +2 -0
  76. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
  77. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +2 -0
  78. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
  79. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +2 -0
  80. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
  81. package/dist/v2/components/chat/CopilotSidebarWelcomeScreen.vue.d.ts.map +1 -1
  82. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
  83. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +0 -1
  84. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
  85. package/dist/v2/components/chat/index.d.ts +17 -1
  86. package/dist/v2/components/chat/index.d.ts.map +1 -1
  87. package/dist/v2/components/chat/inspector-shortcuts.d.ts +12 -0
  88. package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -0
  89. package/dist/v2/components/chat/message-feedback.d.ts +89 -0
  90. package/dist/v2/components/chat/message-feedback.d.ts.map +1 -0
  91. package/dist/v2/components/chat/tool-call-capture.d.ts +39 -0
  92. package/dist/v2/components/chat/tool-call-capture.d.ts.map +1 -0
  93. package/dist/v2/components/chat/tool-call-display-context.d.ts +22 -0
  94. package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -0
  95. package/dist/v2/components/chat/tool-call-group-parts.d.ts +131 -0
  96. package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -0
  97. package/dist/v2/components/chat/turn-work.d.ts +33 -0
  98. package/dist/v2/components/chat/turn-work.d.ts.map +1 -0
  99. package/dist/v2/components/chat/types.d.ts +104 -5
  100. package/dist/v2/components/chat/types.d.ts.map +1 -1
  101. package/dist/v2/components/chat/use-chat-labels.d.ts +8 -0
  102. package/dist/v2/components/chat/use-chat-labels.d.ts.map +1 -0
  103. package/dist/v2/components/chat/use-lightbox.d.ts +18 -0
  104. package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -0
  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 +55 -0
  108. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -0
  109. package/dist/v2/components/ui/CopilotPopover.vue.d.ts +40 -0
  110. package/dist/v2/components/ui/CopilotPopover.vue.d.ts.map +1 -0
  111. package/dist/v2/components/ui/CopilotTooltip.vue.d.ts +37 -0
  112. package/dist/v2/components/ui/CopilotTooltip.vue.d.ts.map +1 -0
  113. package/dist/v2/components/ui/dropdown-menu.d.ts +14 -0
  114. package/dist/v2/components/ui/dropdown-menu.d.ts.map +1 -0
  115. package/dist/v2/components/ui/floating.d.ts +84 -0
  116. package/dist/v2/components/ui/floating.d.ts.map +1 -0
  117. package/dist/v2/components/ui/presence.d.ts +9 -0
  118. package/dist/v2/components/ui/presence.d.ts.map +1 -0
  119. package/dist/v2/components/ui/use-id.d.ts +9 -0
  120. package/dist/v2/components/ui/use-id.d.ts.map +1 -0
  121. package/dist/v2/hooks/use-default-render-tool.d.ts +6 -0
  122. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
  123. package/dist/v2/hooks/use-frontend-tool.d.ts +5 -0
  124. package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -1
  125. package/dist/v2/hooks/use-render-activity-message.d.ts +13 -9
  126. package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
  127. package/dist/v2/hooks/use-render-custom-messages.d.ts +5 -7
  128. package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
  129. package/dist/v2/hooks/use-render-tool.d.ts +4 -0
  130. package/dist/v2/hooks/use-render-tool.d.ts.map +1 -1
  131. package/dist/v2/index.cjs +1 -1
  132. package/dist/v2/index.d.cts +3 -0
  133. package/dist/v2/index.d.mts +3 -0
  134. package/dist/v2/index.d.ts +3 -0
  135. package/dist/v2/index.d.ts.map +1 -1
  136. package/dist/v2/index.mjs +197 -197
  137. package/dist/v2/index.mjs.map +1 -1
  138. package/dist/v2/lib/message-feedback.d.ts +33 -0
  139. package/dist/v2/lib/message-feedback.d.ts.map +1 -0
  140. package/dist/v2/lib/processPartialHtml.d.ts +1 -2
  141. package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
  142. package/dist/v2/lib/vue-core.d.ts +0 -1
  143. package/dist/v2/lib/vue-core.d.ts.map +1 -1
  144. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  145. package/dist/v2/providers/CopilotKitProvider.types.d.ts +56 -6
  146. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  147. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +6 -2
  148. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  149. package/dist/v2/providers/index.d.ts +1 -1
  150. package/dist/v2/providers/index.d.ts.map +1 -1
  151. package/dist/v2/providers/keys.d.ts +8 -0
  152. package/dist/v2/providers/keys.d.ts.map +1 -1
  153. package/dist/v2/providers/types.d.ts +3 -37
  154. package/dist/v2/providers/types.d.ts.map +1 -1
  155. package/dist/v2/styles/CopilotKitStyles.d.ts +18 -0
  156. package/dist/v2/styles/CopilotKitStyles.d.ts.map +1 -0
  157. package/dist/v2/types/defineToolCallRenderer.d.ts +2 -0
  158. package/dist/v2/types/defineToolCallRenderer.d.ts.map +1 -1
  159. package/dist/v2/types/human-in-the-loop.d.ts +8 -29
  160. package/dist/v2/types/human-in-the-loop.d.ts.map +1 -1
  161. package/dist/v2/types/interrupt.d.ts +1 -22
  162. package/dist/v2/types/interrupt.d.ts.map +1 -1
  163. package/dist/v2/types/vue-activity-message-renderer.d.ts +16 -15
  164. package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -1
  165. package/dist/v2/types/vue-custom-message-renderer.d.ts +7 -16
  166. package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -1
  167. package/dist/v2/types/vue-tool-call-renderer.d.ts +16 -28
  168. package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
  169. package/package.json +14 -27
  170. package/src/__tests__/build-entries.test.ts +27 -0
  171. package/src/components/copilot-provider/CopilotKit.vue +4 -1
  172. package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
  173. package/src/hooks/use-copilot-action.ts +2 -1
  174. package/src/hooks/use-frontend-tool.ts +3 -6
  175. package/src/hooks/zod-parameters.ts +162 -0
  176. package/src/v2/__tests__/exports.test.ts +4 -2
  177. package/src/v2/components/A2UIMessageRenderer.ts +56 -68
  178. package/src/v2/components/A2UISurfaceActivityRenderer.vue +11 -23
  179. package/src/v2/components/LicenseWarningBanner.vue +31 -15
  180. package/src/v2/components/OpenGenerativeUIRenderer.ts +51 -373
  181. package/src/v2/components/__tests__/A2UIBasicCatalogColors.test.ts +8 -9
  182. package/src/v2/components/__tests__/A2UICatalogContext.test.ts +1 -1
  183. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +63 -36
  184. package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +20 -0
  185. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +55 -6
  186. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +15 -258
  187. package/src/v2/components/a2ui/A2UICatalogContext.ts +10 -102
  188. package/src/v2/components/a2ui/A2UIRecoveryStates.ts +444 -0
  189. package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +175 -0
  190. package/src/v2/components/a2ui.ts +1 -1
  191. package/src/v2/components/chat/CopilotChat.vue +26 -40
  192. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +267 -67
  193. package/src/v2/components/chat/CopilotChatAssistantToolbarButton.vue +46 -0
  194. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +150 -173
  195. package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +77 -20
  196. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +2 -2
  197. package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +240 -0
  198. package/src/v2/components/chat/CopilotChatInput.vue +250 -191
  199. package/src/v2/components/chat/CopilotChatInspectorButton.vue +331 -0
  200. package/src/v2/components/chat/CopilotChatLightbox.vue +105 -0
  201. package/src/v2/components/chat/CopilotChatMessageView.vue +262 -87
  202. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +52 -35
  203. package/src/v2/components/chat/CopilotChatSuggestionPill.vue +5 -14
  204. package/src/v2/components/chat/CopilotChatSuggestionView.vue +1 -4
  205. package/src/v2/components/chat/CopilotChatToggleButton.vue +3 -9
  206. package/src/v2/components/chat/CopilotChatToggleButtonCloseIcon.ts +1 -1
  207. package/src/v2/components/chat/CopilotChatToggleButtonOpenIcon.ts +1 -1
  208. package/src/v2/components/chat/CopilotChatToolCallGroup.vue +353 -0
  209. package/src/v2/components/chat/CopilotChatToolCallItem.vue +24 -14
  210. package/src/v2/components/chat/CopilotChatToolCallsView.vue +194 -21
  211. package/src/v2/components/chat/CopilotChatUserMessage.vue +105 -42
  212. package/src/v2/components/chat/CopilotChatView.vue +37 -42
  213. package/src/v2/components/chat/CopilotChatWorkSummary.vue +111 -0
  214. package/src/v2/components/chat/CopilotModalHeader.vue +10 -8
  215. package/src/v2/components/chat/CopilotModalHeaderCloseButton.ts +7 -6
  216. package/src/v2/components/chat/CopilotModalHeaderTitle.ts +1 -4
  217. package/src/v2/components/chat/CopilotPopup.vue +3 -0
  218. package/src/v2/components/chat/CopilotPopupView.vue +1 -0
  219. package/src/v2/components/chat/CopilotPopupViewInternal.vue +9 -19
  220. package/src/v2/components/chat/CopilotPopupWelcomeScreen.vue +5 -8
  221. package/src/v2/components/chat/CopilotSidebar.vue +5 -0
  222. package/src/v2/components/chat/CopilotSidebarView.vue +2 -0
  223. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +24 -17
  224. package/src/v2/components/chat/CopilotSidebarWelcomeScreen.vue +7 -10
  225. package/src/v2/components/chat/StreamingMarkdownDefault.vue +3 -5
  226. package/src/v2/components/chat/__tests__/CopilotChat.labels.test.ts +19 -4
  227. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
  228. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.inspector.test.ts +269 -0
  229. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +760 -0
  230. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.slots.e2e.test.ts +3 -5
  231. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.ts +2 -2
  232. package/src/v2/components/chat/__tests__/CopilotChatInput.addMenu.test.ts +328 -0
  233. package/src/v2/components/chat/__tests__/CopilotChatInput.slots.e2e.test.ts +6 -3
  234. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +55 -14
  235. package/src/v2/components/chat/__tests__/CopilotChatLightbox.test.ts +160 -0
  236. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +247 -403
  237. package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +637 -0
  238. package/src/v2/components/chat/__tests__/CopilotChatSuggestionPill.test.ts +1 -1
  239. package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.slots.e2e.test.ts +3 -1
  240. package/src/v2/components/chat/__tests__/CopilotChatToolCallsView.learning.test.ts +75 -0
  241. package/src/v2/components/chat/__tests__/CopilotChatUserMessage.attachments.test.ts +143 -0
  242. package/src/v2/components/chat/__tests__/CopilotChatView.inputOverlay.test.ts +5 -4
  243. package/src/v2/components/chat/__tests__/CopilotChatView.rootWidth.test.ts +7 -33
  244. package/src/v2/components/chat/__tests__/CopilotModalHeader.slots.e2e.test.ts +1 -1
  245. package/src/v2/components/chat/__tests__/CopilotPopupView.slots.e2e.test.ts +3 -3
  246. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +126 -0
  247. package/src/v2/components/chat/__tests__/messageFeedbackDefaults.test.ts +33 -0
  248. package/src/v2/components/chat/__tests__/modalChatDisplayProps.test.ts +44 -0
  249. package/src/v2/components/chat/copilotChatToolCallItemRender.ts +3 -19
  250. package/src/v2/components/chat/index.ts +2 -1
  251. package/src/v2/components/chat/inspector-shortcuts.ts +34 -0
  252. package/src/v2/components/chat/message-feedback.ts +291 -0
  253. package/src/v2/components/chat/tool-call-capture.ts +55 -0
  254. package/src/v2/components/chat/tool-call-display-context.ts +28 -0
  255. package/src/v2/components/chat/tool-call-group-parts.ts +251 -0
  256. package/src/v2/components/chat/turn-work.ts +52 -0
  257. package/src/v2/components/chat/types.ts +114 -4
  258. package/src/v2/components/chat/use-chat-labels.ts +16 -0
  259. package/src/v2/components/chat/use-lightbox.ts +64 -0
  260. package/src/v2/components/icons/__tests__/icons.test.ts +72 -68
  261. package/src/v2/components/icons/index.ts +109 -23
  262. package/src/v2/components/ui/CopilotDropdownMenuContent.vue +465 -0
  263. package/src/v2/components/ui/CopilotPopover.vue +138 -0
  264. package/src/v2/components/ui/CopilotTooltip.vue +237 -0
  265. package/src/v2/components/ui/__tests__/CopilotTooltip.test.ts +168 -0
  266. package/src/v2/components/ui/dropdown-menu.ts +15 -0
  267. package/src/v2/components/ui/floating.ts +321 -0
  268. package/src/v2/components/ui/presence.ts +54 -0
  269. package/src/v2/components/ui/use-id.ts +16 -0
  270. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +62 -1
  271. package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +105 -0
  272. package/src/v2/hooks/__tests__/use-render-tool.test.ts +3 -6
  273. package/src/v2/hooks/__tests__/zod-regression.test.ts +5 -4
  274. package/src/v2/hooks/use-default-render-tool.ts +123 -62
  275. package/src/v2/hooks/use-frontend-tool.ts +10 -10
  276. package/src/v2/hooks/use-render-activity-message.ts +27 -48
  277. package/src/v2/hooks/use-render-custom-messages.ts +14 -35
  278. package/src/v2/hooks/use-render-tool.ts +8 -0
  279. package/src/v2/index.ts +3 -0
  280. package/src/v2/lib/__tests__/message-feedback.test.ts +152 -0
  281. package/src/v2/lib/message-feedback.ts +120 -0
  282. package/src/v2/lib/processPartialHtml.ts +6 -21
  283. package/src/v2/lib/vue-core.ts +3 -5
  284. package/src/v2/providers/CopilotChatConfigurationProvider.vue +29 -2
  285. package/src/v2/providers/CopilotKitProvider.types.ts +57 -5
  286. package/src/v2/providers/CopilotKitProvider.vue +177 -114
  287. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.openThread.test.ts +69 -0
  288. package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +1 -1
  289. package/src/v2/providers/__tests__/CopilotKitProvider.headersAtSendTime.test.ts +3 -3
  290. package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +536 -0
  291. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +17 -33
  292. package/src/v2/providers/index.ts +4 -1
  293. package/src/v2/providers/keys.ts +12 -0
  294. package/src/v2/providers/types.ts +3 -38
  295. package/src/v2/styles/CopilotKitStyles.ts +95 -0
  296. package/src/v2/styles/__tests__/CopilotKitStyles.client.test.ts +149 -0
  297. package/src/v2/styles/__tests__/CopilotKitStyles.ssr.test.ts +71 -0
  298. package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +28 -33
  299. package/src/v2/types/defineToolCallRenderer.ts +9 -4
  300. package/src/v2/types/human-in-the-loop.ts +8 -32
  301. package/src/v2/types/interrupt.ts +7 -31
  302. package/src/v2/types/vue-activity-message-renderer.ts +24 -15
  303. package/src/v2/types/vue-custom-message-renderer.ts +12 -16
  304. package/src/v2/types/vue-tool-call-renderer.ts +23 -31
  305. package/vite.config.ts +5 -5
  306. package/dist/styles.css +0 -2
  307. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts +0 -9
  308. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +0 -1
  309. package/dist/v2/lib/transcription-client.d.ts +0 -19
  310. package/dist/v2/lib/transcription-client.d.ts.map +0 -1
  311. package/scripts/scope-preflight.mjs +0 -100
  312. package/src/styles/globals.css +0 -233
  313. package/src/v2/components/chat/BasicMarkdown.vue +0 -158
  314. package/src/v2/components/chat/__tests__/BasicMarkdown.test.ts +0 -69
  315. package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
  316. package/src/v2/lib/__tests__/transcription-client.test.ts +0 -67
  317. package/src/v2/lib/transcription-client.ts +0 -151
@@ -7,8 +7,9 @@ import {
7
7
  } from "@copilotkit/shared";
8
8
  import type { Attachment } from "@copilotkit/shared";
9
9
  import type { CopilotChatAttachmentQueueProps } from "./types";
10
- import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
11
- import { CopilotChatDefaultLabels } from "../../providers/types";
10
+ import { IconPlay } from "../icons";
11
+ import CopilotChatLightbox from "./CopilotChatLightbox.vue";
12
+ import { useChatLabels } from "./use-chat-labels";
12
13
 
13
14
  const props = withDefaults(defineProps<CopilotChatAttachmentQueueProps>(), {
14
15
  attachments: () => [],
@@ -19,13 +20,21 @@ const emit = defineEmits<{
19
20
  "remove-attachment": [id: string];
20
21
  }>();
21
22
 
22
- const config = useCopilotChatConfiguration();
23
- const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
23
+ const labels = useChatLabels();
24
24
 
25
25
  const activeLightboxAttachment = ref<Attachment | null>(null);
26
26
  const documentBlobUrl = ref<string | null>(null);
27
27
 
28
- const isLightboxOpen = computed(() => activeLightboxAttachment.value !== null);
28
+ const lightboxLabel = computed(() => {
29
+ const attachment = activeLightboxAttachment.value;
30
+ if (!attachment) return undefined;
31
+ if (attachment.filename) return attachment.filename;
32
+ return attachment.type === "image"
33
+ ? labels.value.attachmentImageAltText
34
+ : attachment.type === "video"
35
+ ? "Video attachment"
36
+ : labels.value.attachmentDocumentLabel;
37
+ });
29
38
  const isPreviewableDocument = computed(() => {
30
39
  const attachment = activeLightboxAttachment.value;
31
40
  if (!attachment || attachment.type !== "document") return false;
@@ -78,20 +87,6 @@ watch(
78
87
  { immediate: true },
79
88
  );
80
89
 
81
- watch(isLightboxOpen, (open, _previous, onCleanup) => {
82
- if (!open || typeof document === "undefined") return;
83
-
84
- const handleKeydown = (event: KeyboardEvent) => {
85
- if (event.key === "Escape") {
86
- closeLightbox();
87
- }
88
- };
89
- document.addEventListener("keydown", handleKeydown);
90
- onCleanup(() => {
91
- document.removeEventListener("keydown", handleKeydown);
92
- });
93
- });
94
-
95
90
  onBeforeUnmount(() => {
96
91
  if (documentBlobUrl.value) {
97
92
  URL.revokeObjectURL(documentBlobUrl.value);
@@ -120,12 +115,12 @@ function closeLightbox() {
120
115
 
121
116
  function cardClassName(attachment: Attachment) {
122
117
  if (attachment.type === "image" || attachment.type === "video") {
123
- return "cpk:w-[72px] cpk:h-[72px]";
118
+ return "cpk-attachment-queue-item-media";
124
119
  }
125
120
  if (attachment.type === "audio") {
126
- return "cpk:min-w-[200px] cpk:max-w-[280px] cpk:flex-col cpk:p-1 cpk:pr-8";
121
+ return "cpk-attachment-queue-item-audio";
127
122
  }
128
- return "cpk:p-2 cpk:px-3 cpk:pr-8 cpk:max-w-[240px]";
123
+ return "cpk-attachment-queue-item-document";
129
124
  }
130
125
 
131
126
  function isPdf(mimeType: string | undefined): boolean {
@@ -160,92 +155,87 @@ function createBlobUrl(
160
155
  <template>
161
156
  <div
162
157
  v-if="props.attachments.length > 0"
163
- class="cpk:flex cpk:flex-wrap cpk:gap-2 cpk:p-2"
158
+ class="cpk-attachment-queue"
164
159
  :class="props.className"
165
160
  data-testid="copilot-chat-attachment-queue"
166
161
  >
167
162
  <div
168
163
  v-for="attachment in props.attachments"
169
164
  :key="attachment.id"
170
- class="cpk:relative cpk:inline-flex cpk:rounded-lg cpk:overflow-hidden cpk:border cpk:border-border"
165
+ class="cpk-attachment-queue-item"
171
166
  :class="cardClassName(attachment)"
172
167
  data-testid="copilot-chat-attachment-item"
173
168
  :data-card-type="attachment.type"
174
169
  >
175
170
  <div
176
171
  v-if="attachment.status === 'uploading'"
177
- class="cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:bg-black/40 cpk:z-10"
172
+ class="cpk-attachment-queue-uploading-overlay"
178
173
  data-testid="copilot-chat-attachment-uploading-overlay"
179
174
  >
180
- <div
181
- class="cpk:w-5 cpk:h-5 cpk:border-2 cpk:border-white cpk:border-t-transparent cpk:rounded-full cpk:animate-spin"
182
- />
175
+ <div class="cpk-attachment-queue-uploading-spinner" />
183
176
  </div>
184
177
 
185
178
  <template v-if="attachment.status === 'ready'">
186
179
  <button
187
180
  v-if="attachment.type === 'image'"
188
181
  type="button"
189
- class="cpk:w-full cpk:h-full cpk:border-none cpk:bg-transparent cpk:p-0 cpk:cursor-pointer"
182
+ class="cpk-attachment-queue-preview-button"
190
183
  data-testid="copilot-chat-attachment-image-button"
191
184
  @click="openLightbox(attachment)"
192
185
  >
193
186
  <img
194
187
  :src="getSourceUrl(attachment.source)"
195
188
  :alt="attachment.filename || 'Image attachment'"
196
- class="cpk:w-full cpk:h-full cpk:object-cover"
189
+ class="cpk-attachment-queue-image"
197
190
  data-testid="copilot-chat-attachment-image-thumbnail"
198
191
  />
199
192
  </button>
200
193
 
201
- <div
202
- v-else-if="attachment.type === 'video'"
203
- class="cpk:w-full cpk:h-full cpk:relative"
204
- >
205
- <img
206
- v-if="attachment.thumbnail"
207
- :src="attachment.thumbnail"
208
- :alt="attachment.filename || 'Video thumbnail'"
209
- class="cpk:w-full cpk:h-full cpk:object-cover"
210
- data-testid="copilot-chat-attachment-video-thumbnail"
211
- />
212
- <video
213
- v-else
214
- :src="getSourceUrl(attachment.source)"
215
- preload="metadata"
216
- muted
217
- class="cpk:w-full cpk:h-full cpk:object-cover"
218
- data-testid="copilot-chat-attachment-video-fallback"
219
- />
194
+ <template v-else-if="attachment.type === 'video'">
195
+ <div class="cpk-attachment-queue-video">
196
+ <img
197
+ v-if="attachment.thumbnail"
198
+ :src="attachment.thumbnail"
199
+ :alt="attachment.filename || 'Video thumbnail'"
200
+ class="cpk-attachment-queue-video-thumbnail"
201
+ data-testid="copilot-chat-attachment-video-thumbnail"
202
+ />
203
+ <video
204
+ v-else
205
+ :src="getSourceUrl(attachment.source)"
206
+ preload="metadata"
207
+ muted
208
+ class="cpk-attachment-queue-video-thumbnail"
209
+ data-testid="copilot-chat-attachment-video-fallback"
210
+ />
211
+ </div>
220
212
  <button
221
213
  type="button"
222
- class="cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:z-10 cpk:cursor-pointer cpk:bg-black/20 cpk:border-none cpk:p-0"
214
+ class="cpk-attachment-queue-video-play-button"
223
215
  :aria-label="labels.attachmentPlayVideoButtonLabel"
224
216
  data-testid="copilot-chat-attachment-video-play"
225
217
  @click="openLightbox(attachment)"
226
218
  >
227
- <div
228
- class="cpk:w-8 cpk:h-8 cpk:rounded-full cpk:bg-black/60 cpk:flex cpk:items-center cpk:justify-center cpk:text-white cpk:text-xs cpk:font-semibold"
229
- >
230
- ▶
219
+ <div class="cpk-attachment-queue-video-play-badge">
220
+ <IconPlay class="cpk-attachment-queue-video-play-icon" />
231
221
  </div>
232
222
  </button>
233
- </div>
223
+ </template>
234
224
 
235
225
  <div
236
226
  v-else-if="attachment.type === 'audio'"
237
- class="cpk:flex cpk:flex-col cpk:gap-1 cpk:w-full"
227
+ class="cpk-attachment-queue-audio"
238
228
  >
239
229
  <audio
240
230
  :src="getSourceUrl(attachment.source)"
241
231
  controls
242
232
  preload="metadata"
243
- class="cpk:w-full cpk:h-8"
233
+ class="cpk-attachment-queue-audio-player"
244
234
  data-testid="copilot-chat-attachment-audio-player"
245
235
  />
246
236
  <span
247
237
  v-if="attachment.filename"
248
- class="cpk:text-xs cpk:font-medium cpk:overflow-hidden cpk:text-ellipsis cpk:whitespace-nowrap"
238
+ class="cpk-attachment-queue-audio-filename"
249
239
  >
250
240
  {{ attachment.filename }}
251
241
  </span>
@@ -254,13 +244,12 @@ function createBlobUrl(
254
244
  <button
255
245
  v-else
256
246
  type="button"
257
- class="cpk:flex cpk:items-center cpk:gap-2 cpk:w-full cpk:border-none cpk:bg-transparent cpk:p-0 cpk:text-left"
258
- :class="
259
- isPdf(attachment.source.mimeType) ||
260
- isText(attachment.source.mimeType)
261
- ? 'cpk:cursor-pointer'
262
- : 'cpk:cursor-default'
263
- "
247
+ class="cpk-attachment-queue-preview-button cpk-attachment-queue-document"
248
+ :class="{
249
+ 'cpk-attachment-queue-document-previewable':
250
+ isPdf(attachment.source.mimeType) ||
251
+ isText(attachment.source.mimeType),
252
+ }"
264
253
  data-testid="copilot-chat-attachment-document-button"
265
254
  @click="
266
255
  (isPdf(attachment.source.mimeType) ||
@@ -268,21 +257,19 @@ function createBlobUrl(
268
257
  openLightbox(attachment)
269
258
  "
270
259
  >
271
- <div
272
- class="cpk:w-8 cpk:h-8 cpk:rounded-md cpk:bg-primary cpk:text-primary-foreground cpk:flex cpk:items-center cpk:justify-center cpk:text-[10px] cpk:font-semibold cpk:shrink-0"
273
- >
260
+ <div class="cpk-attachment-queue-document-icon">
274
261
  {{ getDocumentIcon(attachment.source.mimeType ?? "") }}
275
262
  </div>
276
- <div class="cpk:flex cpk:flex-col cpk:min-w-0">
263
+ <div class="cpk-attachment-queue-document-info">
277
264
  <span
278
- class="cpk:text-xs cpk:font-medium cpk:break-all cpk:leading-tight"
265
+ class="cpk-attachment-queue-document-name"
279
266
  data-testid="copilot-chat-attachment-document-filename"
280
267
  >
281
- {{ attachment.filename || "Document" }}
268
+ {{ attachment.filename || labels.attachmentDocumentLabel }}
282
269
  </span>
283
270
  <span
284
271
  v-if="attachment.size != null"
285
- class="cpk:text-[11px] cpk:text-muted-foreground"
272
+ class="cpk-attachment-queue-document-size"
286
273
  >
287
274
  {{ formatFileSize(attachment.size) }}
288
275
  </span>
@@ -292,13 +279,13 @@ function createBlobUrl(
292
279
 
293
280
  <div
294
281
  v-else
295
- class="cpk:w-full cpk:h-full cpk:bg-muted-foreground/20"
282
+ class="cpk-attachment-queue-placeholder"
296
283
  data-testid="copilot-chat-attachment-placeholder"
297
284
  />
298
285
 
299
286
  <button
300
287
  type="button"
301
- class="cpk:absolute cpk:bg-black/60 cpk:text-white cpk:border-none cpk:rounded-full cpk:w-5 cpk:h-5 cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer cpk:text-[10px] cpk:z-20 cpk:top-1 cpk:right-1"
288
+ class="cpk-attachment-queue-remove-button"
302
289
  :aria-label="labels.attachmentRemoveButtonLabel"
303
290
  @click="emit('remove-attachment', attachment.id)"
304
291
  >
@@ -307,110 +294,100 @@ function createBlobUrl(
307
294
  </div>
308
295
  </div>
309
296
 
310
- <Teleport to="body">
311
- <div
312
- v-if="activeLightboxAttachment"
313
- class="cpk:fixed cpk:inset-0 cpk:z-[9999] cpk:flex cpk:items-center cpk:justify-center cpk:bg-black/80"
314
- data-testid="copilot-chat-attachment-lightbox"
315
- @click="closeLightbox"
316
- >
317
- <button
318
- type="button"
319
- class="cpk:absolute cpk:top-4 cpk:right-4 cpk:text-white cpk:bg-white/10 cpk:hover:bg-white/20 cpk:rounded-full cpk:w-10 cpk:h-10 cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer cpk:border-none"
320
- :aria-label="labels.attachmentPreviewCloseButtonLabel"
321
- @click.stop="closeLightbox"
322
- >
323
- ✕
324
- </button>
297
+ <CopilotChatLightbox
298
+ v-if="activeLightboxAttachment"
299
+ :label="lightboxLabel"
300
+ @close="closeLightbox"
301
+ >
302
+ <img
303
+ v-if="activeLightboxAttachment.type === 'image'"
304
+ :src="getSourceUrl(activeLightboxAttachment.source)"
305
+ :alt="activeLightboxAttachment.filename || 'Image attachment'"
306
+ class="cpk-attachment-queue-lightbox-image"
307
+ data-testid="copilot-chat-attachment-lightbox-image"
308
+ />
325
309
 
326
- <div data-testid="copilot-chat-attachment-lightbox-content" @click.stop>
327
- <img
328
- v-if="activeLightboxAttachment.type === 'image'"
329
- :src="getSourceUrl(activeLightboxAttachment.source)"
330
- :alt="activeLightboxAttachment.filename || 'Image attachment'"
331
- class="cpk:max-w-[90vw] cpk:max-h-[90vh] cpk:object-contain cpk:rounded-lg"
332
- data-testid="copilot-chat-attachment-lightbox-image"
333
- />
310
+ <video
311
+ v-else-if="activeLightboxAttachment.type === 'video'"
312
+ :src="getSourceUrl(activeLightboxAttachment.source)"
313
+ controls
314
+ autoplay
315
+ class="cpk-attachment-queue-lightbox-video"
316
+ data-testid="copilot-chat-attachment-lightbox-video"
317
+ />
334
318
 
335
- <video
336
- v-else-if="activeLightboxAttachment.type === 'video'"
337
- :src="getSourceUrl(activeLightboxAttachment.source)"
338
- controls
339
- autoplay
340
- class="cpk:max-w-[90vw] cpk:max-h-[90vh] cpk:rounded-lg"
341
- data-testid="copilot-chat-attachment-lightbox-video"
342
- />
319
+ <template v-else-if="activeLightboxAttachment.type === 'document'">
320
+ <iframe
321
+ v-if="
322
+ isPreviewableDocument &&
323
+ isPdf(activeLightboxAttachment.source.mimeType) &&
324
+ lightboxDocumentSource
325
+ "
326
+ :src="lightboxDocumentSource"
327
+ :title="activeLightboxAttachment.filename || 'PDF preview'"
328
+ class="cpk-attachment-queue-pdf-preview"
329
+ data-testid="copilot-chat-attachment-lightbox-document-iframe"
330
+ />
343
331
 
344
- <template v-else-if="activeLightboxAttachment.type === 'document'">
345
- <iframe
346
- v-if="
347
- isPreviewableDocument &&
348
- isPdf(activeLightboxAttachment.source.mimeType) &&
349
- lightboxDocumentSource
350
- "
351
- :src="lightboxDocumentSource"
352
- :title="activeLightboxAttachment.filename || 'PDF preview'"
353
- class="cpk:w-[90vw] cpk:h-[90vh] cpk:max-w-[1000px] cpk:rounded-lg cpk:bg-white"
354
- data-testid="copilot-chat-attachment-lightbox-document-iframe"
355
- />
332
+ <div
333
+ v-else-if="
334
+ isPreviewableDocument &&
335
+ isText(activeLightboxAttachment.source.mimeType)
336
+ "
337
+ class="cpk-attachment-queue-text-preview"
338
+ >
339
+ <div
340
+ v-if="activeLightboxAttachment.filename"
341
+ class="cpk-attachment-queue-text-preview-filename"
342
+ >
343
+ {{ activeLightboxAttachment.filename }}
344
+ </div>
345
+ <pre
346
+ v-if="decodedTextPreview !== null"
347
+ class="cpk-attachment-queue-text-preview-content"
348
+ data-testid="copilot-chat-attachment-lightbox-document-text"
349
+ >{{ decodedTextPreview }}</pre
350
+ >
351
+ <iframe
352
+ v-else-if="lightboxDocumentSource"
353
+ :src="lightboxDocumentSource"
354
+ :title="activeLightboxAttachment.filename || 'Text preview'"
355
+ class="cpk-attachment-queue-text-preview-frame"
356
+ data-testid="copilot-chat-attachment-lightbox-document-iframe"
357
+ />
358
+ </div>
356
359
 
357
- <div
358
- v-else-if="
359
- isPreviewableDocument &&
360
- isText(activeLightboxAttachment.source.mimeType)
361
- "
362
- class="cpk:w-[90vw] cpk:max-w-[800px] cpk:max-h-[90vh] cpk:overflow-auto cpk:rounded-lg cpk:bg-white cpk:dark:bg-gray-900 cpk:p-6"
363
- >
364
- <pre
365
- v-if="decodedTextPreview !== null"
366
- class="cpk:text-sm cpk:whitespace-pre-wrap cpk:wrap-break-word cpk:text-gray-800 cpk:dark:text-gray-200 cpk:font-mono cpk:m-0"
367
- data-testid="copilot-chat-attachment-lightbox-document-text"
368
- >{{ decodedTextPreview }}</pre
369
- >
370
- <iframe
371
- v-else-if="lightboxDocumentSource"
372
- :src="lightboxDocumentSource"
373
- :title="activeLightboxAttachment.filename || 'Text preview'"
374
- class="cpk:w-full cpk:h-[80vh] cpk:border-none"
375
- data-testid="copilot-chat-attachment-lightbox-document-iframe"
376
- />
360
+ <div
361
+ v-else
362
+ class="cpk-attachment-queue-document-card"
363
+ data-testid="copilot-chat-attachment-lightbox-document-fallback"
364
+ >
365
+ <div class="cpk-attachment-queue-document-card-icon">
366
+ {{ getDocumentIcon(activeLightboxAttachment.source.mimeType ?? "") }}
367
+ </div>
368
+ <div class="cpk-attachment-queue-document-card-details">
369
+ <div class="cpk-attachment-queue-document-card-name">
370
+ {{
371
+ activeLightboxAttachment.filename ||
372
+ labels.attachmentDocumentLabel
373
+ }}
377
374
  </div>
378
-
379
- <div
380
- v-else
381
- class="cpk:flex cpk:flex-col cpk:items-center cpk:gap-4 cpk:p-8 cpk:rounded-lg cpk:bg-white cpk:dark:bg-gray-900"
382
- data-testid="copilot-chat-attachment-lightbox-document-fallback"
383
- >
384
- <div
385
- class="cpk:w-16 cpk:h-16 cpk:rounded-xl cpk:bg-primary cpk:text-primary-foreground cpk:flex cpk:items-center cpk:justify-center cpk:text-xl cpk:font-bold"
386
- >
387
- {{
388
- getDocumentIcon(activeLightboxAttachment.source.mimeType ?? "")
389
- }}
390
- </div>
391
- <div class="cpk:text-center">
392
- <div
393
- class="cpk:text-base cpk:font-medium cpk:text-gray-800 cpk:dark:text-gray-200"
394
- >
395
- {{ activeLightboxAttachment.filename || "Document" }}
396
- </div>
397
- <div
398
- class="cpk:text-sm cpk:text-gray-500 cpk:dark:text-gray-400 cpk:mt-1"
399
- >
400
- {{ activeLightboxAttachment.source.mimeType || "Unknown type" }}
401
- {{
402
- activeLightboxAttachment.size != null
403
- ? ` · ${formatFileSize(activeLightboxAttachment.size)}`
404
- : ""
405
- }}
406
- </div>
407
- </div>
408
- <div class="cpk:text-xs cpk:text-gray-400 cpk:dark:text-gray-500">
409
- No preview available for this file type
410
- </div>
375
+ <div class="cpk-attachment-queue-document-card-meta">
376
+ {{
377
+ activeLightboxAttachment.source.mimeType ||
378
+ labels.attachmentUnknownTypeText
379
+ }}
380
+ {{
381
+ activeLightboxAttachment.size != null
382
+ ? ` · ${formatFileSize(activeLightboxAttachment.size)}`
383
+ : ""
384
+ }}
411
385
  </div>
412
- </template>
386
+ </div>
387
+ <div class="cpk-attachment-queue-document-card-note">
388
+ {{ labels.attachmentNoPreviewText }}
389
+ </div>
413
390
  </div>
414
- </div>
415
- </Teleport>
391
+ </template>
392
+ </CopilotChatLightbox>
416
393
  </template>
@@ -2,41 +2,89 @@
2
2
  import { computed, ref } from "vue";
3
3
  import { getDocumentIcon, getSourceUrl } from "@copilotkit/shared";
4
4
  import type { CopilotChatAttachmentRendererProps } from "./types";
5
+ import CopilotChatLightbox from "./CopilotChatLightbox.vue";
6
+ import { useLightbox } from "./use-lightbox";
7
+ import { useChatLabels } from "./use-chat-labels";
5
8
 
6
9
  const props = withDefaults(defineProps<CopilotChatAttachmentRendererProps>(), {
7
10
  filename: undefined,
8
11
  className: "",
9
12
  });
10
13
 
14
+ const labels = useChatLabels();
11
15
  const imageLoadFailed = ref(false);
12
16
  const sourceUrl = computed(() => getSourceUrl(props.source));
13
17
  const documentLabel = computed(
14
- () => props.filename || props.source.mimeType || "Unknown type",
18
+ () =>
19
+ props.filename ||
20
+ props.source.mimeType ||
21
+ labels.value.attachmentUnknownTypeText,
15
22
  );
23
+ const documentAriaLabel = computed(
24
+ () =>
25
+ props.filename ||
26
+ props.source.mimeType ||
27
+ labels.value.attachmentDocumentAltText,
28
+ );
29
+
30
+ const imageButton = ref<HTMLButtonElement | null>(null);
31
+ const {
32
+ thumbnailRef,
33
+ vtName,
34
+ open: lightboxOpen,
35
+ openLightbox,
36
+ closeLightbox,
37
+ } = useLightbox();
16
38
  </script>
17
39
 
18
40
  <template>
19
- <img
41
+ <!-- React opens the lightbox from the <img>; a button around it lets
42
+ keyboard users open it too. The button has no look of its own. -->
43
+ <button
20
44
  v-if="props.type === 'image' && !imageLoadFailed"
21
- :src="sourceUrl"
22
- alt="Image attachment"
23
- class="cpk:max-w-full cpk:h-auto cpk:rounded-lg"
24
- :class="props.className"
25
- data-testid="copilot-chat-attachment-renderer-image"
26
- @error="imageLoadFailed = true"
27
- />
45
+ ref="imageButton"
46
+ type="button"
47
+ class="cpk-attachment-renderer-image-button"
48
+ data-testid="copilot-chat-attachment-renderer-image-button"
49
+ @click="openLightbox"
50
+ >
51
+ <img
52
+ ref="thumbnailRef"
53
+ :src="sourceUrl"
54
+ :alt="labels.attachmentImageAltText"
55
+ class="cpk-attachment-renderer cpk-attachment-renderer-image"
56
+ :class="props.className"
57
+ data-testid="copilot-chat-attachment-renderer-image"
58
+ @error="imageLoadFailed = true"
59
+ />
60
+ <!-- Teleported to the body; inside the button only to keep one root. -->
61
+ <CopilotChatLightbox
62
+ v-if="lightboxOpen"
63
+ :label="labels.attachmentImageAltText"
64
+ :return-focus-to="imageButton"
65
+ @close="closeLightbox"
66
+ >
67
+ <img
68
+ :style="{ viewTransitionName: vtName }"
69
+ :src="sourceUrl"
70
+ :alt="labels.attachmentImageAltText"
71
+ class="cpk-attachment-renderer-lightbox-image"
72
+ data-testid="copilot-chat-attachment-renderer-lightbox-image"
73
+ />
74
+ </CopilotChatLightbox>
75
+ </button>
28
76
  <div
29
77
  v-else-if="props.type === 'image'"
30
- class="cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:rounded-lg cpk:bg-muted cpk:p-4 cpk:text-sm cpk:text-muted-foreground"
78
+ class="cpk-attachment-renderer cpk-attachment-renderer-image-error"
31
79
  :class="props.className"
32
80
  data-testid="copilot-chat-attachment-renderer-image-fallback"
33
81
  >
34
- <span>Failed to load image</span>
82
+ <span>{{ labels.attachmentImageLoadErrorText }}</span>
35
83
  </div>
36
84
 
37
85
  <div
38
86
  v-else-if="props.type === 'audio'"
39
- class="cpk:flex cpk:flex-col cpk:gap-1"
87
+ class="cpk-attachment-renderer cpk-attachment-renderer-audio"
40
88
  :class="props.className"
41
89
  data-testid="copilot-chat-attachment-renderer-audio"
42
90
  >
@@ -44,11 +92,11 @@ const documentLabel = computed(
44
92
  :src="sourceUrl"
45
93
  controls
46
94
  preload="metadata"
47
- class="cpk:max-w-[300px] cpk:w-full cpk:h-10"
95
+ class="cpk-attachment-renderer-audio-player"
48
96
  />
49
97
  <span
50
98
  v-if="props.filename"
51
- class="cpk:text-xs cpk:text-muted-foreground cpk:truncate cpk:max-w-[300px]"
99
+ class="cpk-attachment-renderer-audio-filename"
52
100
  data-testid="copilot-chat-attachment-renderer-audio-filename"
53
101
  >
54
102
  {{ props.filename }}
@@ -60,28 +108,37 @@ const documentLabel = computed(
60
108
  :src="sourceUrl"
61
109
  controls
62
110
  preload="metadata"
63
- class="cpk:max-w-[400px] cpk:w-full cpk:rounded-lg"
111
+ class="cpk-attachment-renderer cpk-attachment-renderer-video"
64
112
  :class="props.className"
65
113
  data-testid="copilot-chat-attachment-renderer-video"
66
114
  />
67
115
 
68
- <div
116
+ <!-- `download` is honoured for same-origin, data: and blob: URLs. Browsers
117
+ ignore it for cross-origin URLs unless the server sends
118
+ `Content-Disposition: attachment`; `target="_blank"` keeps those from
119
+ navigating the chat away and opens the file in a new tab instead. -->
120
+ <a
69
121
  v-else
70
- class="cpk:inline-flex cpk:items-center cpk:gap-2 cpk:px-3 cpk:py-2 cpk:border cpk:border-border cpk:rounded-lg cpk:bg-muted"
122
+ :href="sourceUrl"
123
+ :download="props.filename ?? ''"
124
+ target="_blank"
125
+ rel="noopener noreferrer"
126
+ :aria-label="documentAriaLabel"
127
+ class="cpk-attachment-renderer cpk-attachment-renderer-document"
71
128
  :class="props.className"
72
129
  data-testid="copilot-chat-attachment-renderer-document"
73
130
  >
74
131
  <span
75
- class="cpk:text-xs cpk:font-bold cpk:uppercase"
132
+ class="cpk-attachment-renderer-document-icon"
76
133
  data-testid="copilot-chat-attachment-renderer-document-icon"
77
134
  >
78
135
  {{ getDocumentIcon(props.source.mimeType ?? "") }}
79
136
  </span>
80
137
  <span
81
- class="cpk:text-sm cpk:text-muted-foreground cpk:truncate"
138
+ class="cpk-attachment-renderer-document-name"
82
139
  data-testid="copilot-chat-attachment-renderer-document-label"
83
140
  >
84
141
  {{ documentLabel }}
85
142
  </span>
86
- </div>
143
+ </a>
87
144
  </template>
@@ -263,7 +263,7 @@ defineExpose({
263
263
  </script>
264
264
 
265
265
  <template>
266
- <div data-copilotkit class="cpk:w-full cpk:px-5 cpk:py-3" v-bind="attrs">
267
- <canvas ref="canvasRef" class="cpk:block cpk:h-[26px] cpk:w-full" />
266
+ <div data-copilotkit class="cpk-audio-recorder" v-bind="attrs">
267
+ <canvas ref="canvasRef" class="cpk-audio-recorder-canvas" />
268
268
  </div>
269
269
  </template>