@copilotkit/core 1.57.0 → 1.57.1-canary.1778272612

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.umd.js CHANGED
@@ -295,10 +295,22 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
295
295
  * Reconnect to an existing thread by fetching websocket credentials and
296
296
  * joining the realtime thread channel.
297
297
  */
298
+ /**
299
+ * Reconnect to an existing thread by fetching websocket credentials
300
+ * and joining the realtime thread channel.
301
+ *
302
+ * Note: this method does NOT clear the replay cursor. Whether to
303
+ * request a full historical replay vs. resume from
304
+ * `lastSeenEventId` is a decision the caller (typically
305
+ * `RunHandler.connectAgent`) makes by calling
306
+ * {@link clearReconnectCursor} ahead of time on a fresh thread
307
+ * restore. Same-thread churn re-connects preserve the cursor so the
308
+ * gateway only streams events past it instead of replaying the
309
+ * entire history every time the chat re-opens a socket.
310
+ */
298
311
  connect(input) {
299
312
  this.threadId = input.threadId;
300
313
  this.canonicalRunId = null;
301
- this.clearReconnectCursor(input.threadId);
302
314
  return (0, rxjs.defer)(() => this.requestJoinCredentials$("connect", input)).pipe((0, rxjs.switchMap)((credentials) => {
303
315
  if (credentials === null) return rxjs.EMPTY;
304
316
  const canonicalInput = this.applyCanonicalRunIdentity(input, credentials, { fallbackToInputRunId: false });
@@ -483,6 +495,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
483
495
  getReconnectCursor(input) {
484
496
  return this.getLastSeenEventId(input.threadId);
485
497
  }
498
+ /**
499
+ * Drop the cached `lastSeenEventId` cursor for `threadId` so the
500
+ * next connect to that topic asks the gateway for a full historical
501
+ * replay (rather than resuming). Public because
502
+ * `RunHandler.connectAgent` calls it on a detected thread switch
503
+ * to rebuild local state from scratch, and skips it on same-thread
504
+ * churn so the gateway can resume.
505
+ */
486
506
  clearReconnectCursor(threadId) {
487
507
  this.sharedState.lastSeenEventIds.delete(threadId);
488
508
  }
@@ -602,10 +622,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
602
622
  var _ProxiedCopilotRuntimeAgent_brand = /* @__PURE__ */ new WeakSet();
603
623
  var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui_client.HttpAgent {
604
624
  constructor(config) {
605
- var _config$transport, _ref, _config$agentId, _config$runtimeMode;
625
+ var _config$transport, _ref, _config$runtimeAgentI, _ref2, _config$runtimeMode;
606
626
  const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
607
627
  const transport = (_config$transport = config.transport) !== null && _config$transport !== void 0 ? _config$transport : "auto";
608
- const runUrl = transport === "single" ? (_ref = normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl) !== null && _ref !== void 0 ? _ref : "" : `${normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl}/agent/${encodeURIComponent((_config$agentId = config.agentId) !== null && _config$agentId !== void 0 ? _config$agentId : "")}/run`;
628
+ const routedId = (_ref = (_config$runtimeAgentI = config.runtimeAgentId) !== null && _config$runtimeAgentI !== void 0 ? _config$runtimeAgentI : config.agentId) !== null && _ref !== void 0 ? _ref : "";
629
+ const runUrl = transport === "single" ? (_ref2 = normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl) !== null && _ref2 !== void 0 ? _ref2 : "" : `${normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl}/agent/${encodeURIComponent(routedId)}/run`;
609
630
  if (!runUrl) throw new Error("ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.");
610
631
  super({
611
632
  ...config,
@@ -614,6 +635,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
614
635
  _classPrivateMethodInitSpec(this, _ProxiedCopilotRuntimeAgent_brand);
615
636
  _defineProperty(this, "runtimeUrl", void 0);
616
637
  _defineProperty(this, "credentials", void 0);
638
+ _defineProperty(this, "runtimeAgentId", void 0);
617
639
  _defineProperty(this, "transport", void 0);
618
640
  _defineProperty(this, "singleEndpointUrl", void 0);
619
641
  _defineProperty(this, "runtimeMode", void 0);
@@ -623,6 +645,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
623
645
  _defineProperty(this, "runtimeInfoPromise", void 0);
624
646
  this.runtimeUrl = normalizedRuntimeUrl !== null && normalizedRuntimeUrl !== void 0 ? normalizedRuntimeUrl : config.runtimeUrl;
625
647
  this.credentials = config.credentials;
648
+ this.runtimeAgentId = config.runtimeAgentId;
626
649
  this.transport = transport;
627
650
  this.runtimeMode = (_config$runtimeMode = config.runtimeMode) !== null && _config$runtimeMode !== void 0 ? _config$runtimeMode : _copilotkit_shared.RUNTIME_MODE_SSE;
628
651
  this.intelligence = config.intelligence;
@@ -630,6 +653,22 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
630
653
  if (config.debug) this.debug = config.debug;
631
654
  if (this.transport === "single") this.singleEndpointUrl = this.runtimeUrl;
632
655
  }
656
+ /**
657
+ * The agent id used for outbound runtime requests — `runtimeAgentId` when
658
+ * set (manually-registered proxy), otherwise `agentId` (registry id
659
+ * matches runtime id). Subscriber bookkeeping keeps using `agentId`
660
+ * directly.
661
+ *
662
+ * Throws when both are unset: a proxy reaching an HTTP path with no
663
+ * routable id is a bug, and a missing id would otherwise produce a
664
+ * malformed `/agent//run` or `/agent/undefined/connect` URL silently.
665
+ */
666
+ routedAgentId() {
667
+ var _this$runtimeAgentId;
668
+ const id = (_this$runtimeAgentId = this.runtimeAgentId) !== null && _this$runtimeAgentId !== void 0 ? _this$runtimeAgentId : this.agentId;
669
+ if (!id) throw new Error("ProxiedCopilotRuntimeAgent: cannot make a runtime request without an agentId or runtimeAgentId.");
670
+ return id;
671
+ }
633
672
  get capabilities() {
634
673
  return this._capabilities;
635
674
  }
@@ -650,6 +689,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
650
689
  }
651
690
  if (!this.agentId || !this.threadId) return;
652
691
  if (typeof fetch === "undefined") return;
692
+ const routedId = this.routedAgentId();
653
693
  if (this.transport === "single") {
654
694
  if (!this.singleEndpointUrl) return;
655
695
  const headers = new Headers({
@@ -662,7 +702,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
662
702
  body: JSON.stringify({
663
703
  method: "agent/stop",
664
704
  params: {
665
- agentId: this.agentId,
705
+ agentId: routedId,
666
706
  threadId: this.threadId
667
707
  }
668
708
  }),
@@ -673,7 +713,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
673
713
  return;
674
714
  }
675
715
  if (!this.runtimeUrl) return;
676
- const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(this.agentId)}/stop/${encodeURIComponent(this.threadId)}`;
716
+ const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(routedId)}/stop/${encodeURIComponent(this.threadId)}`;
677
717
  const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
678
718
  const base = new URL(this.runtimeUrl, origin);
679
719
  const stopUrl = new URL(stopPath, base);
@@ -737,6 +777,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
737
777
  const cloned = new ProxiedCopilotRuntimeAgent({
738
778
  runtimeUrl: this.runtimeUrl,
739
779
  agentId: this.agentId,
780
+ runtimeAgentId: this.runtimeAgentId,
740
781
  description: this.description,
741
782
  headers: { ...this.headers },
742
783
  credentials: this.credentials,
@@ -755,6 +796,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
755
796
  }
756
797
  return cloned;
757
798
  }
799
+ /**
800
+ * Drop the delegate's cached `lastSeenEventId` for this thread so
801
+ * the next connect requests a full historical replay from the
802
+ * gateway. Used by `RunHandler.connectAgent` on a detected thread
803
+ * switch (the chat moved between threads, so its local
804
+ * messages/state are about to be cleared and need rebuilding from
805
+ * the gateway). Skipped on same-thread churn re-connects so the
806
+ * gateway can resume from the cursor instead.
807
+ *
808
+ * No-op for non-Intelligence runtime modes — the HTTP transport
809
+ * doesn't replay.
810
+ */
811
+ clearReplayCursor(threadId) {
812
+ var _delegate$clearReconn;
813
+ if (this.runtimeMode !== _copilotkit_shared.RUNTIME_MODE_INTELLIGENCE) return;
814
+ const delegate = this.delegate;
815
+ delegate === null || delegate === void 0 || (_delegate$clearReconn = delegate.clearReconnectCursor) === null || _delegate$clearReconn === void 0 || _delegate$clearReconn.call(delegate, threadId);
816
+ }
758
817
  async resolveDelegate() {
759
818
  await this.ensureRuntimeMode();
760
819
  if (!this.delegate) {
@@ -849,17 +908,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
849
908
  }
850
909
  createIntelligenceDelegate() {
851
910
  var _this$intelligence;
852
- if (!this.runtimeUrl || !this.agentId || !((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl)) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
911
+ const routedId = this.routedAgentId();
912
+ if (!this.runtimeUrl || !routedId || !((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl)) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
853
913
  return new IntelligenceAgent({
854
914
  url: this.intelligence.wsUrl,
855
915
  runtimeUrl: this.runtimeUrl,
856
- agentId: this.agentId,
916
+ agentId: routedId,
857
917
  headers: { ...this.headers },
858
918
  credentials: this.credentials
859
919
  });
860
920
  }
861
921
  syncDelegate(delegate) {
862
- delegate.agentId = this.agentId;
922
+ delegate.agentId = this.routedAgentId();
863
923
  delegate.description = this.description;
864
924
  delegate.threadId = this.threadId;
865
925
  delegate.setMessages(this.messages);
@@ -873,12 +933,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
873
933
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.connect(input))));
874
934
  }
875
935
  function _connectViaHttp(input) {
936
+ const routedId = this.routedAgentId();
876
937
  if (this.transport === "single") {
877
938
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
878
- const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: this.agentId });
939
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: routedId });
879
940
  return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
880
941
  }
881
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${this.agentId}/connect`, this.requestInit(input))));
942
+ return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${routedId}/connect`, this.requestInit(input))));
882
943
  }
883
944
  function _runViaDelegate(input) {
884
945
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.run(input))));
@@ -886,7 +947,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
886
947
  function _runViaHttp(input) {
887
948
  if (this.transport === "single") {
888
949
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
889
- const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.agentId });
950
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.routedAgentId() });
890
951
  return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
891
952
  }
892
953
  return withAbortErrorHandling(_superPropGet(_ProxiedCopilotRuntimeAgent.prototype, "run", this, 2)([input]));
@@ -1016,6 +1077,52 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1016
1077
  this.notifyAgentsChanged();
1017
1078
  }
1018
1079
  /**
1080
+ * Register a proxied agent that routes outbound runtime requests to an
1081
+ * existing runtime agent (`runtimeAgentId`) while exposing a distinct local
1082
+ * registry id (`agentId`). Throws if `agentId` is already taken by either a
1083
+ * local or runtime-discovered agent.
1084
+ *
1085
+ * Use this to mount multiple frontend agents against a single runtime
1086
+ * agent (e.g. a chat-1 / chat-2 pair both proxying to "default") without
1087
+ * implicit per-thread cloning. The returned `unregister` removes the proxy
1088
+ * from the registry and emits `onAgentsChanged`.
1089
+ */
1090
+ registerProxiedAgent({ agentId, runtimeAgentId }) {
1091
+ 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.`);
1092
+ const friends = this.core;
1093
+ const debug = friends.debug;
1094
+ const agent = new ProxiedCopilotRuntimeAgent({
1095
+ runtimeUrl: this._runtimeUrl,
1096
+ agentId,
1097
+ runtimeAgentId,
1098
+ transport: this._runtimeTransport,
1099
+ credentials: friends.credentials,
1100
+ runtimeMode: this._runtimeUrl ? this._runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected ? this._runtimeMode : "pending" : _copilotkit_shared.RUNTIME_MODE_SSE,
1101
+ intelligence: this._intelligence,
1102
+ debug: debug ? (0, _copilotkit_shared.resolveDebugConfig)(debug) : void 0
1103
+ });
1104
+ this.applyHeadersToAgent(agent);
1105
+ this.localAgents[agentId] = agent;
1106
+ this._agents = {
1107
+ ...this.localAgents,
1108
+ ...this.remoteAgents
1109
+ };
1110
+ this.notifyAgentsChanged();
1111
+ return {
1112
+ agent,
1113
+ unregister: () => {
1114
+ if (this.localAgents[agentId] === agent) {
1115
+ delete this.localAgents[agentId];
1116
+ this._agents = {
1117
+ ...this.localAgents,
1118
+ ...this.remoteAgents
1119
+ };
1120
+ this.notifyAgentsChanged();
1121
+ }
1122
+ }
1123
+ };
1124
+ }
1125
+ /**
1019
1126
  * Get an agent by ID
1020
1127
  */
1021
1128
  getAgent(id) {
@@ -1306,17 +1413,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1306
1413
  /**
1307
1414
  * Reload suggestions for a specific agent
1308
1415
  * This triggers generation of new suggestions based on current configs
1309
- *
1310
- * @param agentId - The consumer agent ID
1311
- * @param consumerAgent - Optional: the specific agent instance whose messages should be used
1312
- * for availability filtering and context. When running with per-thread clones, the thread
1313
- * clone holds the conversation messages; passing it here ensures dynamic suggestions fire
1314
- * after the first message even though the registry agent has an empty message list.
1315
1416
  */
1316
- reloadSuggestions(agentId, consumerAgent) {
1417
+ reloadSuggestions(agentId) {
1317
1418
  var _agent$messages$lengt, _agent$messages;
1318
1419
  this.clearSuggestions(agentId);
1319
- const agent = consumerAgent !== null && consumerAgent !== void 0 ? consumerAgent : this.core.getAgent(agentId);
1420
+ const agent = this.core.getAgent(agentId);
1320
1421
  const messageCount = (_agent$messages$lengt = agent === null || agent === void 0 || (_agent$messages = agent.messages) === null || _agent$messages === void 0 ? void 0 : _agent$messages.length) !== null && _agent$messages$lengt !== void 0 ? _agent$messages$lengt : 0;
1321
1422
  let hasAnySuggestions = false;
1322
1423
  for (const config of Object.values(this._suggestionsConfig)) {
@@ -1329,7 +1430,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1329
1430
  hasAnySuggestions = true;
1330
1431
  this.notifySuggestionsStartedLoading(agentId);
1331
1432
  }
1332
- this.generateSuggestions(suggestionId, config, agentId, agent);
1433
+ this.generateSuggestions(suggestionId, config, agentId);
1333
1434
  } else if (isStaticSuggestionsConfig(config)) this.addStaticSuggestions(suggestionId, config, agentId);
1334
1435
  }
1335
1436
  }
@@ -1358,13 +1459,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1358
1459
  /**
1359
1460
  * Generate suggestions using a provider agent
1360
1461
  */
1361
- async generateSuggestions(suggestionId, config, consumerAgentId, consumerAgent) {
1462
+ async generateSuggestions(suggestionId, config, consumerAgentId) {
1362
1463
  let agent = void 0;
1363
1464
  try {
1364
1465
  var _config$providerAgent, _this$_runningSuggest3, _config$minSuggestion, _config$maxSuggestion;
1365
1466
  const suggestionsProviderAgent = this.core.getAgent((_config$providerAgent = config.providerAgentId) !== null && _config$providerAgent !== void 0 ? _config$providerAgent : "default");
1366
1467
  if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
1367
- const suggestionsConsumerAgent = consumerAgent !== null && consumerAgent !== void 0 ? consumerAgent : this.core.getAgent(consumerAgentId);
1468
+ const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
1368
1469
  if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
1369
1470
  agent = suggestionsProviderAgent.clone();
1370
1471
  agent.threadId = suggestionId;
@@ -1601,6 +1702,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1601
1702
  _defineProperty(this, "_tools", []);
1602
1703
  _defineProperty(this, "_runAbortController", null);
1603
1704
  _defineProperty(this, "_runDepth", 0);
1705
+ _defineProperty(this, "_lastConnectedThreadId", null);
1604
1706
  }
1605
1707
  /**
1606
1708
  * Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal
@@ -1673,17 +1775,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1673
1775
  */
1674
1776
  async connectAgent({ agent }) {
1675
1777
  try {
1778
+ var _agent$threadId;
1779
+ const incomingThreadId = (_agent$threadId = agent.threadId) !== null && _agent$threadId !== void 0 ? _agent$threadId : null;
1780
+ const isFreshRestore = incomingThreadId !== this._lastConnectedThreadId;
1781
+ this._lastConnectedThreadId = incomingThreadId;
1676
1782
  await agent.detachActiveRun();
1677
- agent.setMessages([]);
1678
- agent.setState({});
1783
+ if (isFreshRestore) {
1784
+ agent.setMessages([]);
1785
+ agent.setState({});
1786
+ const proxied = agent;
1787
+ if (incomingThreadId && typeof proxied.clearReplayCursor === "function") proxied.clearReplayCursor(incomingThreadId);
1788
+ }
1679
1789
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1680
- await this._internal.notifySubscribers((subscriber) => {
1681
- var _subscriber$onAgentRu;
1682
- return (_subscriber$onAgentRu = subscriber.onAgentRunStarted) === null || _subscriber$onAgentRu === void 0 ? void 0 : _subscriber$onAgentRu.call(subscriber, {
1683
- copilotkit: this.core,
1684
- agent
1685
- });
1686
- }, "Subscriber onAgentRunStarted error:");
1687
1790
  const runAgentResult = await agent.connectAgent({
1688
1791
  forwardedProps: this._internal.properties,
1689
1792
  tools: this.buildFrontendTools(agent.agentId),
@@ -1714,14 +1817,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1714
1817
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1715
1818
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1716
1819
  if (agent.detachActiveRun) await agent.detachActiveRun();
1717
- this._internal.subscribeAgentToStateManager(agent);
1718
- await this._internal.notifySubscribers((subscriber) => {
1719
- var _subscriber$onAgentRu2;
1720
- return (_subscriber$onAgentRu2 = subscriber.onAgentRunStarted) === null || _subscriber$onAgentRu2 === void 0 ? void 0 : _subscriber$onAgentRu2.call(subscriber, {
1721
- copilotkit: this.core,
1722
- agent
1723
- });
1724
- }, "Subscriber onAgentRunStarted error:");
1725
1820
  const isTopLevel = this._runDepth === 0;
1726
1821
  let originalAbortRun;
1727
1822
  if (isTopLevel) {
@@ -1793,7 +1888,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1793
1888
  await this._internal.waitForPendingFrameworkUpdates();
1794
1889
  return await this.runAgent({ agent });
1795
1890
  }
1796
- this._internal.suggestionEngine.reloadSuggestions(agentId, agent);
1891
+ this._internal.suggestionEngine.reloadSuggestions(agentId);
1797
1892
  return runAgentResult;
1798
1893
  }
1799
1894
  /**
@@ -2222,21 +2317,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2222
2317
  initialize() {}
2223
2318
  /**
2224
2319
  * Subscribe to an agent's events to track state and messages.
2225
- *
2226
- * Registry agents (subscribed via `onAgentsChanged`) use the bare `agentId`
2227
- * key so that `unsubscribeFromAgent(agentId)` can remove them when they
2228
- * are replaced. Per-thread clones (subscribed via `subscribeAgentToStateManager`)
2229
- * pass `{ isClone: true }` to use a composite `agentId:threadId` key, keeping
2230
- * their subscription independent of the registry agent's.
2231
2320
  */
2232
- subscribeToAgent(agent, { isClone = false } = {}) {
2321
+ subscribeToAgent(agent) {
2233
2322
  if (!agent.agentId) return;
2234
2323
  const agentId = agent.agentId;
2235
- const subscriptionKey = isClone && agent.threadId ? `${agentId}:${agent.threadId}` : agentId;
2236
- const existingUnsubscribe = this.agentSubscriptions.get(subscriptionKey);
2324
+ const existingUnsubscribe = this.agentSubscriptions.get(agentId);
2237
2325
  if (existingUnsubscribe) {
2238
2326
  existingUnsubscribe();
2239
- this.agentSubscriptions.delete(subscriptionKey);
2327
+ this.agentSubscriptions.delete(agentId);
2240
2328
  }
2241
2329
  let revoked = false;
2242
2330
  let subRunId;
@@ -2283,16 +2371,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2283
2371
  this.handleNewMessage(agent, message, input ? effectiveInput(input) : void 0);
2284
2372
  }
2285
2373
  });
2286
- this.agentSubscriptions.set(subscriptionKey, () => {
2374
+ this.agentSubscriptions.set(agentId, () => {
2287
2375
  revoked = true;
2288
2376
  unsubscribe();
2289
2377
  });
2290
2378
  }
2291
2379
  /**
2292
- * Unsubscribe a registry agent's subscription (bare `agentId` key).
2293
- * Per-thread clone subscriptions use composite `agentId:threadId` keys and
2294
- * are replaced (not removed) by subsequent subscribeToAgent(agent, { isClone: true })
2295
- * calls for the same (agentId, threadId) pair.
2380
+ * Unsubscribe an agent's subscription.
2296
2381
  */
2297
2382
  unsubscribeFromAgent(agentId) {
2298
2383
  const unsubscribe = this.agentSubscriptions.get(agentId);
@@ -2583,7 +2668,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2583
2668
  if (agent.agentId) this.stateManager.subscribeToAgent(agent);
2584
2669
  });
2585
2670
  const currentAgentIds = new Set(Object.keys(agents));
2586
- for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) this.threadStoreRegistry.unregister(agentId);
2671
+ for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
2672
+ this.threadStoreRegistry.unregister(agentId);
2673
+ } catch (err) {
2674
+ console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
2675
+ }
2676
+ for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
2677
+ this.stateManager.unsubscribeFromAgent(agentId);
2678
+ } catch (err) {
2679
+ console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
2680
+ }
2587
2681
  this.previousAgentIds = currentAgentIds;
2588
2682
  } });
2589
2683
  }
@@ -2755,6 +2849,28 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2755
2849
  removeAgent__unsafe_dev_only(id) {
2756
2850
  this.agentRegistry.removeAgent__unsafe_dev_only(id);
2757
2851
  }
2852
+ /**
2853
+ * Register a proxied agent against an existing runtime agent. The proxy is
2854
+ * exposed under `agentId` (local registry id) and routes outbound runtime
2855
+ * requests to `runtimeAgentId`. Throws if `agentId` is already taken.
2856
+ *
2857
+ * Returns the minted proxy and an `unregister` handle for cleanup.
2858
+ *
2859
+ * Use this to mount multiple frontend agents against a single runtime
2860
+ * agent (e.g. one per chat window) without implicit per-thread cloning.
2861
+ *
2862
+ * @example
2863
+ * const { agent, unregister } = copilotkit.registerProxiedAgent({
2864
+ * agentId: "chat-1",
2865
+ * runtimeAgentId: "default",
2866
+ * });
2867
+ * // ... <CopilotChat agentId="chat-1" />
2868
+ * // on cleanup:
2869
+ * unregister();
2870
+ */
2871
+ registerProxiedAgent(params) {
2872
+ return this.agentRegistry.registerProxiedAgent(params);
2873
+ }
2758
2874
  getAgent(id) {
2759
2875
  return this.agentRegistry.getAgent(id);
2760
2876
  }
@@ -2989,9 +3105,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2989
3105
  getRunIdsForThread(agentId, threadId) {
2990
3106
  return this.stateManager.getRunIdsForThread(agentId, threadId);
2991
3107
  }
2992
- subscribeAgentToStateManager(agent) {
2993
- this.stateManager.subscribeToAgent(agent, { isClone: true });
2994
- }
2995
3108
  /**
2996
3109
  * Internal method used by RunHandler to build frontend tools
2997
3110
  */