@copilotkit/react-core 1.56.5 → 1.57.0-canary.1778082736

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/{copilotkit-DFaI4j2r.d.mts → copilotkit-BNlJq5UO.d.mts} +60 -6
  2. package/dist/copilotkit-BNlJq5UO.d.mts.map +1 -0
  3. package/dist/{copilotkit-DMFu29Kx.cjs → copilotkit-B_k0HSNz.cjs} +322 -175
  4. package/dist/copilotkit-B_k0HSNz.cjs.map +1 -0
  5. package/dist/{copilotkit-Dg4r4Gi_.d.cts → copilotkit-DgC5oCFO.d.cts} +60 -6
  6. package/dist/copilotkit-DgC5oCFO.d.cts.map +1 -0
  7. package/dist/{copilotkit-OmIUrWym.mjs → copilotkit-ak8sGvQr.mjs} +317 -176
  8. package/dist/copilotkit-ak8sGvQr.mjs.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 +332 -181
  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 +24 -9
  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 +286 -0
  35. package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +464 -0
  36. package/src/v2/components/intelligence-indicator/index.ts +2 -0
  37. package/src/v2/hooks/__tests__/use-threads.test.tsx +229 -27
  38. package/src/v2/hooks/use-agent.tsx +7 -116
  39. package/src/v2/hooks/use-render-activity-message.tsx +3 -11
  40. package/src/v2/hooks/use-render-custom-messages.tsx +1 -6
  41. package/src/v2/hooks/use-threads.tsx +7 -1
  42. package/src/v2/styles/globals.css +118 -0
  43. package/dist/copilotkit-DFaI4j2r.d.mts.map +0 -1
  44. package/dist/copilotkit-DMFu29Kx.cjs.map +0 -1
  45. package/dist/copilotkit-Dg4r4Gi_.d.cts.map +0 -1
  46. package/dist/copilotkit-OmIUrWym.mjs.map +0 -1
  47. 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
  /**
@@ -4673,6 +4619,16 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4673
4619
  };
4674
4620
  }, [store]);
4675
4621
  const runtimeStatus = copilotkit.runtimeConnectionStatus;
4622
+ (0, react.useEffect)(() => {
4623
+ copilotkit.registerThreadStore(agentId, store);
4624
+ return () => {
4625
+ copilotkit.unregisterThreadStore(agentId);
4626
+ };
4627
+ }, [
4628
+ copilotkit,
4629
+ agentId,
4630
+ store
4631
+ ]);
4676
4632
  (0, react.useEffect)(() => {
4677
4633
  if (!copilotkit.runtimeUrl) {
4678
4634
  store.setContext(null);
@@ -4696,7 +4652,6 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4696
4652
  headersKey,
4697
4653
  copilotkit.intelligence?.wsUrl,
4698
4654
  agentId,
4699
- copilotkit.headers,
4700
4655
  includeArchived,
4701
4656
  limit
4702
4657
  ]);
@@ -5646,6 +5601,190 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5646
5601
  */
5647
5602
  const ScrollElementContext = react.default.createContext(null);
5648
5603
 
5604
+ //#endregion
5605
+ //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5606
+ /**
5607
+ * Grace window before showing the spinner. A matching tool call must
5608
+ * remain unresolved (no `tool`-role result message in `agent.messages`)
5609
+ * for at least this long before the pill appears. This filters out
5610
+ * history-replay flashes — during `connectAgent` replay, tool calls and
5611
+ * their results arrive back-to-back in sub-millisecond bursts, so the
5612
+ * timer is cancelled before it fires. Live runs cross the threshold
5613
+ * easily because the tool actually has to execute.
5614
+ */
5615
+ const PENDING_THRESHOLD_MS = 100;
5616
+ /** Hold the checkmark briefly before fading out. */
5617
+ const CHECK_HOLD_MS = 800;
5618
+ /**
5619
+ * Duration of the fade-out animation. Must match
5620
+ * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
5621
+ */
5622
+ const FADE_OUT_ANIMATION_MS = 480;
5623
+ /**
5624
+ * Tool-name regex patterns that trigger the indicator. Currently
5625
+ * hardcoded to the Intelligence MCP server's canonical tool name. If
5626
+ * we add per-instance customization later (e.g. a `CopilotKitProvider`
5627
+ * prop or a runtime-info field), this constant becomes the fallback.
5628
+ */
5629
+ const DEFAULT_TOOL_PATTERNS = [/^copilotkit_knowledge_base_shell$/];
5630
+ const isMatchingToolCallName = (name) => typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
5631
+ /**
5632
+ * "Tool-call-like" messages do NOT count as a real follow-up: tool
5633
+ * result messages, assistant messages that carry tool calls, and
5634
+ * empty-content assistant messages (which some providers emit as a
5635
+ * standalone wrapper around a batch of tool calls). A real follow-up
5636
+ * is anything else — most importantly an assistant message with prose
5637
+ * content, or a fresh user message.
5638
+ */
5639
+ const isToolCallLikeMessage = (m) => {
5640
+ if (m.role === "tool") return true;
5641
+ if (m.role === "assistant") {
5642
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).length > 0) return true;
5643
+ const content = m.content;
5644
+ return typeof content !== "string" || content.trim().length === 0;
5645
+ }
5646
+ return false;
5647
+ };
5648
+ /**
5649
+ * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5650
+ * `CopilotChatMessageView` for every message slot when
5651
+ * `copilotkit.intelligence` is configured — callers do not register
5652
+ * this themselves. Self-gates so only the canonical message renders a
5653
+ * pill.
5654
+ *
5655
+ * Render gates (all must hold):
5656
+ * 1. `copilotkit.intelligence !== undefined`
5657
+ * 2. The message is an assistant message with at least one tool call
5658
+ * whose name matches {@link DEFAULT_TOOL_PATTERNS}
5659
+ * 3. The message is the *latest* such matching-assistant message in
5660
+ * `agent.messages` — tool-result messages and prose-only assistant
5661
+ * messages don't invalidate the slot, so the pill stays
5662
+ * continuously through a multi-step tool chain.
5663
+ * 4. The phase machine is past `idle` (the pending-grace timer fired)
5664
+ * and not yet `hidden`.
5665
+ *
5666
+ * Phase machine (per-instance, all timers local):
5667
+ * - Starts in `idle` — nothing rendered.
5668
+ * - `idle → spinner` once a matching tool call has been pending
5669
+ * (no `tool`-role result with a matching `toolCallId`) for
5670
+ * {@link PENDING_THRESHOLD_MS}. Replay flashes (tool call + result
5671
+ * in the same tick) never cross this threshold.
5672
+ * - `spinner → check` as soon as EITHER `agent.isRunning` flips
5673
+ * false OR a non-tool-call-like message appears later in
5674
+ * `agent.messages` (i.e. the agent has produced a "real"
5675
+ * follow-up — prose answer or a new user turn).
5676
+ * - `check → fading` after {@link CHECK_HOLD_MS}.
5677
+ * - `fading → hidden` after {@link FADE_OUT_ANIMATION_MS}.
5678
+ *
5679
+ * Once `hidden`, the phase is sticky — a finished pill never re-spawns
5680
+ * on the same message. New runs mount fresh indicator instances on
5681
+ * their own assistant messages.
5682
+ *
5683
+ * The "exactly one pill at a time" guarantee is structural: only one
5684
+ * message satisfies the latest-matching-assistant gate at any moment.
5685
+ */
5686
+ function IntelligenceIndicator(props) {
5687
+ const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
5688
+ const { copilotkit } = useCopilotKit();
5689
+ const config = useCopilotChatConfiguration();
5690
+ const { agent } = useAgent({
5691
+ agentId,
5692
+ updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
5693
+ });
5694
+ const matchingToolCallIds = (0, react.useMemo)(() => {
5695
+ if (message.role !== "assistant") return [];
5696
+ const tcs = Array.isArray(message.toolCalls) ? message.toolCalls : [];
5697
+ const ids = [];
5698
+ for (const tc of tcs) if (isMatchingToolCallName(tc?.function?.name) && tc?.id) ids.push(tc.id);
5699
+ return ids;
5700
+ }, [message]);
5701
+ const hasPending = (0, react.useMemo)(() => {
5702
+ if (matchingToolCallIds.length === 0) return false;
5703
+ const resolved = /* @__PURE__ */ new Set();
5704
+ for (const m of agent.messages) if (m.role === "tool" && m.toolCallId) resolved.add(m.toolCallId);
5705
+ return matchingToolCallIds.some((id) => !resolved.has(id));
5706
+ }, [matchingToolCallIds, agent.messages]);
5707
+ const sawRealFollowup = (0, react.useMemo)(() => {
5708
+ const idx = agent.messages.findIndex((m) => m.id === message.id);
5709
+ if (idx < 0) return false;
5710
+ for (let i = idx + 1; i < agent.messages.length; i += 1) if (!isToolCallLikeMessage(agent.messages[i])) return true;
5711
+ return false;
5712
+ }, [agent.messages, message.id]);
5713
+ const [phase, setPhase] = (0, react.useState)("idle");
5714
+ (0, react.useEffect)(() => {
5715
+ if (phase !== "idle") return void 0;
5716
+ if (!hasPending) return void 0;
5717
+ const t = setTimeout(() => setPhase("spinner"), PENDING_THRESHOLD_MS);
5718
+ return () => clearTimeout(t);
5719
+ }, [phase, hasPending]);
5720
+ (0, react.useEffect)(() => {
5721
+ if (phase !== "spinner") return void 0;
5722
+ if (!agent.isRunning || sawRealFollowup) setPhase("check");
5723
+ }, [
5724
+ phase,
5725
+ agent.isRunning,
5726
+ sawRealFollowup
5727
+ ]);
5728
+ (0, react.useEffect)(() => {
5729
+ if (phase !== "check") return void 0;
5730
+ const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5731
+ return () => clearTimeout(t);
5732
+ }, [phase]);
5733
+ (0, react.useEffect)(() => {
5734
+ if (phase !== "fading") return void 0;
5735
+ const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5736
+ return () => clearTimeout(t);
5737
+ }, [phase]);
5738
+ if (copilotkit.intelligence === void 0) return null;
5739
+ if (!config) return null;
5740
+ if (phase === "idle" || phase === "hidden") return null;
5741
+ if (message.role !== "assistant") return null;
5742
+ if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) return null;
5743
+ let latestMatchingAssistantId;
5744
+ for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5745
+ const m = agent.messages[i];
5746
+ if (m.role !== "assistant") continue;
5747
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) {
5748
+ latestMatchingAssistantId = m.id;
5749
+ break;
5750
+ }
5751
+ }
5752
+ if (latestMatchingAssistantId !== message.id) return null;
5753
+ const showSpinner = phase === "spinner";
5754
+ const isFading = phase === "fading";
5755
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5756
+ className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5757
+ role: "status",
5758
+ "aria-live": "polite",
5759
+ "aria-hidden": isFading || void 0,
5760
+ "data-testid": `cpk-intelligence-pill-${message.id}`,
5761
+ title: label,
5762
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
5763
+ className: "cpk-intelligence-pill__icon",
5764
+ viewBox: "0 0 24 24",
5765
+ width: "14",
5766
+ height: "14",
5767
+ "aria-hidden": "true",
5768
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
5769
+ cx: "12",
5770
+ cy: "12",
5771
+ r: "9",
5772
+ fill: "none",
5773
+ strokeWidth: "2.5",
5774
+ strokeLinecap: "round",
5775
+ className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5776
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
5777
+ d: "M8 12.5l3 3 5-6",
5778
+ fill: "none",
5779
+ strokeWidth: "2.5",
5780
+ strokeLinecap: "round",
5781
+ strokeLinejoin: "round",
5782
+ className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5783
+ })]
5784
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
5785
+ });
5786
+ }
5787
+
5649
5788
  //#endregion
5650
5789
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5651
5790
  /**
@@ -5803,14 +5942,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5803
5942
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
5804
5943
  (0, react.useEffect)(() => {
5805
5944
  if (!config?.agentId) return;
5806
- const registryAgent = copilotkit.getAgent(config.agentId);
5807
- const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5945
+ const agent = copilotkit.getAgent(config.agentId);
5808
5946
  if (!agent) return;
5809
5947
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5810
5948
  return () => subscription.unsubscribe();
5811
5949
  }, [
5812
5950
  config?.agentId,
5813
- config?.threadId,
5814
5951
  copilotkit,
5815
5952
  forceUpdate
5816
5953
  ]);
@@ -5893,6 +6030,10 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5893
6030
  renderCustomMessage,
5894
6031
  stateSnapshot
5895
6032
  }, `${message.id}-custom-after`));
6033
+ if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
6034
+ message,
6035
+ agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID
6036
+ }, `${message.id}-intelligence`));
5896
6037
  return elements.filter(Boolean);
5897
6038
  };
5898
6039
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6841,7 +6982,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6841
6982
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
6842
6983
  const { agent } = useAgent({
6843
6984
  agentId: resolvedAgentId,
6844
- threadId: resolvedThreadId,
6845
6985
  throttleMs
6846
6986
  });
6847
6987
  const { copilotkit } = useCopilotKit();
@@ -6883,6 +7023,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6883
7023
  let detached = false;
6884
7024
  const connectAbortController = new AbortController();
6885
7025
  if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
7026
+ agent.threadId = resolvedThreadId;
6886
7027
  const connect = async (agent) => {
6887
7028
  try {
6888
7029
  await copilotkit.connectAgent({ agent });
@@ -10015,6 +10156,12 @@ Object.defineProperty(exports, 'DefaultOpenIcon', {
10015
10156
  return DefaultOpenIcon;
10016
10157
  }
10017
10158
  });
10159
+ Object.defineProperty(exports, 'IntelligenceIndicator', {
10160
+ enumerable: true,
10161
+ get: function () {
10162
+ return IntelligenceIndicator;
10163
+ }
10164
+ });
10018
10165
  Object.defineProperty(exports, 'MCPAppsActivityContentSchema', {
10019
10166
  enumerable: true,
10020
10167
  get: function () {
@@ -10243,4 +10390,4 @@ Object.defineProperty(exports, 'useToast', {
10243
10390
  return useToast;
10244
10391
  }
10245
10392
  });
10246
- //# sourceMappingURL=copilotkit-DMFu29Kx.cjs.map
10393
+ //# sourceMappingURL=copilotkit-B_k0HSNz.cjs.map