@copilotkit/core 1.69.2 → 1.70.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.umd.js CHANGED
@@ -166,6 +166,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
166
166
 
167
167
  //#endregion
168
168
  //#region src/intelligence-agent.ts
169
+ const globalFetch = (...args) => fetch(...args);
169
170
  const CLIENT_AG_UI_EVENT = "ag_ui_event";
170
171
  const REPLAY_COMPLETE_EVENT = "replay_complete";
171
172
  const STREAM_IDLE_EVENT = "stream_idle";
@@ -393,7 +394,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
393
394
  requestJoinCredentials$(mode, input, replayCursor) {
394
395
  return (0, rxjs.defer)(async () => {
395
396
  try {
396
- const response = await fetch(this.buildRuntimeUrl(mode), {
397
+ var _this$config$fetch;
398
+ const response = await ((_this$config$fetch = this.config.fetch) !== null && _this$config$fetch !== void 0 ? _this$config$fetch : globalFetch)(this.buildRuntimeUrl(mode), {
397
399
  method: "POST",
398
400
  headers: {
399
401
  "Content-Type": "application/json",
@@ -641,7 +643,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
641
643
  const message = body === null || body === void 0 ? void 0 : body.message;
642
644
  if (typeof message === "string" && message.trim().length > 0) detail = message.trim();
643
645
  } catch (_unused) {}
644
- return new Error(detail ? `${base}: ${detail}` : base);
646
+ const error = new Error(detail ? `${base}: ${detail}` : base);
647
+ error.runtimeInfoStatus = response.status;
648
+ return error;
649
+ }
650
+ function isRuntimeInfoRequestError(error) {
651
+ return typeof error === "object" && error !== null && typeof error.runtimeInfoStatus === "number";
645
652
  }
646
653
 
647
654
  //#endregion
@@ -711,12 +718,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
711
718
  function isZodError(error) {
712
719
  return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
713
720
  }
714
- function isAbortError$1(error) {
721
+ function isAbortError$2(error) {
715
722
  return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
716
723
  }
717
724
  function withAbortErrorHandling(observable) {
718
725
  return observable.pipe((0, rxjs_operators.catchError)((error) => {
719
- if (isZodError(error) || isAbortError$1(error)) return rxjs.EMPTY;
726
+ if (isZodError(error) || isAbortError$2(error)) return rxjs.EMPTY;
720
727
  throw error;
721
728
  }));
722
729
  }
@@ -894,7 +901,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
894
901
  runtimeMode: this.runtimeMode,
895
902
  intelligence: this.intelligence,
896
903
  capabilities: this._capabilities,
897
- debug: this.debug
904
+ debug: this.debug,
905
+ fetch: this.fetch
898
906
  });
899
907
  cloned.threadId = this.threadId;
900
908
  cloned.setState(this.state);
@@ -968,7 +976,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
968
976
  url = `${this.runtimeUrl}/info`;
969
977
  init = {};
970
978
  }
971
- const response = await fetch(url, {
979
+ const response = await this.fetch(url, {
972
980
  ...init,
973
981
  headers,
974
982
  ...this.credentials ? { credentials: this.credentials } : {}
@@ -978,7 +986,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
978
986
  }
979
987
  async fetchRuntimeInfoAutoDetect(headers) {
980
988
  try {
981
- const response = await fetch(`${this.runtimeUrl}/info`, {
989
+ const response = await this.fetch(`${this.runtimeUrl}/info`, {
982
990
  headers: { ...headers },
983
991
  ...this.credentials ? { credentials: this.credentials } : {}
984
992
  });
@@ -989,7 +997,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
989
997
  } catch (_unused) {}
990
998
  const singleHeaders = { ...headers };
991
999
  if (!singleHeaders["Content-Type"]) singleHeaders["Content-Type"] = "application/json";
992
- const response = await fetch(this.runtimeUrl, {
1000
+ const response = await this.fetch(this.runtimeUrl, {
993
1001
  method: "POST",
994
1002
  headers: singleHeaders,
995
1003
  body: JSON.stringify({ method: "info" }),
@@ -1032,7 +1040,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1032
1040
  runtimeUrl: this.runtimeUrl,
1033
1041
  agentId: routedId,
1034
1042
  headers: { ...this.headers },
1035
- credentials: this.credentials
1043
+ credentials: this.credentials,
1044
+ fetch: this.fetch
1036
1045
  });
1037
1046
  }
1038
1047
  syncDelegate(delegate) {
@@ -1072,16 +1081,44 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1072
1081
  return withAbortErrorHandling(_superPropGet(_ProxiedCopilotRuntimeAgent.prototype, "run", this, 2)([input]));
1073
1082
  }
1074
1083
 
1084
+ //#endregion
1085
+ //#region src/utils/abort-error.ts
1086
+ const ABORT_MESSAGES = new Set([
1087
+ "Fetch is aborted",
1088
+ "signal is aborted without reason",
1089
+ "component unmounted"
1090
+ ]);
1091
+ function isAbortError$1(error) {
1092
+ if (typeof error !== "object" || error === null) return false;
1093
+ const { name, message } = error;
1094
+ if (name === "AbortError") return true;
1095
+ return typeof message === "string" && ABORT_MESSAGES.has(message);
1096
+ }
1097
+
1098
+ //#endregion
1099
+ //#region src/utils/runtime-request.ts
1100
+ const RUNTIME_REQUEST_WATCHDOG_MS = 1e4;
1101
+ function runtimeRequestMeta(init) {
1102
+ return init === null || init === void 0 ? void 0 : init.ɵruntimeRequest;
1103
+ }
1104
+
1075
1105
  //#endregion
1076
1106
  //#region src/core/agent-registry.ts
1077
1107
  /** Maximum wait for optional Inspector metadata before degrading to absence. */
1078
1108
  const INSPECTOR_METADATA_REQUEST_TIMEOUT_MS = 5e3;
1109
+ const ɵRUNTIME_PROBE_TIMEOUT_MS = 5e3;
1110
+ function classifyRuntimeRequestFailure(error, meta) {
1111
+ if (meta === null || meta === void 0 ? void 0 : meta.nonCritical) return "ignored";
1112
+ if (isAbortError$1(error) && !(meta === null || meta === void 0 ? void 0 : meta.timedOut)) return "aborted";
1113
+ return "failed";
1114
+ }
1079
1115
  /** Build case-insensitive JSON headers without mutating the Core snapshot. */
1080
1116
  function withJsonContentType(headers) {
1081
1117
  const requestHeaders = new Headers(headers);
1082
1118
  if (!requestHeaders.has("content-type")) requestHeaders.set("content-type", "application/json");
1083
1119
  return requestHeaders;
1084
1120
  }
1121
+ const RUNTIME_ENTITLEMENT_RETRY_DELAY_MS = 5e3;
1085
1122
  /**
1086
1123
  * Manages agent registration, lifecycle, and runtime connectivity for CopilotKitCore.
1087
1124
  * Handles both local development agents and remote runtime agents.
@@ -1092,8 +1129,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1092
1129
  _defineProperty(this, "_agents", {});
1093
1130
  _defineProperty(this, "localAgents", {});
1094
1131
  _defineProperty(this, "remoteAgents", {});
1132
+ _defineProperty(this, "mintedThreadIds", /* @__PURE__ */ new WeakMap());
1095
1133
  _defineProperty(this, "_runtimeUrl", void 0);
1096
1134
  _defineProperty(this, "_connectionInFlight", void 0);
1135
+ _defineProperty(this, "_runtimeConnectionGeneration", 0);
1136
+ _defineProperty(this, "_activeRuntimeConnectionAttempt", void 0);
1137
+ _defineProperty(this, "_runtimeEntitlementRetryTimer", void 0);
1138
+ _defineProperty(this, "_runtimeEntitlementRetryAttemptedKey", void 0);
1139
+ _defineProperty(this, "_runtimeEntitlementRetryPendingKey", void 0);
1097
1140
  _defineProperty(this, "_runtimeVersion", void 0);
1098
1141
  _defineProperty(this, "_runtimeConnectionStatus", CopilotKitCoreRuntimeConnectionStatus.Disconnected);
1099
1142
  _defineProperty(this, "_runtimeTransport", "auto");
@@ -1116,7 +1159,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1116
1159
  _defineProperty(this, "_a2uiAgents", void 0);
1117
1160
  _defineProperty(this, "_openGenerativeUIEnabled", false);
1118
1161
  _defineProperty(this, "_licenseStatus", void 0);
1162
+ _defineProperty(this, "_runtimeEntitlements", void 0);
1119
1163
  _defineProperty(this, "_telemetryDisabled", false);
1164
+ _defineProperty(this, "remoteAgentConnections", /* @__PURE__ */ new WeakMap());
1165
+ _defineProperty(this, "runtimeFetch", void 0);
1166
+ _defineProperty(this, "runtimeProbeInFlight", false);
1167
+ _defineProperty(this, "runtimeProbeToken", 0);
1168
+ _defineProperty(this, "runtimeProbeAbortController", void 0);
1169
+ _defineProperty(this, "runtimeRecoveryRunning", false);
1170
+ _defineProperty(this, "runtimeRecoveryPending", false);
1171
+ _defineProperty(this, "runtimeHealthGeneration", 0);
1120
1172
  _defineProperty(this, "agentOwnHeaders", /* @__PURE__ */ new WeakMap());
1121
1173
  }
1122
1174
  /**
@@ -1171,6 +1223,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1171
1223
  get licenseStatus() {
1172
1224
  return this._licenseStatus;
1173
1225
  }
1226
+ /** Structured Runtime entitlement authority advertised by `/info`. */
1227
+ get runtimeEntitlements() {
1228
+ return this._runtimeEntitlements;
1229
+ }
1230
+ get runtimeEntitlementRetryPending() {
1231
+ return this._runtimeEntitlementRetryPendingKey === this.runtimeConnectionKey();
1232
+ }
1174
1233
  get telemetryDisabled() {
1175
1234
  return this._telemetryDisabled;
1176
1235
  }
@@ -1181,6 +1240,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1181
1240
  this.localAgents = this.assignAgentIds(agents);
1182
1241
  this.applyHeadersToAgents(this.localAgents);
1183
1242
  this.applyCredentialsToAgents(this.localAgents);
1243
+ this.applyRuntimeFetchToAgents(this.localAgents);
1184
1244
  this._agents = this.localAgents;
1185
1245
  }
1186
1246
  /**
@@ -1190,9 +1250,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1190
1250
  const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
1191
1251
  if (this._runtimeUrl === normalizedRuntimeUrl) return;
1192
1252
  this.invalidateInspectorMetadataConnection();
1253
+ this.abandonRuntimeHealthProbe();
1254
+ this.resetRuntimeEntitlementRetry();
1255
+ this._licenseStatus = void 0;
1256
+ this._runtimeEntitlements = void 0;
1193
1257
  this._runtimeUrl = normalizedRuntimeUrl;
1194
1258
  if (options === null || options === void 0 ? void 0 : options.deferConnection) return;
1195
- this.updateRuntimeConnection();
1259
+ this.updateRuntimeConnection({ preserveOnFailure: this.hasLiveRuntimeKnowledgeToProtect() });
1196
1260
  }
1197
1261
  /**
1198
1262
  * Start the initial runtime connection if it has not been started yet.
@@ -1214,9 +1278,41 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1214
1278
  setRuntimeTransport(runtimeTransport) {
1215
1279
  if (this._requestedTransport === runtimeTransport) return;
1216
1280
  this.invalidateInspectorMetadataConnection();
1281
+ this.abandonRuntimeHealthProbe();
1282
+ this.resetRuntimeEntitlementRetry();
1217
1283
  this._requestedTransport = runtimeTransport;
1218
1284
  this._runtimeTransport = runtimeTransport;
1219
- this.updateRuntimeConnection();
1285
+ this.updateRuntimeConnection({ preserveOnFailure: this.hasLiveRuntimeKnowledgeToProtect() });
1286
+ }
1287
+ hasLiveRuntimeKnowledgeToProtect() {
1288
+ if (Object.keys(this.remoteAgents).length === 0) return false;
1289
+ return this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected;
1290
+ }
1291
+ reconcileRecoveredAgents(reported) {
1292
+ const merged = {
1293
+ ...this.remoteAgents,
1294
+ ...reported
1295
+ };
1296
+ if (Object.keys(reported).length === 0) return merged;
1297
+ for (const [id, agent] of Object.entries(merged)) {
1298
+ if (Object.prototype.hasOwnProperty.call(reported, id)) continue;
1299
+ if (this.carriesConversationState(agent)) continue;
1300
+ delete merged[id];
1301
+ }
1302
+ return merged;
1303
+ }
1304
+ carriesConversationState(agent) {
1305
+ if (agent.messages.length > 0) return true;
1306
+ const mintedThreadId = this.mintedThreadIds.get(agent);
1307
+ return mintedThreadId === void 0 || agent.threadId !== mintedThreadId;
1308
+ }
1309
+ abandonRuntimeHealthProbe() {
1310
+ var _this$runtimeProbeAbo;
1311
+ this.runtimeProbeToken += 1;
1312
+ this.runtimeProbeInFlight = false;
1313
+ this.runtimeHealthGeneration += 1;
1314
+ (_this$runtimeProbeAbo = this.runtimeProbeAbortController) === null || _this$runtimeProbeAbo === void 0 || _this$runtimeProbeAbo.abort();
1315
+ this.runtimeProbeAbortController = void 0;
1220
1316
  }
1221
1317
  /**
1222
1318
  * Set all agents at once (for development use)
@@ -1232,6 +1328,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1232
1328
  };
1233
1329
  this.applyHeadersToAgents(this._agents);
1234
1330
  this.applyCredentialsToAgents(this._agents);
1331
+ this.applyRuntimeFetchToAgents(this._agents);
1235
1332
  this.notifyAgentsChanged();
1236
1333
  }
1237
1334
  /**
@@ -1242,6 +1339,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1242
1339
  this.localAgents[id] = agent;
1243
1340
  this.applyHeadersToAgent(agent);
1244
1341
  this.applyCredentialsToAgent(agent);
1342
+ this.applyRuntimeFetchToAgent(agent);
1245
1343
  this._agents = {
1246
1344
  ...this.localAgents,
1247
1345
  ...this.remoteAgents
@@ -1285,6 +1383,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1285
1383
  debug: debug ? (0, _copilotkit_shared.resolveDebugConfig)(debug) : void 0
1286
1384
  });
1287
1385
  this.applyHeadersToAgent(agent);
1386
+ this.applyRuntimeFetchToAgent(agent);
1288
1387
  this.localAgents[agentId] = agent;
1289
1388
  this._agents = {
1290
1389
  ...this.localAgents,
@@ -1350,6 +1449,46 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1350
1449
  this.applyCredentialsToAgent(agent);
1351
1450
  });
1352
1451
  }
1452
+ createRuntimeFetch() {
1453
+ if (!this.runtimeFetch) this.runtimeFetch = (async (input, init) => {
1454
+ const meta = () => runtimeRequestMeta(init);
1455
+ const watchdog = this.armRuntimeRequestWatchdog(meta());
1456
+ try {
1457
+ var _meta;
1458
+ const response = await fetch(input, init);
1459
+ watchdog.clear();
1460
+ this.handleRuntimeRequestOutcome(response.ok ? "ok" : ((_meta = meta()) === null || _meta === void 0 ? void 0 : _meta.nonCritical) ? "ignored" : "failed", watchdog.checked);
1461
+ return response;
1462
+ } catch (error) {
1463
+ watchdog.clear();
1464
+ this.handleRuntimeRequestOutcome(classifyRuntimeRequestFailure(error, meta()), watchdog.checked);
1465
+ throw error;
1466
+ }
1467
+ });
1468
+ return this.runtimeFetch;
1469
+ }
1470
+ armRuntimeRequestWatchdog(meta) {
1471
+ if (typeof window === "undefined" || (meta === null || meta === void 0 ? void 0 : meta.nonCritical) || (meta === null || meta === void 0 ? void 0 : meta.selfBounded)) return {
1472
+ clear: () => {},
1473
+ checked: () => false
1474
+ };
1475
+ let checked = false;
1476
+ const timeoutId = setTimeout(() => {
1477
+ checked = this.handleRuntimeRequestOutcome("failed");
1478
+ }, RUNTIME_REQUEST_WATCHDOG_MS);
1479
+ return {
1480
+ clear: () => clearTimeout(timeoutId),
1481
+ checked: () => checked
1482
+ };
1483
+ }
1484
+ applyRuntimeFetchToAgent(agent) {
1485
+ if (agent instanceof ProxiedCopilotRuntimeAgent) agent.fetch = this.createRuntimeFetch();
1486
+ }
1487
+ applyRuntimeFetchToAgents(agents) {
1488
+ Object.values(agents).forEach((agent) => {
1489
+ this.applyRuntimeFetchToAgent(agent);
1490
+ });
1491
+ }
1353
1492
  /** Refresh metadata after the Core header snapshot changes. */
1354
1493
  handleHeadersChanged() {
1355
1494
  this.inspectorMetadataHeadersGeneration += 1;
@@ -1487,18 +1626,114 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1487
1626
  console.error("Subscriber onInspectorMetadataChanged queue error:", error);
1488
1627
  });
1489
1628
  }
1629
+ setRuntimeConnectionStatus(status) {
1630
+ this._runtimeConnectionStatus = status;
1631
+ this.runtimeHealthGeneration += 1;
1632
+ }
1633
+ handleRuntimeRequestOutcome(outcome, alreadyChecked = () => false) {
1634
+ if (outcome === "aborted" || outcome === "ignored") return false;
1635
+ if (outcome === "failed" && alreadyChecked()) return false;
1636
+ if (typeof window === "undefined") return false;
1637
+ if (!this._runtimeUrl) return false;
1638
+ if (outcome === "ok") {
1639
+ this.runtimeHealthGeneration += 1;
1640
+ if (this.runtimeRecoveryRunning) this.runtimeRecoveryPending = true;
1641
+ if (this._runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Error) this.recoverRuntimeConnection();
1642
+ return false;
1643
+ }
1644
+ if (this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return false;
1645
+ if (this.runtimeProbeInFlight) return false;
1646
+ this.probeRuntimeReachability();
1647
+ return true;
1648
+ }
1649
+ async fetchRuntimeInfoWithTimeout(abortController, runtimeUrl = this.runtimeUrl, runtimeTransport = this._runtimeTransport) {
1650
+ if (!runtimeUrl) throw new Error("Runtime URL is not set");
1651
+ let timeoutId;
1652
+ const request = this.fetchRuntimeInfo(runtimeUrl, runtimeTransport, abortController.signal);
1653
+ request.catch(() => {});
1654
+ try {
1655
+ const timedOut = new Promise((_resolve, reject) => {
1656
+ timeoutId = setTimeout(() => {
1657
+ abortController.abort();
1658
+ reject(/* @__PURE__ */ new Error(`Runtime did not answer within ${ɵRUNTIME_PROBE_TIMEOUT_MS}ms`));
1659
+ }, ɵRUNTIME_PROBE_TIMEOUT_MS);
1660
+ });
1661
+ return await Promise.race([request, timedOut]);
1662
+ } finally {
1663
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
1664
+ }
1665
+ }
1666
+ async probeRuntimeReachability() {
1667
+ const generation = this.runtimeHealthGeneration;
1668
+ const token = ++this.runtimeProbeToken;
1669
+ this.runtimeProbeInFlight = true;
1670
+ const abortController = new AbortController();
1671
+ this.runtimeProbeAbortController = abortController;
1672
+ try {
1673
+ await this.fetchRuntimeInfoWithTimeout(abortController);
1674
+ } catch (error) {
1675
+ if (generation !== this.runtimeHealthGeneration) return;
1676
+ await this.markRuntimeUnreachable(error instanceof Error ? error : new Error(String(error)));
1677
+ } finally {
1678
+ if (this.runtimeProbeAbortController === abortController) this.runtimeProbeAbortController = void 0;
1679
+ if (this.runtimeProbeToken === token) this.runtimeProbeInFlight = false;
1680
+ }
1681
+ }
1682
+ async markRuntimeUnreachable(error) {
1683
+ this.setRuntimeConnectionStatus(CopilotKitCoreRuntimeConnectionStatus.Error);
1684
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Error);
1685
+ const runtimeStatus = isRuntimeInfoRequestError(error) ? error.runtimeInfoStatus : void 0;
1686
+ _copilotkit_shared.logger.warn(runtimeStatus === void 0 ? `Runtime did not answer the identification request (${this._runtimeUrl}/info): ${error.message}. The runtime appears to be unreachable.` : `Runtime answered the identification request with status ${runtimeStatus} (${this._runtimeUrl}/info): ${error.message}. The runtime is reachable but refused the request — check credentials and authorisation before addresses and ports.`);
1687
+ await this.core.emitError({
1688
+ error,
1689
+ code: CopilotKitCoreErrorCode.RUNTIME_INFO_FETCH_FAILED,
1690
+ context: {
1691
+ runtimeUrl: this._runtimeUrl,
1692
+ reason: runtimeStatus === void 0 ? "no-answer" : "answered",
1693
+ ...runtimeStatus === void 0 ? {} : { runtimeStatus }
1694
+ }
1695
+ });
1696
+ }
1697
+ async recoverRuntimeConnection() {
1698
+ if (this.runtimeRecoveryRunning) {
1699
+ this.runtimeRecoveryPending = true;
1700
+ return;
1701
+ }
1702
+ this.runtimeRecoveryRunning = true;
1703
+ try {
1704
+ do {
1705
+ this.runtimeRecoveryPending = false;
1706
+ await this.updateRuntimeConnection({
1707
+ preserveOnFailure: true,
1708
+ recovery: true
1709
+ });
1710
+ } while (this.runtimeRecoveryPending && this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected);
1711
+ } finally {
1712
+ this.runtimeRecoveryRunning = false;
1713
+ this.runtimeRecoveryPending = false;
1714
+ }
1715
+ }
1490
1716
  /**
1491
1717
  * Update runtime connection and fetch remote agents
1492
1718
  */
1493
- async updateRuntimeConnection() {
1494
- var _this$_runtimeUrl;
1719
+ async updateRuntimeConnection(options) {
1495
1720
  if (typeof window === "undefined") return;
1496
- const key = `${(_this$_runtimeUrl = this._runtimeUrl) !== null && _this$_runtimeUrl !== void 0 ? _this$_runtimeUrl : ""}::${this._requestedTransport}`;
1721
+ const key = this.runtimeConnectionKey();
1497
1722
  const inFlight = this._connectionInFlight;
1498
- if (inFlight && inFlight.key === key) return inFlight.promise;
1499
- const promise = this.performRuntimeConnection();
1500
- this._connectionInFlight = {
1723
+ if (inFlight && inFlight.attempt.key === key && this.isCurrentRuntimeConnection(inFlight.attempt)) return inFlight.promise;
1724
+ const attempt = {
1501
1725
  key,
1726
+ generation: ++this._runtimeConnectionGeneration
1727
+ };
1728
+ this._activeRuntimeConnectionAttempt = attempt;
1729
+ const promise = this.performRuntimeConnection({
1730
+ attempt,
1731
+ runtimeUrl: this._runtimeUrl,
1732
+ transport: this._runtimeTransport,
1733
+ options
1734
+ });
1735
+ this._connectionInFlight = {
1736
+ attempt,
1502
1737
  promise
1503
1738
  };
1504
1739
  promise.finally(() => {
@@ -1507,10 +1742,66 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1507
1742
  });
1508
1743
  return promise;
1509
1744
  }
1510
- async performRuntimeConnection() {
1511
- if (!this.runtimeUrl) {
1745
+ /** Return the stable key that scopes connection and entitlement retries. */
1746
+ runtimeConnectionKey() {
1747
+ var _this$_runtimeUrl;
1748
+ return `${(_this$_runtimeUrl = this._runtimeUrl) !== null && _this$_runtimeUrl !== void 0 ? _this$_runtimeUrl : ""}::${this._requestedTransport}`;
1749
+ }
1750
+ /** Return whether a proxy still targets this Runtime connection. */
1751
+ canReuseRuntimeAgent(agent, runtimeUrl, transport) {
1752
+ if (!runtimeUrl) return false;
1753
+ const connection = this.remoteAgentConnections.get(agent);
1754
+ return (connection === null || connection === void 0 ? void 0 : connection.runtimeUrl) === runtimeUrl.replace(/\/$/, "") && connection.transport === transport;
1755
+ }
1756
+ /** Return whether an async attempt still owns the active Runtime state. */
1757
+ isCurrentRuntimeConnection(attempt) {
1758
+ var _this$_activeRuntimeC;
1759
+ return ((_this$_activeRuntimeC = this._activeRuntimeConnectionAttempt) === null || _this$_activeRuntimeC === void 0 ? void 0 : _this$_activeRuntimeC.generation) === attempt.generation && this.runtimeConnectionKey() === attempt.key;
1760
+ }
1761
+ /** Cancel a pending entitlement retry and allow a new target to retry. */
1762
+ resetRuntimeEntitlementRetry() {
1763
+ if (this._runtimeEntitlementRetryTimer !== void 0) {
1764
+ clearTimeout(this._runtimeEntitlementRetryTimer);
1765
+ this._runtimeEntitlementRetryTimer = void 0;
1766
+ }
1767
+ this._runtimeEntitlementRetryAttemptedKey = void 0;
1768
+ this._runtimeEntitlementRetryPendingKey = void 0;
1769
+ }
1770
+ /** Schedule one retry after Runtime's short failed-entitlement cache. */
1771
+ updateRuntimeEntitlementRetry(runtimeEntitlements, attempt) {
1772
+ if (!this.isCurrentRuntimeConnection(attempt)) return;
1773
+ const { key } = attempt;
1774
+ if ((runtimeEntitlements === null || runtimeEntitlements === void 0 ? void 0 : runtimeEntitlements.status) === "ready" || (runtimeEntitlements === null || runtimeEntitlements === void 0 ? void 0 : runtimeEntitlements.error.retryable) !== true) {
1775
+ this.resetRuntimeEntitlementRetry();
1776
+ return;
1777
+ }
1778
+ if (this._runtimeEntitlementRetryTimer !== void 0) return;
1779
+ if (this._runtimeEntitlementRetryAttemptedKey === key) {
1780
+ this._runtimeEntitlementRetryPendingKey = void 0;
1781
+ return;
1782
+ }
1783
+ this._runtimeEntitlementRetryAttemptedKey = key;
1784
+ this._runtimeEntitlementRetryPendingKey = key;
1785
+ this._runtimeEntitlementRetryTimer = setTimeout(() => {
1786
+ this._runtimeEntitlementRetryTimer = void 0;
1787
+ this.executeRuntimeEntitlementRetry(attempt).catch((error) => {
1788
+ const message = error instanceof Error ? error.message : JSON.stringify(error);
1789
+ _copilotkit_shared.logger.warn(`Failed to retry runtime info (${this.runtimeUrl}/info): ${message}`);
1790
+ });
1791
+ }, RUNTIME_ENTITLEMENT_RETRY_DELAY_MS);
1792
+ }
1793
+ /** Start the bounded retry after the original connection has settled. */
1794
+ async executeRuntimeEntitlementRetry(attempt) {
1795
+ const inFlight = this._connectionInFlight;
1796
+ if ((inFlight === null || inFlight === void 0 ? void 0 : inFlight.attempt.generation) === attempt.generation) await inFlight.promise;
1797
+ if (!this._runtimeUrl || !this.isCurrentRuntimeConnection(attempt)) return;
1798
+ await this.updateRuntimeConnection();
1799
+ }
1800
+ async performRuntimeConnection({ attempt, runtimeUrl, transport, options }) {
1801
+ const { key } = attempt;
1802
+ if (!runtimeUrl) {
1512
1803
  this.invalidateInspectorMetadataConnection();
1513
- this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
1804
+ this.setRuntimeConnectionStatus(CopilotKitCoreRuntimeConnectionStatus.Disconnected);
1514
1805
  this._runtimeVersion = void 0;
1515
1806
  this._audioFileTranscriptionEnabled = false;
1516
1807
  this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
@@ -1520,34 +1811,40 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1520
1811
  this._a2uiEnabled = false;
1521
1812
  this._a2uiAgents = void 0;
1522
1813
  this._openGenerativeUIEnabled = false;
1814
+ this._licenseStatus = void 0;
1815
+ this._runtimeEntitlements = void 0;
1523
1816
  this.remoteAgents = {};
1524
1817
  this._agents = this.localAgents;
1525
1818
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Disconnected);
1819
+ if (!this.isCurrentRuntimeConnection(attempt)) return;
1526
1820
  await this.notifyAgentsChanged();
1527
1821
  return;
1528
1822
  }
1529
1823
  const inspectorMetadataConnectionGeneration = this.inspectorMetadataConnectionGeneration;
1530
- this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connecting;
1824
+ this.setRuntimeConnectionStatus(CopilotKitCoreRuntimeConnectionStatus.Connecting);
1825
+ const runtimeHealthGeneration = this.runtimeHealthGeneration;
1531
1826
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connecting);
1827
+ if (!this.isCurrentRuntimeConnection(attempt)) return;
1532
1828
  try {
1533
1829
  var _runtimeInfoResponse$2, _runtimeInfoResponse$3, _ref, _a2uiInfo$enabled, _runtimeInfoResponse$4, _runtimeInfoResponse$5;
1534
1830
  if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1535
- const { runtimeInfo: runtimeInfoResponse, resolvedTransport } = await this.fetchRuntimeInfo();
1536
- if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1831
+ const { runtimeInfo: runtimeInfoResponse, resolvedTransport } = (options === null || options === void 0 ? void 0 : options.recovery) ? await this.fetchRuntimeInfoWithTimeout(new AbortController(), runtimeUrl, transport) : await this.fetchRuntimeInfo(runtimeUrl, transport);
1832
+ if (!this.isCurrentRuntimeConnection(attempt) || inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1537
1833
  this._runtimeTransport = resolvedTransport;
1538
1834
  const { version, ...runtimeInfo } = runtimeInfoResponse;
1539
1835
  const credentials = this.core.credentials;
1540
1836
  const rawDebug = this.core.debug;
1541
- this.remoteAgents = Object.fromEntries(Object.entries(runtimeInfo.agents).map(([id, { description, capabilities }]) => {
1837
+ const agents = Object.fromEntries(Object.entries(runtimeInfo.agents).map(([id, { description, capabilities }]) => {
1542
1838
  var _runtimeInfoResponse$;
1543
1839
  const existing = Object.prototype.hasOwnProperty.call(this.remoteAgents, id) ? this.remoteAgents[id] : void 0;
1544
- if (existing instanceof ProxiedCopilotRuntimeAgent) {
1840
+ if (existing instanceof ProxiedCopilotRuntimeAgent && this.canReuseRuntimeAgent(existing, runtimeUrl, this._runtimeTransport)) {
1545
1841
  this.applyHeadersToAgent(existing);
1546
1842
  this.applyCredentialsToAgent(existing);
1843
+ this.applyRuntimeFetchToAgent(existing);
1547
1844
  return [id, existing];
1548
1845
  }
1549
1846
  const agent = new ProxiedCopilotRuntimeAgent({
1550
- runtimeUrl: this.runtimeUrl,
1847
+ runtimeUrl,
1551
1848
  agentId: id,
1552
1849
  description,
1553
1850
  transport: this._runtimeTransport,
@@ -1558,13 +1855,25 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1558
1855
  debug: rawDebug ? (0, _copilotkit_shared.resolveDebugConfig)(rawDebug) : void 0
1559
1856
  });
1560
1857
  this.applyHeadersToAgent(agent);
1858
+ this.applyRuntimeFetchToAgent(agent);
1859
+ this.mintedThreadIds.set(agent, agent.threadId);
1860
+ if ((options === null || options === void 0 ? void 0 : options.preserveOnFailure) === true && existing) {
1861
+ agent.threadId = existing.threadId;
1862
+ agent.setState(existing.state);
1863
+ agent.setMessages([...existing.messages]);
1864
+ }
1865
+ this.remoteAgentConnections.set(agent, {
1866
+ runtimeUrl,
1867
+ transport: this._runtimeTransport
1868
+ });
1561
1869
  return [id, agent];
1562
1870
  }));
1871
+ this.remoteAgents = (options === null || options === void 0 ? void 0 : options.recovery) ? this.reconcileRecoveredAgents(agents) : agents;
1563
1872
  this._agents = {
1564
1873
  ...this.localAgents,
1565
1874
  ...this.remoteAgents
1566
1875
  };
1567
- this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connected;
1876
+ this.setRuntimeConnectionStatus(CopilotKitCoreRuntimeConnectionStatus.Connected);
1568
1877
  this._runtimeVersion = version;
1569
1878
  this._audioFileTranscriptionEnabled = (_runtimeInfoResponse$2 = runtimeInfoResponse.audioFileTranscriptionEnabled) !== null && _runtimeInfoResponse$2 !== void 0 ? _runtimeInfoResponse$2 : false;
1570
1879
  this._runtimeMode = (_runtimeInfoResponse$3 = runtimeInfoResponse.mode) !== null && _runtimeInfoResponse$3 !== void 0 ? _runtimeInfoResponse$3 : _copilotkit_shared.RUNTIME_MODE_SSE;
@@ -1579,54 +1888,67 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1579
1888
  this._a2uiAgents = (a2uiInfo === null || a2uiInfo === void 0 ? void 0 : a2uiInfo.enabled) ? a2uiInfo.agents : void 0;
1580
1889
  this._openGenerativeUIEnabled = (_runtimeInfoResponse$4 = runtimeInfoResponse.openGenerativeUIEnabled) !== null && _runtimeInfoResponse$4 !== void 0 ? _runtimeInfoResponse$4 : false;
1581
1890
  this._licenseStatus = runtimeInfoResponse.licenseStatus;
1891
+ this._runtimeEntitlements = runtimeInfoResponse.runtimeEntitlements;
1892
+ this.updateRuntimeEntitlementRetry(runtimeInfoResponse.runtimeEntitlements, attempt);
1582
1893
  this._telemetryDisabled = (_runtimeInfoResponse$5 = runtimeInfoResponse.telemetryDisabled) !== null && _runtimeInfoResponse$5 !== void 0 ? _runtimeInfoResponse$5 : false;
1583
1894
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connected);
1895
+ if (!this.isCurrentRuntimeConnection(attempt)) return;
1584
1896
  await this.notifyAgentsChanged();
1585
1897
  if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration || this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return;
1586
1898
  this.inspectorMetadataRefreshReady = true;
1587
1899
  if (this._inspectorMetadataSupported) this.refreshInspectorMetadata();
1588
1900
  } catch (error) {
1589
- if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1590
- this.invalidateInspectorMetadataConnection();
1591
- this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Error;
1592
- this._runtimeVersion = void 0;
1593
- this._audioFileTranscriptionEnabled = false;
1594
- this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
1595
- this._intelligence = void 0;
1596
- this._threadEndpoints = void 0;
1597
- this._suggestions = void 0;
1598
- this._a2uiEnabled = false;
1599
- this._a2uiAgents = void 0;
1600
- this._openGenerativeUIEnabled = false;
1601
- this.remoteAgents = {};
1602
- this._agents = this.localAgents;
1603
- await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Error);
1604
- await this.notifyAgentsChanged();
1901
+ if (!this.isCurrentRuntimeConnection(attempt) || inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1902
+ const boundedEntitlementRetryFailed = this._runtimeEntitlementRetryTimer === void 0 && this._runtimeEntitlementRetryAttemptedKey === key && this._runtimeEntitlementRetryPendingKey === key;
1903
+ if (boundedEntitlementRetryFailed) this._runtimeEntitlementRetryPendingKey = void 0;
1904
+ if (options === null || options === void 0 ? void 0 : options.preserveOnFailure) {
1905
+ if ((options === null || options === void 0 ? void 0 : options.recovery) && runtimeHealthGeneration !== this.runtimeHealthGeneration) return;
1906
+ this.setRuntimeConnectionStatus(CopilotKitCoreRuntimeConnectionStatus.Error);
1907
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Error);
1908
+ } else {
1909
+ this.invalidateInspectorMetadataConnection();
1910
+ this.setRuntimeConnectionStatus(CopilotKitCoreRuntimeConnectionStatus.Error);
1911
+ this._runtimeVersion = void 0;
1912
+ this._audioFileTranscriptionEnabled = false;
1913
+ this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
1914
+ this._intelligence = void 0;
1915
+ this._threadEndpoints = void 0;
1916
+ this._suggestions = void 0;
1917
+ this._a2uiEnabled = false;
1918
+ this._a2uiAgents = void 0;
1919
+ this._openGenerativeUIEnabled = false;
1920
+ if (!boundedEntitlementRetryFailed) {
1921
+ this._licenseStatus = void 0;
1922
+ this._runtimeEntitlements = void 0;
1923
+ }
1924
+ this.remoteAgents = {};
1925
+ this._agents = this.localAgents;
1926
+ await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Error);
1927
+ await this.notifyAgentsChanged();
1928
+ }
1605
1929
  const message = error instanceof Error ? error.message : JSON.stringify(error);
1606
- _copilotkit_shared.logger.warn(`Failed to load runtime info (${this.runtimeUrl}/info): ${message}`);
1930
+ _copilotkit_shared.logger.warn(`Failed to load runtime info (${runtimeUrl}/info): ${message}`);
1607
1931
  const runtimeError = error instanceof Error ? error : new Error(String(error));
1608
1932
  await this.core.emitError({
1609
1933
  error: runtimeError,
1610
1934
  code: CopilotKitCoreErrorCode.RUNTIME_INFO_FETCH_FAILED,
1611
- context: { runtimeUrl: this.runtimeUrl }
1935
+ context: { runtimeUrl }
1612
1936
  });
1613
1937
  }
1614
1938
  }
1615
- async fetchRuntimeInfo() {
1616
- const runtimeUrl = this.runtimeUrl;
1617
- if (!runtimeUrl) throw new Error("Runtime URL is not set");
1939
+ async fetchRuntimeInfo(runtimeUrl, runtimeTransport, signal) {
1618
1940
  const baseHeaders = this.core.headers;
1619
1941
  const credentials = this.core.credentials;
1620
1942
  const headers = { ...baseHeaders };
1621
- const runtimeTransport = this._runtimeTransport;
1622
1943
  if (runtimeTransport === "single") return {
1623
- runtimeInfo: await this.fetchRuntimeInfoSingle(runtimeUrl, headers, credentials),
1944
+ runtimeInfo: await this.fetchRuntimeInfoSingle(runtimeUrl, headers, credentials, signal),
1624
1945
  resolvedTransport: "single"
1625
1946
  };
1626
- if (runtimeTransport === "auto") return this.fetchRuntimeInfoAutoDetect(runtimeUrl, headers, credentials);
1947
+ if (runtimeTransport === "auto") return this.fetchRuntimeInfoAutoDetect(runtimeUrl, headers, credentials, signal);
1627
1948
  const response = await fetch(`${runtimeUrl}/info`, {
1628
1949
  headers,
1629
- ...credentials ? { credentials } : {}
1950
+ ...credentials ? { credentials } : {},
1951
+ ...signal ? { signal } : {}
1630
1952
  });
1631
1953
  if (!response.ok) throw await runtimeInfoError(response);
1632
1954
  return {
@@ -1634,12 +1956,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1634
1956
  resolvedTransport: "rest"
1635
1957
  };
1636
1958
  }
1637
- async fetchRuntimeInfoSingle(runtimeUrl, headers, credentials) {
1959
+ async fetchRuntimeInfoSingle(runtimeUrl, headers, credentials, signal) {
1638
1960
  const response = await fetch(runtimeUrl, {
1639
1961
  method: "POST",
1640
1962
  headers: withJsonContentType(headers),
1641
1963
  body: JSON.stringify({ method: "info" }),
1642
- ...credentials ? { credentials } : {}
1964
+ ...credentials ? { credentials } : {},
1965
+ ...signal ? { signal } : {}
1643
1966
  });
1644
1967
  if (!response.ok) throw await runtimeInfoError(response);
1645
1968
  return await response.json();
@@ -1649,11 +1972,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1649
1972
  * The caller commits the detected transport only after confirming this
1650
1973
  * connection attempt is still current.
1651
1974
  */
1652
- async fetchRuntimeInfoAutoDetect(runtimeUrl, headers, credentials) {
1975
+ async fetchRuntimeInfoAutoDetect(runtimeUrl, headers, credentials, signal) {
1653
1976
  try {
1654
1977
  const response = await fetch(`${runtimeUrl}/info`, {
1655
1978
  headers: { ...headers },
1656
- ...credentials ? { credentials } : {}
1979
+ ...credentials ? { credentials } : {},
1980
+ ...signal ? { signal } : {}
1657
1981
  });
1658
1982
  if (response.status >= 200 && response.status < 300) return {
1659
1983
  runtimeInfo: await response.json(),
@@ -1661,7 +1985,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1661
1985
  };
1662
1986
  } catch (_unused2) {}
1663
1987
  return {
1664
- runtimeInfo: await this.fetchRuntimeInfoSingle(runtimeUrl, { ...headers }, credentials),
1988
+ runtimeInfo: await this.fetchRuntimeInfoSingle(runtimeUrl, { ...headers }, credentials, signal),
1665
1989
  resolvedTransport: "single"
1666
1990
  };
1667
1991
  }
@@ -2183,13 +2507,21 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2183
2507
  */
2184
2508
  const MAX_FOLLOW_UP_DEPTH = 100;
2185
2509
  /**
2510
+ * Name of the catch-all frontend tool. A tool registered under this name
2511
+ * handles any tool call that has no exact match (see `executeWildcardTool`),
2512
+ * and is never advertised to the agent.
2513
+ */
2514
+ const WILDCARD_TOOL_NAME = "*";
2515
+ /**
2186
2516
  * Handles agent execution, tool calling, and agent connectivity for CopilotKitCore.
2187
2517
  * Manages the complete lifecycle of agent runs including tool execution and follow-ups.
2188
2518
  */
2189
2519
  var RunHandler = class {
2190
2520
  constructor(core) {
2191
2521
  this.core = core;
2192
- _defineProperty(this, "_tools", []);
2522
+ _defineProperty(this, "_propTools", []);
2523
+ _defineProperty(this, "_hookTools", /* @__PURE__ */ new Map());
2524
+ _defineProperty(this, "_cachedMergedTools", null);
2193
2525
  _defineProperty(this, "_catalogComponents", []);
2194
2526
  _defineProperty(this, "_disabledCatalogComponents", /* @__PURE__ */ new Set());
2195
2527
  _defineProperty(this, "_disabledToolKeys", /* @__PURE__ */ new Set());
@@ -2230,35 +2562,49 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2230
2562
  return anonymousId;
2231
2563
  }
2232
2564
  /**
2233
- * Get all tools as a readonly array
2565
+ * Get all tools as a readonly array: provider-owned tools in registration
2566
+ * order, with imperatively-added tools appended and taking precedence over a
2567
+ * provider tool of the same name + agentId.
2234
2568
  */
2235
2569
  get tools() {
2236
- return this._tools;
2570
+ if (this._hookTools.size === 0) return this._propTools;
2571
+ if (this._cachedMergedTools) return this._cachedMergedTools;
2572
+ const merged = /* @__PURE__ */ new Map();
2573
+ for (const tool of this._propTools) merged.set(this.capabilityKey(tool.name, tool.agentId), tool);
2574
+ for (const [key, tool] of this._hookTools) merged.set(key, tool);
2575
+ this._cachedMergedTools = Array.from(merged.values());
2576
+ return this._cachedMergedTools;
2237
2577
  }
2238
2578
  /**
2239
2579
  * Initialize with tools
2240
2580
  */
2241
2581
  initialize(tools) {
2242
- this._tools = tools;
2582
+ this._propTools = [...tools];
2583
+ this._cachedMergedTools = null;
2243
2584
  }
2244
2585
  /**
2245
- * Add a tool to the registry
2586
+ * Add a tool to the registry. Survives provider re-syncs ({@link setTools}),
2587
+ * and shadows a provider tool of the same name + agentId.
2246
2588
  */
2247
2589
  addTool(tool) {
2248
- if (this._tools.findIndex((t) => t.name === tool.name && t.agentId === tool.agentId) !== -1) {
2590
+ const key = this.capabilityKey(tool.name, tool.agentId);
2591
+ if (this._hookTools.has(key)) {
2249
2592
  _copilotkit_shared.logger.warn(`Tool already exists: '${tool.name}' for agent '${tool.agentId || "global"}', skipping.`);
2250
2593
  return;
2251
2594
  }
2252
- this._tools.push(tool);
2595
+ this._hookTools.set(key, tool);
2596
+ this._cachedMergedTools = null;
2253
2597
  }
2254
2598
  /**
2255
2599
  * Remove a tool by name and optionally by agentId
2256
2600
  */
2257
2601
  removeTool(id, agentId) {
2258
- this._tools = this._tools.filter((tool) => {
2602
+ this._hookTools.delete(this.capabilityKey(id, agentId));
2603
+ this._propTools = this._propTools.filter((tool) => {
2259
2604
  if (agentId !== void 0) return !(tool.name === id && tool.agentId === agentId);
2260
2605
  return !(tool.name === id && !tool.agentId);
2261
2606
  });
2607
+ this._cachedMergedTools = null;
2262
2608
  }
2263
2609
  /**
2264
2610
  * Get a tool by name and optionally by agentId.
@@ -2267,17 +2613,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2267
2613
  */
2268
2614
  getTool(params) {
2269
2615
  const { toolName, agentId } = params;
2616
+ const tools = this.tools;
2270
2617
  if (agentId) {
2271
- const agentTool = this._tools.find((tool) => tool.name === toolName && tool.agentId === agentId);
2618
+ const agentTool = tools.find((tool) => tool.name === toolName && tool.agentId === agentId);
2272
2619
  if (agentTool) return agentTool;
2273
2620
  }
2274
- return this._tools.find((tool) => tool.name === toolName && !tool.agentId);
2621
+ return tools.find((tool) => tool.name === toolName && !tool.agentId);
2275
2622
  }
2276
2623
  /**
2277
- * Set all tools at once. Replaces existing tools.
2624
+ * Set all provider-owned tools at once. Replaces the previous provider set;
2625
+ * tools registered via {@link addTool} are unaffected.
2278
2626
  */
2279
2627
  setTools(tools) {
2280
- this._tools = [...tools];
2628
+ this._propTools = [...tools];
2629
+ this._cachedMergedTools = null;
2281
2630
  }
2282
2631
  /**
2283
2632
  * Return the registered A2UI catalog components (readonly).
@@ -2346,7 +2695,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2346
2695
  });
2347
2696
  } catch (error) {
2348
2697
  const connectError = error instanceof Error ? error : new Error(String(error));
2349
- if (!(connectError.name === "AbortError" || connectError.message === "Fetch is aborted" || connectError.message === "signal is aborted without reason" || connectError.message === "component unmounted")) {
2698
+ if (!isAbortError$1(connectError)) {
2350
2699
  const context = {};
2351
2700
  if (agent.agentId) context.agentId = agent.agentId;
2352
2701
  if (incomingThreadId) context.threadId = incomingThreadId;
@@ -2463,7 +2812,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2463
2812
  const getWildcardTool = () => {
2464
2813
  if (tool || wildcardTool) return wildcardTool;
2465
2814
  wildcardTool = this.getTool({
2466
- toolName: "*",
2815
+ toolName: WILDCARD_TOOL_NAME,
2467
2816
  agentId: agent.agentId
2468
2817
  });
2469
2818
  return wildcardTool;
@@ -2832,7 +3181,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2832
3181
  * Build frontend tools for an agent
2833
3182
  */
2834
3183
  buildFrontendTools(agentId) {
2835
- return this._tools.filter((tool) => tool.available !== false && tool.available !== "disabled" && (!tool.agentId || tool.agentId === agentId) && this.isToolEnabled(tool.name, tool.agentId)).map((tool) => {
3184
+ return this.tools.filter((tool) => tool.name !== WILDCARD_TOOL_NAME && tool.available !== false && tool.available !== "disabled" && (!tool.agentId || tool.agentId === agentId) && this.isToolEnabled(tool.name, tool.agentId)).map((tool) => {
2836
3185
  var _tool$description;
2837
3186
  return {
2838
3187
  name: tool.name,
@@ -2987,9 +3336,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2987
3336
  subscribeToAgent(agent) {
2988
3337
  if (!agent.agentId) return;
2989
3338
  const agentId = agent.agentId;
2990
- const existingUnsubscribe = this.agentSubscriptions.get(agentId);
2991
- if (existingUnsubscribe) {
2992
- existingUnsubscribe();
3339
+ const existing = this.agentSubscriptions.get(agentId);
3340
+ if (existing) {
3341
+ if (existing.agent === agent) return;
3342
+ existing.unsubscribe();
2993
3343
  this.agentSubscriptions.delete(agentId);
2994
3344
  }
2995
3345
  let revoked = false;
@@ -3144,19 +3494,22 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3144
3494
  if (!input) this.pruneRawEvents(agent.agentId, agent.threadId, messages);
3145
3495
  }
3146
3496
  });
3147
- this.agentSubscriptions.set(agentId, () => {
3148
- revoked = true;
3149
- this.pendingContinuations.delete(agent);
3150
- unsubscribe();
3497
+ this.agentSubscriptions.set(agentId, {
3498
+ agent,
3499
+ unsubscribe: () => {
3500
+ revoked = true;
3501
+ this.pendingContinuations.delete(agent);
3502
+ unsubscribe();
3503
+ }
3151
3504
  });
3152
3505
  }
3153
3506
  /**
3154
3507
  * Unsubscribe an agent's subscription.
3155
3508
  */
3156
3509
  unsubscribeFromAgent(agentId) {
3157
- const unsubscribe = this.agentSubscriptions.get(agentId);
3158
- if (unsubscribe) {
3159
- unsubscribe();
3510
+ const existing = this.agentSubscriptions.get(agentId);
3511
+ if (existing) {
3512
+ existing.unsubscribe();
3160
3513
  this.agentSubscriptions.delete(agentId);
3161
3514
  }
3162
3515
  this.rawEventByMessage.delete(agentId);
@@ -4703,6 +5056,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4703
5056
  get runtimeConnectionStatus() {
4704
5057
  return this.agentRegistry.runtimeConnectionStatus;
4705
5058
  }
5059
+ get ɵruntimeFetch() {
5060
+ return this.agentRegistry.createRuntimeFetch();
5061
+ }
4706
5062
  get audioFileTranscriptionEnabled() {
4707
5063
  return this.agentRegistry.audioFileTranscriptionEnabled;
4708
5064
  }
@@ -4742,6 +5098,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4742
5098
  get licenseStatus() {
4743
5099
  return this.agentRegistry.licenseStatus;
4744
5100
  }
5101
+ /** Structured Runtime entitlement authority advertised by `/info`. */
5102
+ get runtimeEntitlements() {
5103
+ return this.agentRegistry.runtimeEntitlements;
5104
+ }
5105
+ /** Whether Core still has a bounded Runtime entitlement retry to settle. */
5106
+ get runtimeEntitlementRetryPending() {
5107
+ return this.agentRegistry.runtimeEntitlementRetryPending;
5108
+ }
4745
5109
  get telemetryDisabled() {
4746
5110
  return this.agentRegistry.telemetryDisabled;
4747
5111
  }
@@ -5731,22 +6095,34 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5731
6095
  }
5732
6096
  function threadFromFetch(input, init) {
5733
6097
  return new rxjs.Observable((subscriber) => {
5734
- const { fetch: fetchImpl, selector, signal, ...requestInit } = init;
6098
+ const { fetch: fetchImpl, selector, signal, timeoutMs, nonCritical, ...requestInit } = init;
5735
6099
  const controller = new AbortController();
6100
+ const runtimeRequest = {
6101
+ ...nonCritical ? { nonCritical: true } : {},
6102
+ ...timeoutMs === void 0 ? {} : { selfBounded: true }
6103
+ };
6104
+ let timedOut = false;
5736
6105
  const abortRequest = () => controller.abort();
5737
6106
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) abortRequest();
5738
6107
  else signal === null || signal === void 0 || signal.addEventListener("abort", abortRequest, { once: true });
6108
+ const timeoutId = timeoutMs === void 0 ? void 0 : setTimeout(() => {
6109
+ timedOut = true;
6110
+ runtimeRequest.timedOut = true;
6111
+ abortRequest();
6112
+ }, timeoutMs);
5739
6113
  fetchImpl(input, {
5740
6114
  ...requestInit,
5741
- signal: controller.signal
6115
+ signal: controller.signal,
6116
+ ɵruntimeRequest: runtimeRequest
5742
6117
  }).then((response) => selector(response)).then((value) => {
5743
6118
  if (subscriber.closed) return;
5744
6119
  subscriber.next(value);
5745
6120
  subscriber.complete();
5746
6121
  }).catch((error) => {
5747
- if (!subscriber.closed) subscriber.error(error);
6122
+ if (!subscriber.closed) subscriber.error(timedOut ? /* @__PURE__ */ new Error("Request timed out") : error);
5748
6123
  });
5749
6124
  return () => {
6125
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
5750
6126
  signal === null || signal === void 0 || signal.removeEventListener("abort", abortRequest);
5751
6127
  abortRequest();
5752
6128
  };
@@ -5764,14 +6140,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5764
6140
  return response.json();
5765
6141
  },
5766
6142
  fetch: environment.fetch,
6143
+ timeoutMs: REQUEST_TIMEOUT_MS,
5767
6144
  method: "GET",
5768
6145
  headers: { ...context.headers }
5769
- }).pipe((0, rxjs_operators.timeout)({
5770
- first: REQUEST_TIMEOUT_MS,
5771
- with: () => {
5772
- throw new Error("Request timed out");
5773
- }
5774
- }), (0, rxjs_operators.map)((data) => {
6146
+ }).pipe((0, rxjs_operators.map)((data) => {
5775
6147
  var _data$nextCursor;
5776
6148
  return threadRestEvents.listSucceeded({
5777
6149
  sessionId,
@@ -5795,18 +6167,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5795
6167
  return response.json();
5796
6168
  },
5797
6169
  fetch: environment.fetch,
6170
+ timeoutMs: REQUEST_TIMEOUT_MS,
6171
+ nonCritical: true,
5798
6172
  method: "POST",
5799
6173
  headers: {
5800
6174
  ...context.headers,
5801
6175
  "Content-Type": "application/json"
5802
6176
  },
5803
6177
  body: JSON.stringify({})
5804
- }).pipe((0, rxjs_operators.timeout)({
5805
- first: REQUEST_TIMEOUT_MS,
5806
- with: () => {
5807
- throw new Error("Request timed out");
5808
- }
5809
- }), (0, rxjs_operators.map)((data) => {
6178
+ }).pipe((0, rxjs_operators.map)((data) => {
5810
6179
  if (typeof data.joinToken !== "string" || data.joinToken.length === 0) throw new Error("missing joinToken");
5811
6180
  return threadRestEvents.metadataCredentialsSucceeded({
5812
6181
  sessionId,
@@ -5943,14 +6312,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5943
6312
  return response.json();
5944
6313
  },
5945
6314
  fetch: environment.fetch,
6315
+ timeoutMs: REQUEST_TIMEOUT_MS,
5946
6316
  method: "GET",
5947
6317
  headers: { ...context.headers }
5948
- }).pipe((0, rxjs_operators.timeout)({
5949
- first: REQUEST_TIMEOUT_MS,
5950
- with: () => {
5951
- throw new Error("Request timed out");
5952
- }
5953
- }), (0, rxjs_operators.map)((data) => {
6318
+ }).pipe((0, rxjs_operators.map)((data) => {
5954
6319
  var _data$nextCursor2;
5955
6320
  return threadRestEvents.nextPageSucceeded({
5956
6321
  sessionId: state.sessionId,
@@ -6120,6 +6485,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
6120
6485
  * hardcoding the threshold separately from production.
6121
6486
  */
6122
6487
  const ɵMAX_SOCKET_RETRIES = MAX_SOCKET_RETRIES;
6488
+ /**
6489
+ * How long a thread REST request is given before the store gives up on it.
6490
+ * Exposed for tests for the same reason as {@link ɵMAX_SOCKET_RETRIES}: a
6491
+ * separately hardcoded copy silently drifts away from this one.
6492
+ */
6493
+ const ɵTHREAD_REQUEST_TIMEOUT_MS = REQUEST_TIMEOUT_MS;
6123
6494
 
6124
6495
  //#endregion
6125
6496
  //#region src/features.ts
@@ -6438,6 +6809,8 @@ exports.select = select;
6438
6809
  exports.ɵCOPILOTKIT_FEATURES = ɵCOPILOTKIT_FEATURES;
6439
6810
  exports.ɵInterruptState = ɵInterruptState;
6440
6811
  exports.ɵMAX_SOCKET_RETRIES = ɵMAX_SOCKET_RETRIES;
6812
+ exports.ɵRUNTIME_PROBE_TIMEOUT_MS = ɵRUNTIME_PROBE_TIMEOUT_MS;
6813
+ exports.ɵTHREAD_REQUEST_TIMEOUT_MS = ɵTHREAD_REQUEST_TIMEOUT_MS;
6441
6814
  exports.ɵcreateMemoryStore = createMemoryStore;
6442
6815
  exports.ɵcreateThreadSelectors = ɵcreateThreadSelectors;
6443
6816
  exports.ɵcreateThreadStore = createThreadStore;