@copilotkit/vue 2.0.0-rc.20 → 2.0.0-rc.22
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-CyrhHFhA.js +16200 -0
- package/dist/use-render-activity-message-CyrhHFhA.js.map +1 -0
- package/dist/use-render-activity-message-EwHHrwQB.cjs +114 -0
- package/dist/use-render-activity-message-EwHHrwQB.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
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { AGUIConnectNotImplementedError, AbstractAgent } from "@ag-ui/client";
|
|
3
|
-
import {
|
|
4
|
-
createAttachmentContent,
|
|
5
|
-
DEFAULT_AGENT_ID,
|
|
6
|
-
randomUUID,
|
|
7
|
-
} from "@copilotkit/shared";
|
|
3
|
+
import { DEFAULT_AGENT_ID, randomUUID } from "@copilotkit/shared";
|
|
8
4
|
import {
|
|
9
5
|
computed,
|
|
10
6
|
onBeforeUnmount,
|
|
@@ -19,12 +15,13 @@ import {
|
|
|
19
15
|
import {
|
|
20
16
|
CopilotChatDefaultLabels,
|
|
21
17
|
CopilotKitCoreErrorCode,
|
|
22
|
-
|
|
18
|
+
ɵcreateChatSubmitter,
|
|
19
|
+
ɵcreateLastUserMessageTracker,
|
|
23
20
|
ɵisHttpAgent,
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
ɵresolveChatNotice,
|
|
22
|
+
ɵThreadSwitchCoordinator,
|
|
26
23
|
} from "@copilotkit/core";
|
|
27
|
-
import type { Suggestion } from "@copilotkit/core";
|
|
24
|
+
import type { Suggestion, ɵThreadSelection } from "@copilotkit/core";
|
|
28
25
|
import CopilotChatConfigurationProvider from "../../providers/CopilotChatConfigurationProvider.vue";
|
|
29
26
|
import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
|
|
30
27
|
import { useCopilotKit } from "../../providers/useCopilotKit";
|
|
@@ -38,7 +35,6 @@ import CopilotChatView from "./CopilotChatView.vue";
|
|
|
38
35
|
import { LastUserMessageKey } from "./last-user-message-context";
|
|
39
36
|
import type { LastUserMessageState } from "./last-user-message-context";
|
|
40
37
|
import type { Message } from "@ag-ui/core";
|
|
41
|
-
import type { InputContent } from "@copilotkit/shared";
|
|
42
38
|
import { useInspectorThreadOverride } from "../../providers/use-inspector-thread-override";
|
|
43
39
|
import { CopilotKitStyles } from "../../styles/CopilotKitStyles";
|
|
44
40
|
import type {
|
|
@@ -99,27 +95,23 @@ const forwardedChatViewSlotNames = computed(() =>
|
|
|
99
95
|
const generatedThreadId = ref(randomUUID());
|
|
100
96
|
const transcribeMode = ref<"input" | "transcribe" | "processing">("input");
|
|
101
97
|
const inputValue = ref(props.inputValue ?? "");
|
|
102
|
-
const transcriptionError = ref<string | null>(null);
|
|
103
|
-
const isTranscribing = ref(false);
|
|
104
98
|
const isMounted = ref(false);
|
|
105
99
|
const isUnmounting = ref(false);
|
|
106
100
|
|
|
107
101
|
type ActiveConnectCycle = {
|
|
108
102
|
core: object;
|
|
109
|
-
|
|
110
|
-
threadId: string;
|
|
111
|
-
inspectorRequestId: string | null;
|
|
103
|
+
selection: ɵThreadSelection;
|
|
112
104
|
abortController: AbortController;
|
|
113
105
|
detached: boolean;
|
|
114
|
-
clearDiscardedBaseline?: () => void;
|
|
115
106
|
};
|
|
116
107
|
|
|
117
108
|
const activeConnectCycle = shallowRef<ActiveConnectCycle | null>(null);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
109
|
+
// Keeps the agent on the thread this chat shows, orders the teardown of the
|
|
110
|
+
// previous thread, and tracks connections a send must wait for.
|
|
111
|
+
const threads = new ɵThreadSwitchCoordinator({
|
|
112
|
+
stopAgent: (params) => copilotkit.value.stopAgent(params),
|
|
113
|
+
subscribe: (subscriber) => copilotkit.value.subscribe(subscriber),
|
|
114
|
+
});
|
|
123
115
|
|
|
124
116
|
const resolvedAgentId = computed(
|
|
125
117
|
() => props.agentId ?? existingConfig.value?.agentId ?? DEFAULT_AGENT_ID,
|
|
@@ -235,27 +227,11 @@ const shouldAllowStop = computed(
|
|
|
235
227
|
// Track the latest user message id so descendants (notably `usePinToSend`
|
|
236
228
|
// inside `CopilotChatView`) can anchor to the most recent user turn.
|
|
237
229
|
// Mirrors React `CopilotChat.tsx` `lastUserMessageId` + `sendNonce` state.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return null;
|
|
244
|
-
});
|
|
245
|
-
const sendNonce = ref(0);
|
|
246
|
-
// Seed with the current value so restoring a thread with existing messages
|
|
247
|
-
// does not count as a new send. Only later id transitions bump.
|
|
248
|
-
let prevLastUserMessageId: string | null = lastUserMessageId.value;
|
|
249
|
-
watch(lastUserMessageId, (next) => {
|
|
250
|
-
if (next && next !== prevLastUserMessageId) {
|
|
251
|
-
sendNonce.value += 1;
|
|
252
|
-
prevLastUserMessageId = next;
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
const lastUserMessageState = computed<LastUserMessageState>(() => ({
|
|
256
|
-
id: lastUserMessageId.value,
|
|
257
|
-
sendNonce: sendNonce.value,
|
|
258
|
-
}));
|
|
230
|
+
// Messages the chat starts with (a restored thread) do not count as a send.
|
|
231
|
+
const lastUserMessageTracker = ɵcreateLastUserMessageTracker(messages.value);
|
|
232
|
+
const lastUserMessageState = computed<LastUserMessageState>(() =>
|
|
233
|
+
lastUserMessageTracker.update(messages.value),
|
|
234
|
+
);
|
|
259
235
|
provide(LastUserMessageKey, lastUserMessageState);
|
|
260
236
|
|
|
261
237
|
watch(
|
|
@@ -370,35 +346,23 @@ watch(
|
|
|
370
346
|
return;
|
|
371
347
|
}
|
|
372
348
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Pin the thread this chat renders onto its agent, before anything issues a
|
|
388
|
-
// request. `CopilotKitCore.connectAgent` reads `agent.threadId` synchronously
|
|
389
|
-
// to decide whether this is a fresh restore, so a later assignment would let
|
|
390
|
-
// /connect address the previous thread. Assigning inside this callback — as
|
|
391
|
-
// React does — makes the ordering unconditional instead of depending on
|
|
392
|
-
// watcher scheduling. Non-explicit threads skip /connect below, but the first
|
|
393
|
-
// runAgent still has to ship the thread the UI is rendering.
|
|
394
|
-
baselineThreadIds.set(currentAgent, currentAgent.threadId);
|
|
395
|
-
currentAgent.threadId = threadId;
|
|
349
|
+
// Pins the thread on the agent before anything issues a request:
|
|
350
|
+
// `CopilotKitCore.connectAgent` reads `agent.threadId` synchronously. A
|
|
351
|
+
// switch to a fresh, non-explicit thread (a "+ New" reset) empties the
|
|
352
|
+
// agent so the welcome screen shows; moving in or out of an inspector
|
|
353
|
+
// override stops the run.
|
|
354
|
+
const selection = threads.select({
|
|
355
|
+
agent: currentAgent,
|
|
356
|
+
threadId,
|
|
357
|
+
explicit: isExplicit,
|
|
358
|
+
inspectorRequestId: requestId,
|
|
359
|
+
});
|
|
396
360
|
|
|
397
361
|
// When the caller hasn't picked a specific thread, resolvedThreadId is
|
|
398
362
|
// a UUID minted locally. The backend has never seen it, so /connect
|
|
399
363
|
// would always 404 — skip the call. A real thread is only created
|
|
400
364
|
// once the user runs the agent for the first time.
|
|
401
|
-
if (!
|
|
365
|
+
if (!selection.shouldConnect) {
|
|
402
366
|
return;
|
|
403
367
|
}
|
|
404
368
|
|
|
@@ -425,9 +389,7 @@ watch(
|
|
|
425
389
|
const hasSameDeps =
|
|
426
390
|
existingCycle &&
|
|
427
391
|
existingCycle.core === (core as object) &&
|
|
428
|
-
existingCycle.
|
|
429
|
-
existingCycle.threadId === threadId &&
|
|
430
|
-
existingCycle.inspectorRequestId === requestId;
|
|
392
|
+
existingCycle.selection === selection;
|
|
431
393
|
|
|
432
394
|
let cycle: ActiveConnectCycle;
|
|
433
395
|
if (hasSameDeps && existingCycle) {
|
|
@@ -436,58 +398,60 @@ watch(
|
|
|
436
398
|
const connectAbortController = new AbortController();
|
|
437
399
|
cycle = {
|
|
438
400
|
core: core as object,
|
|
439
|
-
|
|
440
|
-
threadId,
|
|
441
|
-
inspectorRequestId: requestId,
|
|
401
|
+
selection,
|
|
442
402
|
abortController: connectAbortController,
|
|
443
403
|
detached: false,
|
|
444
404
|
};
|
|
445
405
|
activeConnectCycle.value = cycle;
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
void
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
currentAgent.abortController = connectAbortController;
|
|
453
|
-
return core.connectAgent({ agent: currentAgent });
|
|
454
|
-
})
|
|
455
|
-
.catch((error: unknown) => {
|
|
456
|
-
if (cycle.detached) {
|
|
457
|
-
cycle.clearDiscardedBaseline?.();
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
if (error instanceof AGUIConnectNotImplementedError) {
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
console.error("CopilotChat: connectAgent failed", error);
|
|
464
|
-
if (requestId) {
|
|
465
|
-
failInspectorOverride(requestId);
|
|
466
|
-
}
|
|
467
|
-
})
|
|
468
|
-
.finally(() => {
|
|
469
|
-
// Whether the connect succeeded or failed, we're no longer in
|
|
470
|
-
// the transitional "connecting" state for this thread — release
|
|
471
|
-
// the welcome / suggestion gating so the view can settle.
|
|
472
|
-
//
|
|
473
|
-
// Defer one animation frame so any trailing reactive commits
|
|
474
|
-
// from the bootstrap replay (final assistant message content)
|
|
475
|
-
// paint before isConnecting flips off. Without this, suggestions
|
|
476
|
-
// can briefly render against an incompletely-laid-out message
|
|
477
|
-
// tree and visibly snap once the last text chunk lands.
|
|
478
|
-
if (cycle.detached) {
|
|
479
|
-
cycle.clearDiscardedBaseline?.();
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
const raf =
|
|
483
|
-
typeof requestAnimationFrame === "function"
|
|
484
|
-
? requestAnimationFrame
|
|
485
|
-
: (cb: () => void) => setTimeout(cb, 16);
|
|
486
|
-
raf(() => {
|
|
406
|
+
|
|
407
|
+
// Tracked, so a send waits for the thread to load instead of racing it.
|
|
408
|
+
void threads.trackConnection(selection, () =>
|
|
409
|
+
threads
|
|
410
|
+
.whenTornDown()
|
|
411
|
+
.then(() => {
|
|
487
412
|
if (cycle.detached) return;
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
413
|
+
if (ɵisHttpAgent(currentAgent))
|
|
414
|
+
currentAgent.abortController = connectAbortController;
|
|
415
|
+
return core.connectAgent({ agent: currentAgent });
|
|
416
|
+
})
|
|
417
|
+
.catch((error: unknown) => {
|
|
418
|
+
if (cycle.detached) {
|
|
419
|
+
selection.clearDiscardedBaseline();
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (error instanceof AGUIConnectNotImplementedError) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
if (requestId) {
|
|
426
|
+
failInspectorOverride(requestId);
|
|
427
|
+
}
|
|
428
|
+
// The coordinator logs the failure and blocks sends on it.
|
|
429
|
+
throw error;
|
|
430
|
+
})
|
|
431
|
+
.finally(() => {
|
|
432
|
+
// Whether the connect succeeded or failed, we're no longer in
|
|
433
|
+
// the transitional "connecting" state for this thread — release
|
|
434
|
+
// the welcome / suggestion gating so the view can settle.
|
|
435
|
+
//
|
|
436
|
+
// Defer one animation frame so any trailing reactive commits
|
|
437
|
+
// from the bootstrap replay (final assistant message content)
|
|
438
|
+
// paint before isConnecting flips off. Without this, suggestions
|
|
439
|
+
// can briefly render against an incompletely-laid-out message
|
|
440
|
+
// tree and visibly snap once the last text chunk lands.
|
|
441
|
+
if (cycle.detached) {
|
|
442
|
+
selection.clearDiscardedBaseline();
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const raf =
|
|
446
|
+
typeof requestAnimationFrame === "function"
|
|
447
|
+
? requestAnimationFrame
|
|
448
|
+
: (cb: () => void) => setTimeout(cb, 16);
|
|
449
|
+
raf(() => {
|
|
450
|
+
if (cycle.detached) return;
|
|
451
|
+
lastConnectedThreadId.value = selection.threadId;
|
|
452
|
+
});
|
|
453
|
+
}),
|
|
454
|
+
);
|
|
491
455
|
}
|
|
492
456
|
|
|
493
457
|
onCleanup(() => {
|
|
@@ -496,227 +460,94 @@ watch(
|
|
|
496
460
|
return;
|
|
497
461
|
}
|
|
498
462
|
|
|
463
|
+
const { selection: cycleSelection } = activeCycle;
|
|
499
464
|
const shouldDetach =
|
|
500
465
|
isUnmounting.value ||
|
|
501
466
|
copilotkit.value !== activeCycle.core ||
|
|
502
|
-
agent.value !==
|
|
503
|
-
resolvedThreadId.value !==
|
|
467
|
+
agent.value !== cycleSelection.agent ||
|
|
468
|
+
resolvedThreadId.value !== cycleSelection.threadId;
|
|
504
469
|
if (!shouldDetach) {
|
|
505
470
|
return;
|
|
506
471
|
}
|
|
507
472
|
|
|
473
|
+
cycleSelection.release();
|
|
508
474
|
activeCycle.detached = true;
|
|
509
475
|
activeCycle.abortController.abort();
|
|
510
|
-
|
|
511
|
-
.detachActiveRun()
|
|
512
|
-
.catch((error: unknown) => {
|
|
513
|
-
console.error("CopilotChat: detachActiveRun failed", error);
|
|
514
|
-
});
|
|
515
|
-
detachPromises.set(activeCycle.agent, detach);
|
|
516
|
-
pendingTeardown = Promise.all([pendingTeardown, detach]).then(() => {});
|
|
517
|
-
void detach.then(() => {
|
|
518
|
-
if (detachPromises.get(activeCycle.agent) === detach)
|
|
519
|
-
detachPromises.delete(activeCycle.agent);
|
|
520
|
-
});
|
|
476
|
+
void threads.detach(cycleSelection.agent);
|
|
521
477
|
activeConnectCycle.value = null;
|
|
522
478
|
});
|
|
523
479
|
},
|
|
524
480
|
{ immediate: true },
|
|
525
481
|
);
|
|
526
482
|
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if (previous === undefined) return;
|
|
544
|
-
if (threadId === previous.threadId) return;
|
|
545
|
-
let active = true;
|
|
546
|
-
let resetPending = true;
|
|
547
|
-
onCleanup(() => {
|
|
548
|
-
active = false;
|
|
549
|
-
});
|
|
550
|
-
const discardedThreadId =
|
|
551
|
-
previous.agent === currentAgent
|
|
552
|
-
? previous.threadId
|
|
553
|
-
: baselineThreadIds.get(currentAgent);
|
|
554
|
-
const clearCursor = () => {
|
|
555
|
-
if (!discardedThreadId) return;
|
|
556
|
-
if (
|
|
557
|
-
"clearReplayCursor" in currentAgent &&
|
|
558
|
-
typeof currentAgent.clearReplayCursor === "function"
|
|
559
|
-
)
|
|
560
|
-
currentAgent.clearReplayCursor(discardedThreadId);
|
|
561
|
-
if (
|
|
562
|
-
"clearReconnectCursor" in currentAgent &&
|
|
563
|
-
typeof currentAgent.clearReconnectCursor === "function"
|
|
564
|
-
)
|
|
565
|
-
currentAgent.clearReconnectCursor(discardedThreadId);
|
|
566
|
-
};
|
|
567
|
-
const clearDiscardedBaseline = () => {
|
|
568
|
-
if (
|
|
569
|
-
!active ||
|
|
570
|
-
!resetPending ||
|
|
571
|
-
isUnmounting.value ||
|
|
572
|
-
lastFreshSelection !== selection ||
|
|
573
|
-
agent.value !== currentAgent
|
|
574
|
-
)
|
|
575
|
-
return;
|
|
576
|
-
currentAgent.setMessages([]);
|
|
577
|
-
currentAgent.setState({});
|
|
578
|
-
currentAgent.pendingInterrupts = [];
|
|
579
|
-
clearCursor();
|
|
580
|
-
};
|
|
581
|
-
if (
|
|
582
|
-
lastConnectCycle?.agent === currentAgent &&
|
|
583
|
-
lastConnectCycle.threadId === discardedThreadId
|
|
584
|
-
)
|
|
585
|
-
lastConnectCycle.clearDiscardedBaseline = clearDiscardedBaseline;
|
|
586
|
-
const detach =
|
|
587
|
-
detachPromises.get(currentAgent) ?? currentAgent.detachActiveRun();
|
|
588
|
-
detachPromises.set(currentAgent, detach);
|
|
589
|
-
const finishReset = () => {
|
|
590
|
-
if (!resetPending) return;
|
|
591
|
-
// The cursor belongs to the discarded view, even after a fast reopen.
|
|
592
|
-
clearCursor();
|
|
593
|
-
clearDiscardedBaseline();
|
|
594
|
-
resetPending = false;
|
|
595
|
-
};
|
|
596
|
-
clearDiscardedBaseline();
|
|
597
|
-
pendingTeardown = Promise.all([pendingTeardown, detach])
|
|
598
|
-
.then(finishReset)
|
|
599
|
-
.catch((error: unknown) => {
|
|
600
|
-
console.error("CopilotChat: detachActiveRun failed", error);
|
|
601
|
-
})
|
|
602
|
-
.finally(() => {
|
|
603
|
-
if (detachPromises.get(currentAgent) === detach)
|
|
604
|
-
detachPromises.delete(currentAgent);
|
|
605
|
-
});
|
|
483
|
+
// The send side — queueing behind the run in flight and the thread's
|
|
484
|
+
// connection, the upload guard, stop, and transcription — lives in core.
|
|
485
|
+
const submitter = ɵcreateChatSubmitter({
|
|
486
|
+
core: {
|
|
487
|
+
get runtimeUrl() {
|
|
488
|
+
return copilotkit.value.runtimeUrl;
|
|
489
|
+
},
|
|
490
|
+
get runtimeTransport() {
|
|
491
|
+
return copilotkit.value.runtimeTransport;
|
|
492
|
+
},
|
|
493
|
+
get credentials() {
|
|
494
|
+
return copilotkit.value.credentials;
|
|
495
|
+
},
|
|
496
|
+
resolveHeaders: () => copilotkit.value.resolveHeaders(),
|
|
497
|
+
runAgent: (params) => copilotkit.value.runAgent(params),
|
|
498
|
+
stopAgent: (params) => copilotkit.value.stopAgent(params),
|
|
606
499
|
},
|
|
607
|
-
|
|
608
|
-
|
|
500
|
+
getAgent: () => agent.value ?? undefined,
|
|
501
|
+
input: {
|
|
502
|
+
get: () => inputValue.value,
|
|
503
|
+
set: (value) => {
|
|
504
|
+
inputValue.value = value;
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
attachments: {
|
|
508
|
+
isUploading: () =>
|
|
509
|
+
attachments.value.some((attachment) => attachment.status === "uploading"),
|
|
510
|
+
consumeReady: consumeAttachments,
|
|
511
|
+
},
|
|
512
|
+
threads,
|
|
513
|
+
});
|
|
514
|
+
const submitterState = shallowRef(submitter.getSnapshot());
|
|
515
|
+
const unsubscribeSubmitter = submitter.subscribe(() => {
|
|
516
|
+
submitterState.value = submitter.getSnapshot();
|
|
517
|
+
});
|
|
518
|
+
const isTranscribing = computed(() => submitterState.value.isTranscribing);
|
|
519
|
+
const transcriptionError = computed(() => {
|
|
520
|
+
const { notice } = submitterState.value;
|
|
521
|
+
return notice ? ɵresolveChatNotice(notice, chatLabels.value) : null;
|
|
522
|
+
});
|
|
609
523
|
|
|
610
524
|
onBeforeUnmount(() => {
|
|
611
525
|
isUnmounting.value = true;
|
|
526
|
+
unsubscribeSubmitter();
|
|
527
|
+
submitter.dispose();
|
|
528
|
+
threads.dispose();
|
|
612
529
|
});
|
|
613
530
|
|
|
614
531
|
onMounted(() => {
|
|
615
532
|
isMounted.value = true;
|
|
616
533
|
});
|
|
617
534
|
|
|
618
|
-
watch(transcriptionError, (next, _old, onCleanup) => {
|
|
619
|
-
if (!next) {
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
const timer = setTimeout(() => {
|
|
623
|
-
transcriptionError.value = null;
|
|
624
|
-
}, 5000);
|
|
625
|
-
onCleanup(() => clearTimeout(timer));
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
async function runCurrentAgent() {
|
|
629
|
-
const currentAgent = agent.value;
|
|
630
|
-
if (!currentAgent) {
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
try {
|
|
635
|
-
const activeCycle = activeConnectCycle.value;
|
|
636
|
-
if (
|
|
637
|
-
activeCycle &&
|
|
638
|
-
activeCycle.agent === currentAgent &&
|
|
639
|
-
activeCycle.threadId === resolvedThreadId.value
|
|
640
|
-
) {
|
|
641
|
-
activeCycle.detached = true;
|
|
642
|
-
activeCycle.abortController.abort();
|
|
643
|
-
activeConnectCycle.value = null;
|
|
644
|
-
await activeCycle.agent.detachActiveRun?.();
|
|
645
|
-
}
|
|
646
|
-
await copilotkit.value.runAgent({ agent: currentAgent });
|
|
647
|
-
} catch (error) {
|
|
648
|
-
console.error("CopilotChat: runAgent failed", error);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
535
|
async function handleSubmitMessage(value: string) {
|
|
653
|
-
|
|
536
|
+
// A send blocked by an upload shows its notice but is not reported.
|
|
537
|
+
const isBlockedByUpload = attachments.value.some(
|
|
654
538
|
(attachment) => attachment.status === "uploading",
|
|
655
539
|
);
|
|
656
|
-
if (
|
|
657
|
-
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
emit("submit-message", value);
|
|
662
|
-
|
|
663
|
-
if (!agent.value) {
|
|
664
|
-
console.error("[CopilotKit] Cannot send message: no agent available");
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
const readyAttachments = consumeAttachments();
|
|
669
|
-
if (readyAttachments.length > 0) {
|
|
670
|
-
const contentParts: InputContent[] = [];
|
|
671
|
-
if (value.trim()) {
|
|
672
|
-
contentParts.push({ type: "text", text: value });
|
|
673
|
-
}
|
|
674
|
-
for (const attachment of readyAttachments) {
|
|
675
|
-
contentParts.push(createAttachmentContent(attachment));
|
|
676
|
-
}
|
|
677
|
-
agent.value.addMessage({
|
|
678
|
-
id: randomUUID(),
|
|
679
|
-
role: "user",
|
|
680
|
-
content: contentParts,
|
|
681
|
-
});
|
|
682
|
-
} else {
|
|
683
|
-
agent.value.addMessage({
|
|
684
|
-
id: randomUUID(),
|
|
685
|
-
role: "user",
|
|
686
|
-
content: value,
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
inputValue.value = "";
|
|
691
|
-
await runCurrentAgent();
|
|
540
|
+
if (!isBlockedByUpload) emit("submit-message", value);
|
|
541
|
+
await submitter.submit(value);
|
|
692
542
|
}
|
|
693
543
|
|
|
694
544
|
async function handleSelectSuggestion(suggestion: Suggestion, index: number) {
|
|
695
545
|
emit("select-suggestion", suggestion, index);
|
|
696
|
-
|
|
697
|
-
id: randomUUID(),
|
|
698
|
-
role: "user",
|
|
699
|
-
content: suggestion.message,
|
|
700
|
-
});
|
|
701
|
-
await runCurrentAgent();
|
|
546
|
+
await submitter.selectSuggestion(suggestion);
|
|
702
547
|
}
|
|
703
548
|
|
|
704
549
|
function stopCurrentRun() {
|
|
705
|
-
|
|
706
|
-
if (!currentAgent) {
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
try {
|
|
711
|
-
copilotkit.value.stopAgent({ agent: currentAgent });
|
|
712
|
-
} catch (error) {
|
|
713
|
-
console.error("CopilotChat: stopAgent failed", error);
|
|
714
|
-
try {
|
|
715
|
-
currentAgent.abortRun();
|
|
716
|
-
} catch (abortError) {
|
|
717
|
-
console.error("CopilotChat: abortRun fallback failed", abortError);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
550
|
+
submitter.stop();
|
|
720
551
|
}
|
|
721
552
|
|
|
722
553
|
function handleStop() {
|
|
@@ -745,7 +576,7 @@ function handleStartTranscribe() {
|
|
|
745
576
|
if (!showTranscription.value) {
|
|
746
577
|
return;
|
|
747
578
|
}
|
|
748
|
-
|
|
579
|
+
submitter.showNotice(null);
|
|
749
580
|
transcribeMode.value = "transcribe";
|
|
750
581
|
emit("start-transcribe");
|
|
751
582
|
}
|
|
@@ -754,7 +585,7 @@ function handleCancelTranscribe() {
|
|
|
754
585
|
if (!showTranscription.value) {
|
|
755
586
|
return;
|
|
756
587
|
}
|
|
757
|
-
|
|
588
|
+
submitter.showNotice(null);
|
|
758
589
|
transcribeMode.value = "input";
|
|
759
590
|
emit("cancel-transcribe");
|
|
760
591
|
}
|
|
@@ -776,26 +607,7 @@ async function handleFinishTranscribeWithAudio(audioBlob: Blob) {
|
|
|
776
607
|
return;
|
|
777
608
|
}
|
|
778
609
|
|
|
779
|
-
|
|
780
|
-
try {
|
|
781
|
-
transcriptionError.value = null;
|
|
782
|
-
const result = await ɵtranscribeAudio(copilotkit.value, audioBlob);
|
|
783
|
-
const trimmedPrevious = inputValue.value.trim();
|
|
784
|
-
inputValue.value = trimmedPrevious
|
|
785
|
-
? `${trimmedPrevious} ${result.text}`
|
|
786
|
-
: result.text;
|
|
787
|
-
} catch (error) {
|
|
788
|
-
console.error("CopilotChat: Transcription failed", error);
|
|
789
|
-
const labels = chatLabels.value;
|
|
790
|
-
if (error instanceof TranscriptionError) {
|
|
791
|
-
const key = ɵtranscriptionErrorMessageKey(error.info);
|
|
792
|
-
transcriptionError.value = key ? labels[key] : error.info.message;
|
|
793
|
-
} else {
|
|
794
|
-
transcriptionError.value = labels.transcriptionErrorGenericText;
|
|
795
|
-
}
|
|
796
|
-
} finally {
|
|
797
|
-
isTranscribing.value = false;
|
|
798
|
-
}
|
|
610
|
+
await submitter.transcribe(audioBlob);
|
|
799
611
|
}
|
|
800
612
|
|
|
801
613
|
const chatViewSlotProps = computed<CopilotChatViewOverrideSlotProps>(() => ({
|