@copilotkit/react-core 1.56.5-canary.1777972218 → 1.57.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 (45) hide show
  1. package/dist/{copilotkit-BVK_b6St.mjs → copilotkit-CPe2-340.mjs} +177 -330
  2. package/dist/copilotkit-CPe2-340.mjs.map +1 -0
  3. package/dist/{copilotkit-DV9LwRgi.d.mts → copilotkit-DFaI4j2r.d.mts} +6 -52
  4. package/dist/copilotkit-DFaI4j2r.d.mts.map +1 -0
  5. package/dist/{copilotkit-BGIsblrk.cjs → copilotkit-DGbvw8n2.cjs} +176 -335
  6. package/dist/copilotkit-DGbvw8n2.cjs.map +1 -0
  7. package/dist/{copilotkit-Bc7kZ72T.d.cts → copilotkit-Dg4r4Gi_.d.cts} +6 -52
  8. package/dist/copilotkit-Dg4r4Gi_.d.cts.map +1 -0
  9. package/dist/index.cjs +5 -2
  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 +5 -2
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/index.umd.js +172 -117
  16. package/dist/index.umd.js.map +1 -1
  17. package/dist/v2/index.cjs +1 -2
  18. package/dist/v2/index.css +1 -1
  19. package/dist/v2/index.d.cts +2 -2
  20. package/dist/v2/index.d.mts +2 -2
  21. package/dist/v2/index.mjs +2 -2
  22. package/dist/v2/index.umd.js +182 -340
  23. package/dist/v2/index.umd.js.map +1 -1
  24. package/package.json +6 -6
  25. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +6 -5
  26. package/src/hooks/use-copilot-chat_internal.ts +1 -0
  27. package/src/v2/components/chat/CopilotChat.tsx +1 -2
  28. package/src/v2/components/chat/CopilotChatMessageView.tsx +13 -124
  29. package/src/v2/components/chat/CopilotChatView.tsx +2 -2
  30. package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +3 -1
  31. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +25 -29
  32. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.tsx +60 -5
  33. package/src/v2/components/index.ts +0 -1
  34. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +333 -0
  35. package/src/v2/hooks/use-agent.tsx +116 -7
  36. package/src/v2/hooks/use-render-activity-message.tsx +11 -3
  37. package/src/v2/hooks/use-render-custom-messages.tsx +6 -1
  38. package/src/v2/styles/globals.css +0 -112
  39. package/dist/copilotkit-BGIsblrk.cjs.map +0 -1
  40. package/dist/copilotkit-BVK_b6St.mjs.map +0 -1
  41. package/dist/copilotkit-Bc7kZ72T.d.cts.map +0 -1
  42. package/dist/copilotkit-DV9LwRgi.d.mts.map +0 -1
  43. package/src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx +0 -265
  44. package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +0 -362
  45. package/src/v2/components/intelligence-indicator/index.ts +0 -2
@@ -3511,6 +3511,168 @@ function useRenderToolCall() {
3511
3511
  ]);
3512
3512
  }
3513
3513
 
3514
+ //#endregion
3515
+ //#region src/v2/hooks/use-agent.tsx
3516
+ let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
3517
+ UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
3518
+ UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
3519
+ UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
3520
+ return UseAgentUpdate;
3521
+ }({});
3522
+ const ALL_UPDATES = [
3523
+ UseAgentUpdate.OnMessagesChanged,
3524
+ UseAgentUpdate.OnStateChanged,
3525
+ UseAgentUpdate.OnRunStatusChanged
3526
+ ];
3527
+ /**
3528
+ * Clone a registry agent for per-thread isolation.
3529
+ * Copies agent configuration (transport, headers, etc.) but resets conversation
3530
+ * state (messages, threadId, state) so each thread starts fresh.
3531
+ */
3532
+ function cloneForThread(source, threadId, headers) {
3533
+ const clone = source.clone();
3534
+ if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
3535
+ clone.threadId = threadId;
3536
+ clone.setMessages([]);
3537
+ clone.setState({});
3538
+ if (clone instanceof _ag_ui_client.HttpAgent) clone.headers = { ...headers };
3539
+ return clone;
3540
+ }
3541
+ /**
3542
+ * Module-level WeakMap: registryAgent → (threadId → clone).
3543
+ * Shared across all useAgent() calls so that every component using the same
3544
+ * (agentId, threadId) pair receives the same agent instance. Using WeakMap
3545
+ * ensures the clone map is garbage-collected when the registry agent is
3546
+ * replaced (e.g. after reconnect or hot-reload).
3547
+ */
3548
+ const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
3549
+ /**
3550
+ * Look up an existing per-thread clone without creating one.
3551
+ * Returns undefined when no clone has been created yet for this pair.
3552
+ */
3553
+ function getThreadClone(registryAgent, threadId) {
3554
+ if (!registryAgent || !threadId) return void 0;
3555
+ return globalThreadCloneMap.get(registryAgent)?.get(threadId);
3556
+ }
3557
+ function getOrCreateThreadClone(existing, threadId, headers) {
3558
+ let byThread = globalThreadCloneMap.get(existing);
3559
+ if (!byThread) {
3560
+ byThread = /* @__PURE__ */ new Map();
3561
+ globalThreadCloneMap.set(existing, byThread);
3562
+ }
3563
+ const cached = byThread.get(threadId);
3564
+ if (cached) return cached;
3565
+ const clone = cloneForThread(existing, threadId, headers);
3566
+ byThread.set(threadId, clone);
3567
+ return clone;
3568
+ }
3569
+ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
3570
+ agentId ??= _copilotkit_shared.DEFAULT_AGENT_ID;
3571
+ const { copilotkit } = useCopilotKit();
3572
+ const providerThrottleMs = copilotkit.defaultThrottleMs;
3573
+ const chatConfig = useCopilotChatConfiguration();
3574
+ threadId ??= chatConfig?.threadId;
3575
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
3576
+ const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
3577
+ const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
3578
+ const agent = (0, react.useMemo)(() => {
3579
+ const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
3580
+ const existing = copilotkit.getAgent(agentId);
3581
+ if (existing) {
3582
+ provisionalAgentCache.current.delete(cacheKey);
3583
+ provisionalAgentCache.current.delete(agentId);
3584
+ if (!threadId) return existing;
3585
+ return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
3586
+ }
3587
+ const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
3588
+ const status = copilotkit.runtimeConnectionStatus;
3589
+ if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
3590
+ const cached = provisionalAgentCache.current.get(cacheKey);
3591
+ if (cached) {
3592
+ cached.headers = { ...copilotkit.headers };
3593
+ return cached;
3594
+ }
3595
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
3596
+ runtimeUrl: copilotkit.runtimeUrl,
3597
+ agentId,
3598
+ transport: copilotkit.runtimeTransport,
3599
+ runtimeMode: "pending"
3600
+ });
3601
+ provisional.headers = { ...copilotkit.headers };
3602
+ if (threadId) provisional.threadId = threadId;
3603
+ provisionalAgentCache.current.set(cacheKey, provisional);
3604
+ return provisional;
3605
+ }
3606
+ if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
3607
+ const cached = provisionalAgentCache.current.get(cacheKey);
3608
+ if (cached) {
3609
+ cached.headers = { ...copilotkit.headers };
3610
+ return cached;
3611
+ }
3612
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
3613
+ runtimeUrl: copilotkit.runtimeUrl,
3614
+ agentId,
3615
+ transport: copilotkit.runtimeTransport,
3616
+ runtimeMode: "pending"
3617
+ });
3618
+ provisional.headers = { ...copilotkit.headers };
3619
+ if (threadId) provisional.threadId = threadId;
3620
+ provisionalAgentCache.current.set(cacheKey, provisional);
3621
+ return provisional;
3622
+ }
3623
+ const knownAgents = Object.keys(copilotkit.agents ?? {});
3624
+ const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
3625
+ throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
3626
+ }, [
3627
+ agentId,
3628
+ threadId,
3629
+ copilotkit.agents,
3630
+ copilotkit.runtimeConnectionStatus,
3631
+ copilotkit.runtimeUrl,
3632
+ copilotkit.runtimeTransport,
3633
+ JSON.stringify(copilotkit.headers)
3634
+ ]);
3635
+ (0, react.useEffect)(() => {
3636
+ if (updateFlags.length === 0) return;
3637
+ let active = true;
3638
+ const handlers = {};
3639
+ let batchScheduled = false;
3640
+ const batchedForceUpdate = () => {
3641
+ if (!active) return;
3642
+ if (!batchScheduled) {
3643
+ batchScheduled = true;
3644
+ queueMicrotask(() => {
3645
+ batchScheduled = false;
3646
+ if (active) forceUpdate();
3647
+ });
3648
+ }
3649
+ };
3650
+ if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
3651
+ if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
3652
+ if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
3653
+ handlers.onRunInitialized = batchedForceUpdate;
3654
+ handlers.onRunFinalized = batchedForceUpdate;
3655
+ handlers.onRunFailed = batchedForceUpdate;
3656
+ handlers.onRunErrorEvent = batchedForceUpdate;
3657
+ }
3658
+ const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
3659
+ return () => {
3660
+ active = false;
3661
+ subscription.unsubscribe();
3662
+ };
3663
+ }, [
3664
+ agent,
3665
+ forceUpdate,
3666
+ throttleMs,
3667
+ providerThrottleMs,
3668
+ updateFlags
3669
+ ]);
3670
+ (0, react.useEffect)(() => {
3671
+ if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
3672
+ }, [agent, JSON.stringify(copilotkit.headers)]);
3673
+ return { agent };
3674
+ }
3675
+
3514
3676
  //#endregion
3515
3677
  //#region src/v2/hooks/use-render-custom-messages.tsx
3516
3678
  function useRenderCustomMessages() {
@@ -3528,7 +3690,8 @@ function useRenderCustomMessages() {
3528
3690
  const { message, position } = params;
3529
3691
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3530
3692
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
3531
- const agent = copilotkit.getAgent(agentId);
3693
+ const registryAgent = copilotkit.getAgent(agentId);
3694
+ const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
3532
3695
  if (!agent) return null;
3533
3696
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
3534
3697
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -3560,7 +3723,8 @@ function useRenderCustomMessages() {
3560
3723
  //#region src/v2/hooks/use-render-activity-message.tsx
3561
3724
  function useRenderActivityMessage() {
3562
3725
  const { copilotkit } = useCopilotKit();
3563
- const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3726
+ const config = useCopilotChatConfiguration();
3727
+ const agentId = config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3564
3728
  const renderers = copilotkit.renderActivityMessages;
3565
3729
  const findRenderer = (0, react.useCallback)((activityType) => {
3566
3730
  if (!renderers.length) return null;
@@ -3576,7 +3740,8 @@ function useRenderActivityMessage() {
3576
3740
  return null;
3577
3741
  }
3578
3742
  const Component = renderer.render;
3579
- const agent = copilotkit.getAgent(agentId);
3743
+ const registryAgent = copilotkit.getAgent(agentId);
3744
+ const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
3580
3745
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3581
3746
  activityType: message.activityType,
3582
3747
  content: parseResult.data,
@@ -3585,6 +3750,7 @@ function useRenderActivityMessage() {
3585
3750
  }, message.id);
3586
3751
  }, [
3587
3752
  agentId,
3753
+ config?.threadId,
3588
3754
  copilotkit,
3589
3755
  findRenderer
3590
3756
  ]);
@@ -4024,118 +4190,6 @@ function useHumanInTheLoop(tool, deps) {
4024
4190
  ]);
4025
4191
  }
4026
4192
 
4027
- //#endregion
4028
- //#region src/v2/hooks/use-agent.tsx
4029
- let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
4030
- UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
4031
- UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
4032
- UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
4033
- return UseAgentUpdate;
4034
- }({});
4035
- const ALL_UPDATES = [
4036
- UseAgentUpdate.OnMessagesChanged,
4037
- UseAgentUpdate.OnStateChanged,
4038
- UseAgentUpdate.OnRunStatusChanged
4039
- ];
4040
- function useAgent({ agentId, updates, throttleMs } = {}) {
4041
- agentId ??= _copilotkit_shared.DEFAULT_AGENT_ID;
4042
- const { copilotkit } = useCopilotKit();
4043
- const providerThrottleMs = copilotkit.defaultThrottleMs;
4044
- const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
4045
- const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4046
- const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
4047
- const agent = (0, react.useMemo)(() => {
4048
- const existing = copilotkit.getAgent(agentId);
4049
- if (existing) {
4050
- provisionalAgentCache.current.delete(agentId);
4051
- return existing;
4052
- }
4053
- const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4054
- const status = copilotkit.runtimeConnectionStatus;
4055
- if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4056
- const cached = provisionalAgentCache.current.get(agentId);
4057
- if (cached) {
4058
- cached.headers = { ...copilotkit.headers };
4059
- return cached;
4060
- }
4061
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4062
- runtimeUrl: copilotkit.runtimeUrl,
4063
- agentId,
4064
- transport: copilotkit.runtimeTransport,
4065
- runtimeMode: "pending"
4066
- });
4067
- provisional.headers = { ...copilotkit.headers };
4068
- provisionalAgentCache.current.set(agentId, provisional);
4069
- return provisional;
4070
- }
4071
- if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
4072
- const cached = provisionalAgentCache.current.get(agentId);
4073
- if (cached) {
4074
- cached.headers = { ...copilotkit.headers };
4075
- return cached;
4076
- }
4077
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4078
- runtimeUrl: copilotkit.runtimeUrl,
4079
- agentId,
4080
- transport: copilotkit.runtimeTransport,
4081
- runtimeMode: "pending"
4082
- });
4083
- provisional.headers = { ...copilotkit.headers };
4084
- provisionalAgentCache.current.set(agentId, provisional);
4085
- return provisional;
4086
- }
4087
- const knownAgents = Object.keys(copilotkit.agents ?? {});
4088
- const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
4089
- throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
4090
- }, [
4091
- agentId,
4092
- copilotkit.agents,
4093
- copilotkit.runtimeConnectionStatus,
4094
- copilotkit.runtimeUrl,
4095
- copilotkit.runtimeTransport,
4096
- JSON.stringify(copilotkit.headers)
4097
- ]);
4098
- (0, react.useEffect)(() => {
4099
- if (updateFlags.length === 0) return;
4100
- let active = true;
4101
- const handlers = {};
4102
- let batchScheduled = false;
4103
- const batchedForceUpdate = () => {
4104
- if (!active) return;
4105
- if (!batchScheduled) {
4106
- batchScheduled = true;
4107
- queueMicrotask(() => {
4108
- batchScheduled = false;
4109
- if (active) forceUpdate();
4110
- });
4111
- }
4112
- };
4113
- if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
4114
- if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
4115
- if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
4116
- handlers.onRunInitialized = batchedForceUpdate;
4117
- handlers.onRunFinalized = batchedForceUpdate;
4118
- handlers.onRunFailed = batchedForceUpdate;
4119
- handlers.onRunErrorEvent = batchedForceUpdate;
4120
- }
4121
- const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
4122
- return () => {
4123
- active = false;
4124
- subscription.unsubscribe();
4125
- };
4126
- }, [
4127
- agent,
4128
- forceUpdate,
4129
- throttleMs,
4130
- providerThrottleMs,
4131
- updateFlags
4132
- ]);
4133
- (0, react.useEffect)(() => {
4134
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
4135
- }, [agent, JSON.stringify(copilotkit.headers)]);
4136
- return { agent };
4137
- }
4138
-
4139
4193
  //#endregion
4140
4194
  //#region src/v2/hooks/use-capabilities.tsx
4141
4195
  /**
@@ -5601,171 +5655,6 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5601
5655
  */
5602
5656
  const ScrollElementContext = react.default.createContext(null);
5603
5657
 
5604
- //#endregion
5605
- //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5606
- /**
5607
- * Brief debounce on `agent.isRunning` falling edges. Multi-step agent
5608
- * runs can emit transient `RUN_FINISHED → RUN_STARTED` cycles between
5609
- * LLM steps inside one user turn; without a small grace window the pill
5610
- * would flicker spinner → check → spinner. 500 ms is well below
5611
- * human-perceptible flash latency yet long enough to absorb step blips.
5612
- */
5613
- const RUN_IDLE_DEBOUNCE_MS = 500;
5614
- /** Hold the checkmark briefly before fading out. */
5615
- const CHECK_HOLD_MS = 800;
5616
- /**
5617
- * Duration of the fade-out animation. Must match
5618
- * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
5619
- */
5620
- const FADE_OUT_ANIMATION_MS = 480;
5621
- /**
5622
- * Polling interval for `agent.isRunning`. Background: AG-UI's `runAgent`
5623
- * snapshots `[...this.subscribers]` at invocation time and threads that
5624
- * snapshot through the entire run pipeline (including the `finalize`
5625
- * block that fires `onRunFinalized` and flips `isRunning` off). A
5626
- * subscriber added AFTER `runAgent` starts — which is always the case
5627
- * here, because the renderer mounts when the matching message first
5628
- * appears INSIDE the run — is missing from that snapshot and never
5629
- * receives the falling edge.
5630
- *
5631
- * Re-renders driven by parent state still keep the pill alive while
5632
- * messages stream, but `agent.isRunning` only flips off via the
5633
- * snapshotted set. A 200 ms poll reads the live property and forces a
5634
- * re-render when it changes, closing the gap.
5635
- */
5636
- const ISRUNNING_POLL_MS = 200;
5637
- /**
5638
- * Tool-name regex patterns that trigger the indicator. Currently
5639
- * hardcoded to the Intelligence MCP server's canonical tool name. If
5640
- * we add per-instance customization later (e.g. a `CopilotKitProvider`
5641
- * prop or a runtime-info field), this constant becomes the fallback.
5642
- */
5643
- const DEFAULT_TOOL_PATTERNS = [/^bash$/];
5644
- /**
5645
- * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5646
- * `CopilotChatMessageView` for every message slot when
5647
- * `copilotkit.intelligence` is configured — callers do not register
5648
- * this themselves. Self-gates so only the canonical message renders a
5649
- * pill.
5650
- *
5651
- * Render gates (all must hold):
5652
- * 1. `copilotkit.intelligence !== undefined` (Intelligence runtime
5653
- * is configured; checked by the parent before mounting, and
5654
- * again here as a defence)
5655
- * 2. The message is the last message of its run
5656
- * 3. The message's run is the latest run on the thread
5657
- * 4. The message has at least one tool call whose name matches
5658
- * {@link DEFAULT_TOOL_PATTERNS}
5659
- * 5. The phase machine is not yet `hidden`
5660
- *
5661
- * Phase machine (per-instance, all timers local):
5662
- * - `spinner` while `agent.isRunning`
5663
- * - → `check` after `agent.isRunning` falls (debounced 500 ms to
5664
- * absorb step-boundary `RUN_FINISHED → RUN_STARTED` blips inside
5665
- * one user turn)
5666
- * - → `fading` after a brief hold ({@link CHECK_HOLD_MS})
5667
- * - → `hidden` after the fade animation
5668
- * ({@link FADE_OUT_ANIMATION_MS})
5669
- *
5670
- * The "exactly one pill at a time" guarantee is structural — only one
5671
- * message at any moment satisfies gates 2–4 — so no shared coordination
5672
- * state is required.
5673
- */
5674
- function IntelligenceIndicator(props) {
5675
- const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
5676
- const { copilotkit } = useCopilotKit();
5677
- const config = useCopilotChatConfiguration();
5678
- const { agent } = useAgent({
5679
- agentId,
5680
- updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
5681
- });
5682
- const [, forceRender] = (0, react.useReducer)((n) => n + 1, 0);
5683
- const lastSeenIsRunningRef = (0, react.useRef)(agent.isRunning);
5684
- (0, react.useEffect)(() => {
5685
- const interval = setInterval(() => {
5686
- const live = agent.isRunning;
5687
- if (live !== lastSeenIsRunningRef.current) {
5688
- lastSeenIsRunningRef.current = live;
5689
- forceRender();
5690
- }
5691
- }, ISRUNNING_POLL_MS);
5692
- return () => clearInterval(interval);
5693
- }, [agent]);
5694
- const [phase, setPhase] = (0, react.useState)(agent.isRunning ? "spinner" : "check");
5695
- (0, react.useEffect)(() => {
5696
- if (agent.isRunning) {
5697
- setPhase("spinner");
5698
- return;
5699
- }
5700
- const t = setTimeout(() => setPhase("check"), RUN_IDLE_DEBOUNCE_MS);
5701
- return () => clearTimeout(t);
5702
- }, [agent.isRunning]);
5703
- (0, react.useEffect)(() => {
5704
- if (phase !== "check") return void 0;
5705
- const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5706
- return () => clearTimeout(t);
5707
- }, [phase]);
5708
- (0, react.useEffect)(() => {
5709
- if (phase !== "fading") return void 0;
5710
- const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5711
- return () => clearTimeout(t);
5712
- }, [phase]);
5713
- if (copilotkit.intelligence === void 0) return null;
5714
- if (!config) return null;
5715
- if (phase === "hidden") return null;
5716
- if (message.role !== "assistant") return null;
5717
- if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => {
5718
- const name = tc?.function?.name;
5719
- return typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
5720
- })) return null;
5721
- const messageRunId = copilotkit.getRunIdForMessage(agentId, config.threadId, message.id);
5722
- if (!messageRunId) return null;
5723
- let latestRunId;
5724
- let lastMessageIdInThisRun;
5725
- for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5726
- const m = agent.messages[i];
5727
- const r = copilotkit.getRunIdForMessage(agentId, config.threadId, m.id);
5728
- if (latestRunId === void 0 && r) latestRunId = r;
5729
- if (lastMessageIdInThisRun === void 0 && r === messageRunId) lastMessageIdInThisRun = m.id;
5730
- if (latestRunId !== void 0 && lastMessageIdInThisRun !== void 0) break;
5731
- }
5732
- if (latestRunId !== messageRunId) return null;
5733
- if (lastMessageIdInThisRun !== message.id) return null;
5734
- const showSpinner = phase === "spinner";
5735
- const isFading = phase === "fading";
5736
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5737
- className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5738
- role: "status",
5739
- "aria-live": "polite",
5740
- "aria-hidden": isFading || void 0,
5741
- "data-testid": `cpk-intelligence-pill-${message.id}`,
5742
- title: label,
5743
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
5744
- className: "cpk-intelligence-pill__icon",
5745
- viewBox: "0 0 24 24",
5746
- width: "14",
5747
- height: "14",
5748
- "aria-hidden": "true",
5749
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
5750
- cx: "12",
5751
- cy: "12",
5752
- r: "9",
5753
- fill: "none",
5754
- strokeWidth: "2.5",
5755
- strokeLinecap: "round",
5756
- className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5757
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
5758
- d: "M8 12.5l3 3 5-6",
5759
- fill: "none",
5760
- strokeWidth: "2.5",
5761
- strokeLinecap: "round",
5762
- strokeLinejoin: "round",
5763
- className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5764
- })]
5765
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
5766
- });
5767
- }
5768
-
5769
5658
  //#endregion
5770
5659
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5771
5660
  /**
@@ -5885,9 +5774,6 @@ const MemoizedCustomMessage = react.default.memo(function MemoizedCustomMessage(
5885
5774
  if (prevProps.message.content !== nextProps.message.content) return false;
5886
5775
  if (prevProps.message.role !== nextProps.message.role) return false;
5887
5776
  if (JSON.stringify(prevProps.stateSnapshot) !== JSON.stringify(nextProps.stateSnapshot)) return false;
5888
- if (prevProps.numberOfMessagesInRun !== nextProps.numberOfMessagesInRun) return false;
5889
- if (prevProps.isInLatestRun !== nextProps.isInLatestRun) return false;
5890
- if (nextProps.isInLatestRun && prevProps.isRunning !== nextProps.isRunning) return false;
5891
5777
  return true;
5892
5778
  });
5893
5779
  /**
@@ -5926,12 +5812,14 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5926
5812
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
5927
5813
  (0, react.useEffect)(() => {
5928
5814
  if (!config?.agentId) return;
5929
- const agent = copilotkit.getAgent(config.agentId);
5815
+ const registryAgent = copilotkit.getAgent(config.agentId);
5816
+ const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5930
5817
  if (!agent) return;
5931
5818
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5932
5819
  return () => subscription.unsubscribe();
5933
5820
  }, [
5934
5821
  config?.agentId,
5822
+ config?.threadId,
5935
5823
  copilotkit,
5936
5824
  forceUpdate
5937
5825
  ]);
@@ -5943,34 +5831,6 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5943
5831
  } });
5944
5832
  return () => subscription.unsubscribe();
5945
5833
  }, [copilotkit]);
5946
- const runMetadata = (0, react.useMemo)(() => {
5947
- if (!config) return null;
5948
- const runIdByMessageId = /* @__PURE__ */ new Map();
5949
- for (const msg of messages) {
5950
- const r = copilotkit.getRunIdForMessage(config.agentId, config.threadId, msg.id);
5951
- if (r) runIdByMessageId.set(msg.id, r);
5952
- }
5953
- const countByRunId = /* @__PURE__ */ new Map();
5954
- for (const r of runIdByMessageId.values()) countByRunId.set(r, (countByRunId.get(r) ?? 0) + 1);
5955
- let latestRunId;
5956
- for (let i = messages.length - 1; i >= 0; i--) {
5957
- const r = runIdByMessageId.get(messages[i].id);
5958
- if (r) {
5959
- latestRunId = r;
5960
- break;
5961
- }
5962
- }
5963
- return {
5964
- runIdByMessageId,
5965
- countByRunId,
5966
- latestRunId
5967
- };
5968
- }, [
5969
- messages,
5970
- config?.agentId,
5971
- config?.threadId,
5972
- copilotkit
5973
- ]);
5974
5834
  const getStateSnapshotForMessage = (messageId) => {
5975
5835
  if (!config) return void 0;
5976
5836
  const resolvedRunId = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId) ?? copilotkit.getRunIdsForThread(config.agentId, config.threadId).slice(-1)[0];
@@ -6007,17 +5867,11 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
6007
5867
  const renderMessageBlock = (message) => {
6008
5868
  const elements = [];
6009
5869
  const stateSnapshot = getStateSnapshotForMessage(message.id);
6010
- const messageRunId = runMetadata?.runIdByMessageId.get(message.id);
6011
- const numberOfMessagesInRun = messageRunId ? runMetadata?.countByRunId.get(messageRunId) : void 0;
6012
- const isInLatestRun = messageRunId === void 0 ? void 0 : messageRunId === runMetadata?.latestRunId;
6013
5870
  if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
6014
5871
  message,
6015
5872
  position: "before",
6016
5873
  renderCustomMessage,
6017
- stateSnapshot,
6018
- numberOfMessagesInRun,
6019
- isInLatestRun,
6020
- isRunning
5874
+ stateSnapshot
6021
5875
  }, `${message.id}-custom-before`));
6022
5876
  if (message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedAssistantMessage, {
6023
5877
  message,
@@ -6046,15 +5900,8 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
6046
5900
  message,
6047
5901
  position: "after",
6048
5902
  renderCustomMessage,
6049
- stateSnapshot,
6050
- numberOfMessagesInRun,
6051
- isInLatestRun,
6052
- isRunning
5903
+ stateSnapshot
6053
5904
  }, `${message.id}-custom-after`));
6054
- if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
6055
- message,
6056
- agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID
6057
- }, `${message.id}-intelligence`));
6058
5905
  return elements.filter(Boolean);
6059
5906
  };
6060
5907
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -7003,6 +6850,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7003
6850
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
7004
6851
  const { agent } = useAgent({
7005
6852
  agentId: resolvedAgentId,
6853
+ threadId: resolvedThreadId,
7006
6854
  throttleMs
7007
6855
  });
7008
6856
  const { copilotkit } = useCopilotKit();
@@ -7044,7 +6892,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7044
6892
  let detached = false;
7045
6893
  const connectAbortController = new AbortController();
7046
6894
  if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
7047
- agent.threadId = resolvedThreadId;
7048
6895
  const connect = async (agent) => {
7049
6896
  try {
7050
6897
  await copilotkit.connectAgent({ agent });
@@ -10177,12 +10024,6 @@ Object.defineProperty(exports, 'DefaultOpenIcon', {
10177
10024
  return DefaultOpenIcon;
10178
10025
  }
10179
10026
  });
10180
- Object.defineProperty(exports, 'IntelligenceIndicator', {
10181
- enumerable: true,
10182
- get: function () {
10183
- return IntelligenceIndicator;
10184
- }
10185
- });
10186
10027
  Object.defineProperty(exports, 'MCPAppsActivityContentSchema', {
10187
10028
  enumerable: true,
10188
10029
  get: function () {
@@ -10411,4 +10252,4 @@ Object.defineProperty(exports, 'useToast', {
10411
10252
  return useToast;
10412
10253
  }
10413
10254
  });
10414
- //# sourceMappingURL=copilotkit-BGIsblrk.cjs.map
10255
+ //# sourceMappingURL=copilotkit-DGbvw8n2.cjs.map