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

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 (239) 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/index.cjs +43 -46
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.mjs +10170 -7506
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/v2/components/A2UIMessageRenderer.d.ts +7 -0
  10. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
  11. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
  12. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +11 -2
  13. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
  14. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +136 -0
  15. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -0
  16. package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +1 -1
  17. package/dist/v2/components/chat/CopilotChat.vue.d.ts +1 -0
  18. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  19. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts +3 -1
  20. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  21. package/dist/v2/components/chat/CopilotChatAssistantToolbarButton.vue.d.ts +16 -0
  22. package/dist/v2/components/chat/CopilotChatAssistantToolbarButton.vue.d.ts.map +1 -0
  23. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
  24. package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
  25. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
  26. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +22 -0
  27. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -0
  28. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +69 -16
  29. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  30. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts +12 -0
  31. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -0
  32. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts +22 -0
  33. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -0
  34. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +20 -0
  35. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  36. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  37. package/dist/v2/components/chat/CopilotChatSuggestionPill.vue.d.ts.map +1 -1
  38. package/dist/v2/components/chat/CopilotChatSuggestionView.vue.d.ts.map +1 -1
  39. package/dist/v2/components/chat/CopilotChatToggleButton.vue.d.ts.map +1 -1
  40. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +32 -0
  41. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -0
  42. package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
  43. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +11 -1
  44. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
  45. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
  46. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +1 -0
  47. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
  48. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts +5 -0
  49. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -0
  50. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  51. package/dist/v2/components/chat/CopilotModalHeaderCloseButton.d.ts.map +1 -1
  52. package/dist/v2/components/chat/CopilotModalHeaderTitle.d.ts.map +1 -1
  53. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +1 -0
  54. package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
  55. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +1 -0
  56. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
  57. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +1 -0
  58. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
  59. package/dist/v2/components/chat/CopilotPopupWelcomeScreen.vue.d.ts.map +1 -1
  60. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +2 -0
  61. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
  62. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +2 -0
  63. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
  64. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +2 -0
  65. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
  66. package/dist/v2/components/chat/CopilotSidebarWelcomeScreen.vue.d.ts.map +1 -1
  67. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
  68. package/dist/v2/components/chat/index.d.ts +17 -0
  69. package/dist/v2/components/chat/index.d.ts.map +1 -1
  70. package/dist/v2/components/chat/inspector-shortcuts.d.ts +12 -0
  71. package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -0
  72. package/dist/v2/components/chat/message-feedback.d.ts +89 -0
  73. package/dist/v2/components/chat/message-feedback.d.ts.map +1 -0
  74. package/dist/v2/components/chat/tool-call-capture.d.ts +39 -0
  75. package/dist/v2/components/chat/tool-call-capture.d.ts.map +1 -0
  76. package/dist/v2/components/chat/tool-call-display-context.d.ts +39 -0
  77. package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -0
  78. package/dist/v2/components/chat/tool-call-group-parts.d.ts +144 -0
  79. package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -0
  80. package/dist/v2/components/chat/tool-call-layout.d.ts +115 -0
  81. package/dist/v2/components/chat/tool-call-layout.d.ts.map +1 -0
  82. package/dist/v2/components/chat/turn-work.d.ts +35 -0
  83. package/dist/v2/components/chat/turn-work.d.ts.map +1 -0
  84. package/dist/v2/components/chat/types.d.ts +104 -4
  85. package/dist/v2/components/chat/types.d.ts.map +1 -1
  86. package/dist/v2/components/chat/use-lightbox.d.ts +18 -0
  87. package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -0
  88. package/dist/v2/components/icons/index.d.ts +1 -1
  89. package/dist/v2/components/icons/index.d.ts.map +1 -1
  90. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +55 -0
  91. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -0
  92. package/dist/v2/components/ui/CopilotPopover.vue.d.ts +40 -0
  93. package/dist/v2/components/ui/CopilotPopover.vue.d.ts.map +1 -0
  94. package/dist/v2/components/ui/CopilotTooltip.vue.d.ts +37 -0
  95. package/dist/v2/components/ui/CopilotTooltip.vue.d.ts.map +1 -0
  96. package/dist/v2/components/ui/dropdown-menu.d.ts +14 -0
  97. package/dist/v2/components/ui/dropdown-menu.d.ts.map +1 -0
  98. package/dist/v2/components/ui/floating.d.ts +84 -0
  99. package/dist/v2/components/ui/floating.d.ts.map +1 -0
  100. package/dist/v2/components/ui/presence.d.ts +9 -0
  101. package/dist/v2/components/ui/presence.d.ts.map +1 -0
  102. package/dist/v2/components/ui/use-id.d.ts +9 -0
  103. package/dist/v2/components/ui/use-id.d.ts.map +1 -0
  104. package/dist/v2/hooks/use-default-render-tool.d.ts +6 -0
  105. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
  106. package/dist/v2/hooks/use-render-tool.d.ts +4 -0
  107. package/dist/v2/hooks/use-render-tool.d.ts.map +1 -1
  108. package/dist/v2/index.cjs +1 -1
  109. package/dist/v2/index.d.cts +3 -0
  110. package/dist/v2/index.d.mts +3 -0
  111. package/dist/v2/index.d.ts +3 -0
  112. package/dist/v2/index.d.ts.map +1 -1
  113. package/dist/v2/index.mjs +165 -162
  114. package/dist/v2/lib/message-feedback.d.ts +33 -0
  115. package/dist/v2/lib/message-feedback.d.ts.map +1 -0
  116. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  117. package/dist/v2/providers/CopilotKitProvider.types.d.ts +56 -1
  118. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  119. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +5 -1
  120. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  121. package/dist/v2/providers/index.d.ts +1 -1
  122. package/dist/v2/providers/index.d.ts.map +1 -1
  123. package/dist/v2/providers/keys.d.ts +8 -0
  124. package/dist/v2/providers/keys.d.ts.map +1 -1
  125. package/dist/v2/providers/types.d.ts +9 -0
  126. package/dist/v2/providers/types.d.ts.map +1 -1
  127. package/dist/v2/styles/CopilotKitStyles.d.ts +18 -0
  128. package/dist/v2/styles/CopilotKitStyles.d.ts.map +1 -0
  129. package/dist/v2/types/defineToolCallRenderer.d.ts +2 -0
  130. package/dist/v2/types/defineToolCallRenderer.d.ts.map +1 -1
  131. package/dist/v2/types/vue-tool-call-renderer.d.ts +7 -0
  132. package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
  133. package/package.json +11 -23
  134. package/src/components/copilot-provider/CopilotKit.vue +4 -1
  135. package/src/v2/__tests__/exports.test.ts +4 -2
  136. package/src/v2/components/A2UIMessageRenderer.ts +55 -67
  137. package/src/v2/components/A2UISurfaceActivityRenderer.vue +11 -23
  138. package/src/v2/components/__tests__/A2UIBasicCatalogColors.test.ts +8 -9
  139. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +63 -36
  140. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +14 -257
  141. package/src/v2/components/a2ui/A2UIRecoveryStates.ts +444 -0
  142. package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +175 -0
  143. package/src/v2/components/chat/BasicMarkdown.vue +8 -6
  144. package/src/v2/components/chat/CopilotChat.vue +7 -0
  145. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +267 -67
  146. package/src/v2/components/chat/CopilotChatAssistantToolbarButton.vue +46 -0
  147. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +141 -168
  148. package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +67 -18
  149. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +2 -2
  150. package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +240 -0
  151. package/src/v2/components/chat/CopilotChatInput.vue +210 -161
  152. package/src/v2/components/chat/CopilotChatInspectorButton.vue +331 -0
  153. package/src/v2/components/chat/CopilotChatLightbox.vue +105 -0
  154. package/src/v2/components/chat/CopilotChatMessageView.vue +261 -18
  155. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +21 -22
  156. package/src/v2/components/chat/CopilotChatSuggestionPill.vue +5 -14
  157. package/src/v2/components/chat/CopilotChatSuggestionView.vue +1 -4
  158. package/src/v2/components/chat/CopilotChatToggleButton.vue +3 -9
  159. package/src/v2/components/chat/CopilotChatToggleButtonCloseIcon.ts +1 -1
  160. package/src/v2/components/chat/CopilotChatToggleButtonOpenIcon.ts +1 -1
  161. package/src/v2/components/chat/CopilotChatToolCallGroup.vue +330 -0
  162. package/src/v2/components/chat/CopilotChatToolCallItem.vue +21 -11
  163. package/src/v2/components/chat/CopilotChatToolCallsView.vue +192 -21
  164. package/src/v2/components/chat/CopilotChatUserMessage.vue +105 -42
  165. package/src/v2/components/chat/CopilotChatView.vue +33 -38
  166. package/src/v2/components/chat/CopilotChatWorkSummary.vue +85 -0
  167. package/src/v2/components/chat/CopilotModalHeader.vue +10 -8
  168. package/src/v2/components/chat/CopilotModalHeaderCloseButton.ts +7 -6
  169. package/src/v2/components/chat/CopilotModalHeaderTitle.ts +1 -4
  170. package/src/v2/components/chat/CopilotPopup.vue +3 -0
  171. package/src/v2/components/chat/CopilotPopupView.vue +1 -0
  172. package/src/v2/components/chat/CopilotPopupViewInternal.vue +9 -19
  173. package/src/v2/components/chat/CopilotPopupWelcomeScreen.vue +5 -8
  174. package/src/v2/components/chat/CopilotSidebar.vue +5 -0
  175. package/src/v2/components/chat/CopilotSidebarView.vue +2 -0
  176. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +24 -17
  177. package/src/v2/components/chat/CopilotSidebarWelcomeScreen.vue +7 -10
  178. package/src/v2/components/chat/StreamingMarkdownDefault.vue +3 -5
  179. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.inspector.test.ts +269 -0
  180. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +760 -0
  181. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.slots.e2e.test.ts +3 -5
  182. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.ts +2 -2
  183. package/src/v2/components/chat/__tests__/CopilotChatInput.addMenu.test.ts +328 -0
  184. package/src/v2/components/chat/__tests__/CopilotChatInput.slots.e2e.test.ts +6 -3
  185. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +22 -13
  186. package/src/v2/components/chat/__tests__/CopilotChatLightbox.test.ts +160 -0
  187. package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +735 -0
  188. package/src/v2/components/chat/__tests__/CopilotChatSuggestionPill.test.ts +1 -1
  189. package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.slots.e2e.test.ts +3 -1
  190. package/src/v2/components/chat/__tests__/CopilotChatToolCallsView.learning.test.ts +75 -0
  191. package/src/v2/components/chat/__tests__/CopilotChatUserMessage.attachments.test.ts +143 -0
  192. package/src/v2/components/chat/__tests__/CopilotChatView.inputOverlay.test.ts +5 -4
  193. package/src/v2/components/chat/__tests__/CopilotChatView.rootWidth.test.ts +7 -33
  194. package/src/v2/components/chat/__tests__/CopilotModalHeader.slots.e2e.test.ts +1 -1
  195. package/src/v2/components/chat/__tests__/CopilotPopupView.slots.e2e.test.ts +3 -3
  196. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +126 -0
  197. package/src/v2/components/chat/__tests__/messageFeedbackDefaults.test.ts +33 -0
  198. package/src/v2/components/chat/__tests__/modalChatDisplayProps.test.ts +44 -0
  199. package/src/v2/components/chat/index.ts +2 -0
  200. package/src/v2/components/chat/inspector-shortcuts.ts +34 -0
  201. package/src/v2/components/chat/message-feedback.ts +291 -0
  202. package/src/v2/components/chat/tool-call-capture.ts +55 -0
  203. package/src/v2/components/chat/tool-call-display-context.ts +49 -0
  204. package/src/v2/components/chat/tool-call-group-parts.ts +292 -0
  205. package/src/v2/components/chat/tool-call-layout.ts +304 -0
  206. package/src/v2/components/chat/turn-work.ts +61 -0
  207. package/src/v2/components/chat/types.ts +113 -3
  208. package/src/v2/components/chat/use-lightbox.ts +64 -0
  209. package/src/v2/components/icons/index.ts +4 -0
  210. package/src/v2/components/ui/CopilotDropdownMenuContent.vue +465 -0
  211. package/src/v2/components/ui/CopilotPopover.vue +138 -0
  212. package/src/v2/components/ui/CopilotTooltip.vue +237 -0
  213. package/src/v2/components/ui/__tests__/CopilotTooltip.test.ts +168 -0
  214. package/src/v2/components/ui/dropdown-menu.ts +15 -0
  215. package/src/v2/components/ui/floating.ts +321 -0
  216. package/src/v2/components/ui/presence.ts +54 -0
  217. package/src/v2/components/ui/use-id.ts +16 -0
  218. package/src/v2/hooks/use-default-render-tool.ts +123 -62
  219. package/src/v2/hooks/use-render-tool.ts +8 -0
  220. package/src/v2/index.ts +3 -0
  221. package/src/v2/lib/__tests__/message-feedback.test.ts +152 -0
  222. package/src/v2/lib/message-feedback.ts +120 -0
  223. package/src/v2/providers/CopilotChatConfigurationProvider.vue +29 -2
  224. package/src/v2/providers/CopilotKitProvider.types.ts +57 -0
  225. package/src/v2/providers/CopilotKitProvider.vue +125 -3
  226. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.openThread.test.ts +69 -0
  227. package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +534 -0
  228. package/src/v2/providers/index.ts +4 -1
  229. package/src/v2/providers/keys.ts +12 -0
  230. package/src/v2/providers/types.ts +11 -0
  231. package/src/v2/styles/CopilotKitStyles.ts +95 -0
  232. package/src/v2/styles/__tests__/CopilotKitStyles.client.test.ts +149 -0
  233. package/src/v2/styles/__tests__/CopilotKitStyles.ssr.test.ts +71 -0
  234. package/src/v2/types/defineToolCallRenderer.ts +4 -0
  235. package/src/v2/types/vue-tool-call-renderer.ts +7 -0
  236. package/vite.config.ts +2 -1
  237. package/dist/styles.css +0 -2
  238. package/scripts/scope-preflight.mjs +0 -100
  239. package/src/styles/globals.css +0 -233
@@ -37,6 +37,7 @@ const props = withDefaults(
37
37
  {
38
38
  messages: () => [],
39
39
  autoScroll: true,
40
+ messageFeedback: true,
40
41
  isRunning: false,
41
42
  suggestions: () => [],
42
43
  suggestionLoadingIndexes: () => [],
@@ -96,8 +97,8 @@ const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
96
97
  const headerTitle = computed(() => labels.value.modalHeaderTitle);
97
98
  const popupAnimationClass = computed(() =>
98
99
  isPopupOpen.value && !isAnimatingOut.value
99
- ? "cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100"
100
- : "cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]",
100
+ ? "cpk-popup-view-window-open"
101
+ : undefined,
101
102
  );
102
103
  const popupStyle = computed(
103
104
  () =>
@@ -109,10 +110,6 @@ const popupStyle = computed(
109
110
  ),
110
111
  "--copilot-popup-max-width": "calc(100vw - 3rem)",
111
112
  "--copilot-popup-max-height": "calc(100dvh - 7.5rem)",
112
- width: "var(--copilot-popup-width)",
113
- height: "var(--copilot-popup-height)",
114
- maxWidth: "var(--copilot-popup-max-width)",
115
- maxHeight: "var(--copilot-popup-max-height)",
116
113
  paddingTop: "env(safe-area-inset-top)",
117
114
  paddingBottom: "env(safe-area-inset-bottom)",
118
115
  paddingLeft: "env(safe-area-inset-left)",
@@ -349,11 +346,7 @@ onBeforeUnmount(() => {
349
346
  <CopilotChatToggleButton />
350
347
  </slot>
351
348
 
352
- <div
353
- v-if="isRendered"
354
- data-copilotkit
355
- class="cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch cpk:bg-transparent cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4"
356
- >
349
+ <div v-if="isRendered" data-copilotkit class="cpk-popup-view">
357
350
  <div
358
351
  ref="containerRef"
359
352
  tabindex="-1"
@@ -361,13 +354,7 @@ onBeforeUnmount(() => {
361
354
  :aria-label="labels.modalHeaderTitle"
362
355
  data-copilot-popup
363
356
  :class="[
364
- 'cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground',
365
- 'cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out',
366
- 'cpk:md:transition-transform cpk:md:transition-opacity',
367
- 'cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0',
368
- 'cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]',
369
- 'cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]',
370
- 'cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40',
357
+ 'copilotKitPopup copilotKitWindow cpk-popup-view-window',
371
358
  popupAnimationClass,
372
359
  ]"
373
360
  :style="popupStyle"
@@ -381,8 +368,9 @@ onBeforeUnmount(() => {
381
368
  <CopilotModalHeader :title="headerTitle" />
382
369
  </slot>
383
370
 
384
- <div class="cpk:flex-1 cpk:overflow-hidden" data-popup-chat>
371
+ <div class="cpk-popup-view-chat" data-popup-chat>
385
372
  <CopilotChatView
373
+ class="cpk-popup-view-chat-view"
386
374
  :messages="messages"
387
375
  :auto-scroll="autoScroll"
388
376
  :is-running="isRunning"
@@ -392,6 +380,8 @@ onBeforeUnmount(() => {
392
380
  :input-value="inputValue"
393
381
  :input-mode="inputMode"
394
382
  :input-tools-menu="inputToolsMenu"
383
+ :tool-call-display="toolCallDisplay"
384
+ :message-feedback="messageFeedback"
395
385
  :on-finish-transcribe-with-audio="onFinishTranscribeWithAudio"
396
386
  v-bind="chatViewBindings"
397
387
  >
@@ -127,25 +127,22 @@ const inputEventProps = computed(() => {
127
127
  <slot name="layout" v-bind="layoutSlotProps">
128
128
  <div
129
129
  data-copilotkit
130
- class="cpk:h-full cpk:flex cpk:flex-col"
130
+ class="cpk-popup-view-welcome-screen"
131
131
  data-testid="copilot-popup-welcome-screen"
132
132
  >
133
- <div
134
- class="cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4"
135
- >
133
+ <div class="cpk-popup-view-welcome-screen-message">
136
134
  <slot name="welcome-message">
137
- <h1
138
- class="cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center"
139
- >
135
+ <h1 class="cpk-chat-view-welcome-message">
140
136
  {{ labels.welcomeMessageText }}
141
137
  </h1>
142
138
  </slot>
143
139
  </div>
144
140
 
145
141
  <div>
146
- <div class="cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4">
142
+ <div class="cpk-popup-view-welcome-screen-suggestions">
147
143
  <slot name="suggestion-view" v-bind="suggestionViewSlotProps">
148
144
  <CopilotChatSuggestionView
145
+ class="cpk-chat-view-suggestion-view"
149
146
  :suggestions="suggestions"
150
147
  :loading-indexes="loadingIndexes"
151
148
  @select-suggestion="onSelectSuggestion"
@@ -36,12 +36,14 @@ function sidebarViewEventBindings(slotProps: CopilotChatViewOverrideSlotProps) {
36
36
 
37
37
  const props = withDefaults(defineProps<CopilotSidebarProps>(), {
38
38
  autoScroll: true,
39
+ messageFeedback: true,
39
40
  welcomeScreen: true,
40
41
  inputValue: undefined,
41
42
  inputMode: "input",
42
43
  inputToolsMenu: () => [],
43
44
  width: undefined,
44
45
  defaultOpen: true,
46
+ position: "right",
45
47
  onFinishTranscribeWithAudio: undefined,
46
48
  });
47
49
 
@@ -114,7 +116,10 @@ watch(
114
116
  :input-mode="slotProps.inputMode"
115
117
  :input-tools-menu="slotProps.inputToolsMenu"
116
118
  :width="width"
119
+ :tool-call-display="slotProps.toolCallDisplay"
120
+ :message-feedback="slotProps.messageFeedback"
117
121
  :default-open="defaultOpen"
122
+ :position="position"
118
123
  :on-finish-transcribe-with-audio="slotProps.onFinishTranscribeWithAudio"
119
124
  v-bind="sidebarViewEventBindings(slotProps)"
120
125
  >
@@ -18,6 +18,7 @@ defineOptions({ inheritAttrs: false });
18
18
  const props = withDefaults(defineProps<CopilotSidebarViewProps>(), {
19
19
  messages: () => [],
20
20
  autoScroll: true,
21
+ messageFeedback: true,
21
22
  isRunning: false,
22
23
  suggestions: () => [],
23
24
  suggestionLoadingIndexes: () => [],
@@ -27,6 +28,7 @@ const props = withDefaults(defineProps<CopilotSidebarViewProps>(), {
27
28
  inputToolsMenu: () => [],
28
29
  width: undefined,
29
30
  defaultOpen: true,
31
+ position: "right",
30
32
  onFinishTranscribeWithAudio: undefined,
31
33
  });
32
34
 
@@ -36,6 +36,7 @@ const props = withDefaults(
36
36
  {
37
37
  messages: () => [],
38
38
  autoScroll: true,
39
+ messageFeedback: true,
39
40
  isRunning: false,
40
41
  suggestions: () => [],
41
42
  suggestionLoadingIndexes: () => [],
@@ -44,6 +45,7 @@ const props = withDefaults(
44
45
  inputMode: "input",
45
46
  inputToolsMenu: () => [],
46
47
  width: undefined,
48
+ position: "right",
47
49
  onFinishTranscribeWithAudio: undefined,
48
50
  },
49
51
  );
@@ -98,12 +100,9 @@ const headerTitle = computed(
98
100
  CopilotChatDefaultLabels.modalHeaderTitle,
99
101
  );
100
102
  const asideClass = computed(() => [
101
- "cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen cpk:w-full",
102
- "cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl",
103
- "cpk:transition-transform cpk:duration-300 cpk:ease-out",
104
- isSidebarOpen.value
105
- ? "cpk:translate-x-0"
106
- : "cpk:translate-x-full cpk:pointer-events-none",
103
+ "copilotKitSidebar copilotKitWindow cpk-sidebar-view",
104
+ // Slides off its edge when closed.
105
+ !isSidebarOpen.value && "cpk-sidebar-view-closed",
107
106
  attrs.class,
108
107
  ]);
109
108
  const asideAttrs = computed(() => {
@@ -118,16 +117,19 @@ const asideStyle = computed(
118
117
  paddingBottom: "env(safe-area-inset-bottom)",
119
118
  }) as Record<string, string>,
120
119
  );
121
- const bodyMarginStyle = computed(
122
- () => `
120
+ // The page makes room on the docked edge (desktop only).
121
+ const bodyMarginStyle = computed(() => {
122
+ const margin =
123
+ props.position === "left" ? "margin-inline-start" : "margin-inline-end";
124
+ return `
123
125
  @media (min-width: 768px) {
124
126
  body {
125
- margin-inline-end: ${widthToMargin(resolvedSidebarWidth.value)};
126
- transition: margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease;
127
+ ${margin}: ${widthToMargin(resolvedSidebarWidth.value)};
128
+ transition: ${margin} ${SIDEBAR_TRANSITION_MS}ms ease;
127
129
  }
128
130
  }
129
- `,
130
- );
131
+ `;
132
+ });
131
133
 
132
134
  function widthToCss(width: number | string): string {
133
135
  return typeof width === "number" ? `${width}px` : width;
@@ -268,13 +270,18 @@ onBeforeUnmount(() => {
268
270
  :open="openSidebar"
269
271
  :close="closeSidebar"
270
272
  >
271
- <CopilotChatToggleButton />
273
+ <CopilotChatToggleButton
274
+ :class="
275
+ position === 'left' ? 'cpk-sidebar-view-toggle-button-left' : undefined
276
+ "
277
+ />
272
278
  </slot>
273
279
 
274
280
  <aside
275
281
  ref="sidebarRef"
276
282
  data-copilotkit
277
283
  data-copilot-sidebar
284
+ :data-position="position"
278
285
  :class="asideClass"
279
286
  :style="asideStyle"
280
287
  :aria-label="
@@ -284,9 +291,7 @@ onBeforeUnmount(() => {
284
291
  role="complementary"
285
292
  v-bind="asideAttrs"
286
293
  >
287
- <div
288
- class="cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden"
289
- >
294
+ <div class="cpk-sidebar-view-panel">
290
295
  <slot
291
296
  name="header"
292
297
  :title="headerTitle"
@@ -296,7 +301,7 @@ onBeforeUnmount(() => {
296
301
  <CopilotModalHeader :title="headerTitle" />
297
302
  </slot>
298
303
 
299
- <div class="cpk:flex-1 cpk:overflow-hidden" data-sidebar-chat>
304
+ <div class="cpk-sidebar-view-chat" data-sidebar-chat>
300
305
  <CopilotChatView
301
306
  :messages="messages"
302
307
  :auto-scroll="autoScroll"
@@ -307,6 +312,8 @@ onBeforeUnmount(() => {
307
312
  :input-value="inputValue"
308
313
  :input-mode="inputMode"
309
314
  :input-tools-menu="inputToolsMenu"
315
+ :tool-call-display="toolCallDisplay"
316
+ :message-feedback="messageFeedback"
310
317
  :on-finish-transcribe-with-audio="onFinishTranscribeWithAudio"
311
318
  v-bind="chatViewEventProps"
312
319
  >
@@ -127,26 +127,23 @@ const inputEventProps = computed(() => {
127
127
  <slot name="layout" v-bind="layoutSlotProps">
128
128
  <div
129
129
  data-copilotkit
130
- class="cpk:h-full cpk:flex cpk:flex-col"
130
+ class="cpk-sidebar-view-welcome-screen"
131
131
  data-testid="copilot-sidebar-welcome-screen"
132
132
  >
133
- <div
134
- class="cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4"
135
- >
133
+ <div class="cpk-sidebar-view-welcome-screen-message">
136
134
  <slot name="welcome-message">
137
- <h1
138
- class="cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center"
139
- >
135
+ <h1 class="cpk-chat-view-welcome-message">
140
136
  {{ labels.welcomeMessageText }}
141
137
  </h1>
142
138
  </slot>
143
139
  </div>
144
140
 
145
- <div class="cpk:px-8 cpk:pb-4">
146
- <div class="cpk:max-w-3xl cpk:mx-auto">
147
- <div class="cpk:mb-4 cpk:flex cpk:justify-center">
141
+ <div class="cpk-sidebar-view-welcome-screen-footer">
142
+ <div class="cpk-sidebar-view-welcome-screen-content">
143
+ <div class="cpk-sidebar-view-welcome-screen-suggestions">
148
144
  <slot name="suggestion-view" v-bind="suggestionViewSlotProps">
149
145
  <CopilotChatSuggestionView
146
+ class="cpk-chat-view-suggestion-view"
150
147
  :suggestions="suggestions"
151
148
  :loading-indexes="loadingIndexes"
152
149
  @select-suggestion="onSelectSuggestion"
@@ -1,9 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, h, watchEffect } from "vue";
3
- import {
4
- StreamingMarkdownRenderer,
5
- type VueStreamingMarkdownNodeRenderer,
6
- } from "@copilotkit/markdown-renderer/vue";
3
+ import { StreamingMarkdownRenderer } from "@copilotkit/markdown-renderer/vue";
4
+ import type { VueStreamingMarkdownNodeRenderer } from "@copilotkit/markdown-renderer/vue";
7
5
  import { warnUnsupportedRichSyntaxOnce } from "@copilotkit/markdown-renderer";
8
6
  import type { StreamingMarkdownParserOptions } from "@copilotkit/markdown-renderer";
9
7
  import type { DefaultMarkdownRendererProps } from "../../providers/markdown-renderer";
@@ -29,7 +27,7 @@ const defaultCodeBlockRenderer: VueStreamingMarkdownNodeRenderer = (
29
27
  {
30
28
  "data-streaming-markdown-node": "code-block",
31
29
  "data-node-open": String(!node.closed),
32
- class: "cpk:overflow-x-auto cpk:rounded-lg cpk:p-3",
30
+ class: "cpk-markdown-code-block",
33
31
  },
34
32
  [h("code", { "data-code-info": node.info ?? undefined }, node.text)],
35
33
  );
@@ -0,0 +1,269 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { computed, defineComponent, h, nextTick, provide } from "vue";
3
+ import type { Component } from "vue";
4
+ import { fireEvent, render, screen, waitFor } from "@testing-library/vue";
5
+ import type { AssistantMessage } from "@ag-ui/core";
6
+ import CopilotChatAssistantMessage from "../CopilotChatAssistantMessage.vue";
7
+ import CopilotChatConfigurationProvider from "../../../providers/CopilotChatConfigurationProvider.vue";
8
+ import CopilotKitProvider from "../../../providers/CopilotKitProvider.vue";
9
+ import { InspectorKey } from "../../../providers/keys";
10
+ import { ɵresetInspectorShortcuts } from "../inspector-shortcuts";
11
+
12
+ const THREAD_ID = "thread-inspector";
13
+ const message: AssistantMessage = {
14
+ id: "message-1",
15
+ role: "assistant",
16
+ content: "Inspect me",
17
+ };
18
+
19
+ function renderMessage({
20
+ enabled = true,
21
+ openInspector = vi.fn(),
22
+ slots = {},
23
+ before,
24
+ }: {
25
+ enabled?: boolean;
26
+ openInspector?: ReturnType<typeof vi.fn>;
27
+ slots?: Record<string, unknown>;
28
+ before?: () => unknown;
29
+ } = {}) {
30
+ const InspectorContext = defineComponent({
31
+ setup(_, { slots: children }) {
32
+ provide(InspectorKey, {
33
+ isInspectorEnabled: computed(() => enabled),
34
+ openInspector,
35
+ });
36
+ return () => children.default?.();
37
+ },
38
+ });
39
+ const Harness = defineComponent({
40
+ setup() {
41
+ return () =>
42
+ h(CopilotKitProvider, null, {
43
+ default: () =>
44
+ h(InspectorContext, null, {
45
+ default: () =>
46
+ h(
47
+ CopilotChatConfigurationProvider,
48
+ { threadId: THREAD_ID },
49
+ {
50
+ default: () => [
51
+ before?.(),
52
+ h(
53
+ CopilotChatAssistantMessage as Component,
54
+ { message },
55
+ slots,
56
+ ),
57
+ ],
58
+ },
59
+ ),
60
+ }),
61
+ });
62
+ },
63
+ });
64
+ render(Harness);
65
+ return { openInspector };
66
+ }
67
+
68
+ const expectedRequest = {
69
+ messageId: message.id,
70
+ threadId: THREAD_ID,
71
+ agentId: "default",
72
+ };
73
+
74
+ describe("CopilotChatAssistantMessage Inspector button", () => {
75
+ afterEach(() => {
76
+ ɵresetInspectorShortcuts();
77
+ document.body.innerHTML = "";
78
+ });
79
+
80
+ it("renders no Inspector button while the Inspector is off", () => {
81
+ renderMessage({ enabled: false });
82
+
83
+ expect(
84
+ screen.queryByRole("button", { name: /copilotkit inspector/i }),
85
+ ).toBeNull();
86
+ });
87
+
88
+ it("renders the local Inspector button and opens it from the toolbar", async () => {
89
+ const { openInspector } = renderMessage();
90
+
91
+ const inspectorButton = screen.getByRole("button", {
92
+ name: "CopilotKit Inspector (local only)",
93
+ });
94
+ const inspectorIcon = screen.getByTestId("copilot-inspector-icon");
95
+ expect(inspectorIcon.classList.contains("lucide-wrench")).toBe(true);
96
+ expect(inspectorButton.textContent).toBe("");
97
+ expect(inspectorButton.getAttribute("aria-haspopup")).toBe("menu");
98
+ expect(inspectorButton.getAttribute("aria-expanded")).toBe("false");
99
+ expect(screen.queryByRole("menu")).toBeNull();
100
+
101
+ await fireEvent.pointerEnter(inspectorButton, { pointerType: "mouse" });
102
+ const item = await screen.findByRole("menuitem", {
103
+ name: "View in Inspector Open this message in the Inspector",
104
+ });
105
+ expect(inspectorButton.getAttribute("aria-expanded")).toBe("true");
106
+ expect(screen.getByRole("menu").classList).toContain(
107
+ "cpk-inspector-button-menu",
108
+ );
109
+
110
+ await fireEvent.click(item);
111
+
112
+ expect(openInspector).toHaveBeenCalledWith(expectedRequest);
113
+ await waitFor(() => expect(screen.queryByRole("menu")).toBeNull());
114
+ });
115
+
116
+ it.each(["click", "hover then click", "Enter", " "])(
117
+ "opens Inspector directly on %s",
118
+ async (interaction) => {
119
+ const { openInspector } = renderMessage();
120
+ const trigger = screen.getByTestId("copilot-inspector-button");
121
+ if (interaction === "hover then click") {
122
+ await fireEvent.pointerEnter(trigger, { pointerType: "mouse" });
123
+ expect(screen.getByRole("menu")).toBeDefined();
124
+ }
125
+ if (interaction.includes("click")) {
126
+ await fireEvent.pointerDown(trigger, { button: 0 });
127
+ if (interaction === "click") {
128
+ expect(screen.queryByRole("menu")).toBeNull();
129
+ }
130
+ await fireEvent.click(trigger);
131
+ } else {
132
+ await fireEvent.keyDown(trigger, { key: interaction });
133
+ }
134
+ expect(openInspector).toHaveBeenCalledExactlyOnceWith(expectedRequest);
135
+ await waitFor(() => expect(screen.queryByRole("menu")).toBeNull());
136
+ },
137
+ );
138
+
139
+ it.each(["hover", "keyboard"])(
140
+ "preserves the appropriate focus when opening by %s",
141
+ async (interaction) => {
142
+ renderMessage({
143
+ before: () => h("textarea", { "aria-label": "Chat input" }),
144
+ });
145
+ const input = screen.getByRole("textbox", { name: "Chat input" });
146
+ input.focus();
147
+ const trigger = screen.getByTestId("copilot-inspector-button");
148
+ if (interaction === "hover") {
149
+ await fireEvent.pointerEnter(trigger, { pointerType: "mouse" });
150
+ } else {
151
+ trigger.focus();
152
+ await fireEvent.keyDown(trigger, { key: "ArrowDown" });
153
+ }
154
+ const menu = await screen.findByRole("menu");
155
+ if (interaction === "hover") {
156
+ expect(document.activeElement).toBe(input);
157
+ } else {
158
+ await waitFor(() =>
159
+ expect(menu.contains(document.activeElement)).toBe(true),
160
+ );
161
+ }
162
+ },
163
+ );
164
+
165
+ it("Escape closes a keyboard-opened menu and returns focus to the button", async () => {
166
+ renderMessage();
167
+ const trigger = screen.getByTestId("copilot-inspector-button");
168
+ trigger.focus();
169
+ await fireEvent.keyDown(trigger, { key: "ArrowDown" });
170
+ const menu = await screen.findByRole("menu");
171
+ await waitFor(() =>
172
+ expect(menu.contains(document.activeElement)).toBe(true),
173
+ );
174
+
175
+ await fireEvent.keyDown(document.activeElement!, { key: "Escape" });
176
+
177
+ await waitFor(() => expect(screen.queryByRole("menu")).toBeNull());
178
+ expect(document.activeElement).toBe(trigger);
179
+ });
180
+
181
+ it("dismisses the hover menu when the pointer leaves", async () => {
182
+ renderMessage();
183
+ const trigger = screen.getByTestId("copilot-inspector-button");
184
+ await fireEvent.pointerEnter(trigger, { pointerType: "mouse" });
185
+ const menu = await screen.findByRole("menu");
186
+ await fireEvent.pointerLeave(trigger, { pointerType: "mouse" });
187
+ await fireEvent.pointerEnter(menu, { pointerType: "mouse" });
188
+ await new Promise((resolve) => setTimeout(resolve, 220));
189
+ expect(screen.getByRole("menu")).toBeDefined();
190
+ await fireEvent.pointerLeave(menu, { pointerType: "mouse" });
191
+ await waitFor(() => expect(screen.queryByRole("menu")).toBeNull());
192
+ });
193
+
194
+ it("hides the shortcut until the page reloads", async () => {
195
+ renderMessage();
196
+ await fireEvent.pointerEnter(
197
+ screen.getByTestId("copilot-inspector-button"),
198
+ { pointerType: "mouse" },
199
+ );
200
+
201
+ await fireEvent.click(
202
+ await screen.findByRole("menuitem", {
203
+ name: "Hide this icon Until you reload this page",
204
+ }),
205
+ );
206
+ await nextTick();
207
+
208
+ expect(screen.queryByTestId("copilot-inspector-button")).toBeNull();
209
+ });
210
+
211
+ it("replaces the default Inspector button with the inspector-button slot", async () => {
212
+ const { openInspector } = renderMessage({
213
+ slots: {
214
+ "inspector-button": ({ onInspect }: { onInspect: () => void }) =>
215
+ h("button", { type: "button", onClick: onInspect }, "Custom inspect"),
216
+ },
217
+ });
218
+
219
+ expect(screen.queryByTestId("copilot-inspector-button")).toBeNull();
220
+ await fireEvent.click(
221
+ screen.getByRole("button", { name: "Custom inspect" }),
222
+ );
223
+ expect(openInspector).toHaveBeenCalledExactlyOnceWith(expectedRequest);
224
+ });
225
+
226
+ it("does not render the inspector-button slot while the Inspector is off", () => {
227
+ renderMessage({
228
+ enabled: false,
229
+ slots: {
230
+ "inspector-button": () => h("button", "Custom inspect"),
231
+ },
232
+ });
233
+
234
+ expect(screen.queryByRole("button", { name: "Custom inspect" })).toBeNull();
235
+ });
236
+ });
237
+
238
+ describe("CopilotChatAssistantMessage toolbar tooltips", () => {
239
+ afterEach(() => {
240
+ document.body.innerHTML = "";
241
+ });
242
+
243
+ it("shows each toolbar label as a tooltip instead of a title", async () => {
244
+ render(
245
+ defineComponent({
246
+ setup: () => () =>
247
+ h(CopilotKitProvider, null, {
248
+ default: () =>
249
+ h(CopilotChatAssistantMessage as Component, {
250
+ message,
251
+ onRegenerate: () => {},
252
+ }),
253
+ }),
254
+ }),
255
+ );
256
+ const copy = screen.getByTestId("copilot-copy-button");
257
+ expect(copy.hasAttribute("title")).toBe(false);
258
+
259
+ await fireEvent.focus(copy);
260
+ const tooltip = screen.getByRole("tooltip");
261
+ expect(tooltip.textContent).toBe("Copy");
262
+ expect(tooltip.getAttribute("data-side")).toBe("bottom");
263
+ expect(copy.getAttribute("aria-describedby")).toBe(tooltip.id);
264
+ await fireEvent.blur(copy);
265
+
266
+ await fireEvent.focus(screen.getByRole("button", { name: "Regenerate" }));
267
+ expect(screen.getByRole("tooltip").textContent).toBe("Regenerate");
268
+ });
269
+ });