@copilotkit/react-core 1.56.5-canary.1777671752 → 1.56.5-canary.1777972218

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-DGbvw8n2.cjs → copilotkit-BGIsblrk.cjs} +335 -176
  2. package/dist/copilotkit-BGIsblrk.cjs.map +1 -0
  3. package/dist/{copilotkit-CPe2-340.mjs → copilotkit-BVK_b6St.mjs} +330 -177
  4. package/dist/copilotkit-BVK_b6St.mjs.map +1 -0
  5. package/dist/{copilotkit-Dg4r4Gi_.d.cts → copilotkit-Bc7kZ72T.d.cts} +52 -6
  6. package/dist/copilotkit-Bc7kZ72T.d.cts.map +1 -0
  7. package/dist/{copilotkit-DFaI4j2r.d.mts → copilotkit-DV9LwRgi.d.mts} +52 -6
  8. package/dist/copilotkit-DV9LwRgi.d.mts.map +1 -0
  9. package/dist/index.cjs +2 -5
  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 +2 -5
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/index.umd.js +117 -172
  16. package/dist/index.umd.js.map +1 -1
  17. package/dist/v2/index.cjs +2 -1
  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 +340 -182
  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 +5 -6
  26. package/src/hooks/use-copilot-chat_internal.ts +0 -1
  27. package/src/v2/components/chat/CopilotChat.tsx +2 -1
  28. package/src/v2/components/chat/CopilotChatMessageView.tsx +124 -13
  29. package/src/v2/components/chat/CopilotChatView.tsx +2 -2
  30. package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +1 -3
  31. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +29 -25
  32. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.tsx +5 -60
  33. package/src/v2/components/index.ts +1 -0
  34. package/src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx +265 -0
  35. package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +362 -0
  36. package/src/v2/components/intelligence-indicator/index.ts +2 -0
  37. package/src/v2/hooks/use-agent.tsx +7 -116
  38. package/src/v2/hooks/use-render-activity-message.tsx +3 -11
  39. package/src/v2/hooks/use-render-custom-messages.tsx +1 -6
  40. package/src/v2/styles/globals.css +112 -0
  41. package/dist/copilotkit-CPe2-340.mjs.map +0 -1
  42. package/dist/copilotkit-DFaI4j2r.d.mts.map +0 -1
  43. package/dist/copilotkit-DGbvw8n2.cjs.map +0 -1
  44. package/dist/copilotkit-Dg4r4Gi_.d.cts.map +0 -1
  45. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +0 -333
@@ -3511,168 +3511,6 @@ 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
-
3676
3514
  //#endregion
3677
3515
  //#region src/v2/hooks/use-render-custom-messages.tsx
3678
3516
  function useRenderCustomMessages() {
@@ -3690,8 +3528,7 @@ function useRenderCustomMessages() {
3690
3528
  const { message, position } = params;
3691
3529
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3692
3530
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
3693
- const registryAgent = copilotkit.getAgent(agentId);
3694
- const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
3531
+ const agent = copilotkit.getAgent(agentId);
3695
3532
  if (!agent) return null;
3696
3533
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
3697
3534
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -3723,8 +3560,7 @@ function useRenderCustomMessages() {
3723
3560
  //#region src/v2/hooks/use-render-activity-message.tsx
3724
3561
  function useRenderActivityMessage() {
3725
3562
  const { copilotkit } = useCopilotKit();
3726
- const config = useCopilotChatConfiguration();
3727
- const agentId = config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3563
+ const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3728
3564
  const renderers = copilotkit.renderActivityMessages;
3729
3565
  const findRenderer = (0, react.useCallback)((activityType) => {
3730
3566
  if (!renderers.length) return null;
@@ -3740,8 +3576,7 @@ function useRenderActivityMessage() {
3740
3576
  return null;
3741
3577
  }
3742
3578
  const Component = renderer.render;
3743
- const registryAgent = copilotkit.getAgent(agentId);
3744
- const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
3579
+ const agent = copilotkit.getAgent(agentId);
3745
3580
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3746
3581
  activityType: message.activityType,
3747
3582
  content: parseResult.data,
@@ -3750,7 +3585,6 @@ function useRenderActivityMessage() {
3750
3585
  }, message.id);
3751
3586
  }, [
3752
3587
  agentId,
3753
- config?.threadId,
3754
3588
  copilotkit,
3755
3589
  findRenderer
3756
3590
  ]);
@@ -4190,6 +4024,118 @@ function useHumanInTheLoop(tool, deps) {
4190
4024
  ]);
4191
4025
  }
4192
4026
 
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
+
4193
4139
  //#endregion
4194
4140
  //#region src/v2/hooks/use-capabilities.tsx
4195
4141
  /**
@@ -5655,6 +5601,171 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5655
5601
  */
5656
5602
  const ScrollElementContext = react.default.createContext(null);
5657
5603
 
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
+
5658
5769
  //#endregion
5659
5770
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5660
5771
  /**
@@ -5774,6 +5885,9 @@ const MemoizedCustomMessage = react.default.memo(function MemoizedCustomMessage(
5774
5885
  if (prevProps.message.content !== nextProps.message.content) return false;
5775
5886
  if (prevProps.message.role !== nextProps.message.role) return false;
5776
5887
  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;
5777
5891
  return true;
5778
5892
  });
5779
5893
  /**
@@ -5812,14 +5926,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5812
5926
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
5813
5927
  (0, react.useEffect)(() => {
5814
5928
  if (!config?.agentId) return;
5815
- const registryAgent = copilotkit.getAgent(config.agentId);
5816
- const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5929
+ const agent = copilotkit.getAgent(config.agentId);
5817
5930
  if (!agent) return;
5818
5931
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5819
5932
  return () => subscription.unsubscribe();
5820
5933
  }, [
5821
5934
  config?.agentId,
5822
- config?.threadId,
5823
5935
  copilotkit,
5824
5936
  forceUpdate
5825
5937
  ]);
@@ -5831,6 +5943,34 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5831
5943
  } });
5832
5944
  return () => subscription.unsubscribe();
5833
5945
  }, [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
+ ]);
5834
5974
  const getStateSnapshotForMessage = (messageId) => {
5835
5975
  if (!config) return void 0;
5836
5976
  const resolvedRunId = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId) ?? copilotkit.getRunIdsForThread(config.agentId, config.threadId).slice(-1)[0];
@@ -5867,11 +6007,17 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5867
6007
  const renderMessageBlock = (message) => {
5868
6008
  const elements = [];
5869
6009
  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;
5870
6013
  if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
5871
6014
  message,
5872
6015
  position: "before",
5873
6016
  renderCustomMessage,
5874
- stateSnapshot
6017
+ stateSnapshot,
6018
+ numberOfMessagesInRun,
6019
+ isInLatestRun,
6020
+ isRunning
5875
6021
  }, `${message.id}-custom-before`));
5876
6022
  if (message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedAssistantMessage, {
5877
6023
  message,
@@ -5900,8 +6046,15 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5900
6046
  message,
5901
6047
  position: "after",
5902
6048
  renderCustomMessage,
5903
- stateSnapshot
6049
+ stateSnapshot,
6050
+ numberOfMessagesInRun,
6051
+ isInLatestRun,
6052
+ isRunning
5904
6053
  }, `${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`));
5905
6058
  return elements.filter(Boolean);
5906
6059
  };
5907
6060
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6850,7 +7003,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6850
7003
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
6851
7004
  const { agent } = useAgent({
6852
7005
  agentId: resolvedAgentId,
6853
- threadId: resolvedThreadId,
6854
7006
  throttleMs
6855
7007
  });
6856
7008
  const { copilotkit } = useCopilotKit();
@@ -6892,6 +7044,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6892
7044
  let detached = false;
6893
7045
  const connectAbortController = new AbortController();
6894
7046
  if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
7047
+ agent.threadId = resolvedThreadId;
6895
7048
  const connect = async (agent) => {
6896
7049
  try {
6897
7050
  await copilotkit.connectAgent({ agent });
@@ -10024,6 +10177,12 @@ Object.defineProperty(exports, 'DefaultOpenIcon', {
10024
10177
  return DefaultOpenIcon;
10025
10178
  }
10026
10179
  });
10180
+ Object.defineProperty(exports, 'IntelligenceIndicator', {
10181
+ enumerable: true,
10182
+ get: function () {
10183
+ return IntelligenceIndicator;
10184
+ }
10185
+ });
10027
10186
  Object.defineProperty(exports, 'MCPAppsActivityContentSchema', {
10028
10187
  enumerable: true,
10029
10188
  get: function () {
@@ -10252,4 +10411,4 @@ Object.defineProperty(exports, 'useToast', {
10252
10411
  return useToast;
10253
10412
  }
10254
10413
  });
10255
- //# sourceMappingURL=copilotkit-DGbvw8n2.cjs.map
10414
+ //# sourceMappingURL=copilotkit-BGIsblrk.cjs.map