@copilotkit/react-core 1.70.3 → 1.71.0

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 (47) hide show
  1. package/dist/{copilotkit-BU3OvveB.cjs → copilotkit-B4Jb1QEy.cjs} +365 -153
  2. package/dist/copilotkit-B4Jb1QEy.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-X2eGbOwf.d.cts → copilotkit-DCIXZawe.d.cts} +33 -8
  6. package/dist/copilotkit-DCIXZawe.d.cts.map +1 -0
  7. package/dist/{copilotkit-Ap_yisA5.mjs → copilotkit-snbJkMqQ.mjs} +364 -152
  8. package/dist/copilotkit-snbJkMqQ.mjs.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 +176 -138
  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 +16 -4
  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 +17 -5
  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 +491 -277
  39. package/dist/v2/index.umd.js.map +1 -1
  40. package/package.json +7 -7
  41. package/skills/react-core/SKILL.md +1 -1
  42. package/skills/react-core/references/agent-access.md +69 -26
  43. package/skills/react-core/references/chat-components.md +22 -5
  44. package/dist/copilotkit-Ap_yisA5.mjs.map +0 -1
  45. package/dist/copilotkit-BU3OvveB.cjs.map +0 -1
  46. package/dist/copilotkit-Bs98akp9.d.mts.map +0 -1
  47. package/dist/copilotkit-X2eGbOwf.d.cts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@copilotkit/react-core",
3
- "version": "1.70.3",
3
+ "version": "1.71.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "ai",
@@ -80,12 +80,12 @@
80
80
  "untruncate-json": "^0.0.1",
81
81
  "use-stick-to-bottom": "^1.1.1",
82
82
  "zod-to-json-schema": "^3.24.5",
83
- "@copilotkit/a2ui-renderer": "1.70.3",
84
- "@copilotkit/runtime-client-gql": "1.70.3",
85
- "@copilotkit/shared": "1.70.3",
86
- "@copilotkit/web-inspector": "1.70.3",
87
- "@copilotkit/core": "1.70.3",
88
- "@copilotkit/web-components": "1.70.3"
83
+ "@copilotkit/a2ui-renderer": "1.71.0",
84
+ "@copilotkit/shared": "1.71.0",
85
+ "@copilotkit/runtime-client-gql": "1.71.0",
86
+ "@copilotkit/web-components": "1.71.0",
87
+ "@copilotkit/core": "1.71.0",
88
+ "@copilotkit/web-inspector": "1.71.0"
89
89
  },
90
90
  "devDependencies": {
91
91
  "@tailwindcss/cli": "^4.1.11",
@@ -13,7 +13,7 @@ description: >
13
13
  alias). Load the reference under references/ that matches your task.
14
14
  type: framework
15
15
  library: copilotkit
16
- library_version: "1.70.3"
16
+ library_version: "1.71.0"
17
17
  requires:
18
18
  - copilotkit/runtime
19
19
  sources:
@@ -29,7 +29,6 @@ export function ChatDriver({
29
29
  }) {
30
30
  const { agent } = useAgent({
31
31
  agentId: "default",
32
- threadId: "main",
33
32
  updates: [
34
33
  UseAgentUpdate.OnMessagesChanged,
35
34
  UseAgentUpdate.OnRunStatusChanged,
@@ -111,6 +110,35 @@ stand-in. It is a fully-constructed `AbstractAgent`, so every call on it
111
110
  is safe — but it is then **replaced**, and `agent` changes reference.
112
111
  Anything keyed to the old instance goes with it.
113
112
 
113
+ ### Scope a private agent to a thread
114
+
115
+ `useAgent` admits exactly two shapes and nothing in between:
116
+
117
+ - **Bind to an agent** — `useAgent()` or `useAgent({ agentId })`. The shared
118
+ instance from the registry; the thread comes from the chat configuration.
119
+ - **Bind a private agent to a thread** —
120
+ `useAgent({ agentId, runtimeAgentId, threadId })`. All three are required.
121
+
122
+ ```tsx
123
+ // A panel with a thread of its own, routed to the runtime's "default" agent.
124
+ const { agent, isReady } = useAgent({
125
+ agentId: "extraction-panel", // local id this hook registers under
126
+ runtimeAgentId: "default", // the runtime agent to route to
127
+ threadId: extractionThreadId,
128
+ });
129
+ ```
130
+
131
+ The second shape registers a private `ProxiedCopilotRuntimeAgent` under the
132
+ local `agentId` and unregisters it on unmount, so the thread is pinned to an
133
+ instance nothing else shares. The registration is a single balanced effect, so
134
+ it survives a StrictMode double-invoke: the cleanup unregisters before the
135
+ remount re-registers.
136
+
137
+ Pick a local `agentId` no real agent uses, and a different one per surface.
138
+
139
+ Source: `packages/react-core/src/v2/hooks/use-agent.tsx:126-137` (the two
140
+ shapes), `:239-254` (register and unregister)
141
+
114
142
  ## Common Mistakes
115
143
 
116
144
  ### CRITICAL — Custom `AbstractAgent.clone()` that returns `this`
@@ -120,7 +148,7 @@ Wrong:
120
148
  ```tsx
121
149
  class MyAgent extends AbstractAgent {
122
150
  clone() {
123
- return this; // wrong same instance is reused across threads
151
+ return this; // aliases one instance everywhere a copy is expected
124
152
  }
125
153
  }
126
154
  ```
@@ -130,18 +158,33 @@ Correct:
130
158
  ```tsx
131
159
  class MyAgent extends AbstractAgent {
132
160
  clone() {
133
- const next = new MyAgent(this.config);
134
- next.state = { ...this.state };
161
+ // Pass the same constructor arguments this instance was built with.
162
+ // `AbstractAgent` takes `config` as a parameter and does not retain it, so
163
+ // keep whatever your subclass needs on a field of its own.
164
+ const next = new MyAgent(this.myConfig);
165
+ next.threadId = this.threadId;
166
+ next.setState(this.state);
167
+ next.setMessages(this.messages);
135
168
  return next;
136
169
  }
137
170
  }
138
171
  ```
139
172
 
140
- `useAgent` calls `source.clone()` to build a per-thread clone and throws
141
- `clone() must return a new, independent object` if the clone is the same
142
- instance. This guards per-thread isolation.
173
+ Nothing validates the return value, so returning `this` fails silently rather
174
+ than throwing. On the stateful suggestions path the engine clones the provider
175
+ agent and then writes a suggestion thread id, seeded messages, and seeded state
176
+ onto the copy — given `this`, it writes all three onto the live agent the user
177
+ is talking to. (With `suggestions: true` on a multi-route runtime it builds a
178
+ fresh `HttpAgent` instead and never clones, so the fault is configuration
179
+ dependent.) Delegate cloning aliases the same way.
180
+
181
+ `useAgent` itself does not clone. It either binds the shared registry instance
182
+ or registers a private proxied agent; see the two shapes above.
143
183
 
144
- Source: `packages/react-core/src/v2/hooks/use-agent.tsx:58-69`
184
+ Source: `packages/core/src/core/suggestion-engine.ts:218-249` (the branch, the
185
+ clone, then the seeding); `packages/core/src/agent.ts:448-472`
186
+ (`ProxiedCopilotRuntimeAgent.clone`, the reference implementation — it rebuilds
187
+ field by field, then copies threadId, state, and messages)
145
188
 
146
189
  ### HIGH — Deriving app state from `agent` without guarding on `isReady`
147
190
 
@@ -323,33 +366,33 @@ sees.
323
366
 
324
367
  Source: `packages/react-core/src/v2/hooks/use-agent-context.tsx` (no `agentId` parameter); `packages/core/src/core/context-store.ts:26-31`
325
368
 
326
- ### MEDIUM — Two components using the same `(agentId, threadId)` expecting isolation
369
+ ### MEDIUM — Scoping a thread with `agentId` and `threadId` alone
327
370
 
328
371
  Wrong:
329
372
 
330
373
  ```tsx
331
- function A() {
332
- const { agent } = useAgent({ agentId: "default", threadId: "t1" });
333
- }
334
- function B() {
335
- const { agent } = useAgent({ agentId: "default", threadId: "t1" });
336
- }
374
+ // A compile error. Bypass the types and a runtime guard throws instead.
375
+ useAgent({ agentId: "default", threadId: "t1" });
337
376
  ```
338
377
 
339
378
  Correct:
340
379
 
341
380
  ```tsx
342
- function A() {
343
- useAgent({ agentId: "default", threadId: "a" });
344
- }
345
- function B() {
346
- useAgent({ agentId: "default", threadId: "b" });
347
- }
381
+ useAgent({
382
+ agentId: "panel-1", // a local id of this hook's own
383
+ runtimeAgentId: "default", // the runtime agent to route to
384
+ threadId: "t1",
385
+ });
348
386
  ```
349
387
 
350
- Per-thread clones are cached in a module-level WeakMap keyed by
351
- `(registryAgent, threadId)`. Two consumers of the same `(agentId,
352
- threadId)` observe the same state. Give each surface a distinct `threadId`
353
- when isolation is intentional.
388
+ `threadId` is written onto a single agent instance, and an agent resolved by
389
+ `agentId` alone is a shared singleton, so pinning a thread to it would clobber
390
+ every other `useAgent` caller. The three keys are therefore a matched set: the
391
+ type rejects every partial combination, and three runtime guards throw for
392
+ callers who bypass the types, each naming the correct call.
393
+
394
+ Give each surface its own local `agentId`. Two mounted hooks registering the
395
+ same one throw `already registered` rather than quietly sharing state.
354
396
 
355
- Source: `packages/react-core/src/v2/hooks/use-agent.tsx:78-119`
397
+ Source: `packages/react-core/src/v2/hooks/use-agent.tsx:160-198` (the guards);
398
+ `packages/core/src/core/agent-registry.ts:486-491` (the duplicate-id throw)
@@ -201,11 +201,28 @@ Correct:
201
201
  // ...or mount only one <CopilotChat> instance per agent/thread.
202
202
  ```
203
203
 
204
- Both components resolve to the same per-thread clone (cached in a
205
- module-level WeakMap) and submit duplicate messages. See `agent-access` for
206
- the clone semantics.
207
-
208
- Source: `packages/react-core/src/v2/hooks/use-agent.tsx:78-119`
204
+ Both components resolve the same shared agent. `CopilotChat` binds with
205
+ `useAgent({ agentId })` the shared-instance shape and then writes
206
+ `agent.threadId` onto it. There is no per-thread clone, so two instances
207
+ naming one `(agentId, threadId)` pair drive a single instance:
208
+
209
+ - Each runs its own connect effect against that instance, so the same thread is
210
+ connected twice.
211
+ - Each assigns `agent.abortController`, so the later mount replaces the
212
+ earlier one and unmounting either can abort the other's in-flight request.
213
+ - Each calls `setMessages` on it, so whichever connect resolves last wins.
214
+
215
+ The bookkeeping that would prevent this (`lastConnectedThreadId`,
216
+ `activeConnectCountRef`) is per component, so it does not coordinate across
217
+ two instances.
218
+
219
+ See `agent-access` for the two shapes `useAgent` admits and which one owns a
220
+ private instance.
221
+
222
+ Source: `packages/react-core/src/v2/components/chat/CopilotChat.tsx:138-141`
223
+ (the shared bind), `:395` (the threadId write), `:421-423` (the shared
224
+ abortController), `:429` (the connect call), `:261-266` (the per-instance
225
+ bookkeeping)
209
226
 
210
227
  ### MEDIUM — Missing the v2 CSS import
211
228