agents 0.9.0 → 0.10.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.
Files changed (50) hide show
  1. package/dist/chat/index.d.ts +151 -2
  2. package/dist/chat/index.js +210 -11
  3. package/dist/chat/index.js.map +1 -1
  4. package/dist/{client-BwgM3cRz.js → client-QBjFV5de.js} +161 -49
  5. package/dist/client-QBjFV5de.js.map +1 -0
  6. package/dist/client.d.ts +2 -2
  7. package/dist/{compaction-helpers-BFTBIzpK.js → compaction-helpers-BPE1_ziA.js} +1 -1
  8. package/dist/{compaction-helpers-BFTBIzpK.js.map → compaction-helpers-BPE1_ziA.js.map} +1 -1
  9. package/dist/{compaction-helpers-DkJreaDR.d.ts → compaction-helpers-CHNQeyRm.d.ts} +1 -1
  10. package/dist/{do-oauth-client-provider-C2jurFjW.d.ts → do-oauth-client-provider-31gqR33H.d.ts} +1 -1
  11. package/dist/{email-DwPlM0bQ.d.ts → email-Cql45SKP.d.ts} +1 -1
  12. package/dist/email.d.ts +2 -2
  13. package/dist/experimental/memory/session/index.d.ts +153 -82
  14. package/dist/experimental/memory/session/index.js +257 -24
  15. package/dist/experimental/memory/session/index.js.map +1 -1
  16. package/dist/experimental/memory/utils/index.d.ts +1 -1
  17. package/dist/experimental/memory/utils/index.js +1 -1
  18. package/dist/{index-BtHngIIG.d.ts → index-BPkkIqMn.d.ts} +204 -74
  19. package/dist/{index-Ua2Nfvbm.d.ts → index-DDSX-g7W.d.ts} +11 -1
  20. package/dist/index.d.ts +30 -26
  21. package/dist/index.js +2 -3049
  22. package/dist/{internal_context-DT8RxmAN.d.ts → internal_context-DuQZFvWI.d.ts} +1 -1
  23. package/dist/internal_context.d.ts +1 -1
  24. package/dist/mcp/client.d.ts +2 -2
  25. package/dist/mcp/client.js +1 -1
  26. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  27. package/dist/mcp/index.d.ts +1 -1
  28. package/dist/mcp/index.js +2 -2
  29. package/dist/observability/index.d.ts +1 -1
  30. package/dist/react.d.ts +3 -1
  31. package/dist/react.js +3 -0
  32. package/dist/react.js.map +1 -1
  33. package/dist/{retries-DXMQGhG3.d.ts → retries-B_CN5KM9.d.ts} +1 -1
  34. package/dist/retries.d.ts +1 -1
  35. package/dist/{serializable-8Jt1B04R.d.ts → serializable-DGdO8CDh.d.ts} +1 -1
  36. package/dist/serializable.d.ts +1 -1
  37. package/dist/src-B8NZxxsO.js +3217 -0
  38. package/dist/src-B8NZxxsO.js.map +1 -0
  39. package/dist/{types-C-m0II8i.d.ts → types-B9A8AU7B.d.ts} +1 -1
  40. package/dist/types.d.ts +1 -1
  41. package/dist/{workflow-types-CZNXKj_D.d.ts → workflow-types-XmOkuI7A.d.ts} +1 -1
  42. package/dist/workflow-types.d.ts +1 -1
  43. package/dist/workflows.d.ts +2 -2
  44. package/dist/workflows.js +1 -1
  45. package/package.json +12 -16
  46. package/dist/client-BwgM3cRz.js.map +0 -1
  47. package/dist/experimental/forever.d.ts +0 -64
  48. package/dist/experimental/forever.js +0 -338
  49. package/dist/experimental/forever.js.map +0 -1
  50. package/dist/index.js.map +0 -1
@@ -274,6 +274,7 @@ var MCPClientConnection = class {
274
274
  this.prompts = [];
275
275
  this.resources = [];
276
276
  this.resourceTemplates = [];
277
+ this._probingCapabilities = false;
277
278
  this._onObservabilityEvent = new Emitter();
278
279
  this.onObservabilityEvent = this._onObservabilityEvent.event;
279
280
  this.client = new Client(info, {
@@ -371,25 +372,28 @@ var MCPClientConnection = class {
371
372
  * This method does the work but does not manage connection state - that's handled by discover().
372
373
  */
373
374
  async discoverAndRegister() {
374
- this.serverCapabilities = this.client.getServerCapabilities();
375
- if (!this.serverCapabilities) throw new Error("The MCP Server failed to return server capabilities");
375
+ const discoveredCapabilities = this.client.getServerCapabilities();
376
+ const shouldProbeCapabilities = !discoveredCapabilities && this.isResumedStreamableHttpSession();
377
+ this.serverCapabilities = discoveredCapabilities;
378
+ this._probingCapabilities = shouldProbeCapabilities;
379
+ if (!discoveredCapabilities && !shouldProbeCapabilities) throw new Error("The MCP Server failed to return server capabilities");
376
380
  const operations = [];
377
381
  const operationNames = [];
378
382
  operations.push(Promise.resolve(this.client.getInstructions()));
379
383
  operationNames.push("instructions");
380
- if (this.serverCapabilities.tools) {
384
+ if (discoveredCapabilities?.tools || shouldProbeCapabilities) {
381
385
  operations.push(this.registerTools());
382
386
  operationNames.push("tools");
383
387
  }
384
- if (this.serverCapabilities.resources) {
388
+ if (discoveredCapabilities?.resources || shouldProbeCapabilities) {
385
389
  operations.push(this.registerResources());
386
390
  operationNames.push("resources");
387
391
  }
388
- if (this.serverCapabilities.prompts) {
392
+ if (discoveredCapabilities?.prompts || shouldProbeCapabilities) {
389
393
  operations.push(this.registerPrompts());
390
394
  operationNames.push("prompts");
391
395
  }
392
- if (this.serverCapabilities.resources) {
396
+ if (discoveredCapabilities?.resources || shouldProbeCapabilities) {
393
397
  operations.push(this.registerResourceTemplates());
394
398
  operationNames.push("resource templates");
395
399
  }
@@ -508,7 +512,7 @@ var MCPClientConnection = class {
508
512
  * Should only be called if serverCapabilities.tools exists
509
513
  */
510
514
  async registerTools() {
511
- if (this.serverCapabilities?.tools?.listChanged) this.client.setNotificationHandler(ToolListChangedNotificationSchema, async (_notification) => {
515
+ if (this.serverCapabilities?.tools?.listChanged || this._probingCapabilities) this.client.setNotificationHandler(ToolListChangedNotificationSchema, async (_notification) => {
512
516
  this.tools = await this.fetchTools();
513
517
  });
514
518
  return this.fetchTools();
@@ -518,7 +522,7 @@ var MCPClientConnection = class {
518
522
  * Should only be called if serverCapabilities.resources exists
519
523
  */
520
524
  async registerResources() {
521
- if (this.serverCapabilities?.resources?.listChanged) this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async (_notification) => {
525
+ if (this.serverCapabilities?.resources?.listChanged || this._probingCapabilities) this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async (_notification) => {
522
526
  this.resources = await this.fetchResources();
523
527
  });
524
528
  return this.fetchResources();
@@ -528,7 +532,7 @@ var MCPClientConnection = class {
528
532
  * Should only be called if serverCapabilities.prompts exists
529
533
  */
530
534
  async registerPrompts() {
531
- if (this.serverCapabilities?.prompts?.listChanged) this.client.setNotificationHandler(PromptListChangedNotificationSchema, async (_notification) => {
535
+ if (this.serverCapabilities?.prompts?.listChanged || this._probingCapabilities) this.client.setNotificationHandler(PromptListChangedNotificationSchema, async (_notification) => {
532
536
  this.prompts = await this.fetchPrompts();
533
537
  });
534
538
  return this.fetchPrompts();
@@ -579,6 +583,64 @@ var MCPClientConnection = class {
579
583
  async handleElicitationRequest(_request) {
580
584
  throw new Error("Elicitation handler must be implemented for your platform. Override handleElicitationRequest method.");
581
585
  }
586
+ isResumedStreamableHttpSession() {
587
+ return this._transport instanceof StreamableHTTPClientTransport && typeof this._transport.sessionId === "string";
588
+ }
589
+ get sessionId() {
590
+ if (this._transport instanceof StreamableHTTPClientTransport) return this._transport.sessionId;
591
+ }
592
+ getTransportName(transport) {
593
+ if (transport instanceof StreamableHTTPClientTransport) return "streamable-http";
594
+ if (transport instanceof SSEClientTransport) return "sse";
595
+ if (transport instanceof RPCClientTransport) return "rpc";
596
+ return this.lastConnectedTransport;
597
+ }
598
+ async close() {
599
+ const transport = this._transport;
600
+ this._transport = void 0;
601
+ const url = this.url.toString();
602
+ const transportName = this.getTransportName(transport);
603
+ if (transport instanceof StreamableHTTPClientTransport && transport.sessionId) try {
604
+ await transport.terminateSession();
605
+ } catch (error) {
606
+ this._onObservabilityEvent.fire({
607
+ type: "mcp:client:close",
608
+ payload: {
609
+ url,
610
+ transport: transportName,
611
+ state: "error",
612
+ error: toErrorMessage(error),
613
+ phase: "terminate-session"
614
+ },
615
+ timestamp: Date.now()
616
+ });
617
+ }
618
+ try {
619
+ await this.client.close();
620
+ } catch (error) {
621
+ this._onObservabilityEvent.fire({
622
+ type: "mcp:client:close",
623
+ payload: {
624
+ url,
625
+ transport: transportName,
626
+ state: "error",
627
+ error: toErrorMessage(error),
628
+ phase: "client-close"
629
+ },
630
+ timestamp: Date.now()
631
+ });
632
+ throw error;
633
+ }
634
+ this._onObservabilityEvent.fire({
635
+ type: "mcp:client:close",
636
+ payload: {
637
+ url,
638
+ transport: transportName,
639
+ state: "closed"
640
+ },
641
+ timestamp: Date.now()
642
+ });
643
+ }
582
644
  /**
583
645
  * Get the transport for the client
584
646
  * @param transportType - The transport type to get
@@ -600,6 +662,7 @@ var MCPClientConnection = class {
600
662
  const transport = this.getTransport(currentTransportType);
601
663
  try {
602
664
  await this.client.connect(transport);
665
+ this._transport = transport;
603
666
  return {
604
667
  state: MCPConnectionState.CONNECTED,
605
668
  transport: currentTransportType
@@ -747,6 +810,23 @@ var MCPClientManager = class {
747
810
  getServersFromStorage() {
748
811
  return this.sql("SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers");
749
812
  }
813
+ filterConnections(filter) {
814
+ if (!filter) return this.mcpConnections;
815
+ const serverIds = filter.serverId ? Array.isArray(filter.serverId) ? filter.serverId : [filter.serverId] : void 0;
816
+ const serverNames = filter.serverName ? Array.isArray(filter.serverName) ? filter.serverName : [filter.serverName] : void 0;
817
+ const states = filter.state ? Array.isArray(filter.state) ? filter.state : [filter.state] : void 0;
818
+ let nameMatchedIds;
819
+ if (serverNames) {
820
+ const servers = this.getServersFromStorage();
821
+ nameMatchedIds = new Set(servers.filter((s) => serverNames.includes(s.name)).map((s) => s.id));
822
+ }
823
+ return Object.fromEntries(Object.entries(this.mcpConnections).filter(([id, conn]) => {
824
+ if (serverIds && !serverIds.includes(id)) return false;
825
+ if (nameMatchedIds && !nameMatchedIds.has(id)) return false;
826
+ if (states && !states.includes(conn.connectionState)) return false;
827
+ return true;
828
+ }));
829
+ }
750
830
  /**
751
831
  * Get the retry options for a server from stored server_options
752
832
  */
@@ -758,6 +838,24 @@ var MCPClientManager = class {
758
838
  clearServerAuthUrl(serverId) {
759
839
  this.sql("UPDATE cf_agents_mcp_servers SET auth_url = NULL WHERE id = ?", serverId);
760
840
  }
841
+ updateStoredSessionId(id, sessionId) {
842
+ const serverRow = this.getServersFromStorage().find((server) => server.id === id);
843
+ if (!serverRow) return;
844
+ const parsedOptions = serverRow.server_options ? JSON.parse(serverRow.server_options) : {};
845
+ if (parsedOptions.transport?.sessionId === sessionId) return;
846
+ const nextTransport = {
847
+ ...parsedOptions.transport ?? {},
848
+ ...sessionId ? { sessionId } : {}
849
+ };
850
+ if (!sessionId) delete nextTransport.sessionId;
851
+ this.saveServerToStorage({
852
+ ...serverRow,
853
+ server_options: JSON.stringify({
854
+ ...parsedOptions,
855
+ transport: nextTransport
856
+ })
857
+ });
858
+ }
761
859
  failConnection(serverId, error) {
762
860
  this.clearServerAuthUrl(serverId);
763
861
  if (this.mcpConnections[serverId]) {
@@ -832,15 +930,12 @@ var MCPClientManager = class {
832
930
  continue;
833
931
  }
834
932
  if (existingConn.connectionState === MCPConnectionState.AUTHENTICATING || existingConn.connectionState === MCPConnectionState.CONNECTING || existingConn.connectionState === MCPConnectionState.DISCOVERING) continue;
835
- if (existingConn.connectionState === MCPConnectionState.FAILED) {
836
- try {
837
- await existingConn.client.close();
838
- } catch (error) {
839
- console.warn(`[MCPClientManager] Error closing failed connection ${server.id}:`, error);
840
- }
841
- delete this.mcpConnections[server.id];
842
- this._connectionDisposables.get(server.id)?.dispose();
843
- this._connectionDisposables.delete(server.id);
933
+ if (existingConn.connectionState === MCPConnectionState.FAILED) try {
934
+ await existingConn.close();
935
+ } catch (error) {
936
+ console.warn(`[MCPClientManager] Error closing failed connection ${server.id}:`, error);
937
+ } finally {
938
+ this.cleanupClosedConnection(server.id);
844
939
  }
845
940
  }
846
941
  const parsedOptions = server.server_options ? JSON.parse(server.server_options) : null;
@@ -1063,6 +1158,7 @@ var MCPClientManager = class {
1063
1158
  const conn = this.mcpConnections[id];
1064
1159
  if (!conn) throw new Error(`Server ${id} is not registered. Call registerServer() first.`);
1065
1160
  const error = await conn.init();
1161
+ this.updateStoredSessionId(id, conn.sessionId);
1066
1162
  this._onServerStateChanged.fire();
1067
1163
  switch (conn.connectionState) {
1068
1164
  case MCPConnectionState.FAILED: return {
@@ -1199,6 +1295,7 @@ var MCPClientManager = class {
1199
1295
  if (conn.connectionState !== MCPConnectionState.AUTHENTICATING) throw new Error(`Failed to authenticate: the client is in "${conn.connectionState}" state, expected "authenticating"`);
1200
1296
  await authProvider.consumeState(state);
1201
1297
  await conn.completeAuthorization(code);
1298
+ this.updateStoredSessionId(serverId, conn.sessionId);
1202
1299
  await authProvider.deleteCodeVerifier();
1203
1300
  this.clearServerAuthUrl(serverId);
1204
1301
  conn.connectionError = null;
@@ -1308,18 +1405,21 @@ var MCPClientManager = class {
1308
1405
  return this._oauthCallbackConfig;
1309
1406
  }
1310
1407
  /**
1408
+ * @param filter - Optional filter to scope results to specific servers
1311
1409
  * @returns namespaced list of tools
1312
1410
  */
1313
- listTools() {
1314
- return getNamespacedData(this.mcpConnections, "tools");
1411
+ listTools(filter) {
1412
+ return getNamespacedData(this.filterConnections(filter), "tools");
1315
1413
  }
1316
1414
  /**
1415
+ * @param filter - Optional filter to scope results to specific servers
1317
1416
  * @returns a set of tools that you can use with the AI SDK
1318
1417
  */
1319
- getAITools() {
1320
- for (const [id, conn] of Object.entries(this.mcpConnections)) if (conn.connectionState !== MCPConnectionState.READY && conn.connectionState !== MCPConnectionState.AUTHENTICATING) console.warn(`[getAITools] WARNING: Reading tools from connection ${id} in state "${conn.connectionState}". Tools may not be loaded yet.`);
1418
+ getAITools(filter) {
1419
+ const connections = this.filterConnections(filter);
1420
+ for (const [id, conn] of Object.entries(connections)) if (conn.connectionState !== MCPConnectionState.READY && conn.connectionState !== MCPConnectionState.AUTHENTICATING) console.warn(`[getAITools] WARNING: Reading tools from connection ${id} in state "${conn.connectionState}". Tools may not be loaded yet.`);
1321
1421
  const entries = [];
1322
- for (const tool of getNamespacedData(this.mcpConnections, "tools")) try {
1422
+ for (const tool of getNamespacedData(connections, "tools")) try {
1323
1423
  const toolKey = `tool_${tool.serverId.replace(/-/g, "")}_${tool.name}`;
1324
1424
  entries.push([toolKey, {
1325
1425
  description: tool.description,
@@ -1346,14 +1446,15 @@ var MCPClientManager = class {
1346
1446
  }
1347
1447
  /**
1348
1448
  * @deprecated this has been renamed to getAITools(), and unstable_getAITools will be removed in the next major version
1449
+ * @param filter - Optional filter to scope results to specific servers
1349
1450
  * @returns a set of tools that you can use with the AI SDK
1350
1451
  */
1351
- unstable_getAITools() {
1452
+ unstable_getAITools(filter) {
1352
1453
  if (!this._didWarnAboutUnstableGetAITools) {
1353
1454
  this._didWarnAboutUnstableGetAITools = true;
1354
1455
  console.warn("unstable_getAITools is deprecated, use getAITools instead. unstable_getAITools will be removed in the next major version.");
1355
1456
  }
1356
- return this.getAITools();
1457
+ return this.getAITools(filter);
1357
1458
  }
1358
1459
  /**
1359
1460
  * Closes all active in-memory connections to MCP servers.
@@ -1365,33 +1466,41 @@ var MCPClientManager = class {
1365
1466
  * Use removeServer() instead if you want to fully clean up a server
1366
1467
  * (closes connection AND removes from storage).
1367
1468
  */
1469
+ cleanupClosedConnection(id) {
1470
+ this.updateStoredSessionId(id, void 0);
1471
+ const store = this._connectionDisposables.get(id);
1472
+ if (store) store.dispose();
1473
+ this._connectionDisposables.delete(id);
1474
+ delete this.mcpConnections[id];
1475
+ }
1368
1476
  async closeAllConnections() {
1369
1477
  const ids = Object.keys(this.mcpConnections);
1370
1478
  this._pendingConnections.clear();
1371
1479
  for (const id of ids) this.mcpConnections[id].cancelDiscovery();
1372
- await Promise.all(ids.map(async (id) => {
1373
- await this.mcpConnections[id].client.close();
1374
- }));
1375
- for (const id of ids) {
1376
- const store = this._connectionDisposables.get(id);
1377
- if (store) store.dispose();
1378
- this._connectionDisposables.delete(id);
1379
- delete this.mcpConnections[id];
1380
- }
1480
+ const errors = (await Promise.allSettled(ids.map(async (id) => {
1481
+ try {
1482
+ await this.mcpConnections[id].close();
1483
+ } finally {
1484
+ this.cleanupClosedConnection(id);
1485
+ }
1486
+ }))).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
1487
+ if (errors.length === 1) throw errors[0];
1488
+ if (errors.length > 1) throw new AggregateError(errors, "Failed to close one or more MCP connections");
1381
1489
  }
1382
1490
  /**
1383
1491
  * Closes a connection to an MCP server
1384
1492
  * @param id The id of the connection to close
1385
1493
  */
1386
1494
  async closeConnection(id) {
1387
- if (!this.mcpConnections[id]) throw new Error(`Connection with id "${id}" does not exist.`);
1388
- this.mcpConnections[id].cancelDiscovery();
1495
+ const connection = this.mcpConnections[id];
1496
+ if (!connection) throw new Error(`Connection with id "${id}" does not exist.`);
1497
+ connection.cancelDiscovery();
1389
1498
  this._pendingConnections.delete(id);
1390
- await this.mcpConnections[id].client.close();
1391
- delete this.mcpConnections[id];
1392
- const store = this._connectionDisposables.get(id);
1393
- if (store) store.dispose();
1394
- this._connectionDisposables.delete(id);
1499
+ try {
1500
+ await connection.close();
1501
+ } finally {
1502
+ this.cleanupClosedConnection(id);
1503
+ }
1395
1504
  }
1396
1505
  /**
1397
1506
  * Remove an MCP server - closes connection if active and removes from storage.
@@ -1421,22 +1530,25 @@ var MCPClientManager = class {
1421
1530
  }
1422
1531
  }
1423
1532
  /**
1533
+ * @param filter - Optional filter to scope results to specific servers
1424
1534
  * @returns namespaced list of prompts
1425
1535
  */
1426
- listPrompts() {
1427
- return getNamespacedData(this.mcpConnections, "prompts");
1536
+ listPrompts(filter) {
1537
+ return getNamespacedData(this.filterConnections(filter), "prompts");
1428
1538
  }
1429
1539
  /**
1430
- * @returns namespaced list of tools
1540
+ * @param filter - Optional filter to scope results to specific servers
1541
+ * @returns namespaced list of resources
1431
1542
  */
1432
- listResources() {
1433
- return getNamespacedData(this.mcpConnections, "resources");
1543
+ listResources(filter) {
1544
+ return getNamespacedData(this.filterConnections(filter), "resources");
1434
1545
  }
1435
1546
  /**
1547
+ * @param filter - Optional filter to scope results to specific servers
1436
1548
  * @returns namespaced list of resource templates
1437
1549
  */
1438
- listResourceTemplates() {
1439
- return getNamespacedData(this.mcpConnections, "resourceTemplates");
1550
+ listResourceTemplates(filter) {
1551
+ return getNamespacedData(this.filterConnections(filter), "resourceTemplates");
1440
1552
  }
1441
1553
  /**
1442
1554
  * Namespaced version of callTool
@@ -1480,4 +1592,4 @@ function getNamespacedData(mcpClients, type) {
1480
1592
  //#endregion
1481
1593
  export { RPCServerTransport as a, RPCClientTransport as i, getNamespacedData as n, RPC_DO_PREFIX as o, MCPConnectionState as r, DisposableStore as s, MCPClientManager as t };
1482
1594
 
1483
- //# sourceMappingURL=client-BwgM3cRz.js.map
1595
+ //# sourceMappingURL=client-QBjFV5de.js.map