@copilotkit/react-core 1.57.0 → 1.57.1
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/{copilotkit-DFaI4j2r.d.mts → copilotkit-BN4I_y1n.d.mts} +64 -8
- package/dist/copilotkit-BN4I_y1n.d.mts.map +1 -0
- package/dist/{copilotkit-DGbvw8n2.cjs → copilotkit-C3k13WZn.cjs} +572 -435
- package/dist/copilotkit-C3k13WZn.cjs.map +1 -0
- package/dist/{copilotkit-CPe2-340.mjs → copilotkit-DjxXMYHG.mjs} +571 -440
- package/dist/copilotkit-DjxXMYHG.mjs.map +1 -0
- package/dist/{copilotkit-Dg4r4Gi_.d.cts → copilotkit-sQWiKtxA.d.cts} +64 -8
- package/dist/copilotkit-sQWiKtxA.d.cts.map +1 -0
- package/dist/index.cjs +2 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -5
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +449 -502
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/context.cjs +135 -0
- package/dist/v2/context.cjs.map +1 -0
- package/dist/v2/context.d.cts +148 -0
- package/dist/v2/context.d.cts.map +1 -0
- package/dist/v2/context.d.mts +148 -0
- package/dist/v2/context.d.mts.map +1 -0
- package/dist/v2/context.mjs +129 -0
- package/dist/v2/context.mjs.map +1 -0
- package/dist/v2/headless.cjs +1043 -0
- package/dist/v2/headless.cjs.map +1 -0
- package/dist/v2/headless.d.cts +605 -0
- package/dist/v2/headless.d.cts.map +1 -0
- package/dist/v2/headless.d.mts +512 -0
- package/dist/v2/headless.d.mts.map +1 -0
- package/dist/v2/headless.mjs +997 -0
- package/dist/v2/headless.mjs.map +1 -0
- package/dist/v2/index.cjs +2 -1
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/index.umd.js +584 -441
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +14 -6
- package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +5 -6
- package/src/hooks/use-copilot-chat_internal.ts +0 -1
- package/src/v2/components/chat/CopilotChat.tsx +2 -1
- package/src/v2/components/chat/CopilotChatMessageView.tsx +24 -9
- package/src/v2/components/chat/CopilotChatView.tsx +2 -2
- package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +1 -3
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +29 -25
- package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.tsx +5 -60
- package/src/v2/components/index.ts +1 -0
- package/src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx +286 -0
- package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +464 -0
- package/src/v2/components/intelligence-indicator/index.ts +2 -0
- package/src/v2/context.ts +62 -0
- package/src/v2/headless.ts +42 -0
- package/src/v2/hooks/__tests__/standard-schema.test.tsx +2 -2
- package/src/v2/hooks/__tests__/use-agent-context.test.tsx +3 -3
- package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +3 -3
- package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +85 -85
- package/src/v2/hooks/__tests__/use-interrupt.test.tsx +2 -2
- package/src/v2/hooks/__tests__/use-render-tool.test.tsx +2 -2
- package/src/v2/hooks/__tests__/use-threads.test.tsx +2 -2
- package/src/v2/hooks/__tests__/zod-regression.test.tsx +2 -2
- package/src/v2/hooks/use-agent-context.tsx +1 -1
- package/src/v2/hooks/use-agent.tsx +9 -118
- package/src/v2/hooks/use-configure-suggestions.tsx +1 -1
- package/src/v2/hooks/use-frontend-tool.tsx +2 -2
- package/src/v2/hooks/use-human-in-the-loop.tsx +1 -1
- package/src/v2/hooks/use-interrupt.tsx +1 -1
- package/src/v2/hooks/use-render-activity-message.tsx +3 -11
- package/src/v2/hooks/use-render-custom-messages.tsx +1 -6
- package/src/v2/hooks/use-render-tool-call.tsx +1 -1
- package/src/v2/hooks/use-render-tool.tsx +2 -2
- package/src/v2/hooks/use-suggestions.tsx +1 -1
- package/src/v2/hooks/use-threads.tsx +1 -1
- package/src/v2/providers/CopilotKitProvider.tsx +19 -59
- package/src/v2/styles/globals.css +118 -0
- package/tsdown.config.ts +75 -0
- package/dist/copilotkit-CPe2-340.mjs.map +0 -1
- package/dist/copilotkit-DFaI4j2r.d.mts.map +0 -1
- package/dist/copilotkit-DGbvw8n2.cjs.map +0 -1
- package/dist/copilotkit-Dg4r4Gi_.d.cts.map +0 -1
- package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +0 -333
|
@@ -2,10 +2,10 @@ import React from "react";
|
|
|
2
2
|
import { act, render, screen, waitFor } from "@testing-library/react";
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
4
|
import { useInterrupt } from "../use-interrupt";
|
|
5
|
-
import { useCopilotKit } from "../../
|
|
5
|
+
import { useCopilotKit } from "../../context";
|
|
6
6
|
import { useAgent } from "../use-agent";
|
|
7
7
|
|
|
8
|
-
vi.mock("../../
|
|
8
|
+
vi.mock("../../context", () => ({
|
|
9
9
|
useCopilotKit: vi.fn(),
|
|
10
10
|
}));
|
|
11
11
|
|
|
@@ -3,10 +3,10 @@ import { render } from "@testing-library/react";
|
|
|
3
3
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { useRenderTool, type RenderToolProps } from "../use-render-tool";
|
|
6
|
-
import { useCopilotKit } from "../../
|
|
6
|
+
import { useCopilotKit } from "../../context";
|
|
7
7
|
import type { ReactToolCallRenderer } from "../../types/react-tool-call-renderer";
|
|
8
8
|
|
|
9
|
-
vi.mock("../../
|
|
9
|
+
vi.mock("../../context", () => ({
|
|
10
10
|
useCopilotKit: vi.fn(),
|
|
11
11
|
}));
|
|
12
12
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
3
3
|
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { useCopilotKit } from "../../
|
|
4
|
+
import { useCopilotKit } from "../../context";
|
|
5
5
|
import {
|
|
6
6
|
CopilotKitCoreRuntimeConnectionStatus,
|
|
7
7
|
ɵMAX_SOCKET_RETRIES,
|
|
8
8
|
} from "@copilotkit/core";
|
|
9
9
|
|
|
10
|
-
vi.mock("../../
|
|
10
|
+
vi.mock("../../context", () => ({
|
|
11
11
|
useCopilotKit: vi.fn(),
|
|
12
12
|
}));
|
|
13
13
|
|
|
@@ -15,11 +15,11 @@ import { z } from "zod";
|
|
|
15
15
|
import { useRenderTool } from "../use-render-tool";
|
|
16
16
|
import { useComponent } from "../use-component";
|
|
17
17
|
import { defineToolCallRenderer } from "../../types/defineToolCallRenderer";
|
|
18
|
-
import { useCopilotKit } from "../../
|
|
18
|
+
import { useCopilotKit } from "../../context";
|
|
19
19
|
import { useFrontendTool } from "../use-frontend-tool";
|
|
20
20
|
import type { ReactToolCallRenderer } from "../../types/react-tool-call-renderer";
|
|
21
21
|
|
|
22
|
-
vi.mock("../../
|
|
22
|
+
vi.mock("../../context", () => ({
|
|
23
23
|
useCopilotKit: vi.fn(),
|
|
24
24
|
}));
|
|
25
25
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { useCopilotKit } from "../
|
|
2
|
-
import { useCopilotChatConfiguration } from "../providers/CopilotChatConfigurationProvider";
|
|
1
|
+
import { useCopilotKit } from "../context";
|
|
3
2
|
import { useMemo, useEffect, useReducer, useRef } from "react";
|
|
4
3
|
import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
|
|
5
4
|
import { AbstractAgent, HttpAgent } from "@ag-ui/client";
|
|
@@ -23,7 +22,6 @@ const ALL_UPDATES: UseAgentUpdate[] = [
|
|
|
23
22
|
|
|
24
23
|
export interface UseAgentProps {
|
|
25
24
|
agentId?: string;
|
|
26
|
-
threadId?: string;
|
|
27
25
|
updates?: UseAgentUpdate[];
|
|
28
26
|
/**
|
|
29
27
|
* Throttle interval (in milliseconds) for re-renders triggered by
|
|
@@ -50,80 +48,7 @@ export interface UseAgentProps {
|
|
|
50
48
|
throttleMs?: number;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
* Clone a registry agent for per-thread isolation.
|
|
55
|
-
* Copies agent configuration (transport, headers, etc.) but resets conversation
|
|
56
|
-
* state (messages, threadId, state) so each thread starts fresh.
|
|
57
|
-
*/
|
|
58
|
-
function cloneForThread(
|
|
59
|
-
source: AbstractAgent,
|
|
60
|
-
threadId: string,
|
|
61
|
-
headers: Record<string, string>,
|
|
62
|
-
): AbstractAgent {
|
|
63
|
-
const clone = source.clone();
|
|
64
|
-
if (clone === source) {
|
|
65
|
-
throw new Error(
|
|
66
|
-
`useAgent: ${source.constructor.name}.clone() returned the same instance. ` +
|
|
67
|
-
`clone() must return a new, independent object.`,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
clone.threadId = threadId;
|
|
71
|
-
clone.setMessages([]);
|
|
72
|
-
clone.setState({});
|
|
73
|
-
if (clone instanceof HttpAgent) {
|
|
74
|
-
clone.headers = { ...headers };
|
|
75
|
-
}
|
|
76
|
-
return clone;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Module-level WeakMap: registryAgent → (threadId → clone).
|
|
81
|
-
* Shared across all useAgent() calls so that every component using the same
|
|
82
|
-
* (agentId, threadId) pair receives the same agent instance. Using WeakMap
|
|
83
|
-
* ensures the clone map is garbage-collected when the registry agent is
|
|
84
|
-
* replaced (e.g. after reconnect or hot-reload).
|
|
85
|
-
*/
|
|
86
|
-
export const globalThreadCloneMap = new WeakMap<
|
|
87
|
-
AbstractAgent,
|
|
88
|
-
Map<string, AbstractAgent>
|
|
89
|
-
>();
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Look up an existing per-thread clone without creating one.
|
|
93
|
-
* Returns undefined when no clone has been created yet for this pair.
|
|
94
|
-
*/
|
|
95
|
-
export function getThreadClone(
|
|
96
|
-
registryAgent: AbstractAgent | undefined | null,
|
|
97
|
-
threadId: string | undefined | null,
|
|
98
|
-
): AbstractAgent | undefined {
|
|
99
|
-
if (!registryAgent || !threadId) return undefined;
|
|
100
|
-
return globalThreadCloneMap.get(registryAgent)?.get(threadId);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function getOrCreateThreadClone(
|
|
104
|
-
existing: AbstractAgent,
|
|
105
|
-
threadId: string,
|
|
106
|
-
headers: Record<string, string>,
|
|
107
|
-
): AbstractAgent {
|
|
108
|
-
let byThread = globalThreadCloneMap.get(existing);
|
|
109
|
-
if (!byThread) {
|
|
110
|
-
byThread = new Map();
|
|
111
|
-
globalThreadCloneMap.set(existing, byThread);
|
|
112
|
-
}
|
|
113
|
-
const cached = byThread.get(threadId);
|
|
114
|
-
if (cached) return cached;
|
|
115
|
-
|
|
116
|
-
const clone = cloneForThread(existing, threadId, headers);
|
|
117
|
-
byThread.set(threadId, clone);
|
|
118
|
-
return clone;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function useAgent({
|
|
122
|
-
agentId,
|
|
123
|
-
threadId,
|
|
124
|
-
updates,
|
|
125
|
-
throttleMs,
|
|
126
|
-
}: UseAgentProps = {}) {
|
|
51
|
+
export function useAgent({ agentId, updates, throttleMs }: UseAgentProps = {}) {
|
|
127
52
|
agentId ??= DEFAULT_AGENT_ID;
|
|
128
53
|
|
|
129
54
|
const { copilotkit } = useCopilotKit();
|
|
@@ -131,12 +56,6 @@ export function useAgent({
|
|
|
131
56
|
// subscribeToAgentWithOptions reads it from the core instance, but React needs the dep
|
|
132
57
|
// to know when to re-subscribe.
|
|
133
58
|
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
134
|
-
// Fall back to the enclosing CopilotChatConfigurationProvider's threadId so
|
|
135
|
-
// that useAgent() called without explicit threadId (e.g. inside a custom
|
|
136
|
-
// message renderer) automatically uses the same per-thread clone as the
|
|
137
|
-
// CopilotChat component it lives within.
|
|
138
|
-
const chatConfig = useCopilotChatConfiguration();
|
|
139
|
-
threadId ??= chatConfig?.threadId;
|
|
140
59
|
|
|
141
60
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
142
61
|
|
|
@@ -153,29 +72,11 @@ export function useAgent({
|
|
|
153
72
|
);
|
|
154
73
|
|
|
155
74
|
const agent: AbstractAgent = useMemo(() => {
|
|
156
|
-
// Use a composite key when threadId is provided so that different threads
|
|
157
|
-
// for the same agent get independent instances.
|
|
158
|
-
const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
|
|
159
|
-
|
|
160
75
|
const existing = copilotkit.getAgent(agentId);
|
|
161
76
|
if (existing) {
|
|
162
|
-
// Real agent found — clear any cached
|
|
163
|
-
// bare agentId key (handles the case where a provisional was created
|
|
164
|
-
// before threadId was available, then the component re-renders with one).
|
|
165
|
-
provisionalAgentCache.current.delete(cacheKey);
|
|
77
|
+
// Real agent found — clear any cached provisional for this ID
|
|
166
78
|
provisionalAgentCache.current.delete(agentId);
|
|
167
|
-
|
|
168
|
-
if (!threadId) {
|
|
169
|
-
// No threadId — return the shared registry agent (original behavior)
|
|
170
|
-
return existing;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// threadId provided — return the shared per-thread clone.
|
|
174
|
-
// The global WeakMap ensures all components using the same
|
|
175
|
-
// (registryAgent, threadId) pair receive the same instance, so state
|
|
176
|
-
// mutations (addMessage, setState) are visible everywhere. The WeakMap
|
|
177
|
-
// entry is GC-collected automatically when the registry agent is replaced.
|
|
178
|
-
return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
|
|
79
|
+
return existing;
|
|
179
80
|
}
|
|
180
81
|
|
|
181
82
|
const isRuntimeConfigured = copilotkit.runtimeUrl !== undefined;
|
|
@@ -188,7 +89,7 @@ export function useAgent({
|
|
|
188
89
|
status === CopilotKitCoreRuntimeConnectionStatus.Connecting)
|
|
189
90
|
) {
|
|
190
91
|
// Return cached provisional if available (keeps reference stable)
|
|
191
|
-
const cached = provisionalAgentCache.current.get(
|
|
92
|
+
const cached = provisionalAgentCache.current.get(agentId);
|
|
192
93
|
if (cached) {
|
|
193
94
|
// Update headers on the cached agent in case they changed
|
|
194
95
|
cached.headers = { ...copilotkit.headers };
|
|
@@ -203,10 +104,7 @@ export function useAgent({
|
|
|
203
104
|
});
|
|
204
105
|
// Apply current headers so runs/connects inherit them
|
|
205
106
|
provisional.headers = { ...copilotkit.headers };
|
|
206
|
-
|
|
207
|
-
provisional.threadId = threadId;
|
|
208
|
-
}
|
|
209
|
-
provisionalAgentCache.current.set(cacheKey, provisional);
|
|
107
|
+
provisionalAgentCache.current.set(agentId, provisional);
|
|
210
108
|
return provisional;
|
|
211
109
|
}
|
|
212
110
|
|
|
@@ -219,10 +117,7 @@ export function useAgent({
|
|
|
219
117
|
isRuntimeConfigured &&
|
|
220
118
|
status === CopilotKitCoreRuntimeConnectionStatus.Error
|
|
221
119
|
) {
|
|
222
|
-
|
|
223
|
-
// headers update) return the same agent reference, matching the
|
|
224
|
-
// Disconnected/Connecting path and preventing spurious re-subscriptions.
|
|
225
|
-
const cached = provisionalAgentCache.current.get(cacheKey);
|
|
120
|
+
const cached = provisionalAgentCache.current.get(agentId);
|
|
226
121
|
if (cached) {
|
|
227
122
|
cached.headers = { ...copilotkit.headers };
|
|
228
123
|
return cached;
|
|
@@ -234,10 +129,7 @@ export function useAgent({
|
|
|
234
129
|
runtimeMode: "pending",
|
|
235
130
|
});
|
|
236
131
|
provisional.headers = { ...copilotkit.headers };
|
|
237
|
-
|
|
238
|
-
provisional.threadId = threadId;
|
|
239
|
-
}
|
|
240
|
-
provisionalAgentCache.current.set(cacheKey, provisional);
|
|
132
|
+
provisionalAgentCache.current.set(agentId, provisional);
|
|
241
133
|
return provisional;
|
|
242
134
|
}
|
|
243
135
|
|
|
@@ -256,7 +148,6 @@ export function useAgent({
|
|
|
256
148
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
257
149
|
}, [
|
|
258
150
|
agentId,
|
|
259
|
-
threadId,
|
|
260
151
|
copilotkit.agents,
|
|
261
152
|
copilotkit.runtimeConnectionStatus,
|
|
262
153
|
copilotkit.runtimeUrl,
|
|
@@ -290,7 +181,7 @@ export function useAgent({
|
|
|
290
181
|
};
|
|
291
182
|
|
|
292
183
|
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {
|
|
293
|
-
handlers.onMessagesChanged =
|
|
184
|
+
handlers.onMessagesChanged = batchedForceUpdate;
|
|
294
185
|
}
|
|
295
186
|
|
|
296
187
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
-
import { useCopilotKit } from "../
|
|
2
|
+
import { useCopilotKit } from "../context";
|
|
3
3
|
import { useCopilotChatConfiguration } from "../providers/CopilotChatConfigurationProvider";
|
|
4
4
|
import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
|
|
5
5
|
import type {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
|
-
import { useCopilotKit } from "../
|
|
2
|
+
import { useCopilotKit } from "../context";
|
|
3
3
|
import type { ReactFrontendTool } from "../types/frontend-tool";
|
|
4
4
|
|
|
5
5
|
const EMPTY_DEPS: ReadonlyArray<unknown> = [];
|
|
@@ -42,5 +42,5 @@ export function useFrontendTool<
|
|
|
42
42
|
// Depend on stable keys by default and allow callers to opt into
|
|
43
43
|
// additional dependencies for dynamic tool configuration.
|
|
44
44
|
// tool.available is included so toggling availability re-registers the tool.
|
|
45
|
-
}, [tool.name, tool.available, copilotkit,
|
|
45
|
+
}, [tool.name, tool.available, copilotkit, JSON.stringify(extraDeps)]);
|
|
46
46
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCopilotKit } from "../
|
|
1
|
+
import { useCopilotKit } from "../context";
|
|
2
2
|
import type { ReactFrontendTool } from "../types/frontend-tool";
|
|
3
3
|
import type { ReactHumanInTheLoop } from "../types/human-in-the-loop";
|
|
4
4
|
import type { ReactToolCallRenderer } from "../types/react-tool-call-renderer";
|
|
@@ -3,12 +3,10 @@ import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
|
|
|
3
3
|
import { useCopilotKit, useCopilotChatConfiguration } from "../providers";
|
|
4
4
|
import { useCallback, useMemo } from "react";
|
|
5
5
|
import { ReactActivityMessageRenderer } from "../types";
|
|
6
|
-
import { getThreadClone } from "./use-agent";
|
|
7
6
|
|
|
8
7
|
export function useRenderActivityMessage() {
|
|
9
8
|
const { copilotkit } = useCopilotKit();
|
|
10
|
-
const
|
|
11
|
-
const agentId = config?.agentId ?? DEFAULT_AGENT_ID;
|
|
9
|
+
const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
|
|
12
10
|
|
|
13
11
|
const renderers = copilotkit.renderActivityMessages;
|
|
14
12
|
|
|
@@ -52,13 +50,7 @@ export function useRenderActivityMessage() {
|
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
const Component = renderer.render;
|
|
55
|
-
|
|
56
|
-
// calls runAgent on the same agent instance that CopilotChat renders from.
|
|
57
|
-
// Without this, button clicks accumulate messages on the registry agent
|
|
58
|
-
// while CopilotChat displays from the clone — responses appear to vanish.
|
|
59
|
-
const registryAgent = copilotkit.getAgent(agentId);
|
|
60
|
-
const agent =
|
|
61
|
-
getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
|
|
53
|
+
const agent = copilotkit.getAgent(agentId);
|
|
62
54
|
|
|
63
55
|
return (
|
|
64
56
|
<Component
|
|
@@ -70,7 +62,7 @@ export function useRenderActivityMessage() {
|
|
|
70
62
|
/>
|
|
71
63
|
);
|
|
72
64
|
},
|
|
73
|
-
[agentId,
|
|
65
|
+
[agentId, copilotkit, findRenderer],
|
|
74
66
|
);
|
|
75
67
|
|
|
76
68
|
return useMemo(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useCopilotChatConfiguration, useCopilotKit } from "../providers";
|
|
2
|
-
import { getThreadClone } from "./use-agent";
|
|
3
2
|
import { ReactCustomMessageRendererPosition } from "../types/react-custom-message-renderer";
|
|
4
3
|
import { Message } from "@ag-ui/core";
|
|
5
4
|
|
|
@@ -39,11 +38,7 @@ export function useRenderCustomMessages() {
|
|
|
39
38
|
copilotkit.getRunIdForMessage(agentId, threadId, message.id) ??
|
|
40
39
|
copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
|
|
41
40
|
const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
|
|
42
|
-
|
|
43
|
-
// conversation state (messages live on the clone, not the registry agent).
|
|
44
|
-
// Fall back to the registry agent when no clone exists (no threadId).
|
|
45
|
-
const registryAgent = copilotkit.getAgent(agentId);
|
|
46
|
-
const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
|
|
41
|
+
const agent = copilotkit.getAgent(agentId);
|
|
47
42
|
if (!agent) {
|
|
48
43
|
return null;
|
|
49
44
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useMemo, useSyncExternalStore } from "react";
|
|
2
2
|
import { ToolCall, ToolMessage } from "@ag-ui/core";
|
|
3
3
|
import { ToolCallStatus } from "@copilotkit/core";
|
|
4
|
-
import { useCopilotKit } from "../
|
|
4
|
+
import { useCopilotKit } from "../context";
|
|
5
5
|
import { useCopilotChatConfiguration } from "../providers/CopilotChatConfigurationProvider";
|
|
6
6
|
import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
|
|
7
7
|
import { partialJSONParse } from "@copilotkit/shared";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
import type { StandardSchemaV1, InferSchemaOutput } from "@copilotkit/shared";
|
|
3
|
-
import { useCopilotKit } from "../
|
|
3
|
+
import { useCopilotKit } from "../context";
|
|
4
4
|
import { defineToolCallRenderer } from "../types/defineToolCallRenderer";
|
|
5
5
|
|
|
6
6
|
const EMPTY_DEPS: ReadonlyArray<unknown> = [];
|
|
@@ -180,5 +180,5 @@ export function useRenderTool<S extends StandardSchemaV1>(
|
|
|
180
180
|
copilotkit.addHookRenderToolCall(renderer);
|
|
181
181
|
|
|
182
182
|
// No cleanup removal — keeps renderer for chat history, same as useFrontendTool
|
|
183
|
-
}, [config.name, copilotkit,
|
|
183
|
+
}, [config.name, copilotkit, JSON.stringify(extraDeps)]);
|
|
184
184
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { Suggestion } from "@copilotkit/core";
|
|
3
|
-
import { useCopilotKit } from "../
|
|
3
|
+
import { useCopilotKit } from "../context";
|
|
4
4
|
import { useCopilotChatConfiguration } from "../providers/CopilotChatConfigurationProvider";
|
|
5
5
|
import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
|
|
6
6
|
|
|
@@ -4,8 +4,6 @@ import type { AbstractAgent } from "@ag-ui/client";
|
|
|
4
4
|
import type { FrontendTool } from "@copilotkit/core";
|
|
5
5
|
import type React from "react";
|
|
6
6
|
import {
|
|
7
|
-
createContext,
|
|
8
|
-
useContext,
|
|
9
7
|
type ReactNode,
|
|
10
8
|
useMemo,
|
|
11
9
|
useEffect,
|
|
@@ -14,6 +12,14 @@ import {
|
|
|
14
12
|
useRef,
|
|
15
13
|
useState,
|
|
16
14
|
} from "react";
|
|
15
|
+
// Context extracted to ../context.ts for cross-platform reuse (React Native)
|
|
16
|
+
import {
|
|
17
|
+
CopilotKitContext,
|
|
18
|
+
type CopilotKitContextValue,
|
|
19
|
+
LicenseContext,
|
|
20
|
+
} from "../context";
|
|
21
|
+
export type { CopilotKitContextValue } from "../context";
|
|
22
|
+
export { CopilotKitContext, useLicenseContext } from "../context";
|
|
17
23
|
import { z } from "zod";
|
|
18
24
|
import { CopilotKitInspector } from "../components/CopilotKitInspector";
|
|
19
25
|
import type { Anchor } from "@copilotkit/web-inspector";
|
|
@@ -81,34 +87,6 @@ const GENERATE_SANDBOXED_UI_DESCRIPTION =
|
|
|
81
87
|
"3. html (streams in live — the user watches the UI build as HTML is generated)\n" +
|
|
82
88
|
"4. jsFunctions (reusable helper functions)\n" +
|
|
83
89
|
"5. jsExpressions (applied one-by-one — the user sees each expression take effect)";
|
|
84
|
-
|
|
85
|
-
// Define the context value interface - idiomatic React naming
|
|
86
|
-
export interface CopilotKitContextValue {
|
|
87
|
-
copilotkit: CopilotKitCoreReact;
|
|
88
|
-
/**
|
|
89
|
-
* Set of tool call IDs currently being executed.
|
|
90
|
-
* This is tracked at the provider level to ensure tool execution events
|
|
91
|
-
* are captured even before child components mount.
|
|
92
|
-
*/
|
|
93
|
-
executingToolCallIds: ReadonlySet<string>;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Empty set for default context value
|
|
97
|
-
const EMPTY_SET: ReadonlySet<string> = new Set();
|
|
98
|
-
|
|
99
|
-
// Create the CopilotKit context
|
|
100
|
-
const CopilotKitContext = createContext<CopilotKitContextValue>({
|
|
101
|
-
copilotkit: null!,
|
|
102
|
-
executingToolCallIds: EMPTY_SET,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
const LicenseContext = createContext<LicenseContextValue>(
|
|
106
|
-
createLicenseContextValue(null),
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
export const useLicenseContext = (): LicenseContextValue =>
|
|
110
|
-
useContext(LicenseContext);
|
|
111
|
-
|
|
112
90
|
// Provider props interface
|
|
113
91
|
export interface CopilotKitProviderProps {
|
|
114
92
|
children: ReactNode;
|
|
@@ -642,15 +620,17 @@ export const CopilotKitProvider: React.FC<CopilotKitProviderProps> = ({
|
|
|
642
620
|
}, [onError]);
|
|
643
621
|
|
|
644
622
|
useEffect(() => {
|
|
645
|
-
if (!onErrorRef.current) return;
|
|
646
|
-
|
|
647
623
|
const subscription = copilotkit.subscribe({
|
|
648
624
|
onError: (event) => {
|
|
649
|
-
onErrorRef.current
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
625
|
+
if (onErrorRef.current) {
|
|
626
|
+
onErrorRef.current(event);
|
|
627
|
+
} else {
|
|
628
|
+
console.error(
|
|
629
|
+
`[CopilotKit] Error (${event.code}):`,
|
|
630
|
+
event.error,
|
|
631
|
+
event.context ?? {},
|
|
632
|
+
);
|
|
633
|
+
}
|
|
654
634
|
},
|
|
655
635
|
});
|
|
656
636
|
|
|
@@ -816,25 +796,5 @@ export const CopilotKitProvider: React.FC<CopilotKitProviderProps> = ({
|
|
|
816
796
|
);
|
|
817
797
|
};
|
|
818
798
|
|
|
819
|
-
//
|
|
820
|
-
export
|
|
821
|
-
const context = useContext(CopilotKitContext);
|
|
822
|
-
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
823
|
-
|
|
824
|
-
if (!context) {
|
|
825
|
-
throw new Error("useCopilotKit must be used within CopilotKitProvider");
|
|
826
|
-
}
|
|
827
|
-
useEffect(() => {
|
|
828
|
-
const subscription = context.copilotkit.subscribe({
|
|
829
|
-
onRuntimeConnectionStatusChanged: () => {
|
|
830
|
-
forceUpdate();
|
|
831
|
-
},
|
|
832
|
-
});
|
|
833
|
-
return () => {
|
|
834
|
-
subscription.unsubscribe();
|
|
835
|
-
};
|
|
836
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
837
|
-
}, []);
|
|
838
|
-
|
|
839
|
-
return context;
|
|
840
|
-
};
|
|
799
|
+
// Re-export useCopilotKit from context for backward compatibility
|
|
800
|
+
export { useCopilotKit } from "../context";
|
|
@@ -229,3 +229,121 @@
|
|
|
229
229
|
background-repeat: no-repeat;
|
|
230
230
|
background-size: 100% 100%;
|
|
231
231
|
}
|
|
232
|
+
/*
|
|
233
|
+
* IntelligenceIndicator pill — visual styles ported from
|
|
234
|
+
* CopilotKit/Intelligence #155.
|
|
235
|
+
*
|
|
236
|
+
* Violet/indigo glassmorphism — text #5B21B6, icon #7C3AED, border
|
|
237
|
+
* #9599E0, gradient stop #EEE6FE, soft shadow #5E64AD.
|
|
238
|
+
*/
|
|
239
|
+
.cpk-intelligence-pill {
|
|
240
|
+
display: inline-flex;
|
|
241
|
+
/* Opt out of the parent flex-column's default `align-items: stretch`
|
|
242
|
+
(the auto-mount lives inside `CopilotChatMessageView`'s
|
|
243
|
+
`cpk:flex cpk:flex-col` container). Without this the pill would
|
|
244
|
+
stretch to the full chat width even though `inline-flex` is
|
|
245
|
+
supposed to shrink to its content. */
|
|
246
|
+
align-self: flex-start;
|
|
247
|
+
align-items: center;
|
|
248
|
+
gap: 0.55rem;
|
|
249
|
+
margin: 0.4rem 0;
|
|
250
|
+
padding: 0.4rem 0.85rem;
|
|
251
|
+
border: 1px solid rgb(149 153 224 / 0.32);
|
|
252
|
+
border-radius: 999px;
|
|
253
|
+
background: linear-gradient(
|
|
254
|
+
135deg,
|
|
255
|
+
rgb(255 255 255 / 0.55) 0%,
|
|
256
|
+
rgb(238 230 254 / 0.55) 100%
|
|
257
|
+
);
|
|
258
|
+
-webkit-backdrop-filter: blur(14px) saturate(160%);
|
|
259
|
+
backdrop-filter: blur(14px) saturate(160%);
|
|
260
|
+
color: rgb(91 33 182 / 0.92);
|
|
261
|
+
font-size: 0.78rem;
|
|
262
|
+
font-weight: 500;
|
|
263
|
+
letter-spacing: 0.01em;
|
|
264
|
+
white-space: nowrap;
|
|
265
|
+
box-shadow:
|
|
266
|
+
0 1px 2px rgb(94 100 173 / 0.06),
|
|
267
|
+
0 8px 24px rgb(149 153 224 / 0.08),
|
|
268
|
+
inset 0 1px 0 rgb(255 255 255 / 0.6);
|
|
269
|
+
opacity: 0;
|
|
270
|
+
transform: translateY(2px);
|
|
271
|
+
animation: cpk-intelligence-pill-fade-in 280ms ease-out forwards;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.cpk-intelligence-pill--fading {
|
|
275
|
+
/* Switching the `animation` property cancels the in-flight fade-in
|
|
276
|
+
and replaces the held final-value (opacity:1 from `forwards`) with
|
|
277
|
+
this fade-out keyframe set. Plain `opacity: 0` declarations would
|
|
278
|
+
otherwise lose to the animation's held value. */
|
|
279
|
+
animation: cpk-intelligence-pill-fade-out 480ms ease-out forwards;
|
|
280
|
+
pointer-events: none;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.cpk-intelligence-pill__icon {
|
|
284
|
+
display: block;
|
|
285
|
+
flex-shrink: 0;
|
|
286
|
+
color: rgb(124 58 237);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.cpk-intelligence-pill__ring {
|
|
290
|
+
stroke: currentColor;
|
|
291
|
+
stroke-dasharray: 40 16.55;
|
|
292
|
+
stroke-dashoffset: 0;
|
|
293
|
+
transform-origin: 12px 12px;
|
|
294
|
+
animation: cpk-intelligence-pill-spin 0.9s linear infinite;
|
|
295
|
+
transition: stroke-dasharray 320ms ease-out;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.cpk-intelligence-pill__ring--done {
|
|
299
|
+
stroke-dasharray: 56.55 0;
|
|
300
|
+
animation: none;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.cpk-intelligence-pill__check {
|
|
304
|
+
stroke: currentColor;
|
|
305
|
+
stroke-dasharray: 12;
|
|
306
|
+
stroke-dashoffset: 12;
|
|
307
|
+
/* Opacity zero hides the rounded `stroke-linecap` end-cap that would
|
|
308
|
+
otherwise leak through as a stationary dot at path end (16, 9.5)
|
|
309
|
+
during spinner phase. The `dasharray + dashoffset` zeroes the
|
|
310
|
+
visible stroke length, but the cap is drawn at the dash boundary
|
|
311
|
+
regardless, so we need opacity to fully hide it. */
|
|
312
|
+
opacity: 0;
|
|
313
|
+
transition:
|
|
314
|
+
stroke-dashoffset 320ms ease-out 200ms,
|
|
315
|
+
opacity 200ms ease-out 200ms;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.cpk-intelligence-pill__check--shown {
|
|
319
|
+
stroke-dashoffset: 0;
|
|
320
|
+
opacity: 1;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
@keyframes cpk-intelligence-pill-fade-in {
|
|
324
|
+
from {
|
|
325
|
+
opacity: 0;
|
|
326
|
+
transform: translateY(2px);
|
|
327
|
+
}
|
|
328
|
+
to {
|
|
329
|
+
opacity: 1;
|
|
330
|
+
transform: translateY(0);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@keyframes cpk-intelligence-pill-fade-out {
|
|
335
|
+
from {
|
|
336
|
+
opacity: 1;
|
|
337
|
+
transform: translateY(0);
|
|
338
|
+
}
|
|
339
|
+
to {
|
|
340
|
+
opacity: 0;
|
|
341
|
+
transform: translateY(-2px);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
@keyframes cpk-intelligence-pill-spin {
|
|
346
|
+
to {
|
|
347
|
+
transform: rotate(360deg);
|
|
348
|
+
}
|
|
349
|
+
}
|