@copilotkit/vue 2.0.0-rc.19 → 2.0.0-rc.20

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 (73) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.mjs +2 -2
  3. package/dist/use-render-activity-message-CsWYyd6r.cjs +91 -0
  4. package/dist/use-render-activity-message-CsWYyd6r.cjs.map +1 -0
  5. package/dist/{use-render-activity-message-g7xEf4ep.js → use-render-activity-message-DntKKNdd.js} +6354 -6747
  6. package/dist/use-render-activity-message-DntKKNdd.js.map +1 -0
  7. package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -1
  8. package/dist/v2/components/LicenseWarningBanner.vue.d.ts +2 -2
  9. package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
  10. package/dist/v2/components/chat/CopilotChat.vue.d.ts +1 -1
  11. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  12. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +1 -1
  13. package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -1
  14. package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -1
  15. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  16. package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
  17. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +1 -1
  18. package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -1
  19. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  20. package/dist/v2/components/chat/CopilotPopup.vue.d.ts +1 -1
  21. package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +1 -1
  22. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +1 -1
  23. package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +1 -1
  24. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +1 -1
  25. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +1 -1
  26. package/dist/v2/components/chat/index.d.ts +12 -12
  27. package/dist/v2/components/chat/inspector-shortcuts.d.ts +2 -1
  28. package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -1
  29. package/dist/v2/components/chat/message-feedback.d.ts +18 -49
  30. package/dist/v2/components/chat/message-feedback.d.ts.map +1 -1
  31. package/dist/v2/components/chat/normalize-auto-scroll.d.ts +2 -2
  32. package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +1 -1
  33. package/dist/v2/components/chat/use-copy-feedback.d.ts +11 -0
  34. package/dist/v2/components/chat/use-copy-feedback.d.ts.map +1 -0
  35. package/dist/v2/hooks/use-keyboard-height.d.ts +1 -1
  36. package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -1
  37. package/dist/v2/hooks/use-pin-to-send.d.ts +4 -12
  38. package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -1
  39. package/dist/v2/index.cjs +1 -1
  40. package/dist/v2/index.mjs +1 -1
  41. package/dist/v2/lib/is-mobile-viewport.d.ts +1 -14
  42. package/dist/v2/lib/is-mobile-viewport.d.ts.map +1 -1
  43. package/dist/v2/lib/shallow-stable.d.ts.map +1 -1
  44. package/package.json +8 -8
  45. package/src/v2/components/InlineFeatureWarning.vue +20 -21
  46. package/src/v2/components/LicenseWarningBanner.vue +25 -149
  47. package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +48 -8
  48. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +19 -43
  49. package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +2 -2
  50. package/src/v2/components/chat/CopilotChatInspectorButton.vue +45 -108
  51. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +2 -28
  52. package/src/v2/components/chat/CopilotChatUserMessage.vue +24 -112
  53. package/src/v2/components/chat/CopilotChatWorkSummary.vue +23 -59
  54. package/src/v2/components/chat/CopilotModalHeader.vue +11 -23
  55. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +5 -5
  56. package/src/v2/components/chat/inspector-shortcuts.ts +10 -16
  57. package/src/v2/components/chat/message-feedback.ts +62 -197
  58. package/src/v2/components/chat/normalize-auto-scroll.ts +3 -17
  59. package/src/v2/components/chat/use-copy-feedback.ts +21 -0
  60. package/src/v2/hooks/use-keyboard-height.ts +17 -40
  61. package/src/v2/hooks/use-pin-to-send.ts +15 -99
  62. package/src/v2/lib/__tests__/shallow-stable.test.ts +54 -0
  63. package/src/v2/lib/is-mobile-viewport.ts +5 -23
  64. package/src/v2/lib/shallow-stable.ts +2 -16
  65. package/dist/use-render-activity-message-IH90zF01.cjs +0 -92
  66. package/dist/use-render-activity-message-IH90zF01.cjs.map +0 -1
  67. package/dist/use-render-activity-message-g7xEf4ep.js.map +0 -1
  68. package/dist/v2/lib/message-feedback.d.ts +0 -33
  69. package/dist/v2/lib/message-feedback.d.ts.map +0 -1
  70. package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -39
  71. package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +0 -48
  72. package/src/v2/lib/__tests__/message-feedback.test.ts +0 -152
  73. package/src/v2/lib/message-feedback.ts +0 -120
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@copilotkit/vue",
3
- "version": "2.0.0-rc.19",
3
+ "version": "2.0.0-rc.20",
4
4
  "private": false,
5
5
  "description": "Vue 3 components and composables for CopilotKit",
6
6
  "keywords": [
@@ -61,13 +61,13 @@
61
61
  "@a2ui/web_core": "0.10.4",
62
62
  "@ag-ui/client": "1.0.2",
63
63
  "@ag-ui/core": "1.0.2",
64
- "@copilotkit/a2ui-renderer": "2.0.0-rc.19",
65
- "@copilotkit/core": "2.0.0-rc.19",
66
- "@copilotkit/markdown": "2.0.0-rc.19",
67
- "@copilotkit/mcp-apps-renderer": "2.0.0-rc.19",
68
- "@copilotkit/shared": "2.0.0-rc.19",
69
- "@copilotkit/web-components": "2.0.0-rc.19",
70
- "@copilotkit/web-inspector": "2.0.0-rc.19",
64
+ "@copilotkit/a2ui-renderer": "2.0.0-rc.20",
65
+ "@copilotkit/core": "2.0.0-rc.20",
66
+ "@copilotkit/markdown": "2.0.0-rc.20",
67
+ "@copilotkit/mcp-apps-renderer": "2.0.0-rc.20",
68
+ "@copilotkit/shared": "2.0.0-rc.20",
69
+ "@copilotkit/web-components": "2.0.0-rc.20",
70
+ "@copilotkit/web-inspector": "2.0.0-rc.20",
71
71
  "zod": "^4.2.0"
72
72
  },
73
73
  "devDependencies": {
@@ -1,35 +1,34 @@
1
1
  <script setup lang="ts">
2
- defineProps<{
2
+ import { computed } from "vue";
3
+ import {
4
+ ɵINLINE_FEATURE_WARNING_STYLE,
5
+ ɵgetInlineFeatureWarningSpec,
6
+ } from "@copilotkit/core";
7
+ import { useChatLabels } from "./chat/use-chat-labels";
8
+
9
+ const props = defineProps<{
3
10
  featureName: string;
4
11
  }>();
5
12
 
6
- const containerStyle = {
7
- padding: "8px 12px",
8
- backgroundColor: "#fffbeb",
9
- border: "1px solid #fbbf24",
10
- borderRadius: "6px",
11
- fontSize: "13px",
12
- color: "#92400e",
13
- fontFamily:
14
- "-apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif",
15
- } as const;
16
-
17
- const linkStyle = {
18
- color: "#b45309",
19
- textDecoration: "underline",
20
- } as const;
13
+ const labels = useChatLabels();
14
+ const spec = computed(() =>
15
+ ɵgetInlineFeatureWarningSpec(props.featureName, labels.value),
16
+ );
21
17
  </script>
22
18
 
23
19
  <template>
24
- <div :style="containerStyle" data-testid="copilot-inline-feature-warning">
25
- ⚠ The "{{ featureName }}" feature requires a CopilotKit license.
20
+ <div
21
+ :style="ɵINLINE_FEATURE_WARNING_STYLE.container"
22
+ data-testid="copilot-inline-feature-warning"
23
+ >
24
+ {{ spec.message }}
26
25
  <a
27
- href="https://copilotkit.ai/pricing"
26
+ :href="spec.actionUrl"
28
27
  target="_blank"
29
28
  rel="noopener noreferrer"
30
- :style="linkStyle"
29
+ :style="ɵINLINE_FEATURE_WARNING_STYLE.link"
31
30
  >
32
- Get one at copilotkit.ai/pricing
31
+ {{ spec.actionLabel }}
33
32
  </a>
34
33
  </div>
35
34
  </template>
@@ -1,23 +1,16 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, onBeforeUnmount, onMounted } from "vue";
3
- import { ɵformatLabel } from "@copilotkit/core";
3
+ import {
4
+ ɵLICENSE_BANNER_STYLE,
5
+ ɵgetLicenseBannerSpec,
6
+ ɵreserveLicenseBannerOffset,
7
+ } from "@copilotkit/core";
8
+ import type { ɵLicenseBannerType } from "@copilotkit/core";
4
9
  import { useChatLabels } from "./chat/use-chat-labels";
5
10
 
6
- // Total reserved vertical space for the fixed license banner: banner height
7
- // (~36px) + bottom offset (8px) + visual gap above the chat input (~8px).
8
- const LICENSE_BANNER_OFFSET_PX = 52;
9
- const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
10
-
11
- type LicenseBannerType =
12
- | "no_license"
13
- | "expired"
14
- | "expiring"
15
- | "invalid"
16
- | "feature_unlicensed";
17
-
18
11
  const props = withDefaults(
19
12
  defineProps<{
20
- type: LicenseBannerType;
13
+ type: ɵLicenseBannerType;
21
14
  featureName?: string;
22
15
  expiryDate?: string;
23
16
  graceRemaining?: number;
@@ -31,166 +24,49 @@ const props = withDefaults(
31
24
  },
32
25
  );
33
26
 
34
- interface BannerSpec {
35
- severity: "info" | "warning" | "critical";
36
- message: string;
37
- actionLabel: string;
38
- actionUrl: string;
39
- }
40
-
41
27
  const labels = useChatLabels();
42
28
 
43
- function expiringMessage(days: number | undefined) {
44
- if (days === undefined) return labels.value.licenseExpiringText;
45
- const template =
46
- days === 1
47
- ? labels.value.licenseExpiringInDaysOne
48
- : labels.value.licenseExpiringInDaysOther;
49
- return ɵformatLabel(template, { days });
50
- }
51
-
52
- const spec = computed<BannerSpec | null>(() => {
53
- const text = labels.value;
54
- switch (props.type) {
55
- case "no_license":
56
- return {
57
- severity: "info",
58
- message: text.licensePoweredByText,
59
- actionLabel: text.licenseGetLicenseLabel,
60
- actionUrl: "https://copilotkit.ai/pricing",
61
- };
62
- case "feature_unlicensed":
63
- return {
64
- severity: "warning",
65
- message: ɵformatLabel(text.licenseFeatureUnlicensedText, {
66
- feature: props.featureName ?? "",
67
- }),
68
- actionLabel: text.licenseGetLicenseLabel,
69
- actionUrl: "https://copilotkit.ai/pricing",
70
- };
71
- case "expiring":
72
- return {
73
- severity: "warning",
74
- message: expiringMessage(props.graceRemaining),
75
- actionLabel: text.licenseRenewLabel,
76
- actionUrl: "https://dashboard.operations.copilotkit.ai",
77
- };
78
- case "expired":
79
- return {
80
- severity: "critical",
81
- message: props.expiryDate
82
- ? ɵformatLabel(text.licenseExpiredOnDateText, {
83
- date: props.expiryDate,
84
- })
85
- : text.licenseExpiredText,
86
- actionLabel: text.licenseRenewNowLabel,
87
- actionUrl: "https://copilotkit.ai/pricing",
88
- };
89
- case "invalid":
90
- return {
91
- severity: "critical",
92
- message: text.licenseInvalidText,
93
- actionLabel: text.licenseGetLicenseLabel,
94
- actionUrl: "https://copilotkit.ai/pricing",
95
- };
96
- default:
97
- return null;
98
- }
99
- });
100
-
101
- const baseStyle = {
102
- position: "fixed",
103
- bottom: "8px",
104
- left: "50%",
105
- transform: "translateX(-50%)",
106
- zIndex: 99999,
107
- display: "inline-flex",
108
- alignItems: "center",
109
- gap: "12px",
110
- whiteSpace: "nowrap",
111
- padding: "8px 16px",
112
- fontSize: "13px",
113
- fontFamily:
114
- "-apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif",
115
- borderRadius: "6px",
116
- boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
117
- } as const;
118
-
119
- const severityStyle = computed(() => {
120
- switch (spec.value?.severity) {
121
- case "warning":
122
- return {
123
- backgroundColor: "#fffbeb",
124
- border: "1px solid #fbbf24",
125
- color: "#92400e",
126
- };
127
- case "critical":
128
- return {
129
- backgroundColor: "#fef2f2",
130
- border: "1px solid #fca5a5",
131
- color: "#991b1b",
132
- };
133
- default:
134
- return {
135
- backgroundColor: "#eff6ff",
136
- border: "1px solid #93c5fd",
137
- color: "#1e40af",
138
- };
139
- }
140
- });
29
+ // Core picks the text, link, and severity; this component renders them.
30
+ const spec = computed(() =>
31
+ ɵgetLicenseBannerSpec(props.type, labels.value, {
32
+ featureName: props.featureName,
33
+ expiryDate: props.expiryDate,
34
+ graceRemaining: props.graceRemaining,
35
+ }),
36
+ );
141
37
 
142
38
  const containerStyle = computed(() => ({
143
- ...baseStyle,
144
- ...severityStyle.value,
39
+ ...ɵLICENSE_BANNER_STYLE.base,
40
+ ...ɵLICENSE_BANNER_STYLE.severity[spec.value.severity],
145
41
  }));
146
42
 
147
43
  // Publish the banner's reserved bottom offset so the chat input can lift
148
44
  // itself above it via padding-bottom: var(--copilotkit-license-banner-offset).
45
+ let releaseOffset: (() => void) | undefined;
149
46
  onMounted(() => {
150
- if (typeof document === "undefined") return;
151
- document.documentElement.style.setProperty(
152
- LICENSE_BANNER_OFFSET_VAR,
153
- `${LICENSE_BANNER_OFFSET_PX}px`,
154
- );
47
+ releaseOffset = ɵreserveLicenseBannerOffset();
155
48
  });
156
-
157
49
  onBeforeUnmount(() => {
158
- if (typeof document === "undefined") return;
159
- document.documentElement.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
50
+ releaseOffset?.();
51
+ releaseOffset = undefined;
160
52
  });
161
53
  </script>
162
54
 
163
55
  <template>
164
- <div v-if="spec" :style="containerStyle" data-testid="copilot-license-banner">
56
+ <div :style="containerStyle" data-testid="copilot-license-banner">
165
57
  <span>{{ spec.message }}</span>
166
- <div
167
- :style="{
168
- display: 'flex',
169
- gap: '8px',
170
- alignItems: 'center',
171
- }"
172
- >
58
+ <div :style="ɵLICENSE_BANNER_STYLE.actions">
173
59
  <a
174
60
  :href="spec.actionUrl"
175
61
  target="_blank"
176
62
  rel="noopener noreferrer"
177
- :style="{
178
- fontWeight: 600,
179
- textDecoration: 'underline',
180
- color: 'inherit',
181
- }"
63
+ :style="ɵLICENSE_BANNER_STYLE.link"
182
64
  >
183
65
  {{ spec.actionLabel }}
184
66
  </a>
185
67
  <button
186
68
  v-if="props.onDismiss"
187
- :style="{
188
- background: 'none',
189
- border: 'none',
190
- cursor: 'pointer',
191
- color: 'inherit',
192
- fontSize: '16px',
193
- }"
69
+ :style="ɵLICENSE_BANNER_STYLE.dismiss"
194
70
  @click="props.onDismiss"
195
71
  >
196
72
  ×
@@ -1,7 +1,24 @@
1
1
  import { mount } from "@vue/test-utils";
2
2
  import { describe, expect, it, vi } from "vitest";
3
+ import { defineComponent, h } from "vue";
4
+ import type { CopilotChatLabels } from "@copilotkit/core";
5
+ import CopilotChatConfigurationProvider from "../../providers/CopilotChatConfigurationProvider.vue";
6
+ import InlineFeatureWarning from "../InlineFeatureWarning.vue";
3
7
  import LicenseWarningBanner from "../LicenseWarningBanner.vue";
4
8
 
9
+ /** Mounts `child` inside a chat configuration with `labels`. */
10
+ function mountWithLabels(
11
+ labels: Partial<CopilotChatLabels>,
12
+ child: () => ReturnType<typeof h>,
13
+ ) {
14
+ const Host = defineComponent({
15
+ setup: () => () =>
16
+ h(CopilotChatConfigurationProvider, { labels }, { default: child }),
17
+ });
18
+ return mount(Host);
19
+ }
20
+
21
+ // The banner text rules are covered next to core's ɵgetLicenseBannerSpec.
5
22
  describe("LicenseWarningBanner", () => {
6
23
  it("reactively renders and invokes the optional dismiss callback", async () => {
7
24
  const onDismiss = vi.fn();
@@ -21,23 +38,46 @@ describe("LicenseWarningBanner", () => {
21
38
  expect(wrapper.find("button").exists()).toBe(false);
22
39
  });
23
40
 
24
- it("says the license expires soon when the day count is unknown", () => {
41
+ it("shows the core spec's text and link", () => {
25
42
  const wrapper = mount(LicenseWarningBanner, {
26
- props: { type: "expiring" },
43
+ props: { type: "expiring", graceRemaining: 1 },
27
44
  });
28
45
 
29
46
  expect(wrapper.get("span").text()).toBe(
30
- "Your CopilotKit license expires soon. Please renew.",
47
+ "Your CopilotKit license expires in 1 day. Please renew.",
48
+ );
49
+ expect(wrapper.get("a").attributes("href")).toBe(
50
+ "https://dashboard.operations.copilotkit.ai",
31
51
  );
32
52
  });
33
53
 
34
- it("counts the days left before the license expires", () => {
35
- const wrapper = mount(LicenseWarningBanner, {
36
- props: { type: "expiring", graceRemaining: 1 },
54
+ it("uses the configured chat labels", () => {
55
+ const wrapper = mountWithLabels(
56
+ { licenseInvalidText: "Token ungültig" },
57
+ () => h(LicenseWarningBanner, { type: "invalid" }),
58
+ );
59
+
60
+ expect(wrapper.get("span").text()).toBe("Token ungültig");
61
+ });
62
+ });
63
+
64
+ describe("InlineFeatureWarning", () => {
65
+ it("shows the default feature-unlicensed label", () => {
66
+ const wrapper = mount(InlineFeatureWarning, {
67
+ props: { featureName: "Chat" },
37
68
  });
38
69
 
39
- expect(wrapper.get("span").text()).toBe(
40
- "Your CopilotKit license expires in 1 day. Please renew.",
70
+ expect(wrapper.text()).toContain(
71
+ '⚠ The "Chat" feature requires a CopilotKit license.',
41
72
  );
42
73
  });
74
+
75
+ it("uses the configured feature-unlicensed label", () => {
76
+ const wrapper = mountWithLabels(
77
+ { licenseFeatureUnlicensedText: "{feature} braucht eine Lizenz." },
78
+ () => h(InlineFeatureWarning, { featureName: "Chat" }),
79
+ );
80
+
81
+ expect(wrapper.text()).toContain("Chat braucht eine Lizenz.");
82
+ });
43
83
  });
@@ -2,7 +2,6 @@
2
2
  import {
3
3
  computed,
4
4
  inject,
5
- onBeforeUnmount,
6
5
  onUpdated,
7
6
  ref,
8
7
  shallowRef,
@@ -34,7 +33,12 @@ import CopilotChatInspectorButton from "./CopilotChatInspectorButton.vue";
34
33
  import { useInspectorShortcutsHidden } from "./inspector-shortcuts";
35
34
  import { InspectorKey } from "../../providers/keys";
36
35
  import { useFeedbackComment, useMessageFeedback } from "./message-feedback";
37
- import type { MessageFeedbackRating } from "../../lib/message-feedback";
36
+ import {
37
+ ɵhasAssistantMessageText,
38
+ ɵshouldShowAssistantToolbar,
39
+ } from "@copilotkit/core";
40
+ import type { ɵMessageFeedbackRating as MessageFeedbackRating } from "@copilotkit/core";
41
+ import { useCopyFeedback } from "./use-copy-feedback";
38
42
  import type {
39
43
  CopilotChatAssistantMessageCopyButtonSlotProps,
40
44
  CopilotChatAssistantMessageFeedbackCommentSlotProps,
@@ -109,8 +113,7 @@ const emit = defineEmits<{
109
113
 
110
114
  const config = useCopilotChatConfiguration();
111
115
  const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
112
- const copied = ref(false);
113
- let copiedResetTimeout: ReturnType<typeof setTimeout> | null = null;
116
+ const { copied, copy } = useCopyFeedback();
114
117
 
115
118
  function normalizeContent(content: unknown): string {
116
119
  if (!content) {
@@ -146,7 +149,9 @@ function normalizeContent(content: unknown): string {
146
149
  const normalizedContent = computed(() =>
147
150
  normalizeContent(props.message.content),
148
151
  );
149
- const hasContent = computed(() => normalizedContent.value.trim().length > 0);
152
+ const hasContent = computed(() =>
153
+ ɵhasAssistantMessageText(normalizedContent.value),
154
+ );
150
155
 
151
156
  const providerMarkdownRenderer = useMarkdownRenderer();
152
157
  const providerIsComponent = computed(() =>
@@ -190,11 +195,14 @@ const hasRegenerate = computed(() => typeof props.onRegenerate === "function");
190
195
  const isLatestAssistantMessage = computed(
191
196
  () => props.messages[props.messages.length - 1]?.id === props.message.id,
192
197
  );
193
- const shouldShowToolbar = computed(
194
- () =>
195
- props.toolbarVisible &&
196
- (hasContent.value || showInspectorShortcut.value) &&
197
- !(props.isRunning && isLatestAssistantMessage.value),
198
+ const shouldShowToolbar = computed(() =>
199
+ ɵshouldShowAssistantToolbar({
200
+ toolbarVisible: props.toolbarVisible,
201
+ hasContent: hasContent.value,
202
+ showInspectorShortcut: showInspectorShortcut.value,
203
+ isRunning: props.isRunning,
204
+ isLatest: isLatestAssistantMessage.value,
205
+ }),
198
206
  );
199
207
 
200
208
  // A custom thumb that calls its handler without an event gives no element:
@@ -325,34 +333,8 @@ function handleInspect() {
325
333
  });
326
334
  }
327
335
 
328
- function resetCopiedStateWithDelay() {
329
- if (copiedResetTimeout) {
330
- clearTimeout(copiedResetTimeout);
331
- }
332
- copied.value = true;
333
- copiedResetTimeout = setTimeout(() => {
334
- copied.value = false;
335
- copiedResetTimeout = null;
336
- }, 2000);
337
- }
338
-
339
336
  async function handleCopyMessage() {
340
- const content = normalizedContent.value;
341
- if (!content) return;
342
-
343
- if (
344
- typeof navigator === "undefined" ||
345
- typeof navigator.clipboard?.writeText !== "function"
346
- ) {
347
- return;
348
- }
349
-
350
- try {
351
- await navigator.clipboard.writeText(content);
352
- resetCopiedStateWithDelay();
353
- } catch (error) {
354
- console.error("Failed to copy to clipboard:", error);
355
- }
337
+ await copy(normalizedContent.value);
356
338
  }
357
339
 
358
340
  function handleThumbsUp(event?: MouseEvent) {
@@ -371,12 +353,6 @@ function handleReadAloud() {
371
353
  function handleRegenerate() {
372
354
  emit("regenerate", props.message);
373
355
  }
374
-
375
- onBeforeUnmount(() => {
376
- if (copiedResetTimeout) {
377
- clearTimeout(copiedResetTimeout);
378
- }
379
- });
380
356
  </script>
381
357
 
382
358
  <template>
@@ -12,8 +12,8 @@
12
12
  import { computed, nextTick, ref, watch } from "vue";
13
13
  import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
14
14
  import { CopilotChatDefaultLabels } from "../../providers/types";
15
- import { MESSAGE_FEEDBACK_MAX_COMMENT_LENGTH } from "../../lib/message-feedback";
16
- import type { MessageFeedbackRating } from "../../lib/message-feedback";
15
+ import { ɵMESSAGE_FEEDBACK_MAX_COMMENT_LENGTH as MESSAGE_FEEDBACK_MAX_COMMENT_LENGTH } from "@copilotkit/core";
16
+ import type { ɵMessageFeedbackRating as MessageFeedbackRating } from "@copilotkit/core";
17
17
  import CopilotPopover from "../ui/CopilotPopover.vue";
18
18
  import { IconArrowUp } from "../icons";
19
19
  import type { FeedbackComment } from "./message-feedback";