@copilotkit/react-core 1.70.3 → 1.71.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.
Files changed (60) hide show
  1. package/dist/{copilotkit-BU3OvveB.cjs → copilotkit-BkVEkUS0.cjs} +369 -154
  2. package/dist/copilotkit-BkVEkUS0.cjs.map +1 -0
  3. package/dist/{copilotkit-Bs98akp9.d.mts → copilotkit-ChjzWqn6.d.mts} +33 -8
  4. package/dist/copilotkit-ChjzWqn6.d.mts.map +1 -0
  5. package/dist/{copilotkit-Ap_yisA5.mjs → copilotkit-D5BTo0YG.mjs} +368 -153
  6. package/dist/copilotkit-D5BTo0YG.mjs.map +1 -0
  7. package/dist/{copilotkit-X2eGbOwf.d.cts → copilotkit-DCIXZawe.d.cts} +33 -8
  8. package/dist/copilotkit-DCIXZawe.d.cts.map +1 -0
  9. package/dist/index.cjs +3 -3
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +1 -1
  12. package/dist/index.d.mts +1 -1
  13. package/dist/index.mjs +4 -4
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/index.umd.js +180 -139
  16. package/dist/index.umd.js.map +1 -1
  17. package/dist/v2/context.cjs +4 -0
  18. package/dist/v2/context.cjs.map +1 -1
  19. package/dist/v2/context.d.cts +3 -1
  20. package/dist/v2/context.d.cts.map +1 -1
  21. package/dist/v2/context.d.mts +3 -1
  22. package/dist/v2/context.d.mts.map +1 -1
  23. package/dist/v2/context.mjs +3 -1
  24. package/dist/v2/context.mjs.map +1 -1
  25. package/dist/v2/headless.cjs +20 -5
  26. package/dist/v2/headless.cjs.map +1 -1
  27. package/dist/v2/headless.d.cts +9 -4
  28. package/dist/v2/headless.d.cts.map +1 -1
  29. package/dist/v2/headless.d.mts +9 -4
  30. package/dist/v2/headless.d.mts.map +1 -1
  31. package/dist/v2/headless.mjs +21 -6
  32. package/dist/v2/headless.mjs.map +1 -1
  33. package/dist/v2/index.cjs +1 -1
  34. package/dist/v2/index.css +1 -1
  35. package/dist/v2/index.d.cts +1 -1
  36. package/dist/v2/index.d.mts +1 -1
  37. package/dist/v2/index.mjs +1 -1
  38. package/dist/v2/index.umd.js +495 -278
  39. package/dist/v2/index.umd.js.map +1 -1
  40. package/package.json +8 -9
  41. package/dist/copilotkit-Ap_yisA5.mjs.map +0 -1
  42. package/dist/copilotkit-BU3OvveB.cjs.map +0 -1
  43. package/dist/copilotkit-Bs98akp9.d.mts.map +0 -1
  44. package/dist/copilotkit-X2eGbOwf.d.cts.map +0 -1
  45. package/skills/react-core/SKILL.md +0 -110
  46. package/skills/react-core/references/agent-access.md +0 -355
  47. package/skills/react-core/references/attachments.md +0 -311
  48. package/skills/react-core/references/capabilities.md +0 -138
  49. package/skills/react-core/references/chat-components.md +0 -229
  50. package/skills/react-core/references/client-side-tools.md +0 -358
  51. package/skills/react-core/references/custom-message-renderers.md +0 -223
  52. package/skills/react-core/references/debug-mode.md +0 -140
  53. package/skills/react-core/references/human-in-the-loop.md +0 -312
  54. package/skills/react-core/references/provider-setup.md +0 -358
  55. package/skills/react-core/references/rendering-activity-messages.md +0 -201
  56. package/skills/react-core/references/rendering-tool-calls.md +0 -319
  57. package/skills/react-core/references/suggestions.md +0 -211
  58. package/skills/react-core/references/switching-agents-recipes.md +0 -161
  59. package/skills/react-core/references/switching-agents.md +0 -240
  60. package/skills/react-core/references/threads.md +0 -289
@@ -1,240 +0,0 @@
1
- # CopilotKit Switching Agents (React)
2
-
3
- This skill builds on `copilotkit/agent-access`, `copilotkit/client-side-tools`,
4
- and `copilotkit/rendering-tool-calls`.
5
-
6
- Three main patterns:
7
-
8
- 1. **Parallel panels** — one `useAgent({ agentId })` per surface.
9
- 2. **Slot swap** — `<CopilotChat key={agentId} agentId={agentId} />`.
10
- 3. **Discovery** — subscribe to `onAgentsChanged` (no `useAgents()` hook).
11
-
12
- ## Setup
13
-
14
- ```tsx
15
- "use client";
16
- import { CopilotChat } from "@copilotkit/react-core/v2";
17
- import { useState } from "react";
18
-
19
- export function AgentSwitcherChat() {
20
- const [activeAgent, setActiveAgent] = useState("research");
21
-
22
- return (
23
- <div>
24
- <div>
25
- <button onClick={() => setActiveAgent("research")}>Research</button>
26
- <button onClick={() => setActiveAgent("coding")}>Coding</button>
27
- </div>
28
-
29
- {/* key={activeAgent} forces remount so thread state doesn't leak */}
30
- <CopilotChat key={activeAgent} agentId={activeAgent} />
31
- </div>
32
- );
33
- }
34
- ```
35
-
36
- ## Core Patterns
37
-
38
- ### Side-by-side chat panels
39
-
40
- ```tsx
41
- <div className="grid grid-cols-2 gap-4">
42
- <CopilotChat agentId="research" threadId="research-main" />
43
- <CopilotChat agentId="coding" threadId="coding-main" />
44
- </div>
45
- ```
46
-
47
- ### Agent-scoped tool
48
-
49
- ```tsx
50
- import { useFrontendTool } from "@copilotkit/react-core/v2";
51
- import { z } from "zod";
52
-
53
- useFrontendTool({
54
- name: "saveFindings",
55
- agentId: "research", // ← only the research agent sees this tool
56
- parameters: z.object({ summary: z.string() }),
57
- handler: async ({ summary }) => {
58
- await fetch("/api/findings", { method: "POST", body: summary });
59
- },
60
- });
61
- ```
62
-
63
- ### Agent-scoped renderer
64
-
65
- ```tsx
66
- import { useRenderTool } from "@copilotkit/react-core/v2";
67
- import { z } from "zod";
68
-
69
- useRenderTool({
70
- name: "search",
71
- agentId: "research", // ← only applies to research's "search" tool
72
- parameters: z.object({ q: z.string() }),
73
- render: ({ status, parameters, result }) => {
74
- if (status === "inProgress") return <div>Preparing...</div>;
75
- if (status === "executing") return <div>Searching {parameters.q}</div>;
76
- return <div>{result}</div>;
77
- },
78
- });
79
- ```
80
-
81
- ### Discover available agents (no `useAgents` hook)
82
-
83
- ```tsx
84
- "use client";
85
- import { useCopilotKit } from "@copilotkit/react-core/v2";
86
- import { useEffect, useState } from "react";
87
-
88
- export function useAvailableAgents() {
89
- const { copilotkit } = useCopilotKit();
90
- const [ids, setIds] = useState<string[]>(() =>
91
- Object.keys(copilotkit.agents ?? {}),
92
- );
93
-
94
- useEffect(() => {
95
- const subscription = copilotkit.subscribe({
96
- onAgentsChanged: ({ agents }) => {
97
- setIds(Object.keys(agents ?? {}));
98
- },
99
- });
100
- return () => subscription.unsubscribe();
101
- }, [copilotkit]);
102
-
103
- return ids;
104
- }
105
- ```
106
-
107
- ## Common Mistakes
108
-
109
- ### HIGH — Switching `agentId` on a persisted `<CopilotChat>` without `key`
110
-
111
- Wrong:
112
-
113
- ```tsx
114
- <CopilotChat agentId={activeAgent} />
115
- ```
116
-
117
- Correct:
118
-
119
- ```tsx
120
- <CopilotChat key={activeAgent} agentId={activeAgent} />
121
- ```
122
-
123
- Without remount via `key`, prior thread state and in-flight runs leak into
124
- the new agent's view. The remount pattern gives each agent a clean slate.
125
-
126
- Keep the `key` on `<CopilotChat>` itself. It discards all state below it, so
127
- hoisting it onto a wrapper or a layout-level provider also destroys app
128
- state that has nothing to do with the agent — correlation maps, in-flight
129
- request records, refs — with no error and no warning. If a component
130
- dispatches requests and matches the responses back, it must sit outside the
131
- keyed subtree. See "Keying a subtree on the active thread id above app
132
- state" in `references/threads.md` for the thread-switching version of the
133
- same trap.
134
-
135
- Source: `examples/v2/react-router/app/routes/_index.tsx:38-39`
136
-
137
- ### MEDIUM — Omitting `agentId` when multiple agents share a tool name
138
-
139
- Wrong:
140
-
141
- ```tsx
142
- // Both research and coding agents have a "search" tool — unscoped wins globally
143
- useRenderToolCall({
144
- name: "search",
145
- args: z.object({ q: z.string() }),
146
- render,
147
- });
148
- ```
149
-
150
- Correct:
151
-
152
- ```tsx
153
- useRenderTool({
154
- name: "search",
155
- agentId: "research",
156
- parameters: z.object({ q: z.string() }),
157
- render: researchSearchRender,
158
- });
159
- useRenderTool({
160
- name: "search",
161
- agentId: "coding",
162
- parameters: z.object({ q: z.string() }),
163
- render: codingSearchRender,
164
- });
165
- ```
166
-
167
- Unscoped renderers apply to every agent. When two agents have a tool with
168
- the same name and only one has a renderer, the unscoped renderer wins
169
- globally and the other agent never gets its intended renderer.
170
-
171
- Source: `packages/react-core/src/v2/hooks/use-render-tool-call.tsx:145-154`
172
-
173
- ### MEDIUM — Tools registered without `agentId` leak across panels
174
-
175
- Wrong:
176
-
177
- ```tsx
178
- useFrontendTool({
179
- name: "saveFindings",
180
- parameters: z.object({ summary: z.string() }),
181
- handler,
182
- });
183
- // Both research and coding agents now see saveFindings.
184
- ```
185
-
186
- Correct:
187
-
188
- ```tsx
189
- useFrontendTool({
190
- name: "saveFindings",
191
- agentId: "research",
192
- parameters: z.object({ summary: z.string() }),
193
- handler,
194
- });
195
- ```
196
-
197
- Omitting `agentId` attaches the tool to every agent. In a multi-agent UI
198
- this leaks the handler across panels. Scope tools explicitly when they
199
- should only apply to one agent.
200
-
201
- Source: `packages/react-core/src/v2/hooks/use-frontend-tool.tsx`
202
-
203
- ### MEDIUM — Using `useAgents()` (does not exist)
204
-
205
- Wrong:
206
-
207
- ```tsx
208
- import { useAgents } from "@copilotkit/react-core/v2"; // not exported
209
- const agents = useAgents();
210
- ```
211
-
212
- Correct:
213
-
214
- ```tsx
215
- import { useCopilotKit } from "@copilotkit/react-core/v2";
216
- import { useEffect, useState } from "react";
217
-
218
- function useAvailableAgents() {
219
- const { copilotkit } = useCopilotKit();
220
- const [ids, setIds] = useState<string[]>(() =>
221
- Object.keys(copilotkit.agents ?? {}),
222
- );
223
- useEffect(() => {
224
- const sub = copilotkit.subscribe({
225
- onAgentsChanged: ({ agents }) => setIds(Object.keys(agents ?? {})),
226
- });
227
- return () => sub.unsubscribe();
228
- }, [copilotkit]);
229
- return ids;
230
- }
231
- ```
232
-
233
- There is no `useAgents` hook in v2. Discover agents by subscribing to
234
- `onAgentsChanged` on the core client.
235
-
236
- Source: `packages/react-core/src/v2/hooks/index.ts` (no `useAgents` export)
237
-
238
- ## References
239
-
240
- - [Agent switcher recipes](switching-agents-recipes.md) — dropdown, tabs, keyboard shortcuts
@@ -1,289 +0,0 @@
1
- # CopilotKit Threads (React)
2
-
3
- This skill builds on `copilotkit/agent-access`. Durable threads only exist
4
- in Intelligence mode — a runtime pointed at `api.cloud.copilotkit.ai` or a
5
- self-managed Intelligence instance. In plain SSE mode the hook errors.
6
-
7
- ## Setup
8
-
9
- ```tsx
10
- "use client";
11
- import { useThreads } from "@copilotkit/react-core/v2";
12
-
13
- export function ThreadSidebar({ agentId }: { agentId: string }) {
14
- const {
15
- threads,
16
- isLoading,
17
- error,
18
- hasMoreThreads,
19
- fetchMoreThreads,
20
- renameThread,
21
- archiveThread,
22
- deleteThread,
23
- } = useThreads({ agentId });
24
-
25
- if (error) return <div className="text-red-500">{error.message}</div>;
26
- if (isLoading) return <div>Loading threads…</div>;
27
-
28
- return (
29
- <ul className="space-y-1">
30
- {threads.map((t) => (
31
- <li key={t.id} className="flex gap-2">
32
- <span>{t.name ?? "Untitled"}</span>
33
- <button onClick={() => renameThread(t.id, "Renamed")}>Rename</button>
34
- <button onClick={() => archiveThread(t.id)}>Archive</button>
35
- </li>
36
- ))}
37
- {hasMoreThreads && <button onClick={fetchMoreThreads}>Load more</button>}
38
- </ul>
39
- );
40
- }
41
- ```
42
-
43
- ## Core Patterns
44
-
45
- ### Paginated list
46
-
47
- ```tsx
48
- const { threads, hasMoreThreads, fetchMoreThreads, isFetchingMoreThreads } =
49
- useThreads({ agentId: "default", limit: 25 });
50
- ```
51
-
52
- ### Include archived threads
53
-
54
- ```tsx
55
- const { threads: archived } = useThreads({
56
- agentId: "default",
57
- includeArchived: true,
58
- });
59
- ```
60
-
61
- ### Optimistic archive with error rollback
62
-
63
- ```tsx
64
- const { threads, archiveThread } = useThreads({ agentId: "default" });
65
-
66
- async function onArchive(id: string) {
67
- try {
68
- await archiveThread(id);
69
- toast.success("Archived");
70
- } catch (err) {
71
- toast.error(`Failed to archive: ${String(err)}`);
72
- }
73
- }
74
- ```
75
-
76
- ### Thread-switcher + `<CopilotChat>`
77
-
78
- ```tsx
79
- import { CopilotChat, useThreads } from "@copilotkit/react-core/v2";
80
- import { useState } from "react";
81
-
82
- export function ThreadSwitcher() {
83
- const { threads } = useThreads({ agentId: "default" });
84
- const [activeId, setActiveId] = useState<string | null>(null);
85
-
86
- return (
87
- <div className="grid grid-cols-[200px_1fr]">
88
- <ul>
89
- {threads.map((t) => (
90
- <li key={t.id}>
91
- <button onClick={() => setActiveId(t.id)}>
92
- {t.name ?? "Untitled"}
93
- </button>
94
- </li>
95
- ))}
96
- </ul>
97
- {/*
98
- `key` here remounts ONLY <CopilotChat>. Keep it that way: a `key` on
99
- an ancestor would remount the app tree below it too. See
100
- "Keying a subtree on the active thread id" below.
101
- */}
102
- {activeId && (
103
- <CopilotChat key={activeId} agentId="default" threadId={activeId} />
104
- )}
105
- </div>
106
- );
107
- }
108
- ```
109
-
110
- `activeId` starts as `null` and becomes a real thread id only after the
111
- `useThreads` fetch resolves — so this is an **asynchronous, post-mount**
112
- change, not something settled during the first render.
113
-
114
- ## Common Mistakes
115
-
116
- ### HIGH — Keying a subtree on the active thread id above app state
117
-
118
- Wrong:
119
-
120
- ```tsx
121
- // app/layout.tsx
122
- const { threadId } = useThreadSelection();
123
-
124
- return (
125
- <CopilotKitProvider runtimeUrl="/api/copilotkit">
126
- {/* Remounts EVERYTHING below on every thread change. */}
127
- <MyAppProvider key={threadId}>{children}</MyAppProvider>
128
- </CopilotKitProvider>
129
- );
130
- ```
131
-
132
- Correct:
133
-
134
- ```tsx
135
- // app/layout.tsx — app state stays mounted across thread changes.
136
- return (
137
- <CopilotKitProvider runtimeUrl="/api/copilotkit">
138
- <MyAppProvider>{children}</MyAppProvider>
139
- </CopilotKitProvider>
140
- );
141
- ```
142
-
143
- ```tsx
144
- // Reset only what is genuinely per-thread, as deep as possible.
145
- <ThreadScopedTranscript key={threadId} />
146
- ```
147
-
148
- `key={threadId}` is a legitimate way to reset per-thread state, but it
149
- discards **all** state below it — refs, correlation maps, in-flight request
150
- bookkeeping, scroll positions. Placed on a layout-level provider it wipes
151
- the whole page, with no error and no warning; the symptom surfaces
152
- somewhere unrelated, as "our response routing is flaky".
153
-
154
- Two properties make this hard to catch:
155
-
156
- - The reset is asynchronous. Durable threads only exist in Intelligence
157
- mode, so with a plain SSE runtime `useThreads` returns nothing, the
158
- selected thread never changes, and the remount never fires. It appears
159
- the moment Intelligence is wired.
160
- - It is timing-dependent. Whether state survives depends on whether the
161
- user acted before the thread list resolved.
162
-
163
- Put the `key` on the smallest subtree that genuinely owns per-thread
164
- state, and never above state the application expects to keep. If a
165
- component both dispatches requests and correlates the responses, it must
166
- sit **outside** the keyed subtree.
167
-
168
- Source: `packages/react-core/src/v2/hooks/use-threads.tsx:282-289` (thread
169
- endpoints exist only in Intelligence mode), `364-368` (the list fetch is
170
- deferred until `/info` resolves)
171
-
172
- ### HIGH — Using `useThreads` with an SSE-only runtime
173
-
174
- Wrong:
175
-
176
- ```tsx
177
- // Runtime has no Intelligence configured
178
- new CopilotRuntime({ agents });
179
-
180
- // Client side:
181
- const { threads, error } = useThreads({ agentId: "default" });
182
- // error: "Runtime URL is not configured" or empty list forever
183
- ```
184
-
185
- Correct:
186
-
187
- ```ts
188
- // Server — upgrade to Intelligence mode:
189
- import {
190
- CopilotIntelligenceRuntime,
191
- CopilotKitIntelligence,
192
- } from "@copilotkit/runtime/v2";
193
-
194
- const intelligence = new CopilotKitIntelligence({
195
- // apiUrl / wsUrl default to cloud-hosted CopilotKit Intelligence — leave unset.
196
- apiKey: process.env.CPK_INTELLIGENCE_API_KEY!,
197
- });
198
-
199
- const runtime = new CopilotIntelligenceRuntime({
200
- agents,
201
- intelligence,
202
- identifyUser: async (req) => ({ userId: await getUserId(req) }),
203
- });
204
- ```
205
-
206
- `CopilotKitIntelligence` and `CopilotIntelligenceRuntime` are only exposed
207
- on the `@copilotkit/runtime/v2` subpath — the package root exports SSE
208
- primitives only.
209
-
210
- Thread routes only exist in Intelligence mode. In plain SSE the list fetch
211
- fails and mutations reject.
212
-
213
- Source: `packages/react-core/src/v2/hooks/use-threads.tsx:207-213,229`
214
-
215
- ### HIGH — Expecting `deleteThread` to be recoverable
216
-
217
- Wrong:
218
-
219
- ```tsx
220
- await deleteThread(id); // user expected a trash bin
221
- ```
222
-
223
- Correct:
224
-
225
- ```tsx
226
- // For soft-delete UX, use archive:
227
- await archiveThread(id);
228
-
229
- // Then expose archived threads in a separate view:
230
- const { threads: archived } = useThreads({
231
- agentId: "default",
232
- includeArchived: true,
233
- });
234
- ```
235
-
236
- `deleteThread` is irreversible in CopilotKit Intelligence. Use
237
- `archiveThread` for user-facing delete UX and only call `deleteThread` for
238
- genuine "permanently erase" flows.
239
-
240
- Source: `packages/react-core/src/v2/hooks/use-threads.tsx:101-105`
241
-
242
- ### MEDIUM — Assuming archived threads appear by default
243
-
244
- Wrong:
245
-
246
- ```tsx
247
- const { threads } = useThreads({ agentId: "default" });
248
- // User archived a thread. User opens the "Archived" tab. It's empty.
249
- ```
250
-
251
- Correct:
252
-
253
- ```tsx
254
- const { threads: activeThreads } = useThreads({ agentId: "default" });
255
- const { threads: archivedThreads } = useThreads({
256
- agentId: "default",
257
- includeArchived: true,
258
- });
259
- ```
260
-
261
- `includeArchived` defaults to `false`. Archived threads are filtered out of
262
- the default list; opt in explicitly for an archived-view tab.
263
-
264
- Source: `packages/react-core/src/v2/hooks/use-threads.tsx:60-62`
265
-
266
- ### MEDIUM — Not handling `error`
267
-
268
- Wrong:
269
-
270
- ```tsx
271
- const { threads } = useThreads({ agentId: "default" });
272
- return <ul>{threads.map(...)}</ul>;
273
- // Silent failures — handshake errors, network errors all vanish.
274
- ```
275
-
276
- Correct:
277
-
278
- ```tsx
279
- const { threads, isLoading, error } = useThreads({ agentId: "default" });
280
- if (error) return <ErrorBanner message={error.message} />;
281
- if (isLoading) return <Spinner />;
282
- return <ul>{threads.map(...)}</ul>;
283
- ```
284
-
285
- `error` holds the most recent fetch/mutation error until the next
286
- successful fetch clears it. Surface it or you'll miss Intelligence-mode
287
- mis-configuration.
288
-
289
- Source: `packages/react-core/src/v2/hooks/use-threads.tsx:70-74`