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

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
@@ -1,5 +1,14 @@
1
1
  <script setup lang="ts">
2
- import { computed, onBeforeUnmount, ref } from "vue";
2
+ import {
3
+ computed,
4
+ inject,
5
+ onBeforeUnmount,
6
+ onUpdated,
7
+ ref,
8
+ shallowRef,
9
+ toRef,
10
+ watch,
11
+ } from "vue";
3
12
  import type { Component } from "vue";
4
13
  import type { AssistantMessage, Message } from "@ag-ui/core";
5
14
  import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
@@ -18,8 +27,18 @@ import {
18
27
  isVueComponentRenderer,
19
28
  } from "../../providers/markdown-renderer";
20
29
  import CopilotChatToolCallsView from "./CopilotChatToolCallsView.vue";
30
+ import { CopilotChatWorkText } from "./turn-work";
31
+ import CopilotChatAssistantToolbarButton from "./CopilotChatAssistantToolbarButton.vue";
32
+ import CopilotChatFeedbackCommentPopover from "./CopilotChatFeedbackCommentPopover.vue";
33
+ import CopilotChatInspectorButton from "./CopilotChatInspectorButton.vue";
34
+ import { useInspectorShortcutsHidden } from "./inspector-shortcuts";
35
+ import { InspectorKey } from "../../providers/keys";
36
+ import { useFeedbackComment, useMessageFeedback } from "./message-feedback";
37
+ import type { MessageFeedbackRating } from "../../lib/message-feedback";
21
38
  import type {
22
39
  CopilotChatAssistantMessageCopyButtonSlotProps,
40
+ CopilotChatAssistantMessageFeedbackCommentSlotProps,
41
+ CopilotChatAssistantMessageInspectorButtonSlotProps,
23
42
  CopilotChatAssistantMessageLayoutSlotProps,
24
43
  CopilotChatAssistantMessageMessageRendererSlotProps,
25
44
  CopilotChatAssistantMessageReadAloudButtonSlotProps,
@@ -71,6 +90,12 @@ defineSlots<{
71
90
  "tool-calls-view"?: (
72
91
  props: CopilotChatAssistantMessageToolCallsViewSlotProps,
73
92
  ) => unknown;
93
+ "inspector-button"?: (
94
+ props: CopilotChatAssistantMessageInspectorButtonSlotProps,
95
+ ) => unknown;
96
+ "feedback-comment"?: (
97
+ props: CopilotChatAssistantMessageFeedbackCommentSlotProps,
98
+ ) => unknown;
74
99
  "toolbar-items"?: () => unknown;
75
100
  [key: string]: ((props: any) => unknown) | undefined;
76
101
  }>();
@@ -87,13 +112,6 @@ const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
87
112
  const copied = ref(false);
88
113
  let copiedResetTimeout: ReturnType<typeof setTimeout> | null = null;
89
114
 
90
- const toolbarButtonClass = [
91
- "cpk:inline-flex cpk:h-8 cpk:w-8 cpk:items-center cpk:justify-center cpk:rounded-md cpk:p-0",
92
- "cpk:cursor-pointer cpk:text-[rgb(93,93,93)] cpk:transition-colors cpk:hover:bg-[#E8E8E8]",
93
- "cpk:hover:text-[rgb(93,93,93)] cpk:dark:text-[rgb(243,243,243)] cpk:dark:hover:bg-[#303030]",
94
- "cpk:dark:hover:text-[rgb(243,243,243)] cpk:disabled:pointer-events-none cpk:disabled:opacity-50",
95
- ].join(" ");
96
-
97
115
  function normalizeContent(content: unknown): string {
98
116
  if (!content) {
99
117
  return "";
@@ -145,8 +163,28 @@ const activeMarkdownConfig = computed(() =>
145
163
  : (providerMarkdownRenderer as Record<string, unknown>),
146
164
  );
147
165
 
148
- const hasThumbsUp = computed(() => typeof props.onThumbsUp === "function");
149
- const hasThumbsDown = computed(() => typeof props.onThumbsDown === "function");
166
+ const inspector = inject(InspectorKey, null);
167
+ const shortcutsHidden = useInspectorShortcutsHidden();
168
+ const showInspectorShortcut = computed(
169
+ () => !!inspector?.isInspectorEnabled.value && !shortcutsHidden.value,
170
+ );
171
+
172
+ // Set while this chat collects ratings for Learning: the thumbs record them.
173
+ const feedback = useMessageFeedback(toRef(props, "message"));
174
+ const comment = useFeedbackComment(feedback);
175
+ const rating = computed(() => feedback.value?.feedback?.rating);
176
+ const root = ref<HTMLElement | null>(null);
177
+ // The chosen thumb the comment popover points at, and the rating the open
178
+ // comment answers.
179
+ const commentAnchor = shallowRef<HTMLElement | null>(null);
180
+ let commentRating = rating.value;
181
+
182
+ const hasThumbsUp = computed(
183
+ () => typeof props.onThumbsUp === "function" || !!feedback.value,
184
+ );
185
+ const hasThumbsDown = computed(
186
+ () => typeof props.onThumbsDown === "function" || !!feedback.value,
187
+ );
150
188
  const hasReadAloud = computed(() => typeof props.onReadAloud === "function");
151
189
  const hasRegenerate = computed(() => typeof props.onRegenerate === "function");
152
190
  const isLatestAssistantMessage = computed(
@@ -155,10 +193,138 @@ const isLatestAssistantMessage = computed(
155
193
  const shouldShowToolbar = computed(
156
194
  () =>
157
195
  props.toolbarVisible &&
158
- hasContent.value &&
196
+ (hasContent.value || showInspectorShortcut.value) &&
159
197
  !(props.isRunning && isLatestAssistantMessage.value),
160
198
  );
161
199
 
200
+ // A custom thumb that calls its handler without an event gives no element:
201
+ // point at the chosen thumb once it renders, before the popover reads it.
202
+ function findCommentAnchor() {
203
+ if (
204
+ comment.open.value &&
205
+ !commentAnchor.value?.isConnected &&
206
+ rating.value &&
207
+ root.value
208
+ ) {
209
+ commentAnchor.value =
210
+ root.value.querySelector<HTMLElement>(
211
+ `[data-copilotkit-rating="${rating.value}"]`,
212
+ ) ??
213
+ // A custom thumb that binds only `aria-pressed`.
214
+ root.value.querySelector<HTMLElement>('button[aria-pressed="true"]') ??
215
+ null;
216
+ }
217
+ }
218
+ onUpdated(findCommentAnchor);
219
+ watch(() => comment.open.value, findCommentAnchor, { flush: "post" });
220
+
221
+ /** Whether focus came from the keyboard; a pointer click also focuses buttons. */
222
+ function isFocusVisible(element: Element): boolean {
223
+ try {
224
+ return element.matches(":focus-visible");
225
+ } catch {
226
+ return false;
227
+ }
228
+ }
229
+
230
+ // Checks `visibility: hidden` too, which a detached popover uses.
231
+ const HIDDEN_TOO = { checkVisibilityCSS: true, visibilityProperty: true };
232
+
233
+ /**
234
+ * Thumbs are toggles: a new rating is saved and opens its comment, and
235
+ * clicking the chosen thumb again removes the rating. A keyboard click
236
+ * (`detail` 0) moves focus into the comment, as there is no pointer. Custom
237
+ * thumb slots may call the handler without an event.
238
+ *
239
+ * @returns Whether the app's handler should run: true for a new rating and
240
+ * whenever this chat does not record ratings, false when one is removed.
241
+ */
242
+ function rate(value: MessageFeedbackRating, event?: MouseEvent): boolean {
243
+ const controls = feedback.value;
244
+ if (!controls) return true;
245
+ if (rating.value === value) {
246
+ comment.close({ save: false });
247
+ controls.clear();
248
+ return false;
249
+ }
250
+ controls.rate(value);
251
+ commentRating = value;
252
+ commentAnchor.value =
253
+ event?.currentTarget instanceof HTMLElement ? event.currentTarget : null;
254
+ comment.show({ comment: "", focus: event?.detail === 0 });
255
+ return true;
256
+ }
257
+
258
+ /** Attributes that let the chosen thumb open and point at its comment. */
259
+ function thumbFeedbackProps(
260
+ value: MessageFeedbackRating,
261
+ ): Record<string, unknown> {
262
+ if (!feedback.value) return {};
263
+ const thumb = { "data-copilotkit-rating": value };
264
+ if (rating.value !== value) return { ...thumb, "aria-pressed": false };
265
+ const enter = (target: HTMLElement, via: "pointer" | "focus") => {
266
+ if (!comment.open.value) commentRating = value;
267
+ commentAnchor.value = target;
268
+ comment.enter(via);
269
+ };
270
+ return {
271
+ ...thumb,
272
+ "aria-pressed": true,
273
+ "aria-haspopup": "dialog",
274
+ "aria-expanded": comment.open.value,
275
+ onPointerenter: (event: PointerEvent) => {
276
+ if (event.pointerType !== "touch")
277
+ enter(event.currentTarget as HTMLElement, "pointer");
278
+ },
279
+ onPointerleave: (event: PointerEvent) => {
280
+ if (event.pointerType !== "touch") comment.leave("pointer");
281
+ },
282
+ // Keyboard focus opens the comment; Tab moves on into its field.
283
+ onFocus: (event: FocusEvent) => {
284
+ const target = event.currentTarget as HTMLElement;
285
+ if (isFocusVisible(target)) enter(target, "focus");
286
+ },
287
+ onBlur: () => comment.leave(),
288
+ onKeydown: (event: KeyboardEvent) => {
289
+ const input = comment.input.value;
290
+ // Not while the popover hides because its thumb scrolled away.
291
+ if (
292
+ event.key === "Tab" &&
293
+ !event.shiftKey &&
294
+ comment.open.value &&
295
+ input &&
296
+ input.checkVisibility?.(HIDDEN_TOO) !== false
297
+ ) {
298
+ event.preventDefault();
299
+ input.focus();
300
+ }
301
+ },
302
+ };
303
+ }
304
+
305
+ const thumbsUpProps = computed(() => thumbFeedbackProps("up"));
306
+ const thumbsDownProps = computed(() => thumbFeedbackProps("down"));
307
+
308
+ // The popover shows only with the toolbar and a rating. Hiding the toolbar
309
+ // keeps the edit; a rating removed elsewhere or Learning turned off ends it.
310
+ watch(
311
+ [() => comment.open.value, shouldShowToolbar, rating],
312
+ ([open, showToolbar, currentRating]) => {
313
+ if (!open) return;
314
+ // Changed or removed elsewhere: the draft answered the old rating.
315
+ if (currentRating !== commentRating) comment.close({ save: false });
316
+ else if (!showToolbar) comment.close();
317
+ },
318
+ );
319
+
320
+ function handleInspect() {
321
+ inspector?.openInspector({
322
+ messageId: props.message.id,
323
+ threadId: config.value?.threadId,
324
+ agentId: config.value?.agentId,
325
+ });
326
+ }
327
+
162
328
  function resetCopiedStateWithDelay() {
163
329
  if (copiedResetTimeout) {
164
330
  clearTimeout(copiedResetTimeout);
@@ -189,12 +355,13 @@ async function handleCopyMessage() {
189
355
  }
190
356
  }
191
357
 
192
- function handleThumbsUp() {
193
- emit("thumbs-up", props.message);
358
+ function handleThumbsUp(event?: MouseEvent) {
359
+ // The app hears about a rating given, not about one removed.
360
+ if (rate("up", event)) emit("thumbs-up", props.message);
194
361
  }
195
362
 
196
- function handleThumbsDown() {
197
- emit("thumbs-down", props.message);
363
+ function handleThumbsDown(event?: MouseEvent) {
364
+ if (rate("down", event)) emit("thumbs-down", props.message);
198
365
  }
199
366
 
200
367
  function handleReadAloud() {
@@ -235,25 +402,30 @@ onBeforeUnmount(() => {
235
402
  :on-regenerate="handleRegenerate"
236
403
  >
237
404
  <div
405
+ ref="root"
238
406
  data-copilotkit
239
407
  data-testid="copilot-assistant-message"
240
- class="cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert"
408
+ class="copilotKitMessage copilotKitAssistantMessage"
241
409
  :data-message-id="message.id"
242
410
  v-bind="$attrs"
243
411
  >
244
- <slot
245
- name="message-renderer"
246
- :message="message"
247
- :content="normalizedContent"
248
- >
249
- <component
250
- :is="ActiveMarkdownRenderer"
251
- v-if="hasContent"
252
- v-bind="activeMarkdownConfig"
253
- :content="normalizedContent"
254
- :is-streaming="isRunning && isLatestAssistantMessage"
255
- />
256
- </slot>
412
+ <CopilotChatWorkText :message-id="message.id">
413
+ <div class="cpk-markdown cpk-assistant-message-markdown">
414
+ <slot
415
+ name="message-renderer"
416
+ :message="message"
417
+ :content="normalizedContent"
418
+ >
419
+ <component
420
+ :is="ActiveMarkdownRenderer"
421
+ v-if="hasContent"
422
+ v-bind="activeMarkdownConfig"
423
+ :content="normalizedContent"
424
+ :is-streaming="isRunning && isLatestAssistantMessage"
425
+ />
426
+ </slot>
427
+ </div>
428
+ </CopilotChatWorkText>
257
429
 
258
430
  <slot name="tool-calls-view" :message="message" :messages="messages">
259
431
  <CopilotChatToolCallsView :message="message" :messages="messages">
@@ -274,26 +446,27 @@ onBeforeUnmount(() => {
274
446
  :should-show-toolbar="shouldShowToolbar"
275
447
  >
276
448
  <div
277
- class="cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]"
449
+ data-testid="copilot-assistant-toolbar"
450
+ class="cpk-assistant-message-toolbar"
278
451
  >
279
- <div class="cpk:flex cpk:items-center cpk:gap-1">
452
+ <div class="cpk-assistant-message-toolbar-items">
280
453
  <slot
281
454
  name="copy-button"
282
455
  :on-copy="handleCopyMessage"
283
456
  :copied="copied"
284
457
  :label="labels.assistantMessageToolbarCopyMessageLabel"
285
458
  >
286
- <button
459
+ <CopilotChatAssistantToolbarButton
287
460
  data-testid="copilot-copy-button"
288
- type="button"
289
- :class="toolbarButtonClass"
290
- :aria-label="labels.assistantMessageToolbarCopyMessageLabel"
291
- :title="labels.assistantMessageToolbarCopyMessageLabel"
461
+ :label="labels.assistantMessageToolbarCopyMessageLabel"
292
462
  @click="handleCopyMessage"
293
463
  >
294
- <IconCheck v-if="copied" class="cpk:size-[18px]" />
295
- <IconCopy v-else class="cpk:size-[18px]" />
296
- </button>
464
+ <IconCheck
465
+ v-if="copied"
466
+ class="cpk-assistant-message-toolbar-icon"
467
+ />
468
+ <IconCopy v-else class="cpk-assistant-message-toolbar-icon" />
469
+ </CopilotChatAssistantToolbarButton>
297
470
  </slot>
298
471
 
299
472
  <slot
@@ -301,16 +474,20 @@ onBeforeUnmount(() => {
301
474
  name="thumbs-up-button"
302
475
  :on-thumbs-up="handleThumbsUp"
303
476
  :label="labels.assistantMessageToolbarThumbsUpLabel"
477
+ :pressed="rating === 'up'"
478
+ :thumb-props="thumbsUpProps"
304
479
  >
305
- <button
306
- type="button"
307
- :class="toolbarButtonClass"
308
- :aria-label="labels.assistantMessageToolbarThumbsUpLabel"
309
- :title="labels.assistantMessageToolbarThumbsUpLabel"
480
+ <CopilotChatAssistantToolbarButton
481
+ data-testid="copilot-thumbs-up-button"
482
+ :label="labels.assistantMessageToolbarThumbsUpLabel"
483
+ v-bind="thumbsUpProps"
310
484
  @click="handleThumbsUp"
311
485
  >
312
- <IconThumbsUp class="cpk:size-[18px]" />
313
- </button>
486
+ <IconThumbsUp
487
+ class="cpk-assistant-message-toolbar-icon"
488
+ :fill="rating === 'up' ? 'currentColor' : 'none'"
489
+ />
490
+ </CopilotChatAssistantToolbarButton>
314
491
  </slot>
315
492
 
316
493
  <slot
@@ -318,16 +495,20 @@ onBeforeUnmount(() => {
318
495
  name="thumbs-down-button"
319
496
  :on-thumbs-down="handleThumbsDown"
320
497
  :label="labels.assistantMessageToolbarThumbsDownLabel"
498
+ :pressed="rating === 'down'"
499
+ :thumb-props="thumbsDownProps"
321
500
  >
322
- <button
323
- type="button"
324
- :class="toolbarButtonClass"
325
- :aria-label="labels.assistantMessageToolbarThumbsDownLabel"
326
- :title="labels.assistantMessageToolbarThumbsDownLabel"
501
+ <CopilotChatAssistantToolbarButton
502
+ data-testid="copilot-thumbs-down-button"
503
+ :label="labels.assistantMessageToolbarThumbsDownLabel"
504
+ v-bind="thumbsDownProps"
327
505
  @click="handleThumbsDown"
328
506
  >
329
- <IconThumbsDown class="cpk:size-[18px]" />
330
- </button>
507
+ <IconThumbsDown
508
+ class="cpk-assistant-message-toolbar-icon"
509
+ :fill="rating === 'down' ? 'currentColor' : 'none'"
510
+ />
511
+ </CopilotChatAssistantToolbarButton>
331
512
  </slot>
332
513
 
333
514
  <slot
@@ -336,15 +517,13 @@ onBeforeUnmount(() => {
336
517
  :on-read-aloud="handleReadAloud"
337
518
  :label="labels.assistantMessageToolbarReadAloudLabel"
338
519
  >
339
- <button
340
- type="button"
341
- :class="toolbarButtonClass"
342
- :aria-label="labels.assistantMessageToolbarReadAloudLabel"
343
- :title="labels.assistantMessageToolbarReadAloudLabel"
520
+ <CopilotChatAssistantToolbarButton
521
+ data-testid="copilot-read-aloud-button"
522
+ :label="labels.assistantMessageToolbarReadAloudLabel"
344
523
  @click="handleReadAloud"
345
524
  >
346
- <IconVolume2 class="cpk:size-[20px]" />
347
- </button>
525
+ <IconVolume2 class="cpk-assistant-message-read-aloud-icon" />
526
+ </CopilotChatAssistantToolbarButton>
348
527
  </slot>
349
528
 
350
529
  <slot
@@ -353,21 +532,42 @@ onBeforeUnmount(() => {
353
532
  :on-regenerate="handleRegenerate"
354
533
  :label="labels.assistantMessageToolbarRegenerateLabel"
355
534
  >
356
- <button
357
- type="button"
358
- :class="toolbarButtonClass"
359
- :aria-label="labels.assistantMessageToolbarRegenerateLabel"
360
- :title="labels.assistantMessageToolbarRegenerateLabel"
535
+ <CopilotChatAssistantToolbarButton
536
+ data-testid="copilot-regenerate-button"
537
+ :label="labels.assistantMessageToolbarRegenerateLabel"
361
538
  @click="handleRegenerate"
362
539
  >
363
- <IconRefreshCw class="cpk:size-[18px]" />
364
- </button>
540
+ <IconRefreshCw class="cpk-assistant-message-toolbar-icon" />
541
+ </CopilotChatAssistantToolbarButton>
365
542
  </slot>
366
543
 
367
544
  <slot name="toolbar-items" />
545
+
546
+ <slot
547
+ v-if="showInspectorShortcut"
548
+ name="inspector-button"
549
+ :on-inspect="handleInspect"
550
+ :label="labels.assistantMessageToolbarInspectorLabel"
551
+ >
552
+ <CopilotChatInspectorButton @click="handleInspect" />
553
+ </slot>
368
554
  </div>
369
555
  </div>
370
556
  </slot>
371
557
  </div>
372
558
  </slot>
559
+
560
+ <!-- Floats in a portal next to the chosen thumb, so it never moves the chat. -->
561
+ <CopilotChatFeedbackCommentPopover
562
+ v-if="feedback?.feedback && shouldShowToolbar"
563
+ :comment="comment"
564
+ :saved-comment="feedback.feedback.comment ?? ''"
565
+ :rating="feedback.feedback.rating"
566
+ :anchor="commentAnchor"
567
+ :message-id="message.id"
568
+ >
569
+ <template v-if="$slots['feedback-comment']" #feedback-comment="slotProps">
570
+ <slot name="feedback-comment" v-bind="slotProps" />
571
+ </template>
572
+ </CopilotChatFeedbackCommentPopover>
373
573
  </template>
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * React's `CopilotChatAssistantMessage.ToolbarButton`: an icon button named by
4
+ * `label`, with the label as its tooltip. While the button's own popup is
5
+ * open (`aria-expanded="true"`), the popup replaces the tooltip: an open
6
+ * tooltip closes, and it does not reappear when the popup closes under a
7
+ * pointer that left.
8
+ *
9
+ * @internal
10
+ */
11
+ import { computed, mergeProps, useAttrs } from "vue";
12
+ import CopilotTooltip from "../ui/CopilotTooltip.vue";
13
+
14
+ defineOptions({ inheritAttrs: false });
15
+
16
+ defineProps<{ label: string }>();
17
+
18
+ defineSlots<{ default(): unknown; tooltip?(): unknown }>();
19
+
20
+ const attrs = useAttrs();
21
+ const popupOpen = computed(
22
+ () => attrs["aria-expanded"] === true || attrs["aria-expanded"] === "true",
23
+ );
24
+
25
+ // Styles live in @copilotkit/core (ui/button.css, assistant-message.css).
26
+ const buttonClass =
27
+ "cpk-button cpk-button-assistant-message-toolbar cpk-button-size-default";
28
+ </script>
29
+
30
+ <template>
31
+ <CopilotTooltip :content="label" side="bottom" :suppressed="popupOpen">
32
+ <template #default="{ triggerProps }">
33
+ <button
34
+ type="button"
35
+ :class="buttonClass"
36
+ :aria-label="label"
37
+ v-bind="mergeProps(triggerProps, $attrs)"
38
+ >
39
+ <slot />
40
+ </button>
41
+ </template>
42
+ <template v-if="$slots.tooltip" #content>
43
+ <slot name="tooltip" />
44
+ </template>
45
+ </CopilotTooltip>
46
+ </template>