@copilotkit/core 1.66.4 → 1.67.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Throttler } from "@tanstack/pacer";
2
2
  import { AbstractAgent, EventType, HttpAgent, buildResumeArray, isInterruptExpired, randomUUID, runHttpRequest, structuredClone_, transformChunks, transformHttpEventStream } from "@ag-ui/client";
3
- import { RUNTIME_MODE_INTELLIGENCE, RUNTIME_MODE_SSE, logger, partialJSONParse, phoenixExponentialBackoff, randomUUID as randomUUID$1, resolveDebugConfig, schemaToJsonSchema } from "@copilotkit/shared";
3
+ import { RUNTIME_MODE_INTELLIGENCE, RUNTIME_MODE_SSE, logger, parseInspectorMetadataV1, partialJSONParse, phoenixExponentialBackoff, randomUUID as randomUUID$1, resolveDebugConfig, schemaToJsonSchema } from "@copilotkit/shared";
4
4
  import { BehaviorSubject, EMPTY, NEVER, Notification, Observable, Subject, Subscription, asapScheduler, combineLatest, concat, defer, dematerialize, firstValueFrom, from, lastValueFrom, merge, observeOn, of, switchMap, throwError } from "rxjs";
5
5
  import { catchError, concatWith, delay, distinctUntilChanged, endWith, filter, finalize, ignoreElements, map, mergeMap, observeOn as observeOn$1, scan, share, shareReplay, switchMap as switchMap$1, take, takeUntil, tap, timeout, withLatestFrom } from "rxjs/operators";
6
6
  import { Socket } from "phoenix";
@@ -894,6 +894,14 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
894
894
 
895
895
  //#endregion
896
896
  //#region src/core/agent-registry.ts
897
+ /** Maximum wait for optional Inspector metadata before degrading to absence. */
898
+ const INSPECTOR_METADATA_REQUEST_TIMEOUT_MS = 5e3;
899
+ /** Build case-insensitive JSON headers without mutating the Core snapshot. */
900
+ function withJsonContentType(headers) {
901
+ const requestHeaders = new Headers(headers);
902
+ if (!requestHeaders.has("content-type")) requestHeaders.set("content-type", "application/json");
903
+ return requestHeaders;
904
+ }
897
905
  /**
898
906
  * Manages agent registration, lifecycle, and runtime connectivity for CopilotKitCore.
899
907
  * Handles both local development agents and remote runtime agents.
@@ -913,6 +921,15 @@ var AgentRegistry = class {
913
921
  _intelligence;
914
922
  _threadEndpoints;
915
923
  _suggestions;
924
+ _inspectorMetadata;
925
+ _inspectorMetadataSupported = false;
926
+ inspectorMetadataRefreshReady = false;
927
+ inspectorMetadataConnectionGeneration = 0;
928
+ inspectorMetadataGeneration = 0;
929
+ inspectorMetadataHeadersGeneration = 0;
930
+ inspectorMetadataCredentialsGeneration = 0;
931
+ inspectorMetadataAbortController;
932
+ inspectorMetadataNotificationQueue = Promise.resolve();
916
933
  _a2uiEnabled = false;
917
934
  _a2uiAgents;
918
935
  _openGenerativeUIEnabled = false;
@@ -965,6 +982,9 @@ var AgentRegistry = class {
965
982
  get suggestions() {
966
983
  return this._suggestions;
967
984
  }
985
+ get inspectorMetadata() {
986
+ return this._inspectorMetadata;
987
+ }
968
988
  get a2uiEnabled() {
969
989
  return this._a2uiEnabled;
970
990
  }
@@ -999,6 +1019,7 @@ var AgentRegistry = class {
999
1019
  setRuntimeUrl(runtimeUrl, options) {
1000
1020
  const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
1001
1021
  if (this._runtimeUrl === normalizedRuntimeUrl) return;
1022
+ this.invalidateInspectorMetadataConnection();
1002
1023
  this._runtimeUrl = normalizedRuntimeUrl;
1003
1024
  if (options?.deferConnection) return;
1004
1025
  this.updateRuntimeConnection();
@@ -1022,6 +1043,7 @@ var AgentRegistry = class {
1022
1043
  }
1023
1044
  setRuntimeTransport(runtimeTransport) {
1024
1045
  if (this._requestedTransport === runtimeTransport) return;
1046
+ this.invalidateInspectorMetadataConnection();
1025
1047
  this._requestedTransport = runtimeTransport;
1026
1048
  this._runtimeTransport = runtimeTransport;
1027
1049
  this.updateRuntimeConnection();
@@ -1158,6 +1180,141 @@ var AgentRegistry = class {
1158
1180
  this.applyCredentialsToAgent(agent);
1159
1181
  });
1160
1182
  }
1183
+ /** Refresh metadata after the Core header snapshot changes. */
1184
+ handleHeadersChanged() {
1185
+ this.inspectorMetadataHeadersGeneration += 1;
1186
+ this.setInspectorMetadata(void 0);
1187
+ this.refreshInspectorMetadata();
1188
+ }
1189
+ /** Refresh metadata after the Core credentials mode changes. */
1190
+ handleCredentialsChanged() {
1191
+ this.inspectorMetadataCredentialsGeneration += 1;
1192
+ this.setInspectorMetadata(void 0);
1193
+ this.refreshInspectorMetadata();
1194
+ }
1195
+ /**
1196
+ * Fetch trusted inspector metadata independently from runtime discovery.
1197
+ * Optional-route failures degrade to absent metadata and never affect the
1198
+ * runtime connection state.
1199
+ */
1200
+ async refreshInspectorMetadata() {
1201
+ const generation = ++this.inspectorMetadataGeneration;
1202
+ this.inspectorMetadataAbortController?.abort();
1203
+ this.inspectorMetadataAbortController = void 0;
1204
+ if (!this._inspectorMetadataSupported || !this.inspectorMetadataRefreshReady || !this.runtimeUrl || this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) {
1205
+ this.setInspectorMetadata(void 0);
1206
+ return;
1207
+ }
1208
+ const runtimeUrl = this.runtimeUrl;
1209
+ const requestedTransport = this._requestedTransport;
1210
+ const resolvedTransport = this._runtimeTransport;
1211
+ const headersGeneration = this.inspectorMetadataHeadersGeneration;
1212
+ const credentialsGeneration = this.inspectorMetadataCredentialsGeneration;
1213
+ const friends = this.core;
1214
+ const headers = { ...friends.headers };
1215
+ const credentials = friends.credentials;
1216
+ const abortController = new AbortController();
1217
+ this.inspectorMetadataAbortController = abortController;
1218
+ let timedOut = false;
1219
+ let timeoutId;
1220
+ let rejectForAbort;
1221
+ const aborted = new Promise((_resolve, reject) => {
1222
+ rejectForAbort = reject;
1223
+ });
1224
+ const handleAbort = () => {
1225
+ rejectForAbort?.(/* @__PURE__ */ new Error("Inspector metadata request aborted"));
1226
+ };
1227
+ abortController.signal.addEventListener("abort", handleAbort, { once: true });
1228
+ const timeout = new Promise((_resolve, reject) => {
1229
+ timeoutId = setTimeout(() => {
1230
+ timedOut = true;
1231
+ reject(/* @__PURE__ */ new Error("Inspector metadata request timed out"));
1232
+ abortController.abort();
1233
+ }, INSPECTOR_METADATA_REQUEST_TIMEOUT_MS);
1234
+ });
1235
+ let nextMetadata;
1236
+ try {
1237
+ const request = (async () => {
1238
+ const response = resolvedTransport === "single" ? await this.fetchInspectorMetadataSingle({
1239
+ runtimeUrl,
1240
+ headers,
1241
+ credentials,
1242
+ signal: abortController.signal
1243
+ }) : await this.fetchInspectorMetadataRest({
1244
+ runtimeUrl,
1245
+ headers,
1246
+ credentials,
1247
+ signal: abortController.signal
1248
+ });
1249
+ if (response.status === 204 || !response.ok) return;
1250
+ return parseInspectorMetadataV1(await response.json());
1251
+ })();
1252
+ nextMetadata = await Promise.race([
1253
+ request,
1254
+ aborted,
1255
+ timeout
1256
+ ]);
1257
+ } catch {
1258
+ nextMetadata = void 0;
1259
+ } finally {
1260
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
1261
+ abortController.signal.removeEventListener("abort", handleAbort);
1262
+ }
1263
+ if (!this.isInspectorMetadataRequestCurrent({
1264
+ generation,
1265
+ runtimeUrl,
1266
+ requestedTransport,
1267
+ resolvedTransport,
1268
+ headersGeneration,
1269
+ credentialsGeneration,
1270
+ signal: abortController.signal,
1271
+ allowAbortedSignal: timedOut
1272
+ })) return;
1273
+ this.inspectorMetadataAbortController = void 0;
1274
+ this.setInspectorMetadata(nextMetadata);
1275
+ }
1276
+ async fetchInspectorMetadataRest({ runtimeUrl, headers, credentials, signal }) {
1277
+ return fetch(`${runtimeUrl}/inspector-metadata`, {
1278
+ method: "GET",
1279
+ headers,
1280
+ ...credentials ? { credentials } : {},
1281
+ signal
1282
+ });
1283
+ }
1284
+ async fetchInspectorMetadataSingle({ runtimeUrl, headers, credentials, signal }) {
1285
+ return fetch(runtimeUrl, {
1286
+ method: "POST",
1287
+ headers: withJsonContentType(headers),
1288
+ body: JSON.stringify({ method: "inspector/metadata" }),
1289
+ ...credentials ? { credentials } : {},
1290
+ signal
1291
+ });
1292
+ }
1293
+ isInspectorMetadataRequestCurrent({ generation, runtimeUrl, requestedTransport, resolvedTransport, headersGeneration, credentialsGeneration, signal, allowAbortedSignal = false }) {
1294
+ return (allowAbortedSignal || !signal.aborted) && generation === this.inspectorMetadataGeneration && runtimeUrl === this.runtimeUrl && requestedTransport === this._requestedTransport && resolvedTransport === this._runtimeTransport && headersGeneration === this.inspectorMetadataHeadersGeneration && credentialsGeneration === this.inspectorMetadataCredentialsGeneration && this._inspectorMetadataSupported && this.inspectorMetadataRefreshReady && this._runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected;
1295
+ }
1296
+ invalidateInspectorMetadataConnection() {
1297
+ this._inspectorMetadataSupported = false;
1298
+ this.inspectorMetadataRefreshReady = false;
1299
+ this.inspectorMetadataConnectionGeneration += 1;
1300
+ this.inspectorMetadataGeneration += 1;
1301
+ this.inspectorMetadataAbortController?.abort();
1302
+ this.inspectorMetadataAbortController = void 0;
1303
+ this.setInspectorMetadata(void 0);
1304
+ }
1305
+ /**
1306
+ * Publish one state transition without making refreshes wait on subscribers.
1307
+ * Each queued callback closes over its readonly snapshot so reentrant changes
1308
+ * cannot replace the value that an older publication is still delivering.
1309
+ */
1310
+ setInspectorMetadata(inspectorMetadata) {
1311
+ if (JSON.stringify(this._inspectorMetadata) === JSON.stringify(inspectorMetadata)) return;
1312
+ this._inspectorMetadata = inspectorMetadata;
1313
+ const snapshot = inspectorMetadata;
1314
+ this.inspectorMetadataNotificationQueue = this.inspectorMetadataNotificationQueue.then(() => this.notifyInspectorMetadataChanged(snapshot)).catch((error) => {
1315
+ console.error("Subscriber onInspectorMetadataChanged queue error:", error);
1316
+ });
1317
+ }
1161
1318
  /**
1162
1319
  * Update runtime connection and fetch remote agents
1163
1320
  */
@@ -1178,6 +1335,7 @@ var AgentRegistry = class {
1178
1335
  }
1179
1336
  async performRuntimeConnection() {
1180
1337
  if (!this.runtimeUrl) {
1338
+ this.invalidateInspectorMetadataConnection();
1181
1339
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
1182
1340
  this._runtimeVersion = void 0;
1183
1341
  this._audioFileTranscriptionEnabled = false;
@@ -1194,10 +1352,14 @@ var AgentRegistry = class {
1194
1352
  await this.notifyAgentsChanged();
1195
1353
  return;
1196
1354
  }
1355
+ const inspectorMetadataConnectionGeneration = this.inspectorMetadataConnectionGeneration;
1197
1356
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connecting;
1198
1357
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connecting);
1199
1358
  try {
1200
- const runtimeInfoResponse = await this.fetchRuntimeInfo();
1359
+ if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1360
+ const { runtimeInfo: runtimeInfoResponse, resolvedTransport } = await this.fetchRuntimeInfo();
1361
+ if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1362
+ this._runtimeTransport = resolvedTransport;
1201
1363
  const { version, ...runtimeInfo } = runtimeInfoResponse;
1202
1364
  const credentials = this.core.credentials;
1203
1365
  const rawDebug = this.core.debug;
@@ -1233,6 +1395,9 @@ var AgentRegistry = class {
1233
1395
  this._intelligence = runtimeInfoResponse.intelligence;
1234
1396
  this._threadEndpoints = runtimeInfoResponse.threadEndpoints;
1235
1397
  this._suggestions = runtimeInfoResponse.suggestions;
1398
+ this._inspectorMetadataSupported = runtimeInfoResponse.inspectorMetadata === true;
1399
+ this.inspectorMetadataRefreshReady = false;
1400
+ if (!this._inspectorMetadataSupported) this.setInspectorMetadata(void 0);
1236
1401
  const a2uiInfo = runtimeInfoResponse.a2ui;
1237
1402
  this._a2uiEnabled = a2uiInfo?.enabled ?? runtimeInfoResponse.a2uiEnabled ?? false;
1238
1403
  this._a2uiAgents = a2uiInfo?.enabled ? a2uiInfo.agents : void 0;
@@ -1241,7 +1406,12 @@ var AgentRegistry = class {
1241
1406
  this._telemetryDisabled = runtimeInfoResponse.telemetryDisabled ?? false;
1242
1407
  await this.notifyRuntimeStatusChanged(CopilotKitCoreRuntimeConnectionStatus.Connected);
1243
1408
  await this.notifyAgentsChanged();
1409
+ if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration || this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return;
1410
+ this.inspectorMetadataRefreshReady = true;
1411
+ if (this._inspectorMetadataSupported) this.refreshInspectorMetadata();
1244
1412
  } catch (error) {
1413
+ if (inspectorMetadataConnectionGeneration !== this.inspectorMetadataConnectionGeneration) return;
1414
+ this.invalidateInspectorMetadataConnection();
1245
1415
  this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Error;
1246
1416
  this._runtimeVersion = void 0;
1247
1417
  this._audioFileTranscriptionEnabled = false;
@@ -1267,24 +1437,31 @@ var AgentRegistry = class {
1267
1437
  }
1268
1438
  }
1269
1439
  async fetchRuntimeInfo() {
1270
- if (!this.runtimeUrl) throw new Error("Runtime URL is not set");
1440
+ const runtimeUrl = this.runtimeUrl;
1441
+ if (!runtimeUrl) throw new Error("Runtime URL is not set");
1271
1442
  const baseHeaders = this.core.headers;
1272
1443
  const credentials = this.core.credentials;
1273
1444
  const headers = { ...baseHeaders };
1274
- if (this._runtimeTransport === "single") return this.fetchRuntimeInfoSingle(headers, credentials);
1275
- if (this._runtimeTransport === "auto") return this.fetchRuntimeInfoAutoDetect(headers, credentials);
1276
- const response = await fetch(`${this.runtimeUrl}/info`, {
1445
+ const runtimeTransport = this._runtimeTransport;
1446
+ if (runtimeTransport === "single") return {
1447
+ runtimeInfo: await this.fetchRuntimeInfoSingle(runtimeUrl, headers, credentials),
1448
+ resolvedTransport: "single"
1449
+ };
1450
+ if (runtimeTransport === "auto") return this.fetchRuntimeInfoAutoDetect(runtimeUrl, headers, credentials);
1451
+ const response = await fetch(`${runtimeUrl}/info`, {
1277
1452
  headers,
1278
1453
  ...credentials ? { credentials } : {}
1279
1454
  });
1280
1455
  if (!response.ok) throw new Error(`Runtime info request failed with status ${response.status}`);
1281
- return await response.json();
1456
+ return {
1457
+ runtimeInfo: await response.json(),
1458
+ resolvedTransport: "rest"
1459
+ };
1282
1460
  }
1283
- async fetchRuntimeInfoSingle(headers, credentials) {
1284
- if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
1285
- const response = await fetch(this.runtimeUrl, {
1461
+ async fetchRuntimeInfoSingle(runtimeUrl, headers, credentials) {
1462
+ const response = await fetch(runtimeUrl, {
1286
1463
  method: "POST",
1287
- headers,
1464
+ headers: withJsonContentType(headers),
1288
1465
  body: JSON.stringify({ method: "info" }),
1289
1466
  ...credentials ? { credentials } : {}
1290
1467
  });
@@ -1293,22 +1470,24 @@ var AgentRegistry = class {
1293
1470
  }
1294
1471
  /**
1295
1472
  * Auto-detect transport by trying REST first, then falling back to single-endpoint.
1296
- * Updates `_runtimeTransport` to the detected value so subsequent requests use it directly.
1473
+ * The caller commits the detected transport only after confirming this
1474
+ * connection attempt is still current.
1297
1475
  */
1298
- async fetchRuntimeInfoAutoDetect(headers, credentials) {
1476
+ async fetchRuntimeInfoAutoDetect(runtimeUrl, headers, credentials) {
1299
1477
  try {
1300
- const response = await fetch(`${this.runtimeUrl}/info`, {
1478
+ const response = await fetch(`${runtimeUrl}/info`, {
1301
1479
  headers: { ...headers },
1302
1480
  ...credentials ? { credentials } : {}
1303
1481
  });
1304
- if (response.status >= 200 && response.status < 300) {
1305
- this._runtimeTransport = "rest";
1306
- return await response.json();
1307
- }
1482
+ if (response.status >= 200 && response.status < 300) return {
1483
+ runtimeInfo: await response.json(),
1484
+ resolvedTransport: "rest"
1485
+ };
1308
1486
  } catch {}
1309
- const result = await this.fetchRuntimeInfoSingle({ ...headers }, credentials);
1310
- this._runtimeTransport = "single";
1311
- return result;
1487
+ return {
1488
+ runtimeInfo: await this.fetchRuntimeInfoSingle(runtimeUrl, { ...headers }, credentials),
1489
+ resolvedTransport: "single"
1490
+ };
1312
1491
  }
1313
1492
  /**
1314
1493
  * Assign agent IDs to a record of agents
@@ -1344,6 +1523,12 @@ var AgentRegistry = class {
1344
1523
  agents: this._agents
1345
1524
  }), "Subscriber onAgentsChanged error:");
1346
1525
  }
1526
+ async notifyInspectorMetadataChanged(inspectorMetadata) {
1527
+ await this.core.notifySubscribers((subscriber) => subscriber.onInspectorMetadataChanged?.({
1528
+ copilotkit: this.core,
1529
+ inspectorMetadata
1530
+ }), "Subscriber onInspectorMetadataChanged error:");
1531
+ }
1347
1532
  };
1348
1533
 
1349
1534
  //#endregion
@@ -4159,6 +4344,14 @@ var CopilotKitCore = class {
4159
4344
  get suggestions() {
4160
4345
  return this.agentRegistry.suggestions;
4161
4346
  }
4347
+ /** Trusted, optional metadata advertised by the connected runtime. */
4348
+ get inspectorMetadata() {
4349
+ return this.agentRegistry.inspectorMetadata;
4350
+ }
4351
+ /** Refresh trusted inspector metadata without reconnecting runtime agents. */
4352
+ async refreshInspectorMetadata() {
4353
+ await this.agentRegistry.refreshInspectorMetadata();
4354
+ }
4162
4355
  get a2uiEnabled() {
4163
4356
  return this.agentRegistry.a2uiEnabled;
4164
4357
  }
@@ -4214,6 +4407,7 @@ var CopilotKitCore = class {
4214
4407
  this._headers = normalizeHeaders(headers);
4215
4408
  if (this._memoryStore) this.syncMemoryContext();
4216
4409
  this.agentRegistry.applyHeadersToAgents(this.agentRegistry.agents);
4410
+ this.agentRegistry.handleHeadersChanged();
4217
4411
  this.notifySubscribers((subscriber) => subscriber.onHeadersChanged?.({
4218
4412
  copilotkit: this,
4219
4413
  headers: this.headers
@@ -4222,6 +4416,7 @@ var CopilotKitCore = class {
4222
4416
  setCredentials(credentials) {
4223
4417
  this._credentials = credentials;
4224
4418
  this.agentRegistry.applyCredentialsToAgents(this.agentRegistry.agents);
4419
+ this.agentRegistry.handleCredentialsChanged();
4225
4420
  }
4226
4421
  setProperties(properties) {
4227
4422
  this._properties = properties;