@copilotkit/react-core 1.56.4 → 1.56.5

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.
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useRef } from "react";
2
2
  import { useCopilotKit } from "../providers/CopilotKitProvider";
3
3
  import { useCopilotChatConfiguration } from "../providers/CopilotChatConfigurationProvider";
4
4
  import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
5
- import {
5
+ import type {
6
6
  DynamicSuggestionsConfig,
7
7
  StaticSuggestionsConfig,
8
8
  SuggestionsConfig,
@@ -106,22 +106,37 @@ export function useConfigureSuggestions(
106
106
  const isGlobalConfig =
107
107
  rawConsumerAgentId === undefined || rawConsumerAgentId === "*";
108
108
 
109
+ const isDynamicConfigType = useMemo(
110
+ () => !!normalizedConfig && "instructions" in normalizedConfig,
111
+ [normalizedConfig],
112
+ );
113
+
109
114
  const requestReload = useCallback(() => {
110
115
  if (!normalizedConfig) {
111
116
  return;
112
117
  }
113
118
 
114
119
  if (isGlobalConfig) {
120
+ const seen = new Set<string>();
115
121
  const agents = Object.values(copilotkit.agents ?? {});
116
122
  for (const entry of agents) {
117
123
  const agentId = entry.agentId;
118
124
  if (!agentId) {
119
125
  continue;
120
126
  }
127
+ seen.add(agentId);
121
128
  if (!entry.isRunning) {
122
129
  copilotkit.reloadSuggestions(agentId);
123
130
  }
124
131
  }
132
+ // Also reload for the chat's resolved consumer agent. The registry can
133
+ // be empty at this point (e.g. runtime info still loading), in which
134
+ // case the loop above wouldn't have fired for the agent the user is
135
+ // actually chatting with — and the welcome screen would render with
136
+ // no suggestions until they navigate away and back.
137
+ if (targetAgentId && !seen.has(targetAgentId)) {
138
+ copilotkit.reloadSuggestions(targetAgentId);
139
+ }
125
140
  return;
126
141
  }
127
142
 
@@ -169,6 +184,40 @@ export function useConfigureSuggestions(
169
184
  }
170
185
  requestReload();
171
186
  }, [extraDeps.length, normalizedConfig, requestReload, ...extraDeps]);
187
+
188
+ // When agents arrive after the initial render (runtime info just landed),
189
+ // re-request a reload so dynamic configs that need a real agent can finally
190
+ // generate. Skip for static configs — they don't need an agent and the
191
+ // initial mount reload already handled them. Skip when the target agent
192
+ // is already in the registry — the initial reload already covered it, and
193
+ // re-firing on every subsequent `onAgentsChanged` (e.g. dev-mode hot
194
+ // reloads, sibling chat configs mounting) would stack overlapping
195
+ // generations.
196
+ useEffect(() => {
197
+ if (!normalizedConfig || !isDynamicConfigType) return;
198
+ if (!targetAgentId) return;
199
+
200
+ const initiallyPresent = !!copilotkit.getAgent(targetAgentId);
201
+ if (initiallyPresent) return;
202
+
203
+ const subscription = copilotkit.subscribe({
204
+ onAgentsChanged: () => {
205
+ if (copilotkit.getAgent(targetAgentId)) {
206
+ requestReload();
207
+ subscription.unsubscribe();
208
+ }
209
+ },
210
+ });
211
+ return () => {
212
+ subscription.unsubscribe();
213
+ };
214
+ }, [
215
+ copilotkit,
216
+ normalizedConfig,
217
+ isDynamicConfigType,
218
+ targetAgentId,
219
+ requestReload,
220
+ ]);
172
221
  }
173
222
 
174
223
  function isDynamicConfig(