@copilotkit/core 1.56.5-canary.1777972218 → 1.57.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
@@ -502,7 +502,6 @@ function withAbortErrorHandling(observable) {
502
502
  var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui_client.HttpAgent {
503
503
  runtimeUrl;
504
504
  credentials;
505
- remoteAgentId;
506
505
  transport;
507
506
  singleEndpointUrl;
508
507
  runtimeMode;
@@ -513,8 +512,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
513
512
  constructor(config) {
514
513
  const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
515
514
  const transport = config.transport ?? "auto";
516
- const routedId = config.remoteAgentId ?? config.agentId ?? "";
517
- const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(routedId)}/run`;
515
+ const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(config.agentId ?? "")}/run`;
518
516
  if (!runUrl) throw new Error("ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.");
519
517
  super({
520
518
  ...config,
@@ -522,7 +520,6 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
522
520
  });
523
521
  this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;
524
522
  this.credentials = config.credentials;
525
- this.remoteAgentId = config.remoteAgentId;
526
523
  this.transport = transport;
527
524
  this.runtimeMode = config.runtimeMode ?? _copilotkit_shared.RUNTIME_MODE_SSE;
528
525
  this.intelligence = config.intelligence;
@@ -530,21 +527,6 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
530
527
  if (config.debug) this.debug = config.debug;
531
528
  if (this.transport === "single") this.singleEndpointUrl = this.runtimeUrl;
532
529
  }
533
- /**
534
- * The agent id used for outbound runtime requests — `remoteAgentId` when
535
- * set (manually-registered proxy), otherwise `agentId` (registry id
536
- * matches runtime id). Subscriber bookkeeping keeps using `agentId`
537
- * directly.
538
- *
539
- * Throws when both are unset: a proxy reaching an HTTP path with no
540
- * routable id is a bug, and a missing id would otherwise produce a
541
- * malformed `/agent//run` or `/agent/undefined/connect` URL silently.
542
- */
543
- routedAgentId() {
544
- const id = this.remoteAgentId ?? this.agentId;
545
- if (!id) throw new Error("ProxiedCopilotRuntimeAgent: cannot make a runtime request without an agentId or remoteAgentId.");
546
- return id;
547
- }
548
530
  get capabilities() {
549
531
  return this._capabilities;
550
532
  }
@@ -564,7 +546,6 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
564
546
  }
565
547
  if (!this.agentId || !this.threadId) return;
566
548
  if (typeof fetch === "undefined") return;
567
- const routedId = this.routedAgentId();
568
549
  if (this.transport === "single") {
569
550
  if (!this.singleEndpointUrl) return;
570
551
  const headers = new Headers({
@@ -577,7 +558,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
577
558
  body: JSON.stringify({
578
559
  method: "agent/stop",
579
560
  params: {
580
- agentId: routedId,
561
+ agentId: this.agentId,
581
562
  threadId: this.threadId
582
563
  }
583
564
  }),
@@ -588,7 +569,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
588
569
  return;
589
570
  }
590
571
  if (!this.runtimeUrl) return;
591
- const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(routedId)}/stop/${encodeURIComponent(this.threadId)}`;
572
+ const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(this.agentId)}/stop/${encodeURIComponent(this.threadId)}`;
592
573
  const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
593
574
  const base = new URL(this.runtimeUrl, origin);
594
575
  const stopUrl = new URL(stopPath, base);
@@ -652,13 +633,12 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
652
633
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.connect(input))));
653
634
  }
654
635
  #connectViaHttp(input) {
655
- const routedId = this.routedAgentId();
656
636
  if (this.transport === "single") {
657
637
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
658
- const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: routedId });
638
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: this.agentId });
659
639
  return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
660
640
  }
661
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${routedId}/connect`, this.requestInit(input))));
641
+ return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${this.agentId}/connect`, this.requestInit(input))));
662
642
  }
663
643
  #runViaDelegate(input) {
664
644
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.run(input))));
@@ -666,7 +646,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
666
646
  #runViaHttp(input) {
667
647
  if (this.transport === "single") {
668
648
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
669
- const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.routedAgentId() });
649
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.agentId });
670
650
  return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
671
651
  }
672
652
  return withAbortErrorHandling(super.run(input));
@@ -675,7 +655,6 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
675
655
  const cloned = new ProxiedCopilotRuntimeAgent({
676
656
  runtimeUrl: this.runtimeUrl,
677
657
  agentId: this.agentId,
678
- remoteAgentId: this.remoteAgentId,
679
658
  description: this.description,
680
659
  headers: { ...this.headers },
681
660
  credentials: this.credentials,
@@ -784,18 +763,17 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
784
763
  };
785
764
  }
786
765
  createIntelligenceDelegate() {
787
- const routedId = this.routedAgentId();
788
- if (!this.runtimeUrl || !routedId || !this.intelligence?.wsUrl) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
766
+ if (!this.runtimeUrl || !this.agentId || !this.intelligence?.wsUrl) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
789
767
  return new IntelligenceAgent({
790
768
  url: this.intelligence.wsUrl,
791
769
  runtimeUrl: this.runtimeUrl,
792
- agentId: routedId,
770
+ agentId: this.agentId,
793
771
  headers: { ...this.headers },
794
772
  credentials: this.credentials
795
773
  });
796
774
  }
797
775
  syncDelegate(delegate) {
798
- delegate.agentId = this.routedAgentId();
776
+ delegate.agentId = this.agentId;
799
777
  delegate.description = this.description;
800
778
  delegate.threadId = this.threadId;
801
779
  delegate.setMessages(this.messages);
@@ -929,52 +907,6 @@ var AgentRegistry = class {
929
907
  this.notifyAgentsChanged();
930
908
  }
931
909
  /**
932
- * Register a proxied agent that routes outbound runtime requests to an
933
- * existing runtime agent (`remoteAgentId`) while exposing a distinct local
934
- * registry id (`agentId`). Throws if `agentId` is already taken by either a
935
- * local or runtime-discovered agent.
936
- *
937
- * Use this to mount multiple frontend agents against a single runtime
938
- * agent (e.g. a chat-1 / chat-2 pair both proxying to "default") without
939
- * implicit per-thread cloning. The returned `unregister` removes the proxy
940
- * from the registry and emits `onAgentsChanged`.
941
- */
942
- registerProxiedAgent({ agentId, remoteAgentId }) {
943
- if (Object.prototype.hasOwnProperty.call(this._agents, agentId)) throw new Error(`CopilotKitCore.registerProxiedAgent: agentId "${agentId}" is already registered. Pick a different agentId, or unregister the existing agent first.`);
944
- const friends = this.core;
945
- const debug = friends.debug;
946
- const agent = new ProxiedCopilotRuntimeAgent({
947
- runtimeUrl: this._runtimeUrl,
948
- agentId,
949
- remoteAgentId,
950
- transport: this._runtimeTransport,
951
- credentials: friends.credentials,
952
- runtimeMode: this._runtimeUrl ? this._runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected ? this._runtimeMode : "pending" : _copilotkit_shared.RUNTIME_MODE_SSE,
953
- intelligence: this._intelligence,
954
- debug: debug ? (0, _copilotkit_shared.resolveDebugConfig)(debug) : void 0
955
- });
956
- this.applyHeadersToAgent(agent);
957
- this.localAgents[agentId] = agent;
958
- this._agents = {
959
- ...this.localAgents,
960
- ...this.remoteAgents
961
- };
962
- this.notifyAgentsChanged();
963
- return {
964
- agent,
965
- unregister: () => {
966
- if (this.localAgents[agentId] === agent) {
967
- delete this.localAgents[agentId];
968
- this._agents = {
969
- ...this.localAgents,
970
- ...this.remoteAgents
971
- };
972
- this.notifyAgentsChanged();
973
- }
974
- }
975
- };
976
- }
977
- /**
978
910
  * Get an agent by ID
979
911
  */
980
912
  getAgent(id) {
@@ -1254,10 +1186,16 @@ var SuggestionEngine = class {
1254
1186
  /**
1255
1187
  * Reload suggestions for a specific agent
1256
1188
  * This triggers generation of new suggestions based on current configs
1189
+ *
1190
+ * @param agentId - The consumer agent ID
1191
+ * @param consumerAgent - Optional: the specific agent instance whose messages should be used
1192
+ * for availability filtering and context. When running with per-thread clones, the thread
1193
+ * clone holds the conversation messages; passing it here ensures dynamic suggestions fire
1194
+ * after the first message even though the registry agent has an empty message list.
1257
1195
  */
1258
- reloadSuggestions(agentId) {
1196
+ reloadSuggestions(agentId, consumerAgent) {
1259
1197
  this.clearSuggestions(agentId);
1260
- const agent = this.core.getAgent(agentId);
1198
+ const agent = consumerAgent ?? this.core.getAgent(agentId);
1261
1199
  const messageCount = agent?.messages?.length ?? 0;
1262
1200
  let hasAnySuggestions = false;
1263
1201
  for (const config of Object.values(this._suggestionsConfig)) {
@@ -1270,7 +1208,7 @@ var SuggestionEngine = class {
1270
1208
  hasAnySuggestions = true;
1271
1209
  this.notifySuggestionsStartedLoading(agentId);
1272
1210
  }
1273
- this.generateSuggestions(suggestionId, config, agentId);
1211
+ this.generateSuggestions(suggestionId, config, agentId, agent);
1274
1212
  } else if (isStaticSuggestionsConfig(config)) this.addStaticSuggestions(suggestionId, config, agentId);
1275
1213
  }
1276
1214
  }
@@ -1298,12 +1236,12 @@ var SuggestionEngine = class {
1298
1236
  /**
1299
1237
  * Generate suggestions using a provider agent
1300
1238
  */
1301
- async generateSuggestions(suggestionId, config, consumerAgentId) {
1239
+ async generateSuggestions(suggestionId, config, consumerAgentId, consumerAgent) {
1302
1240
  let agent = void 0;
1303
1241
  try {
1304
1242
  const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
1305
1243
  if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
1306
- const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
1244
+ const suggestionsConsumerAgent = consumerAgent ?? this.core.getAgent(consumerAgentId);
1307
1245
  if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
1308
1246
  agent = suggestionsProviderAgent.clone();
1309
1247
  agent.threadId = suggestionId;
@@ -1608,6 +1546,10 @@ var RunHandler = class {
1608
1546
  agent.setMessages([]);
1609
1547
  agent.setState({});
1610
1548
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1549
+ await this._internal.notifySubscribers((subscriber) => subscriber.onAgentRunStarted?.({
1550
+ copilotkit: this.core,
1551
+ agent
1552
+ }), "Subscriber onAgentRunStarted error:");
1611
1553
  const runAgentResult = await agent.connectAgent({
1612
1554
  forwardedProps: this._internal.properties,
1613
1555
  tools: this.buildFrontendTools(agent.agentId),
@@ -1638,6 +1580,11 @@ var RunHandler = class {
1638
1580
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1639
1581
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1640
1582
  if (agent.detachActiveRun) await agent.detachActiveRun();
1583
+ this._internal.subscribeAgentToStateManager(agent);
1584
+ await this._internal.notifySubscribers((subscriber) => subscriber.onAgentRunStarted?.({
1585
+ copilotkit: this.core,
1586
+ agent
1587
+ }), "Subscriber onAgentRunStarted error:");
1641
1588
  const isTopLevel = this._runDepth === 0;
1642
1589
  let originalAbortRun;
1643
1590
  if (isTopLevel) {
@@ -1708,7 +1655,7 @@ var RunHandler = class {
1708
1655
  await this._internal.waitForPendingFrameworkUpdates();
1709
1656
  return await this.runAgent({ agent });
1710
1657
  }
1711
- this._internal.suggestionEngine.reloadSuggestions(agentId);
1658
+ this._internal.suggestionEngine.reloadSuggestions(agentId, agent);
1712
1659
  return runAgentResult;
1713
1660
  }
1714
1661
  /**
@@ -2120,14 +2067,21 @@ var StateManager = class {
2120
2067
  initialize() {}
2121
2068
  /**
2122
2069
  * Subscribe to an agent's events to track state and messages.
2070
+ *
2071
+ * Registry agents (subscribed via `onAgentsChanged`) use the bare `agentId`
2072
+ * key so that `unsubscribeFromAgent(agentId)` can remove them when they
2073
+ * are replaced. Per-thread clones (subscribed via `subscribeAgentToStateManager`)
2074
+ * pass `{ isClone: true }` to use a composite `agentId:threadId` key, keeping
2075
+ * their subscription independent of the registry agent's.
2123
2076
  */
2124
- subscribeToAgent(agent) {
2077
+ subscribeToAgent(agent, { isClone = false } = {}) {
2125
2078
  if (!agent.agentId) return;
2126
2079
  const agentId = agent.agentId;
2127
- const existingUnsubscribe = this.agentSubscriptions.get(agentId);
2080
+ const subscriptionKey = isClone && agent.threadId ? `${agentId}:${agent.threadId}` : agentId;
2081
+ const existingUnsubscribe = this.agentSubscriptions.get(subscriptionKey);
2128
2082
  if (existingUnsubscribe) {
2129
2083
  existingUnsubscribe();
2130
- this.agentSubscriptions.delete(agentId);
2084
+ this.agentSubscriptions.delete(subscriptionKey);
2131
2085
  }
2132
2086
  let revoked = false;
2133
2087
  let subRunId;
@@ -2171,13 +2125,16 @@ var StateManager = class {
2171
2125
  this.handleNewMessage(agent, message, input ? effectiveInput(input) : void 0);
2172
2126
  }
2173
2127
  });
2174
- this.agentSubscriptions.set(agentId, () => {
2128
+ this.agentSubscriptions.set(subscriptionKey, () => {
2175
2129
  revoked = true;
2176
2130
  unsubscribe();
2177
2131
  });
2178
2132
  }
2179
2133
  /**
2180
- * Unsubscribe an agent's subscription.
2134
+ * Unsubscribe a registry agent's subscription (bare `agentId` key).
2135
+ * Per-thread clone subscriptions use composite `agentId:threadId` keys and
2136
+ * are replaced (not removed) by subsequent subscribeToAgent(agent, { isClone: true })
2137
+ * calls for the same (agentId, threadId) pair.
2181
2138
  */
2182
2139
  unsubscribeFromAgent(agentId) {
2183
2140
  const unsubscribe = this.agentSubscriptions.get(agentId);
@@ -2462,16 +2419,7 @@ var CopilotKitCore = class {
2462
2419
  if (agent.agentId) this.stateManager.subscribeToAgent(agent);
2463
2420
  });
2464
2421
  const currentAgentIds = new Set(Object.keys(agents));
2465
- for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
2466
- this.threadStoreRegistry.unregister(agentId);
2467
- } catch (err) {
2468
- console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
2469
- }
2470
- for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
2471
- this.stateManager.unsubscribeFromAgent(agentId);
2472
- } catch (err) {
2473
- console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
2474
- }
2422
+ for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) this.threadStoreRegistry.unregister(agentId);
2475
2423
  this.previousAgentIds = currentAgentIds;
2476
2424
  } });
2477
2425
  }
@@ -2634,28 +2582,6 @@ var CopilotKitCore = class {
2634
2582
  removeAgent__unsafe_dev_only(id) {
2635
2583
  this.agentRegistry.removeAgent__unsafe_dev_only(id);
2636
2584
  }
2637
- /**
2638
- * Register a proxied agent against an existing runtime agent. The proxy is
2639
- * exposed under `agentId` (local registry id) and routes outbound runtime
2640
- * requests to `remoteAgentId`. Throws if `agentId` is already taken.
2641
- *
2642
- * Returns the minted proxy and an `unregister` handle for cleanup.
2643
- *
2644
- * Use this to mount multiple frontend agents against a single runtime
2645
- * agent (e.g. one per chat window) without implicit per-thread cloning.
2646
- *
2647
- * @example
2648
- * const { agent, unregister } = copilotkit.registerProxiedAgent({
2649
- * agentId: "chat-1",
2650
- * remoteAgentId: "default",
2651
- * });
2652
- * // ... <CopilotChat agentId="chat-1" />
2653
- * // on cleanup:
2654
- * unregister();
2655
- */
2656
- registerProxiedAgent(params) {
2657
- return this.agentRegistry.registerProxiedAgent(params);
2658
- }
2659
2585
  getAgent(id) {
2660
2586
  return this.agentRegistry.getAgent(id);
2661
2587
  }
@@ -2889,6 +2815,9 @@ var CopilotKitCore = class {
2889
2815
  getRunIdsForThread(agentId, threadId) {
2890
2816
  return this.stateManager.getRunIdsForThread(agentId, threadId);
2891
2817
  }
2818
+ subscribeAgentToStateManager(agent) {
2819
+ this.stateManager.subscribeToAgent(agent, { isClone: true });
2820
+ }
2892
2821
  /**
2893
2822
  * Internal method used by RunHandler to build frontend tools
2894
2823
  */