@copilotkit/core 1.56.5 → 1.57.0-canary.1778078321

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,6 +502,7 @@ function withAbortErrorHandling(observable) {
502
502
  var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui_client.HttpAgent {
503
503
  runtimeUrl;
504
504
  credentials;
505
+ runtimeAgentId;
505
506
  transport;
506
507
  singleEndpointUrl;
507
508
  runtimeMode;
@@ -512,7 +513,8 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
512
513
  constructor(config) {
513
514
  const normalizedRuntimeUrl = config.runtimeUrl ? config.runtimeUrl.replace(/\/$/, "") : void 0;
514
515
  const transport = config.transport ?? "auto";
515
- const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(config.agentId ?? "")}/run`;
516
+ const routedId = config.runtimeAgentId ?? config.agentId ?? "";
517
+ const runUrl = transport === "single" ? normalizedRuntimeUrl ?? config.runtimeUrl ?? "" : `${normalizedRuntimeUrl ?? config.runtimeUrl}/agent/${encodeURIComponent(routedId)}/run`;
516
518
  if (!runUrl) throw new Error("ProxiedCopilotRuntimeAgent requires a runtimeUrl when transport is set to 'single'.");
517
519
  super({
518
520
  ...config,
@@ -520,6 +522,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
520
522
  });
521
523
  this.runtimeUrl = normalizedRuntimeUrl ?? config.runtimeUrl;
522
524
  this.credentials = config.credentials;
525
+ this.runtimeAgentId = config.runtimeAgentId;
523
526
  this.transport = transport;
524
527
  this.runtimeMode = config.runtimeMode ?? _copilotkit_shared.RUNTIME_MODE_SSE;
525
528
  this.intelligence = config.intelligence;
@@ -527,6 +530,21 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
527
530
  if (config.debug) this.debug = config.debug;
528
531
  if (this.transport === "single") this.singleEndpointUrl = this.runtimeUrl;
529
532
  }
533
+ /**
534
+ * The agent id used for outbound runtime requests — `runtimeAgentId` 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.runtimeAgentId ?? this.agentId;
545
+ if (!id) throw new Error("ProxiedCopilotRuntimeAgent: cannot make a runtime request without an agentId or runtimeAgentId.");
546
+ return id;
547
+ }
530
548
  get capabilities() {
531
549
  return this._capabilities;
532
550
  }
@@ -546,6 +564,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
546
564
  }
547
565
  if (!this.agentId || !this.threadId) return;
548
566
  if (typeof fetch === "undefined") return;
567
+ const routedId = this.routedAgentId();
549
568
  if (this.transport === "single") {
550
569
  if (!this.singleEndpointUrl) return;
551
570
  const headers = new Headers({
@@ -558,7 +577,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
558
577
  body: JSON.stringify({
559
578
  method: "agent/stop",
560
579
  params: {
561
- agentId: this.agentId,
580
+ agentId: routedId,
562
581
  threadId: this.threadId
563
582
  }
564
583
  }),
@@ -569,7 +588,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
569
588
  return;
570
589
  }
571
590
  if (!this.runtimeUrl) return;
572
- const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(this.agentId)}/stop/${encodeURIComponent(this.threadId)}`;
591
+ const stopPath = `${this.runtimeUrl}/agent/${encodeURIComponent(routedId)}/stop/${encodeURIComponent(this.threadId)}`;
573
592
  const origin = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
574
593
  const base = new URL(this.runtimeUrl, origin);
575
594
  const stopUrl = new URL(stopPath, base);
@@ -633,12 +652,13 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
633
652
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.connect(input))));
634
653
  }
635
654
  #connectViaHttp(input) {
655
+ const routedId = this.routedAgentId();
636
656
  if (this.transport === "single") {
637
657
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
638
- const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: this.agentId });
658
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/connect", { agentId: routedId });
639
659
  return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
640
660
  }
641
- return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${this.agentId}/connect`, this.requestInit(input))));
661
+ return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(`${this.runtimeUrl}/agent/${routedId}/connect`, this.requestInit(input))));
642
662
  }
643
663
  #runViaDelegate(input) {
644
664
  return (0, rxjs.defer)(() => (0, rxjs.from)(this.resolveDelegate())).pipe((0, rxjs_operators.switchMap)((delegate) => withAbortErrorHandling(delegate.run(input))));
@@ -646,7 +666,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
646
666
  #runViaHttp(input) {
647
667
  if (this.transport === "single") {
648
668
  if (!this.singleEndpointUrl) throw new Error("Single endpoint transport requires a runtimeUrl");
649
- const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.agentId });
669
+ const requestInit = this.createSingleRouteRequestInit(input, "agent/run", { agentId: this.routedAgentId() });
650
670
  return withAbortErrorHandling((0, _ag_ui_client.transformHttpEventStream)((0, _ag_ui_client.runHttpRequest)(this.singleEndpointUrl, requestInit)));
651
671
  }
652
672
  return withAbortErrorHandling(super.run(input));
@@ -655,6 +675,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
655
675
  const cloned = new ProxiedCopilotRuntimeAgent({
656
676
  runtimeUrl: this.runtimeUrl,
657
677
  agentId: this.agentId,
678
+ runtimeAgentId: this.runtimeAgentId,
658
679
  description: this.description,
659
680
  headers: { ...this.headers },
660
681
  credentials: this.credentials,
@@ -763,17 +784,18 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends _ag_ui
763
784
  };
764
785
  }
765
786
  createIntelligenceDelegate() {
766
- if (!this.runtimeUrl || !this.agentId || !this.intelligence?.wsUrl) throw new Error("Intelligence mode requires runtimeUrl, agentId, and intelligence websocket metadata");
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");
767
789
  return new IntelligenceAgent({
768
790
  url: this.intelligence.wsUrl,
769
791
  runtimeUrl: this.runtimeUrl,
770
- agentId: this.agentId,
792
+ agentId: routedId,
771
793
  headers: { ...this.headers },
772
794
  credentials: this.credentials
773
795
  });
774
796
  }
775
797
  syncDelegate(delegate) {
776
- delegate.agentId = this.agentId;
798
+ delegate.agentId = this.routedAgentId();
777
799
  delegate.description = this.description;
778
800
  delegate.threadId = this.threadId;
779
801
  delegate.setMessages(this.messages);
@@ -907,6 +929,52 @@ var AgentRegistry = class {
907
929
  this.notifyAgentsChanged();
908
930
  }
909
931
  /**
932
+ * Register a proxied agent that routes outbound runtime requests to an
933
+ * existing runtime agent (`runtimeAgentId`) 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, runtimeAgentId }) {
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
+ runtimeAgentId,
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
+ /**
910
978
  * Get an agent by ID
911
979
  */
912
980
  getAgent(id) {
@@ -1186,16 +1254,10 @@ var SuggestionEngine = class {
1186
1254
  /**
1187
1255
  * Reload suggestions for a specific agent
1188
1256
  * 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.
1195
1257
  */
1196
- reloadSuggestions(agentId, consumerAgent) {
1258
+ reloadSuggestions(agentId) {
1197
1259
  this.clearSuggestions(agentId);
1198
- const agent = consumerAgent ?? this.core.getAgent(agentId);
1260
+ const agent = this.core.getAgent(agentId);
1199
1261
  const messageCount = agent?.messages?.length ?? 0;
1200
1262
  let hasAnySuggestions = false;
1201
1263
  for (const config of Object.values(this._suggestionsConfig)) {
@@ -1208,7 +1270,7 @@ var SuggestionEngine = class {
1208
1270
  hasAnySuggestions = true;
1209
1271
  this.notifySuggestionsStartedLoading(agentId);
1210
1272
  }
1211
- this.generateSuggestions(suggestionId, config, agentId, agent);
1273
+ this.generateSuggestions(suggestionId, config, agentId);
1212
1274
  } else if (isStaticSuggestionsConfig(config)) this.addStaticSuggestions(suggestionId, config, agentId);
1213
1275
  }
1214
1276
  }
@@ -1236,12 +1298,12 @@ var SuggestionEngine = class {
1236
1298
  /**
1237
1299
  * Generate suggestions using a provider agent
1238
1300
  */
1239
- async generateSuggestions(suggestionId, config, consumerAgentId, consumerAgent) {
1301
+ async generateSuggestions(suggestionId, config, consumerAgentId) {
1240
1302
  let agent = void 0;
1241
1303
  try {
1242
1304
  const suggestionsProviderAgent = this.core.getAgent(config.providerAgentId ?? "default");
1243
1305
  if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${config.providerAgentId}`);
1244
- const suggestionsConsumerAgent = consumerAgent ?? this.core.getAgent(consumerAgentId);
1306
+ const suggestionsConsumerAgent = this.core.getAgent(consumerAgentId);
1245
1307
  if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
1246
1308
  agent = suggestionsProviderAgent.clone();
1247
1309
  agent.threadId = suggestionId;
@@ -1546,10 +1608,6 @@ var RunHandler = class {
1546
1608
  agent.setMessages([]);
1547
1609
  agent.setState({});
1548
1610
  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:");
1553
1611
  const runAgentResult = await agent.connectAgent({
1554
1612
  forwardedProps: this._internal.properties,
1555
1613
  tools: this.buildFrontendTools(agent.agentId),
@@ -1580,11 +1638,6 @@ var RunHandler = class {
1580
1638
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1581
1639
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1582
1640
  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:");
1588
1641
  const isTopLevel = this._runDepth === 0;
1589
1642
  let originalAbortRun;
1590
1643
  if (isTopLevel) {
@@ -1655,7 +1708,7 @@ var RunHandler = class {
1655
1708
  await this._internal.waitForPendingFrameworkUpdates();
1656
1709
  return await this.runAgent({ agent });
1657
1710
  }
1658
- this._internal.suggestionEngine.reloadSuggestions(agentId, agent);
1711
+ this._internal.suggestionEngine.reloadSuggestions(agentId);
1659
1712
  return runAgentResult;
1660
1713
  }
1661
1714
  /**
@@ -2067,21 +2120,14 @@ var StateManager = class {
2067
2120
  initialize() {}
2068
2121
  /**
2069
2122
  * 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.
2076
2123
  */
2077
- subscribeToAgent(agent, { isClone = false } = {}) {
2124
+ subscribeToAgent(agent) {
2078
2125
  if (!agent.agentId) return;
2079
2126
  const agentId = agent.agentId;
2080
- const subscriptionKey = isClone && agent.threadId ? `${agentId}:${agent.threadId}` : agentId;
2081
- const existingUnsubscribe = this.agentSubscriptions.get(subscriptionKey);
2127
+ const existingUnsubscribe = this.agentSubscriptions.get(agentId);
2082
2128
  if (existingUnsubscribe) {
2083
2129
  existingUnsubscribe();
2084
- this.agentSubscriptions.delete(subscriptionKey);
2130
+ this.agentSubscriptions.delete(agentId);
2085
2131
  }
2086
2132
  let revoked = false;
2087
2133
  let subRunId;
@@ -2125,16 +2171,13 @@ var StateManager = class {
2125
2171
  this.handleNewMessage(agent, message, input ? effectiveInput(input) : void 0);
2126
2172
  }
2127
2173
  });
2128
- this.agentSubscriptions.set(subscriptionKey, () => {
2174
+ this.agentSubscriptions.set(agentId, () => {
2129
2175
  revoked = true;
2130
2176
  unsubscribe();
2131
2177
  });
2132
2178
  }
2133
2179
  /**
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.
2180
+ * Unsubscribe an agent's subscription.
2138
2181
  */
2139
2182
  unsubscribeFromAgent(agentId) {
2140
2183
  const unsubscribe = this.agentSubscriptions.get(agentId);
@@ -2265,6 +2308,61 @@ var StateManager = class {
2265
2308
  }
2266
2309
  };
2267
2310
 
2311
+ //#endregion
2312
+ //#region src/core/thread-store-registry.ts
2313
+ var ThreadStoreRegistry = class {
2314
+ _stores = {};
2315
+ _snapshot = null;
2316
+ constructor(core) {
2317
+ this.core = core;
2318
+ }
2319
+ register(agentId, store) {
2320
+ if (agentId in this._stores) {
2321
+ const prevStore = this._stores[agentId];
2322
+ delete this._stores[agentId];
2323
+ this._snapshot = null;
2324
+ this.notifyUnregistered(agentId, prevStore).catch((err) => {
2325
+ console.error("ThreadStoreRegistry notifyUnregistered failed:", err);
2326
+ });
2327
+ }
2328
+ this._stores[agentId] = store;
2329
+ this._snapshot = null;
2330
+ this.notifyRegistered(agentId, store).catch((err) => {
2331
+ console.error("ThreadStoreRegistry notifyRegistered failed:", err);
2332
+ });
2333
+ }
2334
+ unregister(agentId) {
2335
+ if (!(agentId in this._stores)) return;
2336
+ const prevStore = this._stores[agentId];
2337
+ delete this._stores[agentId];
2338
+ this._snapshot = null;
2339
+ this.notifyUnregistered(agentId, prevStore).catch((err) => {
2340
+ console.error("ThreadStoreRegistry notifyUnregistered failed:", err);
2341
+ });
2342
+ }
2343
+ get(agentId) {
2344
+ return this._stores[agentId];
2345
+ }
2346
+ getAll() {
2347
+ if (this._snapshot === null) this._snapshot = Object.freeze({ ...this._stores });
2348
+ return this._snapshot;
2349
+ }
2350
+ async notifyRegistered(agentId, store) {
2351
+ await this.core.notifySubscribers((subscriber) => subscriber.onThreadStoreRegistered?.({
2352
+ copilotkit: this.core,
2353
+ agentId,
2354
+ store
2355
+ }), "Subscriber onThreadStoreRegistered error:");
2356
+ }
2357
+ async notifyUnregistered(agentId, prevStore) {
2358
+ await this.core.notifySubscribers((subscriber) => subscriber.onThreadStoreUnregistered?.({
2359
+ copilotkit: this.core,
2360
+ agentId,
2361
+ prevStore
2362
+ }), "Subscriber onThreadStoreUnregistered error:");
2363
+ }
2364
+ };
2365
+
2268
2366
  //#endregion
2269
2367
  //#region src/core/core.ts
2270
2368
  let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode) {
@@ -2333,6 +2431,14 @@ var CopilotKitCore = class {
2333
2431
  suggestionEngine;
2334
2432
  runHandler;
2335
2433
  stateManager;
2434
+ threadStoreRegistry;
2435
+ /**
2436
+ * Tracks the agent IDs from the most recent `onAgentsChanged` notification.
2437
+ * Used to gate thread-store auto-unregister so the FIRST empty-agents
2438
+ * notification (before published agents are merged in) does not rip out a
2439
+ * store that was registered prior to that initial notification.
2440
+ */
2441
+ previousAgentIds = /* @__PURE__ */ new Set();
2336
2442
  constructor({ runtimeUrl, runtimeTransport = "auto", headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
2337
2443
  this._headers = headers;
2338
2444
  this._credentials = credentials;
@@ -2343,16 +2449,30 @@ var CopilotKitCore = class {
2343
2449
  this.suggestionEngine = new SuggestionEngine(this);
2344
2450
  this.runHandler = new RunHandler(this);
2345
2451
  this.stateManager = new StateManager(this);
2452
+ this.threadStoreRegistry = new ThreadStoreRegistry(this);
2346
2453
  this.agentRegistry.initialize(agents__unsafe_dev_only);
2347
2454
  this.runHandler.initialize(tools);
2348
2455
  this.suggestionEngine.initialize(suggestionsConfig);
2349
2456
  this.stateManager.initialize();
2350
2457
  this.agentRegistry.setRuntimeTransport(runtimeTransport);
2351
2458
  this.agentRegistry.setRuntimeUrl(runtimeUrl);
2459
+ this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
2352
2460
  this.subscribe({ onAgentsChanged: ({ agents }) => {
2353
2461
  Object.values(agents).forEach((agent) => {
2354
2462
  if (agent.agentId) this.stateManager.subscribeToAgent(agent);
2355
2463
  });
2464
+ 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
+ }
2475
+ this.previousAgentIds = currentAgentIds;
2356
2476
  } });
2357
2477
  }
2358
2478
  /**
@@ -2514,6 +2634,28 @@ var CopilotKitCore = class {
2514
2634
  removeAgent__unsafe_dev_only(id) {
2515
2635
  this.agentRegistry.removeAgent__unsafe_dev_only(id);
2516
2636
  }
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 `runtimeAgentId`. 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
+ * runtimeAgentId: "default",
2651
+ * });
2652
+ * // ... <CopilotChat agentId="chat-1" />
2653
+ * // on cleanup:
2654
+ * unregister();
2655
+ */
2656
+ registerProxiedAgent(params) {
2657
+ return this.agentRegistry.registerProxiedAgent(params);
2658
+ }
2517
2659
  getAgent(id) {
2518
2660
  return this.agentRegistry.getAgent(id);
2519
2661
  }
@@ -2527,6 +2669,21 @@ var CopilotKitCore = class {
2527
2669
  this.contextStore.removeContext(id);
2528
2670
  }
2529
2671
  /**
2672
+ * Thread store registry (delegated to ThreadStoreRegistry)
2673
+ */
2674
+ registerThreadStore(agentId, store) {
2675
+ this.threadStoreRegistry.register(agentId, store);
2676
+ }
2677
+ unregisterThreadStore(agentId) {
2678
+ this.threadStoreRegistry.unregister(agentId);
2679
+ }
2680
+ getThreadStore(agentId) {
2681
+ return this.threadStoreRegistry.get(agentId);
2682
+ }
2683
+ getThreadStores() {
2684
+ return this.threadStoreRegistry.getAll();
2685
+ }
2686
+ /**
2530
2687
  * Suggestions management (delegated to SuggestionEngine)
2531
2688
  */
2532
2689
  addSuggestionsConfig(config) {
@@ -2732,9 +2889,6 @@ var CopilotKitCore = class {
2732
2889
  getRunIdsForThread(agentId, threadId) {
2733
2890
  return this.stateManager.getRunIdsForThread(agentId, threadId);
2734
2891
  }
2735
- subscribeAgentToStateManager(agent) {
2736
- this.stateManager.subscribeToAgent(agent, { isClone: true });
2737
- }
2738
2892
  /**
2739
2893
  * Internal method used by RunHandler to build frontend tools
2740
2894
  */
@@ -3611,6 +3765,11 @@ function createThreadStore(environment) {
3611
3765
  setContext(context) {
3612
3766
  store.dispatch(threadAdapterEvents.contextChanged({ context }));
3613
3767
  },
3768
+ refresh() {
3769
+ const { sessionId, context } = store.getState();
3770
+ if (!context) return;
3771
+ store.dispatch(threadRestEvents.listRequested({ sessionId }));
3772
+ },
3614
3773
  fetchNextPage() {
3615
3774
  store.dispatch(threadAdapterEvents.fetchNextPageRequested());
3616
3775
  },
@@ -3645,6 +3804,13 @@ const ɵselectThreadsIsLoading = selectThreadsIsLoading;
3645
3804
  const ɵselectThreadsError = selectThreadsError;
3646
3805
  const ɵselectHasNextPage = selectHasNextPage;
3647
3806
  const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
3807
+ /**
3808
+ * Number of consecutive WebSocket connection failures after which the
3809
+ * threads channel tears itself down rather than retrying indefinitely.
3810
+ * Exposed for tests so they can assert teardown semantics without
3811
+ * hardcoding the threshold separately from production.
3812
+ */
3813
+ const ɵMAX_SOCKET_RETRIES = MAX_SOCKET_RETRIES;
3648
3814
 
3649
3815
  //#endregion
3650
3816
  exports.AgentRegistry = AgentRegistry;
@@ -3672,6 +3838,7 @@ exports.on = on;
3672
3838
  exports.parseToolArguments = parseToolArguments;
3673
3839
  exports.props = props;
3674
3840
  exports.select = select;
3841
+ exports.ɵMAX_SOCKET_RETRIES = ɵMAX_SOCKET_RETRIES;
3675
3842
  exports.ɵcreateThreadStore = createThreadStore;
3676
3843
  exports.ɵjoinPhoenixChannel$ = ɵjoinPhoenixChannel$;
3677
3844
  exports.ɵobservePhoenixEvent$ = ɵobservePhoenixEvent$;