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