@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
@@ -3481,6 +3481,168 @@ function useRenderToolCall() {
3481
3481
  ]);
3482
3482
  }
3483
3483
 
3484
+ //#endregion
3485
+ //#region src/v2/hooks/use-agent.tsx
3486
+ let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
3487
+ UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
3488
+ UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
3489
+ UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
3490
+ return UseAgentUpdate;
3491
+ }({});
3492
+ const ALL_UPDATES = [
3493
+ UseAgentUpdate.OnMessagesChanged,
3494
+ UseAgentUpdate.OnStateChanged,
3495
+ UseAgentUpdate.OnRunStatusChanged
3496
+ ];
3497
+ /**
3498
+ * Clone a registry agent for per-thread isolation.
3499
+ * Copies agent configuration (transport, headers, etc.) but resets conversation
3500
+ * state (messages, threadId, state) so each thread starts fresh.
3501
+ */
3502
+ function cloneForThread(source, threadId, headers) {
3503
+ const clone = source.clone();
3504
+ if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
3505
+ clone.threadId = threadId;
3506
+ clone.setMessages([]);
3507
+ clone.setState({});
3508
+ if (clone instanceof HttpAgent) clone.headers = { ...headers };
3509
+ return clone;
3510
+ }
3511
+ /**
3512
+ * Module-level WeakMap: registryAgent → (threadId → clone).
3513
+ * Shared across all useAgent() calls so that every component using the same
3514
+ * (agentId, threadId) pair receives the same agent instance. Using WeakMap
3515
+ * ensures the clone map is garbage-collected when the registry agent is
3516
+ * replaced (e.g. after reconnect or hot-reload).
3517
+ */
3518
+ const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
3519
+ /**
3520
+ * Look up an existing per-thread clone without creating one.
3521
+ * Returns undefined when no clone has been created yet for this pair.
3522
+ */
3523
+ function getThreadClone(registryAgent, threadId) {
3524
+ if (!registryAgent || !threadId) return void 0;
3525
+ return globalThreadCloneMap.get(registryAgent)?.get(threadId);
3526
+ }
3527
+ function getOrCreateThreadClone(existing, threadId, headers) {
3528
+ let byThread = globalThreadCloneMap.get(existing);
3529
+ if (!byThread) {
3530
+ byThread = /* @__PURE__ */ new Map();
3531
+ globalThreadCloneMap.set(existing, byThread);
3532
+ }
3533
+ const cached = byThread.get(threadId);
3534
+ if (cached) return cached;
3535
+ const clone = cloneForThread(existing, threadId, headers);
3536
+ byThread.set(threadId, clone);
3537
+ return clone;
3538
+ }
3539
+ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
3540
+ agentId ??= DEFAULT_AGENT_ID;
3541
+ const { copilotkit } = useCopilotKit();
3542
+ const providerThrottleMs = copilotkit.defaultThrottleMs;
3543
+ const chatConfig = useCopilotChatConfiguration();
3544
+ threadId ??= chatConfig?.threadId;
3545
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
3546
+ const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
3547
+ const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
3548
+ const agent = useMemo(() => {
3549
+ const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
3550
+ const existing = copilotkit.getAgent(agentId);
3551
+ if (existing) {
3552
+ provisionalAgentCache.current.delete(cacheKey);
3553
+ provisionalAgentCache.current.delete(agentId);
3554
+ if (!threadId) return existing;
3555
+ return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
3556
+ }
3557
+ const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
3558
+ const status = copilotkit.runtimeConnectionStatus;
3559
+ if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
3560
+ const cached = provisionalAgentCache.current.get(cacheKey);
3561
+ if (cached) {
3562
+ cached.headers = { ...copilotkit.headers };
3563
+ return cached;
3564
+ }
3565
+ const provisional = new ProxiedCopilotRuntimeAgent({
3566
+ runtimeUrl: copilotkit.runtimeUrl,
3567
+ agentId,
3568
+ transport: copilotkit.runtimeTransport,
3569
+ runtimeMode: "pending"
3570
+ });
3571
+ provisional.headers = { ...copilotkit.headers };
3572
+ if (threadId) provisional.threadId = threadId;
3573
+ provisionalAgentCache.current.set(cacheKey, provisional);
3574
+ return provisional;
3575
+ }
3576
+ if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
3577
+ const cached = provisionalAgentCache.current.get(cacheKey);
3578
+ if (cached) {
3579
+ cached.headers = { ...copilotkit.headers };
3580
+ return cached;
3581
+ }
3582
+ const provisional = new ProxiedCopilotRuntimeAgent({
3583
+ runtimeUrl: copilotkit.runtimeUrl,
3584
+ agentId,
3585
+ transport: copilotkit.runtimeTransport,
3586
+ runtimeMode: "pending"
3587
+ });
3588
+ provisional.headers = { ...copilotkit.headers };
3589
+ if (threadId) provisional.threadId = threadId;
3590
+ provisionalAgentCache.current.set(cacheKey, provisional);
3591
+ return provisional;
3592
+ }
3593
+ const knownAgents = Object.keys(copilotkit.agents ?? {});
3594
+ const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
3595
+ 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.");
3596
+ }, [
3597
+ agentId,
3598
+ threadId,
3599
+ copilotkit.agents,
3600
+ copilotkit.runtimeConnectionStatus,
3601
+ copilotkit.runtimeUrl,
3602
+ copilotkit.runtimeTransport,
3603
+ JSON.stringify(copilotkit.headers)
3604
+ ]);
3605
+ useEffect(() => {
3606
+ if (updateFlags.length === 0) return;
3607
+ let active = true;
3608
+ const handlers = {};
3609
+ let batchScheduled = false;
3610
+ const batchedForceUpdate = () => {
3611
+ if (!active) return;
3612
+ if (!batchScheduled) {
3613
+ batchScheduled = true;
3614
+ queueMicrotask(() => {
3615
+ batchScheduled = false;
3616
+ if (active) forceUpdate();
3617
+ });
3618
+ }
3619
+ };
3620
+ if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
3621
+ if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
3622
+ if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
3623
+ handlers.onRunInitialized = batchedForceUpdate;
3624
+ handlers.onRunFinalized = batchedForceUpdate;
3625
+ handlers.onRunFailed = batchedForceUpdate;
3626
+ handlers.onRunErrorEvent = batchedForceUpdate;
3627
+ }
3628
+ const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
3629
+ return () => {
3630
+ active = false;
3631
+ subscription.unsubscribe();
3632
+ };
3633
+ }, [
3634
+ agent,
3635
+ forceUpdate,
3636
+ throttleMs,
3637
+ providerThrottleMs,
3638
+ updateFlags
3639
+ ]);
3640
+ useEffect(() => {
3641
+ if (agent instanceof HttpAgent) agent.headers = { ...copilotkit.headers };
3642
+ }, [agent, JSON.stringify(copilotkit.headers)]);
3643
+ return { agent };
3644
+ }
3645
+
3484
3646
  //#endregion
3485
3647
  //#region src/v2/hooks/use-render-custom-messages.tsx
3486
3648
  function useRenderCustomMessages() {
@@ -3498,7 +3660,8 @@ function useRenderCustomMessages() {
3498
3660
  const { message, position } = params;
3499
3661
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3500
3662
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
3501
- const agent = copilotkit.getAgent(agentId);
3663
+ const registryAgent = copilotkit.getAgent(agentId);
3664
+ const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
3502
3665
  if (!agent) return null;
3503
3666
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
3504
3667
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -3530,7 +3693,8 @@ function useRenderCustomMessages() {
3530
3693
  //#region src/v2/hooks/use-render-activity-message.tsx
3531
3694
  function useRenderActivityMessage() {
3532
3695
  const { copilotkit } = useCopilotKit();
3533
- const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
3696
+ const config = useCopilotChatConfiguration();
3697
+ const agentId = config?.agentId ?? DEFAULT_AGENT_ID;
3534
3698
  const renderers = copilotkit.renderActivityMessages;
3535
3699
  const findRenderer = useCallback((activityType) => {
3536
3700
  if (!renderers.length) return null;
@@ -3546,7 +3710,8 @@ function useRenderActivityMessage() {
3546
3710
  return null;
3547
3711
  }
3548
3712
  const Component = renderer.render;
3549
- const agent = copilotkit.getAgent(agentId);
3713
+ const registryAgent = copilotkit.getAgent(agentId);
3714
+ const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
3550
3715
  return /* @__PURE__ */ jsx(Component, {
3551
3716
  activityType: message.activityType,
3552
3717
  content: parseResult.data,
@@ -3555,6 +3720,7 @@ function useRenderActivityMessage() {
3555
3720
  }, message.id);
3556
3721
  }, [
3557
3722
  agentId,
3723
+ config?.threadId,
3558
3724
  copilotkit,
3559
3725
  findRenderer
3560
3726
  ]);
@@ -3994,118 +4160,6 @@ function useHumanInTheLoop(tool, deps) {
3994
4160
  ]);
3995
4161
  }
3996
4162
 
3997
- //#endregion
3998
- //#region src/v2/hooks/use-agent.tsx
3999
- let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
4000
- UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
4001
- UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
4002
- UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
4003
- return UseAgentUpdate;
4004
- }({});
4005
- const ALL_UPDATES = [
4006
- UseAgentUpdate.OnMessagesChanged,
4007
- UseAgentUpdate.OnStateChanged,
4008
- UseAgentUpdate.OnRunStatusChanged
4009
- ];
4010
- function useAgent({ agentId, updates, throttleMs } = {}) {
4011
- agentId ??= DEFAULT_AGENT_ID;
4012
- const { copilotkit } = useCopilotKit();
4013
- const providerThrottleMs = copilotkit.defaultThrottleMs;
4014
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
4015
- const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4016
- const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
4017
- const agent = useMemo(() => {
4018
- const existing = copilotkit.getAgent(agentId);
4019
- if (existing) {
4020
- provisionalAgentCache.current.delete(agentId);
4021
- return existing;
4022
- }
4023
- const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4024
- const status = copilotkit.runtimeConnectionStatus;
4025
- if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4026
- const cached = provisionalAgentCache.current.get(agentId);
4027
- if (cached) {
4028
- cached.headers = { ...copilotkit.headers };
4029
- return cached;
4030
- }
4031
- const provisional = new ProxiedCopilotRuntimeAgent({
4032
- runtimeUrl: copilotkit.runtimeUrl,
4033
- agentId,
4034
- transport: copilotkit.runtimeTransport,
4035
- runtimeMode: "pending"
4036
- });
4037
- provisional.headers = { ...copilotkit.headers };
4038
- provisionalAgentCache.current.set(agentId, provisional);
4039
- return provisional;
4040
- }
4041
- if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
4042
- const cached = provisionalAgentCache.current.get(agentId);
4043
- if (cached) {
4044
- cached.headers = { ...copilotkit.headers };
4045
- return cached;
4046
- }
4047
- const provisional = new ProxiedCopilotRuntimeAgent({
4048
- runtimeUrl: copilotkit.runtimeUrl,
4049
- agentId,
4050
- transport: copilotkit.runtimeTransport,
4051
- runtimeMode: "pending"
4052
- });
4053
- provisional.headers = { ...copilotkit.headers };
4054
- provisionalAgentCache.current.set(agentId, provisional);
4055
- return provisional;
4056
- }
4057
- const knownAgents = Object.keys(copilotkit.agents ?? {});
4058
- const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
4059
- 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.");
4060
- }, [
4061
- agentId,
4062
- copilotkit.agents,
4063
- copilotkit.runtimeConnectionStatus,
4064
- copilotkit.runtimeUrl,
4065
- copilotkit.runtimeTransport,
4066
- JSON.stringify(copilotkit.headers)
4067
- ]);
4068
- useEffect(() => {
4069
- if (updateFlags.length === 0) return;
4070
- let active = true;
4071
- const handlers = {};
4072
- let batchScheduled = false;
4073
- const batchedForceUpdate = () => {
4074
- if (!active) return;
4075
- if (!batchScheduled) {
4076
- batchScheduled = true;
4077
- queueMicrotask(() => {
4078
- batchScheduled = false;
4079
- if (active) forceUpdate();
4080
- });
4081
- }
4082
- };
4083
- if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
4084
- if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
4085
- if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
4086
- handlers.onRunInitialized = batchedForceUpdate;
4087
- handlers.onRunFinalized = batchedForceUpdate;
4088
- handlers.onRunFailed = batchedForceUpdate;
4089
- handlers.onRunErrorEvent = batchedForceUpdate;
4090
- }
4091
- const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
4092
- return () => {
4093
- active = false;
4094
- subscription.unsubscribe();
4095
- };
4096
- }, [
4097
- agent,
4098
- forceUpdate,
4099
- throttleMs,
4100
- providerThrottleMs,
4101
- updateFlags
4102
- ]);
4103
- useEffect(() => {
4104
- if (agent instanceof HttpAgent) agent.headers = { ...copilotkit.headers };
4105
- }, [agent, JSON.stringify(copilotkit.headers)]);
4106
- return { agent };
4107
- }
4108
-
4109
4163
  //#endregion
4110
4164
  //#region src/v2/hooks/use-capabilities.tsx
4111
4165
  /**
@@ -5571,171 +5625,6 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5571
5625
  */
5572
5626
  const ScrollElementContext = React.createContext(null);
5573
5627
 
5574
- //#endregion
5575
- //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5576
- /**
5577
- * Brief debounce on `agent.isRunning` falling edges. Multi-step agent
5578
- * runs can emit transient `RUN_FINISHED → RUN_STARTED` cycles between
5579
- * LLM steps inside one user turn; without a small grace window the pill
5580
- * would flicker spinner → check → spinner. 500 ms is well below
5581
- * human-perceptible flash latency yet long enough to absorb step blips.
5582
- */
5583
- const RUN_IDLE_DEBOUNCE_MS = 500;
5584
- /** Hold the checkmark briefly before fading out. */
5585
- const CHECK_HOLD_MS = 800;
5586
- /**
5587
- * Duration of the fade-out animation. Must match
5588
- * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
5589
- */
5590
- const FADE_OUT_ANIMATION_MS = 480;
5591
- /**
5592
- * Polling interval for `agent.isRunning`. Background: AG-UI's `runAgent`
5593
- * snapshots `[...this.subscribers]` at invocation time and threads that
5594
- * snapshot through the entire run pipeline (including the `finalize`
5595
- * block that fires `onRunFinalized` and flips `isRunning` off). A
5596
- * subscriber added AFTER `runAgent` starts — which is always the case
5597
- * here, because the renderer mounts when the matching message first
5598
- * appears INSIDE the run — is missing from that snapshot and never
5599
- * receives the falling edge.
5600
- *
5601
- * Re-renders driven by parent state still keep the pill alive while
5602
- * messages stream, but `agent.isRunning` only flips off via the
5603
- * snapshotted set. A 200 ms poll reads the live property and forces a
5604
- * re-render when it changes, closing the gap.
5605
- */
5606
- const ISRUNNING_POLL_MS = 200;
5607
- /**
5608
- * Tool-name regex patterns that trigger the indicator. Currently
5609
- * hardcoded to the Intelligence MCP server's canonical tool name. If
5610
- * we add per-instance customization later (e.g. a `CopilotKitProvider`
5611
- * prop or a runtime-info field), this constant becomes the fallback.
5612
- */
5613
- const DEFAULT_TOOL_PATTERNS = [/^bash$/];
5614
- /**
5615
- * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5616
- * `CopilotChatMessageView` for every message slot when
5617
- * `copilotkit.intelligence` is configured — callers do not register
5618
- * this themselves. Self-gates so only the canonical message renders a
5619
- * pill.
5620
- *
5621
- * Render gates (all must hold):
5622
- * 1. `copilotkit.intelligence !== undefined` (Intelligence runtime
5623
- * is configured; checked by the parent before mounting, and
5624
- * again here as a defence)
5625
- * 2. The message is the last message of its run
5626
- * 3. The message's run is the latest run on the thread
5627
- * 4. The message has at least one tool call whose name matches
5628
- * {@link DEFAULT_TOOL_PATTERNS}
5629
- * 5. The phase machine is not yet `hidden`
5630
- *
5631
- * Phase machine (per-instance, all timers local):
5632
- * - `spinner` while `agent.isRunning`
5633
- * - → `check` after `agent.isRunning` falls (debounced 500 ms to
5634
- * absorb step-boundary `RUN_FINISHED → RUN_STARTED` blips inside
5635
- * one user turn)
5636
- * - → `fading` after a brief hold ({@link CHECK_HOLD_MS})
5637
- * - → `hidden` after the fade animation
5638
- * ({@link FADE_OUT_ANIMATION_MS})
5639
- *
5640
- * The "exactly one pill at a time" guarantee is structural — only one
5641
- * message at any moment satisfies gates 2–4 — so no shared coordination
5642
- * state is required.
5643
- */
5644
- function IntelligenceIndicator(props) {
5645
- const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
5646
- const { copilotkit } = useCopilotKit();
5647
- const config = useCopilotChatConfiguration();
5648
- const { agent } = useAgent({
5649
- agentId,
5650
- updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
5651
- });
5652
- const [, forceRender] = useReducer((n) => n + 1, 0);
5653
- const lastSeenIsRunningRef = useRef(agent.isRunning);
5654
- useEffect(() => {
5655
- const interval = setInterval(() => {
5656
- const live = agent.isRunning;
5657
- if (live !== lastSeenIsRunningRef.current) {
5658
- lastSeenIsRunningRef.current = live;
5659
- forceRender();
5660
- }
5661
- }, ISRUNNING_POLL_MS);
5662
- return () => clearInterval(interval);
5663
- }, [agent]);
5664
- const [phase, setPhase] = useState(agent.isRunning ? "spinner" : "check");
5665
- useEffect(() => {
5666
- if (agent.isRunning) {
5667
- setPhase("spinner");
5668
- return;
5669
- }
5670
- const t = setTimeout(() => setPhase("check"), RUN_IDLE_DEBOUNCE_MS);
5671
- return () => clearTimeout(t);
5672
- }, [agent.isRunning]);
5673
- useEffect(() => {
5674
- if (phase !== "check") return void 0;
5675
- const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5676
- return () => clearTimeout(t);
5677
- }, [phase]);
5678
- useEffect(() => {
5679
- if (phase !== "fading") return void 0;
5680
- const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5681
- return () => clearTimeout(t);
5682
- }, [phase]);
5683
- if (copilotkit.intelligence === void 0) return null;
5684
- if (!config) return null;
5685
- if (phase === "hidden") return null;
5686
- if (message.role !== "assistant") return null;
5687
- if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => {
5688
- const name = tc?.function?.name;
5689
- return typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
5690
- })) return null;
5691
- const messageRunId = copilotkit.getRunIdForMessage(agentId, config.threadId, message.id);
5692
- if (!messageRunId) return null;
5693
- let latestRunId;
5694
- let lastMessageIdInThisRun;
5695
- for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5696
- const m = agent.messages[i];
5697
- const r = copilotkit.getRunIdForMessage(agentId, config.threadId, m.id);
5698
- if (latestRunId === void 0 && r) latestRunId = r;
5699
- if (lastMessageIdInThisRun === void 0 && r === messageRunId) lastMessageIdInThisRun = m.id;
5700
- if (latestRunId !== void 0 && lastMessageIdInThisRun !== void 0) break;
5701
- }
5702
- if (latestRunId !== messageRunId) return null;
5703
- if (lastMessageIdInThisRun !== message.id) return null;
5704
- const showSpinner = phase === "spinner";
5705
- const isFading = phase === "fading";
5706
- return /* @__PURE__ */ jsxs("span", {
5707
- className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5708
- role: "status",
5709
- "aria-live": "polite",
5710
- "aria-hidden": isFading || void 0,
5711
- "data-testid": `cpk-intelligence-pill-${message.id}`,
5712
- title: label,
5713
- children: [/* @__PURE__ */ jsxs("svg", {
5714
- className: "cpk-intelligence-pill__icon",
5715
- viewBox: "0 0 24 24",
5716
- width: "14",
5717
- height: "14",
5718
- "aria-hidden": "true",
5719
- children: [/* @__PURE__ */ jsx("circle", {
5720
- cx: "12",
5721
- cy: "12",
5722
- r: "9",
5723
- fill: "none",
5724
- strokeWidth: "2.5",
5725
- strokeLinecap: "round",
5726
- className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5727
- }), /* @__PURE__ */ jsx("path", {
5728
- d: "M8 12.5l3 3 5-6",
5729
- fill: "none",
5730
- strokeWidth: "2.5",
5731
- strokeLinecap: "round",
5732
- strokeLinejoin: "round",
5733
- className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5734
- })]
5735
- }), /* @__PURE__ */ jsx("span", { children: label })]
5736
- });
5737
- }
5738
-
5739
5628
  //#endregion
5740
5629
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5741
5630
  /**
@@ -5855,9 +5744,6 @@ const MemoizedCustomMessage = React.memo(function MemoizedCustomMessage({ messag
5855
5744
  if (prevProps.message.content !== nextProps.message.content) return false;
5856
5745
  if (prevProps.message.role !== nextProps.message.role) return false;
5857
5746
  if (JSON.stringify(prevProps.stateSnapshot) !== JSON.stringify(nextProps.stateSnapshot)) return false;
5858
- if (prevProps.numberOfMessagesInRun !== nextProps.numberOfMessagesInRun) return false;
5859
- if (prevProps.isInLatestRun !== nextProps.isInLatestRun) return false;
5860
- if (nextProps.isInLatestRun && prevProps.isRunning !== nextProps.isRunning) return false;
5861
5747
  return true;
5862
5748
  });
5863
5749
  /**
@@ -5896,12 +5782,14 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5896
5782
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
5897
5783
  useEffect(() => {
5898
5784
  if (!config?.agentId) return;
5899
- const agent = copilotkit.getAgent(config.agentId);
5785
+ const registryAgent = copilotkit.getAgent(config.agentId);
5786
+ const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5900
5787
  if (!agent) return;
5901
5788
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5902
5789
  return () => subscription.unsubscribe();
5903
5790
  }, [
5904
5791
  config?.agentId,
5792
+ config?.threadId,
5905
5793
  copilotkit,
5906
5794
  forceUpdate
5907
5795
  ]);
@@ -5913,34 +5801,6 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5913
5801
  } });
5914
5802
  return () => subscription.unsubscribe();
5915
5803
  }, [copilotkit]);
5916
- const runMetadata = useMemo(() => {
5917
- if (!config) return null;
5918
- const runIdByMessageId = /* @__PURE__ */ new Map();
5919
- for (const msg of messages) {
5920
- const r = copilotkit.getRunIdForMessage(config.agentId, config.threadId, msg.id);
5921
- if (r) runIdByMessageId.set(msg.id, r);
5922
- }
5923
- const countByRunId = /* @__PURE__ */ new Map();
5924
- for (const r of runIdByMessageId.values()) countByRunId.set(r, (countByRunId.get(r) ?? 0) + 1);
5925
- let latestRunId;
5926
- for (let i = messages.length - 1; i >= 0; i--) {
5927
- const r = runIdByMessageId.get(messages[i].id);
5928
- if (r) {
5929
- latestRunId = r;
5930
- break;
5931
- }
5932
- }
5933
- return {
5934
- runIdByMessageId,
5935
- countByRunId,
5936
- latestRunId
5937
- };
5938
- }, [
5939
- messages,
5940
- config?.agentId,
5941
- config?.threadId,
5942
- copilotkit
5943
- ]);
5944
5804
  const getStateSnapshotForMessage = (messageId) => {
5945
5805
  if (!config) return void 0;
5946
5806
  const resolvedRunId = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId) ?? copilotkit.getRunIdsForThread(config.agentId, config.threadId).slice(-1)[0];
@@ -5977,17 +5837,11 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5977
5837
  const renderMessageBlock = (message) => {
5978
5838
  const elements = [];
5979
5839
  const stateSnapshot = getStateSnapshotForMessage(message.id);
5980
- const messageRunId = runMetadata?.runIdByMessageId.get(message.id);
5981
- const numberOfMessagesInRun = messageRunId ? runMetadata?.countByRunId.get(messageRunId) : void 0;
5982
- const isInLatestRun = messageRunId === void 0 ? void 0 : messageRunId === runMetadata?.latestRunId;
5983
5840
  if (renderCustomMessage) elements.push(/* @__PURE__ */ jsx(MemoizedCustomMessage, {
5984
5841
  message,
5985
5842
  position: "before",
5986
5843
  renderCustomMessage,
5987
- stateSnapshot,
5988
- numberOfMessagesInRun,
5989
- isInLatestRun,
5990
- isRunning
5844
+ stateSnapshot
5991
5845
  }, `${message.id}-custom-before`));
5992
5846
  if (message.role === "assistant") elements.push(/* @__PURE__ */ jsx(MemoizedAssistantMessage, {
5993
5847
  message,
@@ -6016,15 +5870,8 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
6016
5870
  message,
6017
5871
  position: "after",
6018
5872
  renderCustomMessage,
6019
- stateSnapshot,
6020
- numberOfMessagesInRun,
6021
- isInLatestRun,
6022
- isRunning
5873
+ stateSnapshot
6023
5874
  }, `${message.id}-custom-after`));
6024
- if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ jsx(IntelligenceIndicator, {
6025
- message,
6026
- agentId: config?.agentId ?? DEFAULT_AGENT_ID
6027
- }, `${message.id}-intelligence`));
6028
5875
  return elements.filter(Boolean);
6029
5876
  };
6030
5877
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6973,6 +6820,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6973
6820
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
6974
6821
  const { agent } = useAgent({
6975
6822
  agentId: resolvedAgentId,
6823
+ threadId: resolvedThreadId,
6976
6824
  throttleMs
6977
6825
  });
6978
6826
  const { copilotkit } = useCopilotKit();
@@ -7014,7 +6862,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7014
6862
  let detached = false;
7015
6863
  const connectAbortController = new AbortController();
7016
6864
  if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
7017
- agent.threadId = resolvedThreadId;
7018
6865
  const connect = async (agent) => {
7019
6866
  try {
7020
6867
  await copilotkit.connectAgent({ agent });
@@ -9955,5 +9802,5 @@ function validateProps(props) {
9955
9802
  }
9956
9803
 
9957
9804
  //#endregion
9958
- export { useRenderToolCall as $, IntelligenceIndicator as A, useInterrupt as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAttachmentRenderer as F, useAgent as G, useSuggestions as H, CopilotChatAssistantMessage_default as I, useRenderTool as J, useHumanInTheLoop as K, CopilotChatToolCallsView as L, CopilotChatSuggestionPill as M, CopilotChatReasoningMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatUserMessage_default as P, useRenderCustomMessages as Q, useAttachments as R, CopilotModalHeader as S, DefaultOpenIcon as T, useCapabilities as U, useConfigureSuggestions as V, UseAgentUpdate as W, useFrontendTool as X, useComponent as Y, useRenderActivityMessage as Z, WildcardToolCallRender as _, ThreadsProvider as a, createA2UIMessageRenderer as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, MCPAppsActivityContentSchema as ct, shouldShowDevConsole as d, CopilotKitInspector as dt, CopilotKitProvider as et, useToast as f, CopilotChatInput_default as ft, useCopilotContext as g, useCopilotChatConfiguration as gt, CopilotContext as h, CopilotChatConfigurationProvider as ht, ThreadsContext as i, defineToolCallRenderer as it, CopilotChatSuggestionView as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, MCPAppsActivityRenderer as lt, useCopilotMessagesContext as m, CopilotChatAudioRecorder as mt, defaultCopilotContextCategories as n, CopilotKitCoreReact as nt, useThreads as o, SandboxFunctionsContext as ot, CopilotMessagesContext as p, AudioRecorderError as pt, useDefaultRenderTool as q, CoAgentStateRenderBridge as r, useAgentContext as rt, CoAgentStateRendersContext as s, useSandboxFunctions as st, CopilotKit as t, useCopilotKit as tt, useAsyncCallback as u, MCPAppsActivityType as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useThreads$1 as z };
9959
- //# sourceMappingURL=copilotkit-BVK_b6St.mjs.map
9805
+ export { CopilotKitProvider as $, CopilotChatSuggestionView as A, useConfigureSuggestions as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAssistantMessage_default as F, useRenderTool as G, useCapabilities as H, CopilotChatToolCallsView as I, useRenderActivityMessage as J, useComponent as K, useAttachments as L, CopilotChatReasoningMessage_default as M, CopilotChatUserMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatAttachmentRenderer as P, useRenderToolCall as Q, useThreads$1 as R, CopilotModalHeader as S, DefaultOpenIcon as T, useHumanInTheLoop as U, useSuggestions as V, useDefaultRenderTool as W, UseAgentUpdate as X, useRenderCustomMessages as Y, useAgent as Z, WildcardToolCallRender as _, ThreadsProvider as a, SandboxFunctionsContext as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, MCPAppsActivityRenderer as ct, shouldShowDevConsole as d, CopilotChatInput_default as dt, useCopilotKit as et, useToast as f, AudioRecorderError as ft, useCopilotContext as g, CopilotContext as h, useCopilotChatConfiguration as ht, ThreadsContext as i, createA2UIMessageRenderer as it, CopilotChatSuggestionPill as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, MCPAppsActivityType as lt, useCopilotMessagesContext as m, CopilotChatConfigurationProvider as mt, defaultCopilotContextCategories as n, useAgentContext as nt, useThreads as o, useSandboxFunctions as ot, CopilotMessagesContext as p, CopilotChatAudioRecorder as pt, useFrontendTool as q, CoAgentStateRenderBridge as r, defineToolCallRenderer as rt, CoAgentStateRendersContext as s, MCPAppsActivityContentSchema as st, CopilotKit as t, CopilotKitCoreReact as tt, useAsyncCallback as u, CopilotKitInspector as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useInterrupt as z };
9806
+ //# sourceMappingURL=copilotkit-CPe2-340.mjs.map