@copilotkit/core 1.55.0-next.8 → 1.55.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.
package/dist/index.cjs CHANGED
@@ -520,7 +520,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
520
520
  runtimeInfoPromise;
521
521
  constructor(config) {
522
522
  const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
523
- const transport = config.transport ?? "rest";
523
+ const transport = config.transport ?? "auto";
524
524
  const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(config.agentId ?? "")}/run`;
525
525
  if (!runUrl) throw new Error("ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.");
526
526
  super({
@@ -689,6 +689,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
689
689
  }
690
690
  async fetchRuntimeInfo() {
691
691
  const headers = { ...this.headers };
692
+ if (this.transport === "auto") return this.fetchRuntimeInfoAutoDetect(headers);
692
693
  let init;
693
694
  let url;
694
695
  if (this.transport === "single") {
@@ -711,6 +712,30 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
711
712
  if (!response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
712
713
  return await response.json();
713
714
  }
715
+ async fetchRuntimeInfoAutoDetect(headers) {
716
+ try {
717
+ const response = await fetch(`${this.runtimeUrl}/info`, {
718
+ headers: { ...headers },
719
+ ...this.credentials ? { credentials: this.credentials } : {}
720
+ });
721
+ if (response.status >= 200 && response.status < 300) {
722
+ this.transport = "rest";
723
+ return await response.json();
724
+ }
725
+ } catch {}
726
+ const singleHeaders = { ...headers };
727
+ if (!singleHeaders["Content-Type"]) singleHeaders["Content-Type"] = "application/json";
728
+ const response = await fetch(this.runtimeUrl, {
729
+ method: "POST",
730
+ headers: singleHeaders,
731
+ body: JSON.stringify({ method: "info" }),
732
+ ...this.credentials ? { credentials: this.credentials } : {}
733
+ });
734
+ if (!response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
735
+ this.transport = "single";
736
+ this.singleEndpointUrl = this.runtimeUrl;
737
+ return await response.json();
738
+ }
714
739
  createSingleRouteRequestInit(input, method, params) {
715
740
  if (!this.agentId) throw new Error("ProxiedCopilotRuntimeAgent requires agentId to make runtime requests");
716
741
  const baseInit = super.requestInit(input);
@@ -767,11 +792,12 @@ var AgentRegistry = class {
767
792
  _runtimeUrl;
768
793
  _runtimeVersion;
769
794
  _runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
770
- _runtimeTransport = "rest";
795
+ _runtimeTransport = "auto";
771
796
  _audioFileTranscriptionEnabled = false;
772
797
  _runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
773
798
  _intelligence;
774
799
  _a2uiEnabled = false;
800
+ _openGenerativeUIEnabled = false;
775
801
  _licenseStatus;
776
802
  constructor(core) {
777
803
  this.core = core;
@@ -806,6 +832,9 @@ var AgentRegistry = class {
806
832
  get a2uiEnabled() {
807
833
  return this._a2uiEnabled;
808
834
  }
835
+ get openGenerativeUIEnabled() {
836
+ return this._openGenerativeUIEnabled;
837
+ }
809
838
  get licenseStatus() {
810
839
  return this._licenseStatus;
811
840
  }
@@ -918,6 +947,7 @@ var AgentRegistry = class {
918
947
  this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
919
948
  this._intelligence = void 0;
920
949
  this._a2uiEnabled = false;
950
+ this._openGenerativeUIEnabled = false;
921
951
  this.remoteAgents = {};
922
952
  this._agents = this.localAgents;
923
953
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Disconnected);
@@ -953,6 +983,7 @@ var AgentRegistry = class {
953
983
  this._runtimeMode = runtimeInfoResponse.mode ?? _copilotkit_shared.RUNTIME_MODE_SSE;
954
984
  this._intelligence = runtimeInfoResponse.intelligence;
955
985
  this._a2uiEnabled = runtimeInfoResponse.a2uiEnabled ?? false;
986
+ this._openGenerativeUIEnabled = runtimeInfoResponse.openGenerativeUIEnabled ?? false;
956
987
  this._licenseStatus = runtimeInfoResponse.licenseStatus;
957
988
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connected);
958
989
  await this.notifyAgentsChanged();
@@ -963,6 +994,7 @@ var AgentRegistry = class {
963
994
  this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
964
995
  this._intelligence = void 0;
965
996
  this._a2uiEnabled = false;
997
+ this._openGenerativeUIEnabled = false;
966
998
  this.remoteAgents = {};
967
999
  this._agents = this.localAgents;
968
1000
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Error);
@@ -982,24 +1014,45 @@ var AgentRegistry = class {
982
1014
  const baseHeaders = this.core.headers;
983
1015
  const credentials = this.core.credentials;
984
1016
  const headers = { ...baseHeaders };
985
- if (this._runtimeTransport === "single") {
986
- if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
987
- const response = await fetch(this.runtimeUrl, {
988
- method: "POST",
989
- headers,
990
- body: JSON.stringify({ method: "info" }),
991
- ...credentials ? { credentials } : {}
992
- });
993
- if ("ok" in response && !response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
994
- return await response.json();
995
- }
1017
+ if (this._runtimeTransport === "single") return this.fetchRuntimeInfoSingle(headers, credentials);
1018
+ if (this._runtimeTransport === "auto") return this.fetchRuntimeInfoAutoDetect(headers, credentials);
996
1019
  const response = await fetch(`${this.runtimeUrl}/info`, {
997
1020
  headers,
998
1021
  ...credentials ? { credentials } : {}
999
1022
  });
1000
- if ("ok" in response && !response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
1023
+ if (!response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
1001
1024
  return await response.json();
1002
1025
  }
1026
+ async fetchRuntimeInfoSingle(headers, credentials) {
1027
+ if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
1028
+ const response = await fetch(this.runtimeUrl, {
1029
+ method: "POST",
1030
+ headers,
1031
+ body: JSON.stringify({ method: "info" }),
1032
+ ...credentials ? { credentials } : {}
1033
+ });
1034
+ if (!response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
1035
+ return await response.json();
1036
+ }
1037
+ /**
1038
+ * Auto-detect transport by trying REST first, then falling back to single-endpoint.
1039
+ * Updates `_runtimeTransport` to the detected value so subsequent requests use it directly.
1040
+ */
1041
+ async fetchRuntimeInfoAutoDetect(headers, credentials) {
1042
+ try {
1043
+ const response = await fetch(`${this.runtimeUrl}/info`, {
1044
+ headers: { ...headers },
1045
+ ...credentials ? { credentials } : {}
1046
+ });
1047
+ if (response.status >= 200 && response.status < 300) {
1048
+ this._runtimeTransport = "rest";
1049
+ return await response.json();
1050
+ }
1051
+ } catch {}
1052
+ const result = await this.fetchRuntimeInfoSingle({ ...headers }, credentials);
1053
+ this._runtimeTransport = "single";
1054
+ return result;
1055
+ }
1003
1056
  /**
1004
1057
  * Assign agent IDs to a record of agents
1005
1058
  */
@@ -1123,10 +1176,16 @@ var SuggestionEngine = class {
1123
1176
  /**
1124
1177
  * Reload suggestions for a specific agent
1125
1178
  * This triggers generation of new suggestions based on current configs
1179
+ *
1180
+ * @param agentId - The consumer agent ID
1181
+ * @param consumerAgent - Optional: the specific agent instance whose messages should be used
1182
+ * for availability filtering and context. When running with per-thread clones, the thread
1183
+ * clone holds the conversation messages; passing it here ensures dynamic suggestions fire
1184
+ * after the first message even though the registry agent has an empty message list.
1126
1185
  */
1127
- reloadSuggestions(agentId) {
1186
+ reloadSuggestions(agentId, consumerAgent) {
1128
1187
  this.clearSuggestions(agentId);
1129
- const agent = this.core.getAgent(agentId);
1188
+ const agent = consumerAgent ?? this.core.getAgent(agentId);
1130
1189
  if (!agent) return;
1131
1190
  const messageCount = agent.messages?.length ?? 0;
1132
1191
  let hasAnySuggestions = false;
@@ -1139,7 +1198,7 @@ var SuggestionEngine = class {
1139
1198
  hasAnySuggestions = true;
1140
1199
  this.notifySuggestionsStartedLoading(agentId);
1141
1200
  }
1142
- this.generateSuggestions(suggestionId, config, agentId);
1201
+ this.generateSuggestions(suggestionId, config, agentId, agent);
1143
1202
  } else if (isStaticSuggestionsConfig(config)) this.addStaticSuggestions(suggestionId, config, agentId);
1144
1203
  }
1145
1204
  }
@@ -1167,12 +1226,12 @@ var SuggestionEngine = class {
1167
1226
  /**
1168
1227
  * Generate suggestions using a provider agent
1169
1228
  */
1170
- async generateSuggestions(suggestionId, config, consumerAgentId) {
1229
+ async generateSuggestions(suggestionId, config, consumerAgentId, consumerAgent) {
1171
1230
  let agent = void 0;
1172
1231
  try {
1173
1232
  const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
1174
1233
  if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
1175
- const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
1234
+ const suggestionsConsumerAgent = consumerAgent ?? this.core.getAgent(consumerAgentId);
1176
1235
  if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
1177
1236
  agent = suggestionsProviderAgent.clone();
1178
1237
  agent.threadId = suggestionId;
@@ -1488,13 +1547,15 @@ var RunHandler = class {
1488
1547
  });
1489
1548
  } catch (error) {
1490
1549
  const connectError = error instanceof Error ? error : new Error(String(error));
1491
- const context = {};
1492
- if (agent.agentId) context.agentId = agent.agentId;
1493
- await this._internal.emitError({
1494
- error: connectError,
1495
- code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,
1496
- context
1497
- });
1550
+ if (!(connectError.name === "AbortError" || connectError.message === "Fetch is aborted" || connectError.message === "signal is aborted without reason" || connectError.message === "component unmounted")) {
1551
+ const context = {};
1552
+ if (agent.agentId) context.agentId = agent.agentId;
1553
+ await this._internal.emitError({
1554
+ error: connectError,
1555
+ code: CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED,
1556
+ context
1557
+ });
1558
+ }
1498
1559
  return { newMessages: [] };
1499
1560
  }
1500
1561
  }
@@ -1505,6 +1566,7 @@ var RunHandler = class {
1505
1566
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1506
1567
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1507
1568
  if (agent.detachActiveRun) await agent.detachActiveRun();
1569
+ this._internal.subscribeAgentToStateManager(agent);
1508
1570
  const isTopLevel = this._runDepth === 0;
1509
1571
  let originalAbortRun;
1510
1572
  if (isTopLevel) {
@@ -1575,7 +1637,7 @@ var RunHandler = class {
1575
1637
  await this._internal.waitForPendingFrameworkUpdates();
1576
1638
  return await this.runAgent({ agent });
1577
1639
  }
1578
- this._internal.suggestionEngine.reloadSuggestions(agentId);
1640
+ this._internal.suggestionEngine.reloadSuggestions(agentId, agent);
1579
1641
  return runAgentResult;
1580
1642
  }
1581
1643
  /**
@@ -1976,6 +2038,7 @@ function parseToolArguments(rawArgs, toolName) {
1976
2038
  var StateManager = class {
1977
2039
  stateByRun = /* @__PURE__ */ new Map();
1978
2040
  messageToRun = /* @__PURE__ */ new Map();
2041
+ activeRun = /* @__PURE__ */ new Map();
1979
2042
  agentSubscriptions = /* @__PURE__ */ new Map();
1980
2043
  constructor(core) {
1981
2044
  this.core = core;
@@ -1985,36 +2048,70 @@ var StateManager = class {
1985
2048
  */
1986
2049
  initialize() {}
1987
2050
  /**
1988
- * Subscribe to an agent's events to track state and messages
2051
+ * Subscribe to an agent's events to track state and messages.
2052
+ *
2053
+ * Registry agents (subscribed via `onAgentsChanged`) use the bare `agentId`
2054
+ * key so that `unsubscribeFromAgent(agentId)` can remove them when they
2055
+ * are replaced. Per-thread clones (subscribed via `subscribeAgentToStateManager`)
2056
+ * pass `{ isClone: true }` to use a composite `agentId:threadId` key, keeping
2057
+ * their subscription independent of the registry agent's.
1989
2058
  */
1990
- subscribeToAgent(agent) {
2059
+ subscribeToAgent(agent, { isClone = false } = {}) {
1991
2060
  if (!agent.agentId) return;
1992
2061
  const agentId = agent.agentId;
1993
- this.unsubscribeFromAgent(agentId);
2062
+ const subscriptionKey = isClone && agent.threadId ? `${agentId}:${agent.threadId}` : agentId;
2063
+ const existingUnsubscribe = this.agentSubscriptions.get(subscriptionKey);
2064
+ if (existingUnsubscribe) {
2065
+ existingUnsubscribe();
2066
+ this.agentSubscriptions.delete(subscriptionKey);
2067
+ }
2068
+ let revoked = false;
2069
+ let subRunId;
2070
+ let runFinished = false;
2071
+ const effectiveInput = (input) => ({
2072
+ ...input,
2073
+ runId: subRunId ?? input.runId
2074
+ });
1994
2075
  const { unsubscribe } = agent.subscribe({
1995
- onRunStartedEvent: ({ event, state }) => {
1996
- this.handleRunStarted(agent, event, state);
2076
+ onRunStartedEvent: ({ input, state }) => {
2077
+ if (revoked) return;
2078
+ if (runFinished && input.runId === subRunId) subRunId = (0, _ag_ui_client.randomUUID)();
2079
+ else subRunId = input.runId;
2080
+ runFinished = false;
2081
+ this.handleRunStarted(agent, effectiveInput(input), state);
1997
2082
  },
1998
- onRunFinishedEvent: ({ event, state }) => {
1999
- this.handleRunFinished(agent, event, state);
2083
+ onRunFinishedEvent: ({ input, state }) => {
2084
+ if (revoked) return;
2085
+ runFinished = true;
2086
+ this.handleRunFinished(agent, effectiveInput(input), state);
2000
2087
  },
2001
2088
  onStateSnapshotEvent: ({ event, input, state }) => {
2002
- this.handleStateSnapshot(agent, event, input, state);
2089
+ if (revoked) return;
2090
+ this.handleStateSnapshot(agent, event, effectiveInput(input), state);
2003
2091
  },
2004
2092
  onStateDeltaEvent: ({ event, input, state }) => {
2005
- this.handleStateDelta(agent, event, input, state);
2093
+ if (revoked) return;
2094
+ this.handleStateDelta(agent, event, effectiveInput(input), state);
2006
2095
  },
2007
2096
  onMessagesSnapshotEvent: ({ event, input, messages }) => {
2008
- this.handleMessagesSnapshot(agent, event, input, messages);
2097
+ if (revoked) return;
2098
+ this.handleMessagesSnapshot(agent, event, effectiveInput(input), messages);
2009
2099
  },
2010
2100
  onNewMessage: ({ message, input }) => {
2011
- this.handleNewMessage(agent, message, input);
2101
+ if (revoked) return;
2102
+ this.handleNewMessage(agent, message, input ? effectiveInput(input) : void 0);
2012
2103
  }
2013
2104
  });
2014
- this.agentSubscriptions.set(agentId, unsubscribe);
2105
+ this.agentSubscriptions.set(subscriptionKey, () => {
2106
+ revoked = true;
2107
+ unsubscribe();
2108
+ });
2015
2109
  }
2016
2110
  /**
2017
- * Unsubscribe from an agent's events
2111
+ * Unsubscribe a registry agent's subscription (bare `agentId` key).
2112
+ * Per-thread clone subscriptions use composite `agentId:threadId` keys and
2113
+ * are replaced (not removed) by subsequent subscribeToAgent(agent, { isClone: true })
2114
+ * calls for the same (agentId, threadId) pair.
2018
2115
  */
2019
2116
  unsubscribeFromAgent(agentId) {
2020
2117
  const unsubscribe = this.agentSubscriptions.get(agentId);
@@ -2054,18 +2151,20 @@ var StateManager = class {
2054
2151
  /**
2055
2152
  * Handle run started event
2056
2153
  */
2057
- handleRunStarted(agent, event, state) {
2154
+ handleRunStarted(agent, input, state) {
2058
2155
  if (!agent.agentId) return;
2059
- const { threadId, runId } = event;
2060
- this.saveState(agent.agentId, threadId, runId, state);
2156
+ const { threadId, runId } = input;
2157
+ this.activeRun.set(`${agent.agentId}:${threadId}`, runId);
2158
+ if (state && Object.keys(state).length > 0) this.saveState(agent.agentId, threadId, runId, state);
2061
2159
  }
2062
2160
  /**
2063
2161
  * Handle run finished event
2064
2162
  */
2065
- handleRunFinished(agent, event, state) {
2163
+ handleRunFinished(agent, input, state) {
2066
2164
  if (!agent.agentId) return;
2067
- const { threadId, runId } = event;
2068
- this.saveState(agent.agentId, threadId, runId, state);
2165
+ const { threadId, runId } = input;
2166
+ this.activeRun.delete(`${agent.agentId}:${threadId}`);
2167
+ if (state && Object.keys(state).length > 0) this.saveState(agent.agentId, threadId, runId, state);
2069
2168
  }
2070
2169
  /**
2071
2170
  * Handle state snapshot event
@@ -2099,7 +2198,13 @@ var StateManager = class {
2099
2198
  * Handle new message event
2100
2199
  */
2101
2200
  handleNewMessage(agent, message, input) {
2102
- if (!agent.agentId || !input) return;
2201
+ if (!agent.agentId) return;
2202
+ if (!input) {
2203
+ const threadId = agent.threadId ?? "";
2204
+ const runId = this.activeRun.get(`${agent.agentId}:${threadId}`);
2205
+ if (runId) this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
2206
+ return;
2207
+ }
2103
2208
  const { threadId, runId } = input;
2104
2209
  this.associateMessageWithRun(agent.agentId, threadId, message.id, runId);
2105
2210
  }
@@ -2184,13 +2289,14 @@ var CopilotKitCore = class {
2184
2289
  _headers;
2185
2290
  _credentials;
2186
2291
  _properties;
2292
+ _defaultThrottleMs;
2187
2293
  subscribers = /* @__PURE__ */ new Set();
2188
2294
  agentRegistry;
2189
2295
  contextStore;
2190
2296
  suggestionEngine;
2191
2297
  runHandler;
2192
2298
  stateManager;
2193
- constructor({ runtimeUrl, runtimeTransport = "rest", headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [] }) {
2299
+ constructor({ runtimeUrl, runtimeTransport = "auto", headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [] }) {
2194
2300
  this._headers = headers;
2195
2301
  this._credentials = credentials;
2196
2302
  this._properties = properties;
@@ -2270,6 +2376,22 @@ var CopilotKitCore = class {
2270
2376
  get properties() {
2271
2377
  return this._properties;
2272
2378
  }
2379
+ /**
2380
+ * Default throttle interval (ms) applied by framework hooks (e.g.
2381
+ * `useAgent()`) when the hook/component does not specify an explicit
2382
+ * `throttleMs`. An explicit `0` passed as `throttleMs` to `useAgent()`
2383
+ * or `<CopilotChat>` overrides this default and disables throttling.
2384
+ */
2385
+ get defaultThrottleMs() {
2386
+ return this._defaultThrottleMs;
2387
+ }
2388
+ setDefaultThrottleMs(value) {
2389
+ if (value !== void 0 && (!Number.isFinite(value) || value < 0)) {
2390
+ this._defaultThrottleMs = void 0;
2391
+ return;
2392
+ }
2393
+ this._defaultThrottleMs = value;
2394
+ }
2273
2395
  get runtimeConnectionStatus() {
2274
2396
  return this.agentRegistry.runtimeConnectionStatus;
2275
2397
  }
@@ -2285,6 +2407,9 @@ var CopilotKitCore = class {
2285
2407
  get a2uiEnabled() {
2286
2408
  return this.agentRegistry.a2uiEnabled;
2287
2409
  }
2410
+ get openGenerativeUIEnabled() {
2411
+ return this.agentRegistry.openGenerativeUIEnabled;
2412
+ }
2288
2413
  get licenseStatus() {
2289
2414
  return this.agentRegistry.licenseStatus;
2290
2415
  }
@@ -2409,6 +2534,9 @@ var CopilotKitCore = class {
2409
2534
  getRunIdsForThread(agentId, threadId) {
2410
2535
  return this.stateManager.getRunIdsForThread(agentId, threadId);
2411
2536
  }
2537
+ subscribeAgentToStateManager(agent) {
2538
+ this.stateManager.subscribeToAgent(agent, { isClone: true });
2539
+ }
2412
2540
  /**
2413
2541
  * Internal method used by RunHandler to build frontend tools
2414
2542
  */