@copilotkit/vue 2.0.0-rc.20 → 2.0.0-rc.21
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/dist/index.cjs +1 -1
- package/dist/index.mjs +13 -13
- package/dist/use-render-activity-message-BAhbpSDh.js +16200 -0
- package/dist/use-render-activity-message-BAhbpSDh.js.map +1 -0
- package/dist/use-render-activity-message-DJ6q1qHV.cjs +114 -0
- package/dist/use-render-activity-message-DJ6q1qHV.cjs.map +1 -0
- package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
- package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
- package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
- package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
- package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
- package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
- package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +7 -21
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +0 -5
- package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -138
- 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 +3 -15
- package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
- package/dist/v2/components/a2ui.d.ts +6 -1
- package/dist/v2/components/a2ui.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
- package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +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.map +1 -1
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +1 -1
- package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
- package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
- package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
- package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +3 -2
- package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
- package/dist/v2/components/chat/index.d.ts +6 -6
- package/dist/v2/components/chat/tool-call-display-context.d.ts +3 -1
- 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.map +1 -1
- package/dist/v2/components/chat/types.d.ts +1 -1
- package/dist/v2/components/chat/types.d.ts.map +1 -1
- package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
- package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
- package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
- package/dist/v2/hooks/use-agent-context.d.ts +2 -3
- package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
- package/dist/v2/hooks/use-agent.d.ts +4 -1
- package/dist/v2/hooks/use-agent.d.ts.map +1 -1
- package/dist/v2/hooks/use-attachments.d.ts +7 -0
- package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
- package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
- package/dist/v2/hooks/use-component.d.ts +1 -0
- package/dist/v2/hooks/use-component.d.ts.map +1 -1
- package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
- package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
- package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
- package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
- package/dist/v2/hooks/use-interrupt.d.ts +0 -1
- package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
- package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
- package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
- package/dist/v2/hooks/use-threads.d.ts +0 -8
- package/dist/v2/hooks/use-threads.d.ts.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/lib/vue-core.d.ts +12 -11
- package/dist/v2/lib/vue-core.d.ts.map +1 -1
- package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -124
- package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
- package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
- package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
- package/dist/v2/providers/markdown-renderer.d.ts +3 -1
- package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
- package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
- package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/v2/__tests__/exports.test.ts +10 -0
- package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
- package/src/v2/__tests__/utils/test-helpers.ts +34 -4
- package/src/v2/components/A2UIMessageRenderer.ts +98 -68
- package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
- package/src/v2/components/CopilotKitInspector.vue +104 -51
- package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
- package/src/v2/components/OpenGenerativeUIRenderer.ts +78 -80
- package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
- package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
- package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +9 -2
- package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
- package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +1 -6
- package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -93
- package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
- package/src/v2/components/a2ui/catalog.ts +2 -3
- package/src/v2/components/a2ui/utils.ts +13 -67
- package/src/v2/components/a2ui.ts +14 -21
- package/src/v2/components/chat/CopilotChat.vue +136 -324
- package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +22 -45
- package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
- package/src/v2/components/chat/CopilotChatInput.vue +69 -407
- package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
- package/src/v2/components/chat/CopilotChatMessageView.vue +52 -112
- package/src/v2/components/chat/CopilotChatToolCallGroup.vue +14 -45
- package/src/v2/components/chat/CopilotChatToolCallItem.vue +6 -4
- package/src/v2/components/chat/CopilotChatToolCallsView.vue +16 -19
- package/src/v2/components/chat/CopilotChatView.vue +28 -23
- package/src/v2/components/chat/CopilotPopupViewInternal.vue +21 -97
- package/src/v2/components/chat/CopilotSidebarViewInternal.vue +24 -25
- package/src/v2/components/chat/CopilotThreadsDrawer.vue +37 -102
- package/src/v2/components/chat/StreamingMarkdownDefault.vue +13 -26
- package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
- package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +56 -0
- package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
- package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
- package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
- package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
- package/src/v2/components/chat/audioRecorder.ts +4 -7
- package/src/v2/components/chat/copilotChatToolCallItemRender.ts +22 -71
- package/src/v2/components/chat/tool-call-display-context.ts +6 -1
- package/src/v2/components/chat/tool-call-group-parts.ts +13 -33
- package/src/v2/components/chat/types.ts +1 -1
- package/src/v2/components/chat/use-lightbox.ts +15 -33
- package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
- package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
- package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
- package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
- package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
- package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
- package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
- package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +4 -0
- package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
- package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
- package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
- package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +2 -1
- package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
- package/src/v2/hooks/use-agent-context.ts +4 -10
- package/src/v2/hooks/use-agent.ts +86 -290
- package/src/v2/hooks/use-attachments.ts +42 -166
- package/src/v2/hooks/use-capabilities.ts +2 -7
- package/src/v2/hooks/use-component.ts +7 -4
- package/src/v2/hooks/use-configure-suggestions.ts +28 -218
- package/src/v2/hooks/use-default-render-tool.ts +34 -94
- package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
- package/src/v2/hooks/use-interrupt.ts +29 -308
- package/src/v2/hooks/use-render-activity-message.ts +17 -20
- package/src/v2/hooks/use-render-custom-messages.ts +20 -63
- package/src/v2/hooks/use-suggestions.ts +9 -33
- package/src/v2/hooks/use-threads.ts +43 -273
- package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
- package/src/v2/lib/vue-core.ts +67 -72
- package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
- package/src/v2/providers/CopilotKitProvider.types.ts +12 -127
- package/src/v2/providers/CopilotKitProvider.vue +188 -402
- package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
- package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +19 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
- package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +45 -2
- package/src/v2/providers/chat-configuration-store-key.ts +9 -0
- package/src/v2/providers/markdown-renderer.ts +7 -1
- package/src/v2/providers/use-inspector-thread-override.ts +22 -80
- package/vite.config.ts +5 -1
- package/vitest.config.ts +12 -7
- package/dist/use-render-activity-message-CsWYyd6r.cjs +0 -91
- package/dist/use-render-activity-message-CsWYyd6r.cjs.map +0 -1
- package/dist/use-render-activity-message-DntKKNdd.js +0 -17418
- package/dist/use-render-activity-message-DntKKNdd.js.map +0 -1
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
- package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
- package/dist/v2/lib/is-mobile-viewport.d.ts +0 -2
- package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
- package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
- package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
- package/src/v2/components/chat/normalize-auto-scroll.ts +0 -3
- package/src/v2/lib/is-mobile-viewport.ts +0 -5
|
@@ -5,23 +5,10 @@ import {
|
|
|
5
5
|
ref,
|
|
6
6
|
shallowRef,
|
|
7
7
|
toValue,
|
|
8
|
-
watch,
|
|
9
8
|
} from "vue";
|
|
10
9
|
import type { MaybeRefOrGetter, Ref } from "vue";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
getModalityFromMimeType,
|
|
14
|
-
exceedsMaxSize,
|
|
15
|
-
readFileAsBase64,
|
|
16
|
-
generateVideoThumbnail,
|
|
17
|
-
matchesAcceptFilter,
|
|
18
|
-
formatFileSize,
|
|
19
|
-
} from "@copilotkit/shared";
|
|
20
|
-
import type {
|
|
21
|
-
Attachment,
|
|
22
|
-
AttachmentUploadResult,
|
|
23
|
-
AttachmentsConfig,
|
|
24
|
-
} from "@copilotkit/shared";
|
|
10
|
+
import { ɵAttachmentQueue } from "@copilotkit/core";
|
|
11
|
+
import type { Attachment, AttachmentsConfig } from "@copilotkit/shared";
|
|
25
12
|
|
|
26
13
|
export interface UseAttachmentsProps {
|
|
27
14
|
config?: MaybeRefOrGetter<AttachmentsConfig | undefined>;
|
|
@@ -33,6 +20,7 @@ export interface UseAttachmentsReturn {
|
|
|
33
20
|
dragOver: Ref<boolean>;
|
|
34
21
|
fileInputRef: Ref<HTMLInputElement | null>;
|
|
35
22
|
containerRef: Ref<HTMLElement | null>;
|
|
23
|
+
/** Process files (validate, upload, add to state). No-op while attachments are disabled. */
|
|
36
24
|
processFiles: (files: File[]) => Promise<void>;
|
|
37
25
|
handleFileUpload: (event: Event) => Promise<void>;
|
|
38
26
|
handleDragOver: (event: DragEvent) => void;
|
|
@@ -42,133 +30,43 @@ export interface UseAttachmentsReturn {
|
|
|
42
30
|
consumeAttachments: () => Attachment[];
|
|
43
31
|
}
|
|
44
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Manages file attachment state — uploads, drag-and-drop, paste. The queue
|
|
35
|
+
* itself (validation, uploads, ready state) lives in `@copilotkit/core`'s
|
|
36
|
+
* `ɵAttachmentQueue`; this composable adds the DOM wiring and projects the
|
|
37
|
+
* queue into a `shallowRef`.
|
|
38
|
+
*/
|
|
45
39
|
export function useAttachments(
|
|
46
40
|
props: UseAttachmentsProps,
|
|
47
41
|
): UseAttachmentsReturn {
|
|
48
|
-
const
|
|
42
|
+
const queue = new ɵAttachmentQueue(() => toValue(props.config));
|
|
43
|
+
const attachments = shallowRef<Attachment[]>(queue.getSnapshot());
|
|
44
|
+
const unsubscribe = queue.subscribe(() => {
|
|
45
|
+
attachments.value = queue.getSnapshot();
|
|
46
|
+
});
|
|
49
47
|
const dragOver = ref(false);
|
|
50
48
|
const fileInputRef = ref<HTMLInputElement | null>(null);
|
|
51
49
|
const containerRef = ref<HTMLElement | null>(null);
|
|
52
|
-
const
|
|
53
|
-
const attachmentsRef = shallowRef<Attachment[]>(attachments.value);
|
|
54
|
-
const enabled = computed(() => configRef.value?.enabled ?? false);
|
|
55
|
-
|
|
56
|
-
watch(
|
|
57
|
-
() => toValue(props.config),
|
|
58
|
-
(next) => {
|
|
59
|
-
configRef.value = next;
|
|
60
|
-
},
|
|
61
|
-
{ immediate: true },
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const setAttachments = (next: Attachment[]) => {
|
|
65
|
-
attachments.value = next;
|
|
66
|
-
attachmentsRef.value = next;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const updateAttachments = (
|
|
70
|
-
updater: (previous: Attachment[]) => Attachment[],
|
|
71
|
-
) => {
|
|
72
|
-
setAttachments(updater(attachmentsRef.value));
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
async function processFiles(files: File[]) {
|
|
76
|
-
const config = configRef.value;
|
|
77
|
-
const accept = config?.accept ?? "*/*";
|
|
78
|
-
const maxSize = config?.maxSize ?? 20 * 1024 * 1024;
|
|
79
|
-
|
|
80
|
-
const rejectedFiles = files.filter(
|
|
81
|
-
(file) => !matchesAcceptFilter(file, accept),
|
|
82
|
-
);
|
|
83
|
-
for (const file of rejectedFiles) {
|
|
84
|
-
config?.onUploadFailed?.({
|
|
85
|
-
reason: "invalid-type",
|
|
86
|
-
file,
|
|
87
|
-
message: `File "${file.name}" is not accepted. Supported types: ${accept}`,
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const validFiles = files.filter((file) =>
|
|
92
|
-
matchesAcceptFilter(file, accept),
|
|
93
|
-
);
|
|
94
|
-
for (const file of validFiles) {
|
|
95
|
-
if (exceedsMaxSize(file, maxSize)) {
|
|
96
|
-
config?.onUploadFailed?.({
|
|
97
|
-
reason: "file-too-large",
|
|
98
|
-
file,
|
|
99
|
-
message: `File "${file.name}" exceeds the maximum size of ${formatFileSize(maxSize)}`,
|
|
100
|
-
});
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const modality = getModalityFromMimeType(file.type);
|
|
105
|
-
const placeholderId = randomUUID();
|
|
106
|
-
updateAttachments((previous) => [
|
|
107
|
-
...previous,
|
|
108
|
-
{
|
|
109
|
-
id: placeholderId,
|
|
110
|
-
type: modality,
|
|
111
|
-
source: { type: "data", value: "", mimeType: file.type },
|
|
112
|
-
filename: file.name,
|
|
113
|
-
size: file.size,
|
|
114
|
-
status: "uploading",
|
|
115
|
-
},
|
|
116
|
-
]);
|
|
50
|
+
const enabled = computed(() => toValue(props.config)?.enabled ?? false);
|
|
117
51
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (config?.onUpload) {
|
|
122
|
-
const uploadResult: AttachmentUploadResult =
|
|
123
|
-
await config.onUpload(file);
|
|
124
|
-
const { metadata, ...uploadSource } = uploadResult;
|
|
125
|
-
source = uploadSource;
|
|
126
|
-
uploadMetadata = metadata;
|
|
127
|
-
} else {
|
|
128
|
-
const base64 = await readFileAsBase64(file);
|
|
129
|
-
source = { type: "data", value: base64, mimeType: file.type };
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
let thumbnail: string | undefined;
|
|
133
|
-
if (modality === "video") {
|
|
134
|
-
thumbnail = await generateVideoThumbnail(file);
|
|
135
|
-
}
|
|
52
|
+
function processFiles(files: File[]) {
|
|
53
|
+
return queue.processFiles(files);
|
|
54
|
+
}
|
|
136
55
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
source,
|
|
143
|
-
status: "ready",
|
|
144
|
-
thumbnail,
|
|
145
|
-
metadata: uploadMetadata,
|
|
146
|
-
}
|
|
147
|
-
: attachment,
|
|
148
|
-
),
|
|
149
|
-
);
|
|
150
|
-
} catch (error) {
|
|
151
|
-
updateAttachments((previous) =>
|
|
152
|
-
previous.filter((attachment) => attachment.id !== placeholderId),
|
|
153
|
-
);
|
|
154
|
-
console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
|
|
155
|
-
config?.onUploadFailed?.({
|
|
156
|
-
reason: "upload-failed",
|
|
157
|
-
file,
|
|
158
|
-
message:
|
|
159
|
-
error instanceof Error
|
|
160
|
-
? error.message
|
|
161
|
-
: `Failed to upload "${file.name}"`,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
56
|
+
async function processSafely(files: File[], label: string) {
|
|
57
|
+
try {
|
|
58
|
+
await queue.processFiles(files);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error(`[CopilotKit] ${label}:`, error);
|
|
164
61
|
}
|
|
165
62
|
}
|
|
166
63
|
|
|
167
64
|
async function handleFileUpload(event: Event) {
|
|
168
|
-
const target = event.target
|
|
169
|
-
if (!target
|
|
170
|
-
await
|
|
171
|
-
|
|
65
|
+
const target = event.target;
|
|
66
|
+
if (!(target instanceof HTMLInputElement) || !target.files?.length) return;
|
|
67
|
+
await processSafely(Array.from(target.files), "Upload error");
|
|
68
|
+
// Clear the picker so choosing the same file again fires `change`.
|
|
69
|
+
target.value = "";
|
|
172
70
|
}
|
|
173
71
|
|
|
174
72
|
function handleDragOver(event: DragEvent) {
|
|
@@ -188,56 +86,32 @@ export function useAttachments(
|
|
|
188
86
|
event.preventDefault();
|
|
189
87
|
event.stopPropagation();
|
|
190
88
|
dragOver.value = false;
|
|
191
|
-
if (!enabled.value) return;
|
|
192
|
-
|
|
193
89
|
const files = Array.from(event.dataTransfer?.files ?? []);
|
|
194
|
-
if (files.length > 0)
|
|
195
|
-
await processFiles(files);
|
|
196
|
-
}
|
|
90
|
+
if (files.length > 0) await processSafely(files, "Drop error");
|
|
197
91
|
}
|
|
198
92
|
|
|
199
93
|
function removeAttachment(id: string) {
|
|
200
|
-
|
|
201
|
-
previous.filter((attachment) => attachment.id !== id),
|
|
202
|
-
);
|
|
94
|
+
queue.remove(id);
|
|
203
95
|
}
|
|
204
96
|
|
|
205
97
|
function consumeAttachments() {
|
|
206
|
-
const ready =
|
|
207
|
-
|
|
208
|
-
);
|
|
209
|
-
if (ready.length === 0) {
|
|
210
|
-
return ready;
|
|
211
|
-
}
|
|
212
|
-
updateAttachments((previous) =>
|
|
213
|
-
previous.filter((attachment) => attachment.status !== "ready"),
|
|
214
|
-
);
|
|
215
|
-
if (fileInputRef.value) {
|
|
98
|
+
const ready = queue.consumeReady();
|
|
99
|
+
if (ready.length > 0 && fileInputRef.value) {
|
|
216
100
|
fileInputRef.value.value = "";
|
|
217
101
|
}
|
|
218
102
|
return ready;
|
|
219
103
|
}
|
|
220
104
|
|
|
221
105
|
async function handlePaste(event: ClipboardEvent) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const fileItems = items.filter((item) => {
|
|
230
|
-
if (item.kind !== "file") return false;
|
|
231
|
-
const file = item.getAsFile();
|
|
232
|
-
return file !== null && matchesAcceptFilter(file, accept);
|
|
233
|
-
});
|
|
234
|
-
if (fileItems.length === 0) return;
|
|
235
|
-
|
|
106
|
+
const target = event.target;
|
|
107
|
+
if (!(target instanceof Node) || !containerRef.value?.contains(target))
|
|
108
|
+
return;
|
|
109
|
+
const files = queue.filterPastedFiles(
|
|
110
|
+
Array.from(event.clipboardData?.items ?? []),
|
|
111
|
+
);
|
|
112
|
+
if (files.length === 0) return;
|
|
236
113
|
event.preventDefault();
|
|
237
|
-
|
|
238
|
-
.map((item) => item.getAsFile())
|
|
239
|
-
.filter((file): file is File => file !== null);
|
|
240
|
-
await processFiles(files);
|
|
114
|
+
await processSafely(files, "Paste error");
|
|
241
115
|
}
|
|
242
116
|
|
|
243
117
|
function onPaste(event: ClipboardEvent) {
|
|
@@ -254,6 +128,8 @@ export function useAttachments(
|
|
|
254
128
|
if (typeof document !== "undefined") {
|
|
255
129
|
document.removeEventListener("paste", onPaste);
|
|
256
130
|
}
|
|
131
|
+
unsubscribe();
|
|
132
|
+
queue.dispose();
|
|
257
133
|
});
|
|
258
134
|
|
|
259
135
|
return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentCapabilities } from "@ag-ui/core";
|
|
2
2
|
import { computed } from "vue";
|
|
3
3
|
import type { ComputedRef } from "vue";
|
|
4
|
+
import { ɵgetAgentCapabilities } from "@copilotkit/core";
|
|
4
5
|
import { useAgent } from "./use-agent";
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -20,11 +21,5 @@ export function useCapabilities(
|
|
|
20
21
|
): ComputedRef<AgentCapabilities | undefined> {
|
|
21
22
|
const { agent } = useAgent({ agentId });
|
|
22
23
|
|
|
23
|
-
return computed(() =>
|
|
24
|
-
const a = agent.value;
|
|
25
|
-
if (a && "capabilities" in a) {
|
|
26
|
-
return (a as { capabilities?: AgentCapabilities }).capabilities;
|
|
27
|
-
}
|
|
28
|
-
return undefined;
|
|
29
|
-
});
|
|
24
|
+
return computed(() => ɵgetAgentCapabilities(agent.value));
|
|
30
25
|
}
|
|
@@ -2,6 +2,7 @@ import type { StandardSchemaV1, InferSchemaOutput } from "@copilotkit/shared";
|
|
|
2
2
|
import type { Component } from "vue";
|
|
3
3
|
import { h } from "vue";
|
|
4
4
|
import type { WatchSource } from "vue";
|
|
5
|
+
import { ɵcomponentToolDescription } from "@copilotkit/core";
|
|
5
6
|
import { useFrontendTool } from "./use-frontend-tool";
|
|
6
7
|
|
|
7
8
|
type InferRenderProps<T> = T extends StandardSchemaV1
|
|
@@ -17,13 +18,14 @@ export function useComponent<
|
|
|
17
18
|
parameters?: TSchema;
|
|
18
19
|
render: Component<NoInfer<InferRenderProps<TSchema>>>;
|
|
19
20
|
agentId?: string;
|
|
21
|
+
followUp?: boolean;
|
|
20
22
|
},
|
|
21
23
|
deps?: WatchSource<unknown>[],
|
|
22
24
|
): void {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const fullDescription = ɵcomponentToolDescription(
|
|
26
|
+
config.name,
|
|
27
|
+
config.description,
|
|
28
|
+
);
|
|
27
29
|
|
|
28
30
|
useFrontendTool(
|
|
29
31
|
{
|
|
@@ -40,6 +42,7 @@ export function useComponent<
|
|
|
40
42
|
);
|
|
41
43
|
},
|
|
42
44
|
agentId: config.agentId,
|
|
45
|
+
followUp: config.followUp,
|
|
43
46
|
},
|
|
44
47
|
deps,
|
|
45
48
|
);
|
|
@@ -1,49 +1,17 @@
|
|
|
1
|
-
import { computed,
|
|
1
|
+
import { computed, watch } from "vue";
|
|
2
2
|
import type { WatchSource } from "vue";
|
|
3
3
|
import { useCopilotKit } from "../providers/useCopilotKit";
|
|
4
4
|
import { useCopilotChatConfiguration } from "../providers/useCopilotChatConfiguration";
|
|
5
5
|
import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
Suggestion,
|
|
9
|
-
StaticSuggestionsConfig,
|
|
10
|
-
SuggestionsConfig,
|
|
11
|
-
} from "@copilotkit/core";
|
|
12
|
-
|
|
13
|
-
type StaticSuggestionInput = Omit<Suggestion, "isLoading"> &
|
|
14
|
-
Partial<Pick<Suggestion, "isLoading">>;
|
|
15
|
-
|
|
16
|
-
type StaticSuggestionsConfigInput = Omit<
|
|
17
|
-
StaticSuggestionsConfig,
|
|
18
|
-
"suggestions"
|
|
19
|
-
> & {
|
|
20
|
-
suggestions: StaticSuggestionInput[];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
type SuggestionsConfigInput =
|
|
24
|
-
| DynamicSuggestionsConfig
|
|
25
|
-
| StaticSuggestionsConfigInput;
|
|
26
|
-
|
|
27
|
-
function isDynamicConfig(
|
|
28
|
-
config: SuggestionsConfigInput,
|
|
29
|
-
): config is DynamicSuggestionsConfig {
|
|
30
|
-
return "instructions" in config;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function normalizeStaticSuggestions(
|
|
34
|
-
suggestions: StaticSuggestionInput[],
|
|
35
|
-
): Suggestion[] {
|
|
36
|
-
return suggestions.map((s) => ({
|
|
37
|
-
...s,
|
|
38
|
-
isLoading: s.isLoading ?? false,
|
|
39
|
-
}));
|
|
40
|
-
}
|
|
6
|
+
import { ɵbindSuggestionsConfig } from "@copilotkit/core";
|
|
7
|
+
import type { ɵSuggestionsConfigInput } from "@copilotkit/core";
|
|
41
8
|
|
|
42
9
|
/**
|
|
43
10
|
* Registers a suggestions configuration (dynamic or static) for the current
|
|
44
11
|
* chat context.
|
|
45
12
|
*
|
|
46
|
-
* Configuration is kept in sync reactively and removed on scope cleanup.
|
|
13
|
+
* Configuration is kept in sync reactively and removed on scope cleanup. Pass
|
|
14
|
+
* `deps` to reload suggestions when values the config reads change.
|
|
47
15
|
*
|
|
48
16
|
* @example
|
|
49
17
|
* ```ts
|
|
@@ -54,197 +22,39 @@ function normalizeStaticSuggestions(
|
|
|
54
22
|
* ```
|
|
55
23
|
*/
|
|
56
24
|
export function useConfigureSuggestions(
|
|
57
|
-
config:
|
|
25
|
+
config: ɵSuggestionsConfigInput | null | undefined,
|
|
58
26
|
deps?: WatchSource<unknown>[],
|
|
59
27
|
): void {
|
|
60
28
|
const { copilotkit } = useCopilotKit();
|
|
61
29
|
const chatConfig = useCopilotChatConfiguration();
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const resolvedConsumerAgentId = computed(
|
|
30
|
+
const chatAgentId = computed(
|
|
65
31
|
() => chatConfig.value?.agentId ?? DEFAULT_AGENT_ID,
|
|
66
32
|
);
|
|
67
|
-
const
|
|
68
|
-
config ? (config as SuggestionsConfigInput).consumerAgentId : undefined,
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const normalizedConfig = computed<SuggestionsConfig | null>(() => {
|
|
72
|
-
if (
|
|
73
|
-
!config ||
|
|
74
|
-
(config as { available?: string }).available === "disabled"
|
|
75
|
-
) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
if (isDynamicConfig(config)) {
|
|
79
|
-
return { ...config };
|
|
80
|
-
}
|
|
81
|
-
const normalizedSuggestions = normalizeStaticSuggestions(
|
|
82
|
-
config.suggestions,
|
|
83
|
-
);
|
|
84
|
-
return { ...config, suggestions: normalizedSuggestions };
|
|
85
|
-
});
|
|
86
|
-
const serializedConfig = computed(() =>
|
|
87
|
-
normalizedConfig.value ? JSON.stringify(normalizedConfig.value) : null,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const targetAgentId = computed(() => {
|
|
91
|
-
if (!normalizedConfig.value) return resolvedConsumerAgentId.value;
|
|
92
|
-
const consumer = (
|
|
93
|
-
normalizedConfig.value as
|
|
94
|
-
| StaticSuggestionsConfig
|
|
95
|
-
| DynamicSuggestionsConfig
|
|
96
|
-
).consumerAgentId;
|
|
97
|
-
if (!consumer || consumer === "*") return resolvedConsumerAgentId.value;
|
|
98
|
-
return consumer;
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const isGlobalConfig = computed(
|
|
102
|
-
() =>
|
|
103
|
-
rawConsumerAgentId.value === undefined ||
|
|
104
|
-
rawConsumerAgentId.value === "*",
|
|
105
|
-
);
|
|
106
|
-
const pendingGlobalReload = ref(false);
|
|
107
|
-
const pendingReloadTimer = ref<ReturnType<typeof setTimeout> | null>(null);
|
|
108
|
-
const previousSerializedConfig = ref<string | null>(null);
|
|
109
|
-
|
|
110
|
-
const flushPendingGlobalReload = () => {
|
|
111
|
-
if (!pendingGlobalReload.value || !isGlobalConfig.value) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const hasRunning = Object.values(copilotkit.value.agents ?? {}).some(
|
|
115
|
-
(entry) => !!entry.agentId && entry.isRunning,
|
|
116
|
-
);
|
|
117
|
-
if (hasRunning) {
|
|
118
|
-
pendingReloadTimer.value = setTimeout(() => {
|
|
119
|
-
pendingReloadTimer.value = null;
|
|
120
|
-
flushPendingGlobalReload();
|
|
121
|
-
}, 0);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
pendingGlobalReload.value = false;
|
|
126
|
-
requestReload();
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const requestReload = () => {
|
|
130
|
-
if (!normalizedConfig.value) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (isGlobalConfig.value) {
|
|
135
|
-
let skippedBecauseRunning = false;
|
|
136
|
-
const agents = Object.values(copilotkit.value.agents ?? {});
|
|
137
|
-
for (const entry of agents) {
|
|
138
|
-
const aid = entry.agentId;
|
|
139
|
-
if (!aid) {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (!entry.isRunning) {
|
|
143
|
-
copilotkit.value.reloadSuggestions(aid);
|
|
144
|
-
} else {
|
|
145
|
-
skippedBecauseRunning = true;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
pendingGlobalReload.value = skippedBecauseRunning;
|
|
149
|
-
if (skippedBecauseRunning && pendingReloadTimer.value === null) {
|
|
150
|
-
pendingReloadTimer.value = setTimeout(() => {
|
|
151
|
-
pendingReloadTimer.value = null;
|
|
152
|
-
flushPendingGlobalReload();
|
|
153
|
-
}, 0);
|
|
154
|
-
}
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (targetAgentId.value) {
|
|
159
|
-
copilotkit.value.reloadSuggestions(targetAgentId.value);
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
watch(
|
|
164
|
-
[() => copilotkit.value, serializedConfig],
|
|
165
|
-
([_core, serialized], _old, onCleanup) => {
|
|
166
|
-
if (!serialized || !normalizedConfig.value) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const core = copilotkit.value;
|
|
171
|
-
const cfg = normalizedConfig.value;
|
|
172
|
-
const id = core.addSuggestionsConfig(cfg);
|
|
173
|
-
requestReload();
|
|
174
|
-
|
|
175
|
-
onCleanup(() => core.removeSuggestionsConfig(id));
|
|
176
|
-
},
|
|
177
|
-
{ immediate: true },
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
watch(
|
|
181
|
-
[normalizedConfig, serializedConfig],
|
|
182
|
-
([cfg, serialized]) => {
|
|
183
|
-
if (!cfg) {
|
|
184
|
-
previousSerializedConfig.value = null;
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (serialized && previousSerializedConfig.value === serialized) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (serialized) {
|
|
193
|
-
previousSerializedConfig.value = serialized;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
requestReload();
|
|
197
|
-
},
|
|
198
|
-
{ immediate: false },
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
watch(
|
|
202
|
-
[normalizedConfig, () => extraDeps.length, ...extraDeps],
|
|
203
|
-
([cfg]) => {
|
|
204
|
-
if (!cfg || extraDeps.length === 0) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
requestReload();
|
|
208
|
-
},
|
|
209
|
-
{ immediate: true },
|
|
210
|
-
);
|
|
33
|
+
const extraDeps = deps ?? [];
|
|
211
34
|
|
|
212
35
|
watch(
|
|
213
|
-
|
|
214
|
-
(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
clearTimeout(pendingReloadTimer.value);
|
|
218
|
-
pendingReloadTimer.value = null;
|
|
219
|
-
}
|
|
36
|
+
() => copilotkit.value,
|
|
37
|
+
(core, _old, onCleanup) => {
|
|
38
|
+
const binding = ɵbindSuggestionsConfig(core, config, {
|
|
39
|
+
chatAgentId: chatAgentId.value,
|
|
220
40
|
});
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
.map((agent) =>
|
|
235
|
-
agent.subscribe({
|
|
236
|
-
onRunStartedEvent: flushPendingGlobalReload,
|
|
237
|
-
onRunFinishedEvent: flushPendingGlobalReload,
|
|
238
|
-
onRunFinalized: flushPendingGlobalReload,
|
|
239
|
-
onRunFailed: flushPendingGlobalReload,
|
|
240
|
-
onRunErrorEvent: flushPendingGlobalReload,
|
|
241
|
-
}),
|
|
242
|
-
);
|
|
243
|
-
|
|
41
|
+
// Deep, so a `reactive()` config that changes in place is applied. The
|
|
42
|
+
// binding compares configs by content, so other re-runs are no-ops.
|
|
43
|
+
const stopConfig = watch(
|
|
44
|
+
[() => config, chatAgentId],
|
|
45
|
+
([nextConfig, nextChatAgentId]) => {
|
|
46
|
+
binding.update(nextConfig, { chatAgentId: nextChatAgentId });
|
|
47
|
+
},
|
|
48
|
+
{ deep: true },
|
|
49
|
+
);
|
|
50
|
+
const stopDeps =
|
|
51
|
+
extraDeps.length > 0
|
|
52
|
+
? watch(extraDeps, () => binding.reload())
|
|
53
|
+
: undefined;
|
|
244
54
|
onCleanup(() => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
55
|
+
stopConfig();
|
|
56
|
+
stopDeps?.();
|
|
57
|
+
binding.dispose();
|
|
248
58
|
});
|
|
249
59
|
},
|
|
250
60
|
{ immediate: true },
|