@copilotkit/vue 2.0.0-rc.2 → 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.
- package/PARITY.md +3 -3
- package/dist/hooks/use-copilot-action.d.ts.map +1 -1
- package/dist/hooks/use-frontend-tool.d.ts +1 -1
- package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
- package/dist/hooks/zod-parameters.d.ts +14 -0
- package/dist/hooks/zod-parameters.d.ts.map +1 -0
- package/dist/index.cjs +1 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +353 -16908
- package/dist/index.mjs.map +1 -1
- package/dist/use-render-activity-message-CsWYyd6r.cjs +91 -0
- package/dist/use-render-activity-message-CsWYyd6r.cjs.map +1 -0
- package/dist/use-render-activity-message-DntKKNdd.js +17418 -0
- package/dist/use-render-activity-message-DntKKNdd.js.map +1 -0
- package/dist/v2/components/InlineFeatureWarning.vue.d.ts.map +1 -1
- package/dist/v2/components/LicenseWarningBanner.vue.d.ts +2 -2
- package/dist/v2/components/LicenseWarningBanner.vue.d.ts.map +1 -1
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -45
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +13 -5
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
- package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
- package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
- package/dist/v2/components/a2ui.d.ts +3 -7
- package/dist/v2/components/a2ui.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChat.vue.d.ts +2 -2
- package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAttachmentRenderer.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatFeedbackCommentPopover.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +6 -270
- package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatInspectorButton.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatUserMessage.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts +2 -2
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatWorkSummary.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopup.vue.d.ts +8 -3
- package/dist/v2/components/chat/CopilotPopup.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopupView.vue.d.ts +5 -3
- package/dist/v2/components/chat/CopilotPopupView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts +5 -3
- package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebar.vue.d.ts +8 -3
- package/dist/v2/components/chat/CopilotSidebar.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +5 -3
- package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +5 -3
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +0 -1
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
- package/dist/v2/components/chat/forwarded-slots.d.ts +12 -0
- package/dist/v2/components/chat/forwarded-slots.d.ts.map +1 -0
- package/dist/v2/components/chat/index.d.ts +28 -25
- package/dist/v2/components/chat/index.d.ts.map +1 -1
- package/dist/v2/components/chat/inspector-shortcuts.d.ts +2 -1
- package/dist/v2/components/chat/inspector-shortcuts.d.ts.map +1 -1
- package/dist/v2/components/chat/message-feedback.d.ts +18 -49
- package/dist/v2/components/chat/message-feedback.d.ts.map +1 -1
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts +2 -2
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +1 -1
- package/dist/v2/components/chat/tool-call-display-context.d.ts +2 -19
- package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
- package/dist/v2/components/chat/tool-call-group-parts.d.ts +7 -20
- package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
- package/dist/v2/components/chat/turn-work.d.ts +0 -2
- package/dist/v2/components/chat/turn-work.d.ts.map +1 -1
- package/dist/v2/components/chat/types.d.ts +8 -3
- package/dist/v2/components/chat/types.d.ts.map +1 -1
- package/dist/v2/components/chat/use-chat-labels.d.ts +8 -0
- package/dist/v2/components/chat/use-chat-labels.d.ts.map +1 -0
- package/dist/v2/components/chat/use-copy-feedback.d.ts +11 -0
- package/dist/v2/components/chat/use-copy-feedback.d.ts.map +1 -0
- package/dist/v2/components/icons/index.d.ts +968 -1
- package/dist/v2/components/icons/index.d.ts.map +1 -1
- package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
- package/dist/v2/hooks/use-frontend-tool.d.ts +5 -0
- package/dist/v2/hooks/use-frontend-tool.d.ts.map +1 -1
- package/dist/v2/hooks/use-keyboard-height.d.ts +1 -1
- package/dist/v2/hooks/use-keyboard-height.d.ts.map +1 -1
- package/dist/v2/hooks/use-pin-to-send.d.ts +4 -12
- package/dist/v2/hooks/use-pin-to-send.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-activity-message.d.ts +13 -9
- package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-custom-messages.d.ts +5 -7
- package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.mjs +197 -200
- package/dist/v2/index.mjs.map +1 -1
- package/dist/v2/lib/is-mobile-viewport.d.ts +1 -14
- package/dist/v2/lib/is-mobile-viewport.d.ts.map +1 -1
- package/dist/v2/lib/processPartialHtml.d.ts +1 -2
- package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
- package/dist/v2/lib/shallow-stable.d.ts.map +1 -1
- package/dist/v2/lib/vue-core.d.ts +0 -1
- package/dist/v2/lib/vue-core.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.types.d.ts +0 -5
- package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/markdown-renderer.d.ts +2 -2
- package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
- package/dist/v2/providers/types.d.ts +3 -46
- package/dist/v2/providers/types.d.ts.map +1 -1
- package/dist/v2/types/human-in-the-loop.d.ts +8 -29
- package/dist/v2/types/human-in-the-loop.d.ts.map +1 -1
- package/dist/v2/types/interrupt.d.ts +1 -22
- package/dist/v2/types/interrupt.d.ts.map +1 -1
- package/dist/v2/types/vue-activity-message-renderer.d.ts +16 -15
- package/dist/v2/types/vue-activity-message-renderer.d.ts.map +1 -1
- package/dist/v2/types/vue-custom-message-renderer.d.ts +7 -16
- package/dist/v2/types/vue-custom-message-renderer.d.ts.map +1 -1
- package/dist/v2/types/vue-tool-call-renderer.d.ts +16 -35
- package/dist/v2/types/vue-tool-call-renderer.d.ts.map +1 -1
- package/package.json +10 -11
- package/src/__tests__/build-entries.test.ts +27 -0
- package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
- package/src/hooks/use-copilot-action.ts +2 -1
- package/src/hooks/use-frontend-tool.ts +3 -6
- package/src/hooks/zod-parameters.ts +162 -0
- package/src/v2/components/A2UIMessageRenderer.ts +3 -3
- package/src/v2/components/InlineFeatureWarning.vue +20 -21
- package/src/v2/components/LicenseWarningBanner.vue +27 -135
- package/src/v2/components/OpenGenerativeUIRenderer.ts +51 -373
- package/src/v2/components/__tests__/A2UICatalogContext.test.ts +1 -1
- package/src/v2/components/__tests__/LicenseWarningBanner.test.ts +60 -0
- package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +55 -6
- package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +1 -1
- package/src/v2/components/a2ui/A2UICatalogContext.ts +10 -102
- package/src/v2/components/a2ui/A2UIRecoveryStates.ts +1 -1
- package/src/v2/components/a2ui/catalog.ts +1 -0
- package/src/v2/components/a2ui/utils.ts +2 -0
- package/src/v2/components/a2ui.ts +1 -1
- package/src/v2/components/chat/CopilotChat.vue +19 -40
- package/src/v2/components/chat/CopilotChatAssistantMessage.vue +19 -43
- package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +14 -10
- package/src/v2/components/chat/CopilotChatAttachmentRenderer.vue +14 -6
- package/src/v2/components/chat/CopilotChatFeedbackCommentPopover.vue +2 -2
- package/src/v2/components/chat/CopilotChatInput.vue +40 -30
- package/src/v2/components/chat/CopilotChatInspectorButton.vue +45 -108
- package/src/v2/components/chat/CopilotChatMessageView.vue +72 -140
- package/src/v2/components/chat/CopilotChatReasoningMessage.vue +7 -15
- package/src/v2/components/chat/CopilotChatToolCallGroup.vue +60 -37
- package/src/v2/components/chat/CopilotChatToolCallItem.vue +3 -3
- package/src/v2/components/chat/CopilotChatToolCallsView.vue +15 -13
- package/src/v2/components/chat/CopilotChatUserMessage.vue +24 -112
- package/src/v2/components/chat/CopilotChatView.vue +5 -5
- package/src/v2/components/chat/CopilotChatWorkSummary.vue +26 -36
- package/src/v2/components/chat/CopilotModalHeader.vue +11 -23
- package/src/v2/components/chat/CopilotPopup.vue +23 -25
- package/src/v2/components/chat/CopilotPopupView.vue +10 -39
- package/src/v2/components/chat/CopilotPopupViewInternal.vue +14 -34
- package/src/v2/components/chat/CopilotSidebar.vue +23 -25
- package/src/v2/components/chat/CopilotSidebarView.vue +10 -39
- package/src/v2/components/chat/CopilotSidebarViewInternal.vue +14 -34
- package/src/v2/components/chat/StreamingMarkdownDefault.vue +4 -4
- package/src/v2/components/chat/__tests__/CopilotChat.labels.test.ts +19 -4
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
- package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.learningFeedback.test.ts +5 -5
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +33 -1
- package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.ts +247 -403
- package/src/v2/components/chat/__tests__/CopilotChatMessageView.toolCallDisplay.test.ts +1 -99
- package/src/v2/components/chat/__tests__/CopilotPopup.test.ts +90 -1
- package/src/v2/components/chat/__tests__/CopilotSidebar.test.ts +90 -1
- package/src/v2/components/chat/copilotChatToolCallItemRender.ts +3 -19
- package/src/v2/components/chat/forwarded-slots.ts +17 -0
- package/src/v2/components/chat/index.ts +0 -1
- package/src/v2/components/chat/inspector-shortcuts.ts +10 -16
- package/src/v2/components/chat/message-feedback.ts +62 -197
- package/src/v2/components/chat/normalize-auto-scroll.ts +3 -17
- package/src/v2/components/chat/tool-call-display-context.ts +2 -23
- package/src/v2/components/chat/tool-call-group-parts.ts +44 -85
- package/src/v2/components/chat/turn-work.ts +0 -9
- package/src/v2/components/chat/types.ts +12 -4
- package/src/v2/components/chat/use-chat-labels.ts +16 -0
- package/src/v2/components/chat/use-copy-feedback.ts +21 -0
- package/src/v2/components/icons/__tests__/icons.test.ts +72 -68
- package/src/v2/components/icons/index.ts +109 -27
- package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +62 -1
- package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +105 -0
- package/src/v2/hooks/__tests__/use-render-tool.test.ts +3 -6
- package/src/v2/hooks/__tests__/zod-regression.test.ts +5 -4
- package/src/v2/hooks/use-attachments.ts +6 -2
- package/src/v2/hooks/use-frontend-tool.ts +10 -10
- package/src/v2/hooks/use-keyboard-height.ts +17 -40
- package/src/v2/hooks/use-pin-to-send.ts +15 -99
- package/src/v2/hooks/use-render-activity-message.ts +27 -48
- package/src/v2/hooks/use-render-custom-messages.ts +14 -35
- package/src/v2/lib/__tests__/shallow-stable.test.ts +54 -0
- package/src/v2/lib/is-mobile-viewport.ts +5 -23
- package/src/v2/lib/processPartialHtml.ts +6 -21
- package/src/v2/lib/shallow-stable.ts +2 -16
- package/src/v2/lib/vue-core.ts +9 -13
- package/src/v2/providers/CopilotKitProvider.types.ts +0 -5
- package/src/v2/providers/CopilotKitProvider.vue +53 -112
- package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +1 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.headersAtSendTime.test.ts +3 -3
- package/src/v2/providers/__tests__/CopilotKitProvider.learning.test.ts +3 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +17 -33
- package/src/v2/providers/markdown-renderer.ts +2 -2
- package/src/v2/providers/types.ts +3 -49
- package/src/v2/types/__tests__/defineToolCallRenderer.test.ts +28 -33
- package/src/v2/types/defineToolCallRenderer.ts +5 -4
- package/src/v2/types/human-in-the-loop.ts +8 -32
- package/src/v2/types/interrupt.ts +7 -31
- package/src/v2/types/vue-activity-message-renderer.ts +24 -15
- package/src/v2/types/vue-custom-message-renderer.ts +12 -16
- package/src/v2/types/vue-tool-call-renderer.ts +23 -38
- package/tsconfig.json +0 -1
- package/vite.config.ts +3 -4
- package/dist/v2/components/chat/BasicMarkdown.vue.d.ts +0 -9
- package/dist/v2/components/chat/BasicMarkdown.vue.d.ts.map +0 -1
- package/dist/v2/components/chat/tool-call-layout.d.ts +0 -115
- package/dist/v2/components/chat/tool-call-layout.d.ts.map +0 -1
- package/dist/v2/lib/message-feedback.d.ts +0 -33
- package/dist/v2/lib/message-feedback.d.ts.map +0 -1
- package/dist/v2/lib/transcription-client.d.ts +0 -19
- package/dist/v2/lib/transcription-client.d.ts.map +0 -1
- package/src/v2/components/chat/BasicMarkdown.vue +0 -160
- package/src/v2/components/chat/__tests__/BasicMarkdown.test.ts +0 -69
- package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -39
- package/src/v2/components/chat/tool-call-layout.ts +0 -304
- package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +0 -48
- package/src/v2/lib/__tests__/message-feedback.test.ts +0 -152
- package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
- package/src/v2/lib/__tests__/transcription-client.test.ts +0 -67
- package/src/v2/lib/message-feedback.ts +0 -120
- package/src/v2/lib/transcription-client.ts +0 -151
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { onBeforeUnmount, readonly, ref } from "vue";
|
|
2
|
+
import { ɵCopyFeedback } from "@copilotkit/core";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The "copied" check mark of a copy button, from core's `ɵCopyFeedback`:
|
|
6
|
+
* `copy(text)` writes to the clipboard and shows the check mark for two
|
|
7
|
+
* seconds; a second copy restarts the wait.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export function useCopyFeedback() {
|
|
11
|
+
const feedback = new ɵCopyFeedback();
|
|
12
|
+
const copied = ref(feedback.getSnapshot());
|
|
13
|
+
const unsubscribe = feedback.subscribe(() => {
|
|
14
|
+
copied.value = feedback.getSnapshot();
|
|
15
|
+
});
|
|
16
|
+
onBeforeUnmount(() => {
|
|
17
|
+
unsubscribe();
|
|
18
|
+
feedback.dispose();
|
|
19
|
+
});
|
|
20
|
+
return { copied: readonly(copied), copy: feedback.copy };
|
|
21
|
+
}
|
|
@@ -1,86 +1,90 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { h } from "vue";
|
|
2
3
|
import { mount } from "@vue/test-utils";
|
|
3
|
-
import {
|
|
4
|
-
IconArrowUp,
|
|
5
|
-
IconCheck,
|
|
6
|
-
IconCheckCircle,
|
|
7
|
-
IconChevronDown,
|
|
8
|
-
IconChevronLeft,
|
|
9
|
-
IconChevronRight,
|
|
10
|
-
IconCircle,
|
|
11
|
-
IconCopy,
|
|
12
|
-
IconEdit,
|
|
13
|
-
IconLoader2,
|
|
14
|
-
IconMessageCircle,
|
|
15
|
-
IconMic,
|
|
16
|
-
IconPlus,
|
|
17
|
-
IconRefreshCw,
|
|
18
|
-
IconSquare,
|
|
19
|
-
IconThumbsDown,
|
|
20
|
-
IconThumbsUp,
|
|
21
|
-
IconVolume2,
|
|
22
|
-
IconX,
|
|
23
|
-
} from "../index";
|
|
4
|
+
import { CopilotIcon, IconCircle, IconPlay, IconX } from "../index";
|
|
24
5
|
|
|
25
|
-
describe("
|
|
26
|
-
it("
|
|
27
|
-
const
|
|
28
|
-
IconMessageCircle,
|
|
29
|
-
IconX,
|
|
30
|
-
IconChevronDown,
|
|
31
|
-
IconPlus,
|
|
32
|
-
IconMic,
|
|
33
|
-
IconArrowUp,
|
|
34
|
-
IconCheck,
|
|
35
|
-
IconSquare,
|
|
36
|
-
IconLoader2,
|
|
37
|
-
IconCopy,
|
|
38
|
-
IconEdit,
|
|
39
|
-
IconChevronLeft,
|
|
40
|
-
IconChevronRight,
|
|
41
|
-
IconThumbsUp,
|
|
42
|
-
IconThumbsDown,
|
|
43
|
-
IconVolume2,
|
|
44
|
-
IconRefreshCw,
|
|
45
|
-
IconCheckCircle,
|
|
46
|
-
IconCircle,
|
|
47
|
-
];
|
|
6
|
+
describe("CopilotIcon", () => {
|
|
7
|
+
it("draws the named icon with Lucide's classes and default attributes", () => {
|
|
8
|
+
const svg = mount(CopilotIcon, { props: { name: "X" } }).find("svg");
|
|
48
9
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
10
|
+
expect(svg.classes()).toEqual(["lucide", "lucide-x"]);
|
|
11
|
+
expect(svg.attributes()).toMatchObject({
|
|
12
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
13
|
+
width: "24",
|
|
14
|
+
height: "24",
|
|
15
|
+
viewBox: "0 0 24 24",
|
|
16
|
+
fill: "none",
|
|
17
|
+
stroke: "currentColor",
|
|
18
|
+
"stroke-width": "2",
|
|
19
|
+
"stroke-linecap": "round",
|
|
20
|
+
"stroke-linejoin": "round",
|
|
21
|
+
});
|
|
22
|
+
expect(svg.findAll("path").map((path) => path.attributes("d"))).toEqual([
|
|
23
|
+
"M18 6 6 18",
|
|
24
|
+
"m6 6 12 12",
|
|
25
|
+
]);
|
|
52
26
|
});
|
|
53
27
|
|
|
54
|
-
it("
|
|
55
|
-
const
|
|
56
|
-
const
|
|
28
|
+
it("draws circle and polygon nodes", () => {
|
|
29
|
+
const circle = mount(IconCircle).find("svg").find("circle");
|
|
30
|
+
const polygon = mount(IconPlay).find("svg").find("polygon");
|
|
57
31
|
|
|
58
|
-
expect(
|
|
59
|
-
expect(
|
|
32
|
+
expect(circle.attributes()).toMatchObject({ cx: "12", cy: "12", r: "10" });
|
|
33
|
+
expect(polygon.attributes("points")).toBe("6 3 20 12 6 21 6 3");
|
|
60
34
|
});
|
|
61
35
|
|
|
62
|
-
it("
|
|
63
|
-
const
|
|
36
|
+
it("applies size, color and stroke-width", () => {
|
|
37
|
+
const svg = mount(IconX, {
|
|
38
|
+
props: { size: 18, color: "red", strokeWidth: 1.75 },
|
|
39
|
+
}).find("svg");
|
|
40
|
+
|
|
41
|
+
expect(svg.attributes()).toMatchObject({
|
|
42
|
+
width: "18",
|
|
43
|
+
height: "18",
|
|
44
|
+
stroke: "red",
|
|
45
|
+
"stroke-width": "1.75",
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("passes other attributes to the svg after the Lucide classes", () => {
|
|
50
|
+
const svg = mount(IconX, {
|
|
64
51
|
attrs: {
|
|
65
52
|
class: "icon-class",
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"stroke-width": "1.5",
|
|
69
|
-
role: "img",
|
|
70
|
-
"aria-hidden": "true",
|
|
53
|
+
fill: "currentColor",
|
|
54
|
+
"data-testid": "close-icon",
|
|
71
55
|
style: "color: rgb(255, 0, 0);",
|
|
72
56
|
},
|
|
73
|
-
});
|
|
57
|
+
}).find("svg");
|
|
58
|
+
|
|
59
|
+
expect(svg.classes()).toEqual(["lucide", "lucide-x", "icon-class"]);
|
|
60
|
+
expect(svg.attributes("fill")).toBe("currentColor");
|
|
61
|
+
expect(svg.attributes("data-testid")).toBe("close-icon");
|
|
62
|
+
expect(svg.attributes("style")).toContain("color: rgb(255, 0, 0)");
|
|
63
|
+
});
|
|
74
64
|
|
|
75
|
-
|
|
65
|
+
it("hides an unnamed icon from screen readers", () => {
|
|
66
|
+
const svg = mount(IconX).find("svg");
|
|
76
67
|
|
|
77
|
-
expect(svg.exists()).toBe(true);
|
|
78
|
-
expect(svg.classes()).toContain("icon-class");
|
|
79
|
-
expect(svg.attributes("width")).toBe("18");
|
|
80
|
-
expect(svg.attributes("height")).toBe("20");
|
|
81
|
-
expect(svg.attributes("stroke-width")).toBe("1.5");
|
|
82
|
-
expect(svg.attributes("role")).toBe("img");
|
|
83
68
|
expect(svg.attributes("aria-hidden")).toBe("true");
|
|
84
|
-
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("keeps a named icon visible to screen readers", () => {
|
|
72
|
+
const labelled = mount(IconX, { attrs: { "aria-label": "Close" } }).find(
|
|
73
|
+
"svg",
|
|
74
|
+
);
|
|
75
|
+
const withRole = mount(IconX, { attrs: { role: "img" } }).find("svg");
|
|
76
|
+
|
|
77
|
+
expect(labelled.attributes("aria-hidden")).toBeUndefined();
|
|
78
|
+
expect(labelled.attributes("aria-label")).toBe("Close");
|
|
79
|
+
expect(withRole.attributes("aria-hidden")).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("keeps an icon with slot content visible to screen readers", () => {
|
|
83
|
+
const svg = mount(IconX, {
|
|
84
|
+
slots: { default: () => h("title", "Close") },
|
|
85
|
+
}).find("svg");
|
|
86
|
+
|
|
87
|
+
expect(svg.attributes("aria-hidden")).toBeUndefined();
|
|
88
|
+
expect(svg.find("title").text()).toBe("Close");
|
|
85
89
|
});
|
|
86
90
|
});
|
|
@@ -1,27 +1,109 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
import { defineComponent, h } from "vue";
|
|
2
|
+
import type { PropType } from "vue";
|
|
3
|
+
import { ɵcopilotIcons, ɵcopilotIconSvgAttributes } from "@copilotkit/core";
|
|
4
|
+
import type { CopilotIconName } from "@copilotkit/core";
|
|
5
|
+
|
|
6
|
+
/** True when the attributes give the icon an accessible name or role. */
|
|
7
|
+
function hasAccessibleAttribute(attributes: object) {
|
|
8
|
+
return Object.keys(attributes).some(
|
|
9
|
+
(key) => key.startsWith("aria-") || key === "role" || key === "title",
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Props that change how an icon is drawn. Other attributes go on the `<svg>`. */
|
|
14
|
+
const iconDrawProps = {
|
|
15
|
+
/** Width and height of the icon. Defaults to `24`. */
|
|
16
|
+
size: { type: [Number, String], default: 24 },
|
|
17
|
+
/** Line color. Defaults to `currentColor`. */
|
|
18
|
+
color: { type: String, default: "currentColor" },
|
|
19
|
+
/** Line width. Defaults to `2`. */
|
|
20
|
+
strokeWidth: { type: [Number, String], default: 2 },
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Draws one of the chat icons as an inline `<svg>`.
|
|
25
|
+
*
|
|
26
|
+
* The `<svg>` has the classes `lucide lucide-<icon name>`, so CSS that selects
|
|
27
|
+
* them (for example `svg.lucide-arrow-up`) keeps working. The icon is hidden
|
|
28
|
+
* from screen readers unless you give it an `aria-*` attribute, a `role` or a
|
|
29
|
+
* `title`. Other attributes, such as `class` or `fill`, go on the `<svg>`.
|
|
30
|
+
*
|
|
31
|
+
* Props:
|
|
32
|
+
* - `name`: the chat icon, for example `"ArrowUp"` or `"X"`.
|
|
33
|
+
* - `size`: width and height. Defaults to `24`.
|
|
34
|
+
* - `stroke-width`: line width. Defaults to `2`.
|
|
35
|
+
* - `color`: line color. Defaults to `currentColor`.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```vue
|
|
39
|
+
* <CopilotIcon name="ArrowUp" class="cpk-chat-input-send-icon" />
|
|
40
|
+
* <CopilotIcon name="X" aria-label="Close" />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const CopilotIcon = defineComponent({
|
|
44
|
+
name: "CopilotIcon",
|
|
45
|
+
props: {
|
|
46
|
+
/** The chat icon to draw, for example `"ArrowUp"`. */
|
|
47
|
+
name: { type: String as PropType<CopilotIconName>, required: true },
|
|
48
|
+
...iconDrawProps,
|
|
49
|
+
},
|
|
50
|
+
setup(props, { attrs, slots }) {
|
|
51
|
+
return () => {
|
|
52
|
+
const icon = ɵcopilotIcons[props.name];
|
|
53
|
+
const content = slots.default?.() ?? [];
|
|
54
|
+
const isDecorative =
|
|
55
|
+
content.length === 0 && !hasAccessibleAttribute(attrs);
|
|
56
|
+
return h(
|
|
57
|
+
"svg",
|
|
58
|
+
{
|
|
59
|
+
...ɵcopilotIconSvgAttributes,
|
|
60
|
+
width: props.size,
|
|
61
|
+
height: props.size,
|
|
62
|
+
stroke: props.color,
|
|
63
|
+
"stroke-width": props.strokeWidth,
|
|
64
|
+
class: ["lucide", `lucide-${icon.name}`],
|
|
65
|
+
"aria-hidden": isDecorative ? "true" : undefined,
|
|
66
|
+
},
|
|
67
|
+
[...icon.nodes.map((node) => h(node.tag, node.attributes)), ...content],
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Internal. Makes a component that draws one chat icon, such as `IconArrowUp`.
|
|
75
|
+
* It takes the same `size`, `color` and `stroke-width` props as `CopilotIcon`.
|
|
76
|
+
*/
|
|
77
|
+
function defineIcon(name: CopilotIconName) {
|
|
78
|
+
return defineComponent({
|
|
79
|
+
name: `Icon${name}`,
|
|
80
|
+
props: iconDrawProps,
|
|
81
|
+
setup(props, { slots }) {
|
|
82
|
+
return () => h(CopilotIcon, { name, ...props }, slots);
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const IconArrowUp = defineIcon("ArrowUp");
|
|
88
|
+
export const IconCheck = defineIcon("Check");
|
|
89
|
+
export const IconChevronDown = defineIcon("ChevronDown");
|
|
90
|
+
export const IconChevronLeft = defineIcon("ChevronLeft");
|
|
91
|
+
export const IconChevronRight = defineIcon("ChevronRight");
|
|
92
|
+
export const IconCircle = defineIcon("Circle");
|
|
93
|
+
export const IconCopy = defineIcon("Copy");
|
|
94
|
+
export const IconEdit = defineIcon("Edit");
|
|
95
|
+
export const IconEyeOff = defineIcon("EyeOff");
|
|
96
|
+
export const IconLoader2 = defineIcon("Loader2");
|
|
97
|
+
export const IconMessageCircle = defineIcon("MessageCircle");
|
|
98
|
+
export const IconMic = defineIcon("Mic");
|
|
99
|
+
export const IconPanelLeftOpen = defineIcon("PanelLeftOpen");
|
|
100
|
+
export const IconPlay = defineIcon("Play");
|
|
101
|
+
export const IconPlus = defineIcon("Plus");
|
|
102
|
+
export const IconRefreshCw = defineIcon("RefreshCw");
|
|
103
|
+
export const IconSquare = defineIcon("Square");
|
|
104
|
+
export const IconThumbsDown = defineIcon("ThumbsDown");
|
|
105
|
+
export const IconThumbsUp = defineIcon("ThumbsUp");
|
|
106
|
+
export const IconUpload = defineIcon("Upload");
|
|
107
|
+
export const IconVolume2 = defineIcon("Volume2");
|
|
108
|
+
export const IconWrench = defineIcon("Wrench");
|
|
109
|
+
export const IconX = defineIcon("X");
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
defineComponent,
|
|
4
|
+
h,
|
|
5
|
+
nextTick,
|
|
6
|
+
onMounted,
|
|
7
|
+
ref,
|
|
8
|
+
watch,
|
|
9
|
+
} from "vue";
|
|
2
10
|
import type { PropType } from "vue";
|
|
3
11
|
import { screen, fireEvent, waitFor, cleanup } from "@testing-library/vue";
|
|
4
12
|
import { afterEach, describe, expect, it } from "vitest";
|
|
@@ -27,6 +35,11 @@ import {
|
|
|
27
35
|
textChunkEvent,
|
|
28
36
|
testId,
|
|
29
37
|
} from "../../__tests__/utils/test-helpers";
|
|
38
|
+
import { mountWithProvider } from "../../__tests__/utils/mount";
|
|
39
|
+
import {
|
|
40
|
+
StateCapturingAgent,
|
|
41
|
+
toolCallMessage,
|
|
42
|
+
} from "../../__tests__/utils/agents";
|
|
30
43
|
|
|
31
44
|
afterEach(() => {
|
|
32
45
|
cleanup();
|
|
@@ -912,6 +925,54 @@ describe("useFrontendTool E2E - Dynamic Registration", () => {
|
|
|
912
925
|
});
|
|
913
926
|
});
|
|
914
927
|
|
|
928
|
+
describe("Overriding a provider tool", () => {
|
|
929
|
+
it("brings the provider tool back after the overriding component unmounts", async () => {
|
|
930
|
+
const calls: string[] = [];
|
|
931
|
+
const lookupTool = (owner: string): VueFrontendTool => ({
|
|
932
|
+
name: "lookup",
|
|
933
|
+
parameters: z.object({}),
|
|
934
|
+
followUp: false,
|
|
935
|
+
handler: async () => {
|
|
936
|
+
calls.push(owner);
|
|
937
|
+
return owner;
|
|
938
|
+
},
|
|
939
|
+
});
|
|
940
|
+
|
|
941
|
+
const OverridingTool = defineComponent({
|
|
942
|
+
setup() {
|
|
943
|
+
useFrontendTool(lookupTool("component"));
|
|
944
|
+
return () => null;
|
|
945
|
+
},
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
const showOverride = ref(true);
|
|
949
|
+
const agent = new StateCapturingAgent(
|
|
950
|
+
[
|
|
951
|
+
{ newMessages: [toolCallMessage("lookup")] },
|
|
952
|
+
{ newMessages: [toolCallMessage("lookup")] },
|
|
953
|
+
],
|
|
954
|
+
"test-agent",
|
|
955
|
+
);
|
|
956
|
+
const { getCore, wrapper } = mountWithProvider(
|
|
957
|
+
() => (showOverride.value ? h(OverridingTool) : h("div")),
|
|
958
|
+
{
|
|
959
|
+
frontendTools: [lookupTool("provider")],
|
|
960
|
+
agents__unsafe_dev_only: { "test-agent": agent },
|
|
961
|
+
},
|
|
962
|
+
);
|
|
963
|
+
|
|
964
|
+
await nextTick();
|
|
965
|
+
await getCore().runAgent({ agent });
|
|
966
|
+
|
|
967
|
+
showOverride.value = false;
|
|
968
|
+
await nextTick();
|
|
969
|
+
await getCore().runAgent({ agent });
|
|
970
|
+
|
|
971
|
+
expect(calls).toEqual(["component", "provider"]);
|
|
972
|
+
wrapper.unmount();
|
|
973
|
+
});
|
|
974
|
+
});
|
|
975
|
+
|
|
915
976
|
describe("Integration with Chat UI", () => {
|
|
916
977
|
it("should render tool output correctly in chat interface", async () => {
|
|
917
978
|
const agent = new MockStepwiseAgent();
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterEach,
|
|
3
|
+
beforeEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
expectTypeOf,
|
|
7
|
+
it,
|
|
8
|
+
vi,
|
|
9
|
+
} from "vitest";
|
|
10
|
+
import { defineComponent, h, toRaw } from "vue";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import type { ActivityMessage } from "@ag-ui/core";
|
|
13
|
+
import { useRenderActivityMessage } from "../use-render-activity-message";
|
|
14
|
+
import type {
|
|
15
|
+
VueActivityMessageRenderer,
|
|
16
|
+
VueActivityMessageRendererProps,
|
|
17
|
+
} from "../../types";
|
|
18
|
+
import { renderWithCopilotKit } from "../../__tests__/utils/mount";
|
|
19
|
+
|
|
20
|
+
const ProgressRenderer = defineComponent({
|
|
21
|
+
props: { content: { type: Object, required: true } },
|
|
22
|
+
setup: () => () => null,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const progressSchema = z.object({
|
|
26
|
+
label: z.string(),
|
|
27
|
+
percent: z.number().default(0),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// A zod schema is a Standard Schema, so it fits the `content` field, and the
|
|
31
|
+
// renderer's content type is the schema's output type.
|
|
32
|
+
const progressRenderer = {
|
|
33
|
+
activityType: "progress",
|
|
34
|
+
content: progressSchema,
|
|
35
|
+
render: ProgressRenderer,
|
|
36
|
+
} satisfies VueActivityMessageRenderer<z.output<typeof progressSchema>>;
|
|
37
|
+
|
|
38
|
+
function activityMessage(content: Record<string, unknown>): ActivityMessage {
|
|
39
|
+
return {
|
|
40
|
+
id: "activity-1",
|
|
41
|
+
role: "activity",
|
|
42
|
+
activityType: "progress",
|
|
43
|
+
content,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function renderWithProgressRenderer() {
|
|
48
|
+
let helpers: ReturnType<typeof useRenderActivityMessage> | undefined;
|
|
49
|
+
const Probe = defineComponent({
|
|
50
|
+
setup() {
|
|
51
|
+
helpers = useRenderActivityMessage();
|
|
52
|
+
return () => null;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
renderWithCopilotKit(() => h(Probe), {
|
|
57
|
+
providerProps: { renderActivityMessages: [progressRenderer] },
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!helpers) throw new Error("useRenderActivityMessage did not run");
|
|
61
|
+
return helpers;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
describe("useRenderActivityMessage", () => {
|
|
65
|
+
let consoleWarnSpy: ReturnType<typeof vi.spyOn>;
|
|
66
|
+
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
consoleWarnSpy.mockRestore();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("types a zod content schema's output as the render props content", () => {
|
|
76
|
+
type Props = VueActivityMessageRendererProps<
|
|
77
|
+
z.output<typeof progressSchema>
|
|
78
|
+
>;
|
|
79
|
+
expectTypeOf<Props["content"]>().toEqualTypeOf<{
|
|
80
|
+
label: string;
|
|
81
|
+
percent: number;
|
|
82
|
+
}>();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("passes the zod schema's parsed output to the renderer", () => {
|
|
86
|
+
const { renderActivityMessage } = renderWithProgressRenderer();
|
|
87
|
+
|
|
88
|
+
const result = renderActivityMessage(activityMessage({ label: "Upload" }));
|
|
89
|
+
|
|
90
|
+
// The provider stores renderers in reactive state, so compare the raw value.
|
|
91
|
+
expect(toRaw(result?.renderer)).toBe(ProgressRenderer);
|
|
92
|
+
expect(result?.props.content).toEqual({ label: "Upload", percent: 0 });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("returns null and warns when the content fails the schema", () => {
|
|
96
|
+
const { renderActivityMessage } = renderWithProgressRenderer();
|
|
97
|
+
|
|
98
|
+
const result = renderActivityMessage(activityMessage({ label: 42 }));
|
|
99
|
+
|
|
100
|
+
expect(result).toBeNull();
|
|
101
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
102
|
+
"Failed to validate content for activity message 'progress'.",
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -93,7 +93,7 @@ describe("useRenderTool", () => {
|
|
|
93
93
|
expect(typeof renderer?.render).toBe("function");
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
-
it("registers wildcard renderer and defaults parameters schema
|
|
96
|
+
it("registers wildcard renderer and defaults parameters to a schema that accepts any value", () => {
|
|
97
97
|
const core = createMockCore();
|
|
98
98
|
mockUseCopilotKit.mockReturnValue({ copilotkit: { value: core } });
|
|
99
99
|
|
|
@@ -118,11 +118,8 @@ describe("useRenderTool", () => {
|
|
|
118
118
|
const renderer = core.renderToolCalls.find((item) => item.name === "*");
|
|
119
119
|
expect(renderer).toBeDefined();
|
|
120
120
|
expect(typeof renderer?.render).toBe("function");
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
| undefined;
|
|
124
|
-
expect(wildcardArgs).toBeDefined();
|
|
125
|
-
expect(wildcardArgs!.safeParse({ arbitrary: true }).success).toBe(true);
|
|
121
|
+
const result = renderer?.args["~standard"].validate({ arbitrary: true });
|
|
122
|
+
expect(result).toEqual({ value: { arbitrary: true } });
|
|
126
123
|
});
|
|
127
124
|
|
|
128
125
|
it("accepts a Vue component renderer", () => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Covers:
|
|
6
6
|
* 1. useRenderTool with complex Zod schemas
|
|
7
|
-
* 2. defineToolCallRenderer with Zod (named + wildcard default
|
|
7
|
+
* 2. defineToolCallRenderer with Zod (named + wildcard default schema)
|
|
8
8
|
* 3. useComponent with Zod schemas
|
|
9
9
|
* 4. The registered schema object is the original Zod instance (identity check)
|
|
10
10
|
*/
|
|
@@ -134,7 +134,7 @@ describe("useRenderTool Zod regression", () => {
|
|
|
134
134
|
const schema = z.object({
|
|
135
135
|
action: z.discriminatedUnion("type", [
|
|
136
136
|
z.object({ type: z.literal("search"), query: z.string() }),
|
|
137
|
-
z.object({ type: z.literal("navigate"), url: z.
|
|
137
|
+
z.object({ type: z.literal("navigate"), url: z.url() }),
|
|
138
138
|
]),
|
|
139
139
|
});
|
|
140
140
|
|
|
@@ -196,14 +196,15 @@ describe("useRenderTool Zod regression", () => {
|
|
|
196
196
|
});
|
|
197
197
|
|
|
198
198
|
describe("defineToolCallRenderer Zod regression", () => {
|
|
199
|
-
it("wildcard tool defaults to
|
|
199
|
+
it("wildcard tool defaults to a schema that accepts any value", () => {
|
|
200
200
|
const renderer = defineToolCallRenderer({
|
|
201
201
|
name: "*",
|
|
202
202
|
render: () => "wildcard",
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
expect(renderer.name).toBe("*");
|
|
206
|
-
|
|
206
|
+
const result = renderer.args["~standard"].validate({ city: "Paris" });
|
|
207
|
+
expect(result).toEqual({ value: { city: "Paris" } });
|
|
207
208
|
});
|
|
208
209
|
|
|
209
210
|
it("named tool with Zod args preserves schema identity", () => {
|
|
@@ -240,15 +240,19 @@ export function useAttachments(
|
|
|
240
240
|
await processFiles(files);
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
function onPaste(event: ClipboardEvent) {
|
|
244
|
+
void handlePaste(event);
|
|
245
|
+
}
|
|
246
|
+
|
|
243
247
|
onMounted(() => {
|
|
244
248
|
if (typeof document !== "undefined") {
|
|
245
|
-
document.addEventListener("paste",
|
|
249
|
+
document.addEventListener("paste", onPaste);
|
|
246
250
|
}
|
|
247
251
|
});
|
|
248
252
|
|
|
249
253
|
onBeforeUnmount(() => {
|
|
250
254
|
if (typeof document !== "undefined") {
|
|
251
|
-
document.removeEventListener("paste",
|
|
255
|
+
document.removeEventListener("paste", onPaste);
|
|
252
256
|
}
|
|
253
257
|
});
|
|
254
258
|
|
|
@@ -12,6 +12,11 @@ const EMPTY_DEPS: WatchSource<unknown>[] = [];
|
|
|
12
12
|
* The tool registration is reactive to provided dependencies and is cleaned up
|
|
13
13
|
* automatically when the current scope is disposed.
|
|
14
14
|
*
|
|
15
|
+
* A tool with the same name and `agentId` as a tool that is already
|
|
16
|
+
* registered (for example a provider `frontendTools` entry) takes its place
|
|
17
|
+
* while this scope is active. When the scope is disposed, the earlier tool is
|
|
18
|
+
* active again.
|
|
19
|
+
*
|
|
15
20
|
* @example
|
|
16
21
|
* ```ts
|
|
17
22
|
* useFrontendTool({
|
|
@@ -42,13 +47,10 @@ export function useFrontendTool<T extends Record<string, unknown>>(
|
|
|
42
47
|
const core = copilotkit.value;
|
|
43
48
|
const name = tool.name;
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
core.removeTool(name, tool.agentId);
|
|
50
|
-
}
|
|
51
|
-
core.addTool(tool);
|
|
50
|
+
// Registrations stack in core: this one shadows an earlier tool with the
|
|
51
|
+
// same name and agentId (a provider tool, or another component's), and
|
|
52
|
+
// unregistering it brings that tool back.
|
|
53
|
+
const unregister = core.addTool(tool);
|
|
52
54
|
|
|
53
55
|
// The render function is registered even when tool.parameters is
|
|
54
56
|
// undefined — tools like HITL confirm dialogs have no parameters
|
|
@@ -62,9 +64,7 @@ export function useFrontendTool<T extends Record<string, unknown>>(
|
|
|
62
64
|
} as VueToolCallRenderer<unknown>);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
onCleanup(
|
|
66
|
-
core.removeTool(name, tool.agentId);
|
|
67
|
-
});
|
|
67
|
+
onCleanup(unregister);
|
|
68
68
|
},
|
|
69
69
|
{ immediate: true },
|
|
70
70
|
);
|